- Sync scripting branch with what was in trunk on Sunday. I believe that would be revision 2739.

SVN r2790 (scripting)
This commit is contained in:
Randy Heit 2010-09-16 03:14:32 +00:00
commit 99670b708c
317 changed files with 17655 additions and 7629 deletions

View file

@ -64,42 +64,39 @@ set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
if( CMAKE_COMPILER_IS_GNUCXX AND PROFILE ) option(FORCE_INTERNAL_ZLIB "Use internal zlib")
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" ) option(FORCE_INTERNAL_JPEG "Use internal jpeg")
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" ) option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -pg" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" )
endif( CMAKE_COMPILER_IS_GNUCXX AND PROFILE )
if( ZLIB_FOUND ) if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
message( STATUS "Using system zlib" ) message( STATUS "Using system zlib" )
else( ZLIB_FOUND ) else( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
message( STATUS "Using internal zlib" ) message( STATUS "Using internal zlib" )
add_subdirectory( zlib ) add_subdirectory( zlib )
set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib ) set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib )
set( ZLIB_LIBRARIES z ) set( ZLIB_LIBRARIES z )
set( ZLIB_LIBRARY z ) set( ZLIB_LIBRARY z )
endif( ZLIB_FOUND ) endif( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
if( JPEG_FOUND ) if( JPEG_FOUND AND NOT FORCE_INTERNAL_JPEG )
message( STATUS "Using system jpeg library" ) message( STATUS "Using system jpeg library" )
else( JPEG_FOUND ) else( JPEG_FOUND AND NOT FORCE_INTERNAL_JPEG )
message( STATUS "Using internal jpeg library" ) message( STATUS "Using internal jpeg library" )
add_subdirectory( jpeg-6b ) add_subdirectory( jpeg-6b )
set( JPEG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/jpeg-6b ) set( JPEG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/jpeg-6b )
set( JPEG_LIBRARIES jpeg ) set( JPEG_LIBRARIES jpeg )
set( JPEG_LIBRARY jpeg ) set( JPEG_LIBRARY jpeg )
endif( JPEG_FOUND ) endif( JPEG_FOUND AND NOT FORCE_INTERNAL_JPEG )
if( BZIP2_FOUND ) if( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 )
message( STATUS "Using system bzip2 library" ) message( STATUS "Using system bzip2 library" )
else( BZIP2_FOUND ) else( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 )
message( STATUS "Using internal bzip2 library" ) message( STATUS "Using internal bzip2 library" )
add_subdirectory( bzip2 ) add_subdirectory( bzip2 )
set( BZIP2_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bzip2" ) set( BZIP2_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bzip2" )
set( BZIP2_LIBRARIES bz2 ) set( BZIP2_LIBRARIES bz2 )
set( BZIP2_LIBRARY bz2 ) set( BZIP2_LIBRARY bz2 )
endif( BZIP2_FOUND) endif( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 )
set( LZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lzma/C" ) set( LZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lzma/C" )

23
FindFluidSynth.cmake Normal file
View file

@ -0,0 +1,23 @@
# - Find fluidsynth
# Find the native fluidsynth includes and library
#
# FLUIDSYNTH_INCLUDE_DIR - where to find fluidsynth.h
# FLUIDSYNTH_LIBRARIES - List of libraries when using fluidsynth.
# FLUIDSYNTH_FOUND - True if fluidsynth found.
IF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES)
# Already in cache, be silent
SET(FluidSynth_FIND_QUIETLY TRUE)
ENDIF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES)
FIND_PATH(FLUIDSYNTH_INCLUDE_DIR fluidsynth.h)
FIND_LIBRARY(FLUIDSYNTH_LIBRARIES NAMES fluidsynth )
MARK_AS_ADVANCED( FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR )
# handle the QUIETLY and REQUIRED arguments and set FLUIDSYNTH_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth DEFAULT_MSG FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR)

View file

@ -1 +1,3 @@
This version of ZDoom must be compiled with any version between 4.22 and 4.28 inclusive. This version of ZDoom must be compiled with any version between 4.22 and 4.28 inclusive.
Use of the latest 4.26 is recommended though due to technical issues with 4.28.

View file

@ -1,5 +1,5 @@
=============================================================================== ===============================================================================
Universal Doom Map Format ZDoom extensions v1.8 - 16.07.2009 Universal Doom Map Format ZDoom extensions v1.10 - 25.04.2010
Copyright (c) 2008 Christoph Oelckers. Copyright (c) 2008 Christoph Oelckers.
@ -38,7 +38,8 @@ between the TEXTMAP and ENDMAP lumps:
BEHAVIOR = contains compiled ACS code BEHAVIOR = contains compiled ACS code
DIALOGUE = contains compiled Strife conversation scripts. DIALOGUE = contains compiled Strife conversation scripts.
ZNODES = Nodes (must be stored as compressed GL nodes) ZNODES = Nodes (must be stored as extended GL nodes. Compression is allowed
but deprecated for portability reasons.)
BLOCKMAP = blockmap. It is recommended not to include this lump in UDMF maps. BLOCKMAP = blockmap. It is recommended not to include this lump in UDMF maps.
REJECT = reject table. Recommended use is for special effects only. REJECT = reject table. Recommended use is for special effects only.
@ -88,6 +89,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
alpha = <float>; // Translucency of this line, default is 1.0 alpha = <float>; // Translucency of this line, default is 1.0
renderstyle = <string>; // Render style, can be "translucent" or "add", renderstyle = <string>; // Render style, can be "translucent" or "add",
// default is "translucent". // default is "translucent".
playeruseback = <bool>; // New SPAC flag, true = player can use from back side.
anycross = <bool>; // New SPAC flag, true = any non-projectile anycross = <bool>; // New SPAC flag, true = any non-projectile
// crossing will trigger this line // crossing will trigger this line
monsteractivate = <bool>; // Monsters can trigger this line. monsteractivate = <bool>; // Monsters can trigger this line.
@ -159,6 +161,9 @@ Note: All <bool> fields default to false unless mentioned otherwise.
nofallingdamage = <bool>; // Falling damage is disabled in this sector nofallingdamage = <bool>; // Falling damage is disabled in this sector
dropactors = <bool>; // Actors drop with instantly moving floors (*) dropactors = <bool>; // Actors drop with instantly moving floors (*)
norespawn = <bool>; // Players can not respawn in this sector norespawn = <bool>; // Players can not respawn in this sector
soundsequence = <string>; // The sound sequence to play when this sector moves. Placing a
// sound sequence thing in the sector will override this property.
hidden = <bool>; // if true this sector will not be drawn on the textured automap.
* Note about dropactors * Note about dropactors
@ -176,6 +181,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
class# = <bool> // Unlike the base spec, # can range from 1-8. class# = <bool> // Unlike the base spec, # can range from 1-8.
// 8 is the maximum amount of classes the class // 8 is the maximum amount of classes the class
// menu can display. // menu can display.
conversation = <int> // Assigns a conversation dialogue to this thing.
// Parameter is the conversation ID, 0 meaning none.
} }
@ -255,6 +262,21 @@ Added sidedef scaling properties and side specific clipmidtex and wrapmidtex.
Added NoDecals sidedef option Added NoDecals sidedef option
Fixed conversion specifications for TranslucentLine special. Fixed conversion specifications for TranslucentLine special.
1.9 17.04.2010
Changed node specifications to deprecate compression of node lump.
1.10 25.04.2010
Added 'playeruseback' line trigger flag.
1.11 07.08.2010
Added 'soundsequnce' sector property.
1.12 22.08.2010
Added 'conversation' thing property.
1.13 29.08.2010
Added 'hidden' sector property.
=============================================================================== ===============================================================================
EOF EOF
=============================================================================== ===============================================================================

158
specs/usdf.txt Normal file
View file

@ -0,0 +1,158 @@
===============================================================================
Universal Strife Dialog Format Specification v2.0 - 08/20/10
Written by Braden "Blzut3" Obrzut - admin@maniacsvault.net
Defined with input from:
CodeImp
Gez
Graf Zahl
Quasar
et al.
Copyright (c) 2010 Braden Obrzut.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
===============================================================================
=======================================
I. Grammar / Syntax
=======================================
The grammar and syntax is similar to that of UDMF. A compliant UDMF parser
should be applyable to the USDF. However, it will need to be capable of
handling sub-blocks. Unknown sub-blocks should be skipped.
=======================================
II. Implementation Semantics
=======================================
------------------------------------
II.A : Storage and Retrieval of Data
------------------------------------
This is the same as in UDMF.
-----------------------------------
II.B : Storage Within Archive Files
-----------------------------------
There are two options for the USDF lump placement. This can either be a part
of the UDMF lump list or standalone. If used stand alone the lump name
DIALOGXY is used corresponding with MAPXY. For UDMF the lump shall be called
"DIALOGUE".
--------------------------------
II.C : Implementation Dependence
--------------------------------
USDF also implements the namespace statement. This has all the same
requirements as UDMF.
=======================================
III. Standardized Fields
=======================================
The following are required for all USDF complient implementations. Like UDMF,
any unknown field/function should be ignored and not treated as an error.
NOTE: "mobj" refers to Strife's conversationIDs and not doom editor numbers or
Hexen's spawnids. A valid mobj value is any positive integer greater
than or equal to 1.
---------------------
III.A : Conversations
---------------------
Conversations are groups of pages that can be assigned to a particular object.
Implementors should preserve the IDs to allow for dynamic reassignment through
scripting although this is not a requirement.
conversation // Starts a dialog.
{
actor = <integer>; // mobj for this conversation's actor. If previously
// used, this will override the previous conversation.
page // Starts a new page. Pages are automatically numbered starting at 0.
{
name = <string>; // Name that goes in the upper left hand corner
panel = <string>; // Name of lump to render as the background.
voice = <string>; // Narration sound lump.
dialog = <string>; // Dialog of the page.
drop = <integer>; // mobj for the object to drop if the actor is
// killed.
link = <integer>; // Page to jump to if all ifitem conditions are
// satisified.
// jumps to the specified page if the player has the specified amount
// or more of item in their inventory. This can be repeated as many
// times as the author wants, all conditions must be met for the
// jump to occur.
ifitem
{
item = <integer>; // mobj of item to check.
amount = <integer>; // amount required to be in inventory.
}
// Choices shall be automatically numbered.
choice
{
text = <string>; // Name of the choice.
// The amount of an item needed to successfully pick this option.
// This can be repeated, but only the first will be shown (provided
// diaplaycost is true). All costs must be satisfied for success.
cost
{
item = <integer>; // Item that is required for this option.
amount = <integer>; // Minimum amount of the item needed.
}
displaycost = <bool>; // Weather the cost should be
// displayed with the option.
// If no cost is specified this should
// be ignored.
yesmessage = <string>; // Text to add to console when choice
// is accepted.
nomessage = <string>; // Text to add to console when choice
// is denied.
log = <string>; // LOG entry to use on success.
giveitem = <integer>; // Gives the specified item upon
// success.
// The following are the same as the special for linedefs in UDMF.
// They are executed on success.
special = <integer>;
arg0 = <integer>;
arg1 = <integer>;
arg2 = <integer>;
arg3 = <integer>;
arg4 = <integer>;
nextpage = <integer>; // Sets the next page.
closedialog = <bool>; // Should the dialog be closed upon
// selecting this choice?
// Default: false
}
}
}
-------------------------------
III.B : Including Other Dialogs
-------------------------------
Unlike the original Strife dialog format. The lump "SCRIPT00" should not be
included automatically. Instead the user must specify this behavior by using
the include function, which takes the name of a lump to include. Include only
needs to be available in the global scope and for compatibility reasons, must
include the result of the script and not act like a preprocessor statement.
include = <string>;
===============================================================================
EOF
===============================================================================

89
specs/usdf_zdoom.txt Normal file
View file

@ -0,0 +1,89 @@
===============================================================================
ZDoom Strife Dialog Format ZDoom v1.1 - 23.08.2010
based on Universal Strife Dialog Format v2.0
Copyright (c) 2010 Christoph Oelckers.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
===============================================================================
=======================================
I. Grammar / Syntax
=======================================
No changes.
=======================================
II. Implementation Semantics
=======================================
No changes.
=======================================
III. Changes to USDF spec
=======================================
ZDoom Strife Dialogue format implements the USDF base specification as described with one important change:
To take advantage of named actor classes any field specifying an actor type
by a conversationID takes a class name instead.
The following fields are affected by this change:
conversation
{
actor = <string>;
page
{
drop = <string>;
ifitem
{
item = <string>;
}
choice
{
cost
{
item = <string>;
}
giveitem = <string>;
}
}
}
It should be noted that this change creates an incompatibility with USDF
so technically speaking the ZDoom format is no longer 'real' USDF.
To accomodate what is needed here this is unavoidable, unfortunately.
Any proper USDF implementation not supporting named actor classes should
either refuse loading dialogues with the 'ZDoom' namespace or if it does not
outright abort on incompatible namespaces fail with a type mismatch error on
one of the specified propeties.
ZDoom-format dialogues need to start with the line:
namespace = "ZDoom";
---------------------
III.A : Conversations
---------------------
This block only lists the newly added fields. Currently ZDoom only adds one
field to the specification:
conversation // Starts a dialog.
{
id = <int>; // assigns an ID to a dialogue. IDs are used to dynamically assign
// dialogues to actors. For 'Strife' namespace or binary dialogues
// the standard conversation ID ('actor' property) is used instead
// for this purpose but since 'ZDoom' namespace requires the actor
// to be a class name it needs a separate field for this.
}
===============================================================================
EOF
===============================================================================

View file

@ -6,13 +6,21 @@ endif( COMMAND cmake_policy )
include( CheckCXXSourceCompiles ) include( CheckCXXSourceCompiles )
include( CheckFunctionExists ) include( CheckFunctionExists )
include( CheckCXXCompilerFlag )
include( FindPkgConfig ) include( FindPkgConfig )
option( NO_ASM "Disable assembly code" ) option( NO_ASM "Disable assembly code" )
if( CMAKE_COMPILER_IS_GNUCXX ) if( CMAKE_COMPILER_IS_GNUCXX )
option( NO_STRIP "Do not strip Release or MinSizeRel builds" ) option( NO_STRIP "Do not strip Release or MinSizeRel builds" )
# At least some versions of Xcode fail if you strip with the linker
# instead of the separate strip utility.
if( APPLE )
set( NO_STRIP ON )
endif( APPLE )
endif( CMAKE_COMPILER_IS_GNUCXX ) endif( CMAKE_COMPILER_IS_GNUCXX )
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" )
if( CMAKE_SIZEOF_VOID_P MATCHES "8" ) if( CMAKE_SIZEOF_VOID_P MATCHES "8" )
set( X64 64 ) set( X64 64 )
endif( CMAKE_SIZEOF_VOID_P MATCHES "8" ) endif( CMAKE_SIZEOF_VOID_P MATCHES "8" )
@ -25,6 +33,10 @@ endif( CMAKE_SIZEOF_VOID_P MATCHES "8" )
# fmodapi<version>linux[64] -or simply- fmod # fmodapi<version>linux[64] -or simply- fmod
# jpeg-6b # jpeg-6b
# ... # ...
# The recommended method is to put it in the zdoom tree, since its
# headers are unversioned. Especially now that we can't work properly
# with anything newer than 4.26.xx, you probably don't want to use
# a system-wide version.
# Construct version numbers for searching for the FMOD library on Linux. # Construct version numbers for searching for the FMOD library on Linux.
set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41" set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41"
@ -32,7 +44,7 @@ set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41"
"27" "26" "25" "24" "23" "22" "21" "20" "21" "19" "18" "17" "16" "27" "26" "25" "24" "23" "22" "21" "20" "21" "19" "18" "17" "16"
"15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03" "15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03"
"02" "01" "00" ) "02" "01" "00" )
set( MAJOR_VERSIONS "26" "24" "22" "20" ) set( MAJOR_VERSIONS "30" "28" "26" "24" "22" "20" )
set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" ) set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" )
foreach( majver ${MAJOR_VERSIONS} ) foreach( majver ${MAJOR_VERSIONS} )
foreach( minver ${MINOR_VERSIONS} ) foreach( minver ${MINOR_VERSIONS} )
@ -230,14 +242,11 @@ else( FMOD_LIBRARY )
endif( FMOD_LIBRARY ) endif( FMOD_LIBRARY )
# Search for NASM # Search for FluidSynth
if( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc ) include( ../FindFluidSynth.cmake )
if( NOT NO_ASM )
message( STATUS "Disabling assembly code for PowerPC." ) # Search for NASM
set( NO_ASM ON )
endif( NOT NO_ASM )
endif( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc )
if( NOT NO_ASM ) if( NOT NO_ASM )
if( UNIX AND X64 ) if( UNIX AND X64 )
@ -297,7 +306,12 @@ if( NOT NO_ASM )
set( ASM_FLAGS ) set( ASM_FLAGS )
set( ASM_SOURCE_EXTENSION .s ) set( ASM_SOURCE_EXTENSION .s )
else( X64 ) else( X64 )
set( ASM_FLAGS -f elf -DM_TARGET_LINUX -i${CMAKE_CURRENT_SOURCE_DIR}/ ) if( APPLE )
set( ASM_FLAGS -fmacho -DM_TARGET_MACHO )
else( APPLE )
set( ASM_FLAGS -felf -DM_TARGET_LINUX )
endif( APPLE )
set( ASM_FLAGS "${ASM_FLAGS}" -i${CMAKE_CURRENT_SOURCE_DIR}/ )
set( ASM_SOURCE_EXTENSION .asm ) set( ASM_SOURCE_EXTENSION .asm )
endif( X64 ) endif( X64 )
else( UNIX ) else( UNIX )
@ -327,9 +341,52 @@ if( NOT NO_ASM )
ENDMACRO( ADD_ASM_FILE ) ENDMACRO( ADD_ASM_FILE )
endif( NOT NO_ASM ) endif( NOT NO_ASM )
# Decide on SSE setup
set( SSE_MATTERS NO )
# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it.
if( CMAKE_SIZEOF_VOID_P MATCHES "4" )
CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH )
CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 )
if( CAN_DO_MFPMATH )
set( SSE1_ENABLE "-msse -mfpmath=sse" )
set( SSE2_ENABLE "-msse2 -mfpmath=sse" )
set( SSE_MATTERS YES )
elseif( CAN_DO_ARCHSSE2 )
set( SSE1_ENABLE -arch:SSE )
set( SSE2_ENABLE -arch:SSE2 )
set( SSE_MATTERS YES )
endif( CAN_DO_MFPMATH )
endif( CMAKE_SIZEOF_VOID_P MATCHES "4" )
if( SSE_MATTERS )
if( WIN32 )
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
else( WIN32 )
CHECK_FUNCTION_EXISTS(mprotect HAVE_MPROTECT)
if( HAVE_MPROTECT )
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
else( HAVE_MPROTECT )
set( BACKPATCH 0 )
endif( HAVE_MPROTECT )
endif( WIN32 )
set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." )
else( SSE_MATTERS )
set( BACKPATCH 0 )
endif( SSE_MATTERS )
# Set up flags for GCC # Set up flags for GCC
if( CMAKE_COMPILER_IS_GNUCXX ) if( CMAKE_COMPILER_IS_GNUCXX )
if( PROFILE )
set( CMAKE_C_FLinclude( FindFluidSynth.cmake )
AGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" )
set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -pg" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" )
endif( PROFILE )
set( REL_CXX_FLAGS "-fno-rtti" ) set( REL_CXX_FLAGS "-fno-rtti" )
if( NOT PROFILE ) if( NOT PROFILE )
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" ) set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
@ -375,6 +432,13 @@ if( NOT STRNICMP_EXISTS )
add_definitions( -Dstrnicmp=strncasecmp ) add_definitions( -Dstrnicmp=strncasecmp )
endif( NOT STRNICMP_EXISTS ) endif( NOT STRNICMP_EXISTS )
if( NOT WIN32 )
CHECK_FUNCTION_EXISTS( sigtimedwait SIGTIMEDWAIT_EXISTS )
if( SIGTIMEDWAIT_EXISTS )
add_definitions( -DHAVE_SIGTIMEDWAIT )
endif( SIGTIMEDWAIT_EXISTS )
endif( NOT WIN32)
if( NOT MSVC ) if( NOT MSVC )
add_definitions( -D__forceinline=inline ) add_definitions( -D__forceinline=inline )
endif( NOT MSVC ) endif( NOT MSVC )
@ -408,6 +472,12 @@ if( NOT HAS_VA_COPY )
endif( HAS___VA_COPY ) endif( HAS___VA_COPY )
endif( NOT HAS_VA_COPY ) endif( NOT HAS_VA_COPY )
# Flags
if( BACKPATCH )
add_definitions( -DBACKPATCH )
endif( BACKPATCH )
# Update svnrevision.h # Update svnrevision.h
add_custom_target( revision_check ALL add_custom_target( revision_check ALL
@ -417,8 +487,16 @@ add_custom_target( revision_check ALL
# Libraries ZDoom needs # Libraries ZDoom needs
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" ) set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" )
include_directories( "${ZLIB_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" )
if( FLUIDSYNTH_FOUND )
if( NOT DYN_FLUIDSYNTH)
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" )
endif( NOT DYN_FLUIDSYNTH )
endif( FLUIDSYNTH_FOUND )
# Start defining source files for ZDoom # Start defining source files for ZDoom
@ -466,7 +544,7 @@ else( WIN32 )
sdl/sdlvideo.cpp sdl/sdlvideo.cpp
sdl/st_start.cpp ) sdl/st_start.cpp )
if( APPLE ) if( APPLE )
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} sdl/SDLMain.m ) set( SYSTEM_SOURCES ${SYSTEM_SOURCES} sdl/SDLMain.m sdl/iwadpicker_cocoa.mm )
endif( APPLE ) endif( APPLE )
endif( WIN32 ) endif( WIN32 )
@ -507,12 +585,23 @@ add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h
include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
if( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc ) if( SSE_MATTERS )
if( SSE )
set( X86_SOURCES nodebuild_classify_sse2.cpp )
set_source_files_properties( nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "${SSE2_ENABLE}" )
else( SSE )
add_definitions( -DDISABLE_SSE )
endif( SSE )
else( SSE_MATTERS )
add_definitions( -DDISABLE_SSE )
set( X86_SOURCES ) set( X86_SOURCES )
set( NOT_X86 ON ) endif( SSE_MATTERS )
else( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc )
set( X86_SOURCES nodebuild_classify_sse2.cpp ) if( DYN_FLUIDSYNTH )
endif( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc ) add_definitions( -DHAVE_FLUIDSYNTH -DDYN_FLUIDSYNTH )
elseif( FLUIDSYNTH_FOUND )
add_definitions( -DHAVE_FLUIDSYNTH )
endif( DYN_FLUIDSYNTH )
add_executable( zdoom WIN32 add_executable( zdoom WIN32
autostart.cpp autostart.cpp
@ -578,7 +667,6 @@ add_executable( zdoom WIN32
m_png.cpp m_png.cpp
m_random.cpp m_random.cpp
md5.cpp md5.cpp
mus2midi.cpp
name.cpp name.cpp
nodebuild.cpp nodebuild.cpp
nodebuild_classify_nosse2.cpp nodebuild_classify_nosse2.cpp
@ -596,6 +684,7 @@ add_executable( zdoom WIN32
p_effect.cpp p_effect.cpp
p_enemy.cpp p_enemy.cpp
p_floor.cpp p_floor.cpp
p_glnodes.cpp
p_interaction.cpp p_interaction.cpp
p_lights.cpp p_lights.cpp
p_linkedsectors.cpp p_linkedsectors.cpp
@ -620,6 +709,7 @@ add_executable( zdoom WIN32
p_tick.cpp p_tick.cpp
p_trace.cpp p_trace.cpp
p_udmf.cpp p_udmf.cpp
p_usdf.cpp
p_user.cpp p_user.cpp
p_writemap.cpp p_writemap.cpp
p_xlat.cpp p_xlat.cpp
@ -663,9 +753,7 @@ add_executable( zdoom WIN32
zstring.cpp zstring.cpp
g_doom/a_doommisc.cpp g_doom/a_doommisc.cpp
g_heretic/a_hereticmisc.cpp g_heretic/a_hereticmisc.cpp
g_heretic/heretic_sbar.cpp
g_hexen/a_hexenmisc.cpp g_hexen/a_hexenmisc.cpp
g_hexen/hexen_sbar.cpp
g_raven/a_artitele.cpp g_raven/a_artitele.cpp
g_raven/a_minotaur.cpp g_raven/a_minotaur.cpp
g_strife/a_strifestuff.cpp g_strife/a_strifestuff.cpp
@ -729,13 +817,16 @@ add_executable( zdoom WIN32
sound/music_cd.cpp sound/music_cd.cpp
sound/music_dumb.cpp sound/music_dumb.cpp
sound/music_gme.cpp sound/music_gme.cpp
sound/music_mus_midiout.cpp
sound/music_smf_midiout.cpp
sound/music_hmi_midiout.cpp
sound/music_midistream.cpp sound/music_midistream.cpp
sound/music_midi_base.cpp sound/music_midi_base.cpp
sound/music_midi_midiout.cpp
sound/music_midi_timidity.cpp sound/music_midi_timidity.cpp
sound/music_mus_midiout.cpp
sound/music_mus_opl.cpp sound/music_mus_opl.cpp
sound/music_stream.cpp sound/music_stream.cpp
sound/music_fluidsynth_mididevice.cpp
sound/music_softsynth_mididevice.cpp
sound/music_timidity_mididevice.cpp sound/music_timidity_mididevice.cpp
sound/music_win_mididevice.cpp sound/music_win_mididevice.cpp
textures/automaptexture.cpp textures/automaptexture.cpp
@ -824,21 +915,12 @@ if( NOT WIN32 )
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make ) COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
endif( NOT WIN32 ) endif( NOT WIN32 )
if( CMAKE_COMPILER_IS_GNUCXX ) if( CMAKE_COMPILER_IS_GNUCXX )
# GCC misoptimizes this file # GCC misoptimizes this file
set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" )
# Compile this one file with SSE2 support.
set_source_files_properties( nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mfpmath=sse" )
# Need to enable intrinsics for this file. # Need to enable intrinsics for this file.
if( NOT NOT_X86 ) if( SSE_MATTERS )
set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" ) set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
endif( NOT NOT_X86 ) endif( SSE_MATTERS )
endif( CMAKE_COMPILER_IS_GNUCXX ) endif( CMAKE_COMPILER_IS_GNUCXX )
if( MSVC )
# Compile this one file with SSE2 support.
set_source_files_properties( nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE2" )
endif( MSVC )

View file

@ -56,7 +56,8 @@ DEFINE_SPECIAL(Sector_ChangeFlags, 54, 3, 3, 3)
DEFINE_SPECIAL(Line_SetBlocking, 55, 3, 3, 3) DEFINE_SPECIAL(Line_SetBlocking, 55, 3, 3, 3)
DEFINE_SPECIAL(Line_SetTextureScale, 56, 5, 5, 5) DEFINE_SPECIAL(Line_SetTextureScale, 56, 5, 5, 5)
DEFINE_SPECIAL(Sector_SetPortal, 57, -1, -1, 5) DEFINE_SPECIAL(Sector_SetPortal, 57, -1, -1, 5)
DEFINE_SPECIAL(Sector_CopyScroller, 58, -1, -1, 2)
DEFINE_SPECIAL(Polyobj_OR_MoveToSpot, 59, 3, 3, 3)
DEFINE_SPECIAL(Plat_PerpetualRaise, 60, 3, 3, 3) DEFINE_SPECIAL(Plat_PerpetualRaise, 60, 3, 3, 3)
DEFINE_SPECIAL(Plat_Stop, 61, 1, 1, 1) DEFINE_SPECIAL(Plat_Stop, 61, 1, 1, 1)
DEFINE_SPECIAL(Plat_DownWaitUpStay, 62, 3, 3, 3) DEFINE_SPECIAL(Plat_DownWaitUpStay, 62, 3, 3, 3)
@ -76,14 +77,17 @@ DEFINE_SPECIAL(Teleport_EndGame, 75, 0, 0, 0)
DEFINE_SPECIAL(TeleportOther, 76, 3, 3, 3) DEFINE_SPECIAL(TeleportOther, 76, 3, 3, 3)
DEFINE_SPECIAL(TeleportGroup, 77, 5, 5, 5) DEFINE_SPECIAL(TeleportGroup, 77, 5, 5, 5)
DEFINE_SPECIAL(TeleportInSector, 78, 4, 5, 5) DEFINE_SPECIAL(TeleportInSector, 78, 4, 5, 5)
DEFINE_SPECIAL(Thing_SetConversation, 79, 2, 2, 2)
DEFINE_SPECIAL(ACS_Execute, 80, 1, 5, 5) DEFINE_SPECIAL(ACS_Execute, 80, 1, 5, 5)
DEFINE_SPECIAL(ACS_Suspend, 81, 2, 2, 2) DEFINE_SPECIAL(ACS_Suspend, 81, 2, 2, 2)
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2, 2) DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2, 2)
DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5, 5) DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5, 5)
DEFINE_SPECIAL(ACS_ExecuteWithResult, 84, 1, 4, 4) DEFINE_SPECIAL(ACS_ExecuteWithResult, 84, 1, 4, 4)
DEFINE_SPECIAL(ACS_LockedExecuteDoor, 85, 5, 5, 5) DEFINE_SPECIAL(ACS_LockedExecuteDoor, 85, 5, 5, 5)
DEFINE_SPECIAL(Polyobj_MoveToSpot, 86, 3, 3, 3)
DEFINE_SPECIAL(Polyobj_Stop, 87, 1, 1, 1)
DEFINE_SPECIAL(Polyobj_MoveTo, 88, 4, 4, 4)
DEFINE_SPECIAL(Polyobj_OR_MoveTo, 89, 4, 4, 4)
DEFINE_SPECIAL(Polyobj_OR_RotateLeft, 90, 3, 3, 3) DEFINE_SPECIAL(Polyobj_OR_RotateLeft, 90, 3, 3, 3)
DEFINE_SPECIAL(Polyobj_OR_RotateRight, 91, 3, 3, 3) DEFINE_SPECIAL(Polyobj_OR_RotateRight, 91, 3, 3, 3)
DEFINE_SPECIAL(Polyobj_OR_Move, 92, 4, 4, 4) DEFINE_SPECIAL(Polyobj_OR_Move, 92, 4, 4, 4)
@ -110,7 +114,9 @@ DEFINE_SPECIAL(Plane_Copy, 118, -1, -1, 5)
DEFINE_SPECIAL(Thing_Damage, 119, 2, 3, 3) DEFINE_SPECIAL(Thing_Damage, 119, 2, 3, 3)
DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake
DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5) DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5)
DEFINE_SPECIAL(Thing_Move, 125, 2, 3, 3) DEFINE_SPECIAL(Thing_Move, 125, 2, 3, 3)
DEFINE_SPECIAL(Thing_SetSpecial, 127, 5, 5, 5) DEFINE_SPECIAL(Thing_SetSpecial, 127, 5, 5, 5)
DEFINE_SPECIAL(ThrustThingZ, 128, 4, 4, 4) DEFINE_SPECIAL(ThrustThingZ, 128, 4, 4, 4)
DEFINE_SPECIAL(UsePuzzleItem, 129, 2, 5, 5) DEFINE_SPECIAL(UsePuzzleItem, 129, 2, 5, 5)

View file

@ -40,6 +40,7 @@
#include "r_blend.h" #include "r_blend.h"
#include "s_sound.h" #include "s_sound.h"
struct subsector_t;
class PClassAmmo; class PClassAmmo;
// //
@ -262,7 +263,7 @@ enum
MF4_NOEXTREMEDEATH = 0x10000000, // this projectile or weapon never gibs its victim MF4_NOEXTREMEDEATH = 0x10000000, // this projectile or weapon never gibs its victim
MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
/* = 0x80000000, */ MF4_BOSSSPAWNED = 0x80000000, // Spawned by a boss spawn cube
// --- mobj.flags5 --- // --- mobj.flags5 ---
@ -321,6 +322,9 @@ enum
MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions
MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering
MF6_KILLED = 0x00040000, // Something that was killed (but not necessarily a corpse) MF6_KILLED = 0x00040000, // Something that was killed (but not necessarily a corpse)
MF6_BLOCKEDBYSOLIDACTORS = 0x00080000, // Blocked by solid actors, even if not solid itself
MF6_ADDITIVEPOISONDAMAGE = 0x00100000,
MF6_ADDITIVEPOISONDURATION = 0x00200000,
// --- mobj.renderflags --- // --- mobj.renderflags ---
@ -616,7 +620,7 @@ public:
bool CheckLocalView (int playernum) const; bool CheckLocalView (int playernum) const;
// Finds the first item of a particular type. // Finds the first item of a particular type.
AInventory *FindInventory (PClassActor *type); AInventory *FindInventory (PClassActor *type, bool subclass=false);
AInventory *FindInventory (FName type); AInventory *FindInventory (FName type);
template<class T> T *FindInventory () template<class T> T *FindInventory ()
{ {
@ -695,22 +699,29 @@ public:
PClassActor *GetBloodType(int type = 0) const PClassActor *GetBloodType(int type = 0) const
{ {
PClassActor *bloodcls;
if (type == 0) if (type == 0)
{ {
return PClass::FindActor(GetClass()->BloodType); bloodcls = PClass::FindActor(GetClass()->BloodType);
} }
else if (type == 1) else if (type == 1)
{ {
return PClass::FindActor(GetClass()->BloodType2); bloodcls = PClass::FindActor(GetClass()->BloodType2);
} }
else if (type == 2) else if (type == 2)
{ {
return PClass::FindActor(GetClass()->BloodType3); bloodcls = PClass::FindActor(GetClass()->BloodType3);
} }
else else
{ {
return NULL; return NULL;
} }
if (bloodcls != NULL)
{
bloodcls = bloodcls->GetReplacement();
}
return bloodcls;
} }
// Calculate amount of missile damage // Calculate amount of missile damage
@ -742,6 +753,7 @@ public:
fixed_t pitch, roll; fixed_t pitch, roll;
FBlockNode *BlockNode; // links in blocks (if needed) FBlockNode *BlockNode; // links in blocks (if needed)
struct sector_t *Sector; struct sector_t *Sector;
subsector_t * subsector;
fixed_t floorz, ceilingz; // closest together of contacted secs fixed_t floorz, ceilingz; // closest together of contacted secs
fixed_t dropoffz; // killough 11/98: the lowest floor over all contacted Sectors. fixed_t dropoffz; // killough 11/98: the lowest floor over all contacted Sectors.
@ -820,6 +832,15 @@ public:
AActor *BlockingMobj; // Actor that blocked the last move AActor *BlockingMobj; // Actor that blocked the last move
line_t *BlockingLine; // Line that blocked the last move line_t *BlockingLine; // Line that blocked the last move
int PoisonDamage; // Damage received per tic from poison.
int PoisonDuration; // Duration left for receiving poison damage.
int PoisonPeriod; // How often poison damage is applied. (Every X tics.)
int PoisonDamageReceived; // Damage received per tic from poison.
int PoisonDurationReceived; // Duration left for receiving poison damage.
int PoisonPeriodReceived; // How often poison damage is applied. (Every X tics.)
TObjPtr<AActor> Poisoner; // Last source of received poison damage.
// a linked list of sectors where this object appears // a linked list of sectors where this object appears
struct msecnode_t *touching_sectorlist; // phares 3/14/98 struct msecnode_t *touching_sectorlist; // phares 3/14/98
@ -859,8 +880,9 @@ public:
FState *MeleeState; FState *MeleeState;
FState *MissileState; FState *MissileState;
// [RH] The dialogue to show when this actor is "used."
FStrifeDialogueNode *Conversation; int ConversationRoot; // THe root of the current dialogue
FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is "used."
// [RH] Decal(s) this weapon/projectile generates on impact. // [RH] Decal(s) this weapon/projectile generates on impact.
FDecalBase *DecalGenerator; FDecalBase *DecalGenerator;
@ -890,8 +912,7 @@ public:
void SetOrigin (fixed_t x, fixed_t y, fixed_t z); void SetOrigin (fixed_t x, fixed_t y, fixed_t z);
bool InStateSequence(FState * newstate, FState * basestate); bool InStateSequence(FState * newstate, FState * basestate);
int GetTics(FState * newstate); int GetTics(FState * newstate);
bool SetState (FState *newstate); bool SetState (FState *newstate, bool nofunction=false);
bool SetStateNF (FState *newstate);
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true); virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
bool isFast(); bool isFast();
void SetIdle(); void SetIdle();

View file

@ -36,6 +36,9 @@
#include "r_translate.h" #include "r_translate.h"
#include "d_event.h" #include "d_event.h"
#include "gi.h" #include "gi.h"
#include "r_bsp.h"
#include "p_setup.h"
#include "c_bind.h"
#include "m_cheat.h" #include "m_cheat.h"
#include "i_system.h" #include "i_system.h"
@ -58,6 +61,8 @@
#include "am_map.h" #include "am_map.h"
#include "a_artifacts.h" #include "a_artifacts.h"
#include "po_man.h"
#include "a_keys.h"
struct AMColor struct AMColor
{ {
@ -79,7 +84,7 @@ struct AMColor
static AMColor Background, YourColor, WallColor, TSWallColor, static AMColor Background, YourColor, WallColor, TSWallColor,
FDWallColor, CDWallColor, ThingColor, FDWallColor, CDWallColor, ThingColor,
ThingColor_Item, ThingColor_Monster, ThingColor_Friend, ThingColor_Item, ThingColor_CountItem, ThingColor_Monster, ThingColor_Friend,
SecretWallColor, GridColor, XHairColor, SecretWallColor, GridColor, XHairColor,
NotSeenColor, NotSeenColor,
LockedColor, LockedColor,
@ -170,27 +175,66 @@ CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE);
CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE); CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE);
CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE);
CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE); CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE);
CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_citem, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_friend, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_friend, 0xe88800, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_citem, 0xe88800, CVAR_ARCHIVE);
static int bigstate = 0;
static bool textured = 1; // internal toggle for texture mode
CUSTOM_CVAR(Bool, am_textured, false, CVAR_ARCHIVE)
{
textured |= self;
}
CVAR(Int, am_showsubsector, -1, 0);
// Disable the ML_DONTDRAW line flag if x% of all lines in a map are flagged with it
// (To counter annoying mappers who think they are smart by making the automap unusable)
bool am_showallenabled;
CUSTOM_CVAR (Int, am_showalllines, -1, 0) // This is a cheat so don't save it.
{
int flagged = 0;
int total = 0;
if (self > 0 && numlines > 0)
{
for(int i=0;i<numlines;i++)
{
line_t *line = &lines[i];
// disregard intra-sector lines
if (line->frontsector == line->backsector) continue;
// disregard control sectors for deep water
if (line->frontsector->e->FakeFloor.Sectors.Size() > 0) continue;
// disregard control sectors for 3D-floors
if (line->frontsector->e->XFloor.attached.Size() > 0) continue;
total++;
if (line->flags & ML_DONTDRAW) flagged++;
}
am_showallenabled = (flagged * 100 / total >= self);
}
else if (self == 0)
{
am_showallenabled = true;
}
else
{
am_showallenabled = false;
}
}
// drawing stuff
#define AM_PANDOWNKEY KEY_DOWNARROW
#define AM_PANUPKEY KEY_UPARROW
#define AM_PANRIGHTKEY KEY_RIGHTARROW
#define AM_PANLEFTKEY KEY_LEFTARROW
#define AM_ZOOMINKEY KEY_EQUALS
#define AM_ZOOMINKEY2 0x4e // DIK_ADD
#define AM_ZOOMOUTKEY KEY_MINUS
#define AM_ZOOMOUTKEY2 0x4a // DIK_SUBTRACT
#define AM_GOBIGKEY 0x0b // DIK_0
#define AM_FOLLOWKEY 'f'
#define AM_GRIDKEY 'g'
#define AM_MARKKEY 'm'
#define AM_CLEARMARKKEY 'c'
#define AM_NUMMARKPOINTS 10 #define AM_NUMMARKPOINTS 10
@ -202,10 +246,10 @@ CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE);
#define F_PANINC (140/TICRATE) #define F_PANINC (140/TICRATE)
// how much zoom-in per tic // how much zoom-in per tic
// goes to 2x in 1 second // goes to 2x in 1 second
#define M_ZOOMIN ((int) (1.02*MAPUNIT)) #define M_ZOOMIN (1.02*MAPUNIT)
// how much zoom-out per tic // how much zoom-out per tic
// pulls out to 0.5x in 1 second // pulls out to 0.5x in 1 second
#define M_ZOOMOUT ((int) (MAPUNIT/1.02)) #define M_ZOOMOUT (MAPUNIT/1.02)
// translates between frame-buffer and map coordinates // translates between frame-buffer and map coordinates
#define CXMTOF(x) (MTOF((x)-m_x)/* - f_x*/) #define CXMTOF(x) (MTOF((x)-m_x)/* - f_x*/)
@ -253,25 +297,22 @@ mline_t player_arrow[] = {
{ { -R+3*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 } } { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
}; };
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
mline_t player_arrow_raven[] = { mline_t player_arrow_raven[] = {
{ { -R+R/4, 0 }, { 0, 0} }, // center line. { { -R+R/4, 0 }, { 0, 0} }, // center line.
{ { -R+R/4, R/8 }, { R, 0} }, // blade { { -R+R/4, R/8 }, { R, 0} }, // blade
{ { -R+R/4, -R/8 }, { R, 0 } }, { { -R+R/4, -R/8 }, { R, 0 } },
{ { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece { { -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/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} }, //crosspiece connectors
{ { -R+R/8, R/4 }, { -R+R/4, R/4} }, { { -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/4, -R/8 } }, //pommel
{ { -R-R/4, R/8 }, { -R+R/8, R/8 } }, { { -R-R/4, R/8 }, { -R+R/8, R/8 } },
{ { -R-R/4, -R/8}, { -R+R/8, -R/8 } } { { -R-R/4, -R/8}, { -R+R/8, -R/8 } }
}; };
#undef R
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
#define NUMPLYRLINES_RAVEN (sizeof(player_arrow_raven)/sizeof(mline_t)) #define NUMPLYRLINES_RAVEN (sizeof(player_arrow_raven)/sizeof(mline_t))
#define R ((8*PLAYERRADIUS)/7)
mline_t cheat_player_arrow[] = { mline_t cheat_player_arrow[] = {
{ { -R+R/8, 0 }, { R, 0 } }, // ----- { { -R+R/8, 0 }, { R, 0 } }, // -----
{ { R, 0 }, { R-R/2, R/6 } }, // -----> { { R, 0 }, { R-R/2, R/6 } }, // ----->
@ -290,9 +331,9 @@ mline_t cheat_player_arrow[] = {
{ { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, { { 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 } } { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
}; };
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
#undef R #undef R
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
#define R (MAPUNIT) #define R (MAPUNIT)
// [RH] Avoid lots of warnings without compiler-specific #pragmas // [RH] Avoid lots of warnings without compiler-specific #pragmas
@ -309,9 +350,37 @@ mline_t thintriangle_guy[] = {
L (1,0, -.5,.7), L (1,0, -.5,.7),
L (-.5,.7, -.5,-.7) L (-.5,.7, -.5,-.7)
}; };
#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
mline_t square_guy[] = {
L (0,1,1,0),
L (1,0,0,-1),
L (0,-1,-1,0),
L (-1,0,0,1)
};
#define NUMSQUAREGUYLINES (sizeof(square_guy)/sizeof(mline_t))
#undef R
#define R (MAPUNIT)
mline_t key_guy[] = {
L (-2, 0, -1.7, -0.5),
L (-1.7, -0.5, -1.5, -0.7),
L (-1.5, -0.7, -0.8, -0.5),
L (-0.8, -0.5, -0.6, 0),
L (-0.6, 0, -0.8, 0.5),
L (-1.5, 0.7, -0.8, 0.5),
L (-1.7, 0.5, -1.5, 0.7),
L (-2, 0, -1.7, 0.5),
L (-0.6, 0, 2, 0),
L (1.7, 0, 1.7, -1),
L (1.5, 0, 1.5, -1),
L (1.3, 0, 1.3, -1)
};
#define NUMKEYGUYLINES (sizeof(key_guy)/sizeof(mline_t))
#undef L #undef L
#undef R #undef R
#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
@ -344,7 +413,7 @@ static int amclock;
static mpoint_t m_paninc; // how far the window pans each tic (map coords) static mpoint_t m_paninc; // how far the window pans each tic (map coords)
static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) static float am_zoomdir;
static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords)
static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
@ -393,7 +462,69 @@ static void AM_calcMinMaxMtoF();
void AM_rotatePoint (fixed_t *x, fixed_t *y); void AM_rotatePoint (fixed_t *x, fixed_t *y);
void AM_rotate (fixed_t *x, fixed_t *y, angle_t an); void AM_rotate (fixed_t *x, fixed_t *y, angle_t an);
void AM_doFollowPlayer (); void AM_doFollowPlayer ();
static void AM_ToggleFollowPlayer();
//=============================================================================
//
// map functions
//
//=============================================================================
bool AM_addMark ();
bool AM_clearMarks ();
void AM_saveScaleAndLoc ();
void AM_restoreScaleAndLoc ();
void AM_minOutWindowScale ();
CCMD(am_togglefollow)
{
followplayer = !followplayer;
f_oldloc.x = FIXED_MAX;
Printf ("%s\n", GStrings(followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF"));
}
CCMD(am_togglegrid)
{
grid = !grid;
Printf ("%s\n", GStrings(grid ? "AMSTR_GRIDON" : "AMSTR_GRIDOFF"));
}
CCMD(am_toggletexture)
{
if (am_textured && hasglnodes)
{
textured = !textured;
Printf ("%s\n", GStrings(textured ? "AMSTR_TEXON" : "AMSTR_TEXOFF"));
}
}
CCMD(am_setmark)
{
if (AM_addMark())
{
Printf ("%s %d\n", GStrings("AMSTR_MARKEDSPOT"), markpointnum);
}
}
CCMD(am_clearmarks)
{
if (AM_clearMarks())
{
Printf ("%s\n", GStrings("AMSTR_MARKSCLEARED"));
}
}
CCMD(am_gobig)
{
bigstate = !bigstate;
if (bigstate)
{
AM_saveScaleAndLoc();
AM_minOutWindowScale();
}
else
AM_restoreScaleAndLoc();
}
// Calculates the slope and slope according to the x-axis of a line // Calculates the slope and slope according to the x-axis of a line
// segment in map coordinates (with the upright y-axis n' all) so // segment in map coordinates (with the upright y-axis n' all) so
@ -702,11 +833,19 @@ void AM_initVariables ()
automapactive = true; automapactive = true;
// Reset AM buttons
Button_AM_PanLeft.Reset();
Button_AM_PanRight.Reset();
Button_AM_PanUp.Reset();
Button_AM_PanDown.Reset();
Button_AM_ZoomIn.Reset();
Button_AM_ZoomOut.Reset();
f_oldloc.x = FIXED_MAX; f_oldloc.x = FIXED_MAX;
amclock = 0; amclock = 0;
m_paninc.x = m_paninc.y = 0; m_paninc.x = m_paninc.y = 0;
ftom_zoommul = MAPUNIT;
mtof_zoommul = MAPUNIT; mtof_zoommul = MAPUNIT;
m_w = FTOM(SCREENWIDTH); m_w = FTOM(SCREENWIDTH);
@ -774,6 +913,7 @@ static void AM_initColors (bool overlayed)
SecretWallColor = WallColor; SecretWallColor = WallColor;
SecretSectorColor.FromCVar (am_ovsecretsectorcolor); SecretSectorColor.FromCVar (am_ovsecretsectorcolor);
ThingColor_Item.FromCVar (am_ovthingcolor_item); ThingColor_Item.FromCVar (am_ovthingcolor_item);
ThingColor_CountItem.FromCVar (am_ovthingcolor_citem);
ThingColor_Friend.FromCVar (am_ovthingcolor_friend); ThingColor_Friend.FromCVar (am_ovthingcolor_friend);
ThingColor_Monster.FromCVar (am_ovthingcolor_monster); ThingColor_Monster.FromCVar (am_ovthingcolor_monster);
ThingColor.FromCVar (am_ovthingcolor); ThingColor.FromCVar (am_ovthingcolor);
@ -797,6 +937,7 @@ static void AM_initColors (bool overlayed)
FDWallColor.FromCVar (am_fdwallcolor); FDWallColor.FromCVar (am_fdwallcolor);
CDWallColor.FromCVar (am_cdwallcolor); CDWallColor.FromCVar (am_cdwallcolor);
ThingColor_Item.FromCVar (am_thingcolor_item); ThingColor_Item.FromCVar (am_thingcolor_item);
ThingColor_CountItem.FromCVar (am_thingcolor_citem);
ThingColor_Friend.FromCVar (am_thingcolor_friend); ThingColor_Friend.FromCVar (am_thingcolor_friend);
ThingColor_Monster.FromCVar (am_thingcolor_monster); ThingColor_Monster.FromCVar (am_thingcolor_monster);
ThingColor.FromCVar (am_thingcolor); ThingColor.FromCVar (am_thingcolor);
@ -946,6 +1087,8 @@ void AM_LevelInit ()
if (scale_mtof > max_scale_mtof) if (scale_mtof > max_scale_mtof)
scale_mtof = min_scale_mtof; scale_mtof = min_scale_mtof;
scale_ftom = MapDiv(MAPUNIT, scale_mtof); scale_ftom = MapDiv(MAPUNIT, scale_mtof);
am_showalllines.Callback();
} }
//============================================================================= //=============================================================================
@ -1081,127 +1224,28 @@ void AM_ToggleMap ()
// //
//============================================================================= //=============================================================================
bool AM_Responder (event_t *ev) bool AM_Responder (event_t *ev, bool last)
{ {
bool rc; if (automapactive && (ev->type == EV_KeyDown || ev->type == EV_KeyUp))
static int cheatstate = 0;
static int bigstate = 0;
rc = false;
if (automapactive && ev->type == EV_KeyDown)
{ {
rc = true; if (followplayer)
switch (ev->data1)
{ {
case AM_PANRIGHTKEY: // pan right // check for am_pan* and ignore in follow mode
if (!followplayer) const char *defbind = AutomapBindings.GetBind(ev->data1);
m_paninc.x = FTOM(F_PANINC); if (!strnicmp(defbind, "+am_pan", 7)) return false;
else
rc = false;
break;
case AM_PANLEFTKEY: // pan left
if (!followplayer)
m_paninc.x = -FTOM(F_PANINC);
else
rc = false;
break;
case AM_PANUPKEY: // pan up
if (!followplayer)
m_paninc.y = FTOM(F_PANINC);
else
rc = false;
break;
case AM_PANDOWNKEY: // pan down
if (!followplayer)
m_paninc.y = -FTOM(F_PANINC);
else
rc = false;
break;
case AM_ZOOMOUTKEY: // zoom out
case AM_ZOOMOUTKEY2:
mtof_zoommul = M_ZOOMOUT;
ftom_zoommul = M_ZOOMIN;
break;
case AM_ZOOMINKEY: // zoom in
case AM_ZOOMINKEY2:
mtof_zoommul = M_ZOOMIN;
ftom_zoommul = M_ZOOMOUT;
break;
case AM_GOBIGKEY:
bigstate = !bigstate;
if (bigstate)
{
AM_saveScaleAndLoc();
AM_minOutWindowScale();
}
else
AM_restoreScaleAndLoc();
break;
default:
switch (ev->data2)
{
case AM_FOLLOWKEY:
AM_ToggleFollowPlayer();
break;
case AM_GRIDKEY:
grid = !grid;
Printf ("%s\n", GStrings(grid ? "AMSTR_GRIDON" : "AMSTR_GRIDOFF"));
break;
case AM_MARKKEY:
if (AM_addMark())
{
Printf ("%s %d\n", GStrings("AMSTR_MARKEDSPOT"), markpointnum);
}
else
{
rc = false;
}
break;
case AM_CLEARMARKKEY:
if (AM_clearMarks())
{
Printf ("%s\n", GStrings("AMSTR_MARKSCLEARED"));
}
else
{
rc = false;
}
break;
default:
cheatstate = 0;
rc = false;
}
} }
}
else if (ev->type == EV_KeyUp)
{
rc = false;
switch (ev->data1)
{
case AM_PANRIGHTKEY:
if (!followplayer) m_paninc.x = 0;
break;
case AM_PANLEFTKEY:
if (!followplayer) m_paninc.x = 0;
break;
case AM_PANUPKEY:
if (!followplayer) m_paninc.y = 0;
break;
case AM_PANDOWNKEY:
if (!followplayer) m_paninc.y = 0;
break;
case AM_ZOOMOUTKEY:
case AM_ZOOMOUTKEY2:
case AM_ZOOMINKEY:
case AM_ZOOMINKEY2:
mtof_zoommul = MAPUNIT;
ftom_zoommul = MAPUNIT;
break;
}
}
return rc; bool res = C_DoKey(ev, &AutomapBindings, NULL);
if (res && ev->type == EV_KeyUp && !last)
{
// If this is a release event we also need to check if it released a button in the main Bindings
// so that that button does not get stuck.
const char *defbind = Bindings.GetBind(ev->data1);
return (defbind[0] != '+'); // Let G_Responder handle button releases
}
return res;
}
return false;
} }
@ -1213,6 +1257,26 @@ bool AM_Responder (event_t *ev)
void AM_changeWindowScale () void AM_changeWindowScale ()
{ {
int mtof_zoommul;
if (am_zoomdir > 0)
{
mtof_zoommul = int(M_ZOOMIN * am_zoomdir);
}
else if (am_zoomdir < 0)
{
mtof_zoommul = int(M_ZOOMOUT / -am_zoomdir);
}
else if (Button_AM_ZoomIn.bDown)
{
mtof_zoommul = int(M_ZOOMIN);
}
else if (Button_AM_ZoomOut.bDown)
{
mtof_zoommul = int(M_ZOOMOUT);
}
am_zoomdir = 0;
// Change the scaling multipliers // Change the scaling multipliers
scale_mtof = MapMul(scale_mtof, mtof_zoommul); scale_mtof = MapMul(scale_mtof, mtof_zoommul);
scale_ftom = MapDiv(MAPUNIT, scale_mtof); scale_ftom = MapDiv(MAPUNIT, scale_mtof);
@ -1223,6 +1287,13 @@ void AM_changeWindowScale ()
AM_maxOutWindowScale(); AM_maxOutWindowScale();
} }
CCMD(am_zoom)
{
if (argv.argc() >= 2)
{
am_zoomdir = (float)atof(argv[1]);
}
}
//============================================================================= //=============================================================================
// //
@ -1257,19 +1328,6 @@ void AM_doFollowPlayer ()
} }
} }
//=============================================================================
//
//
//
//=============================================================================
static void AM_ToggleFollowPlayer()
{
followplayer = !followplayer;
f_oldloc.x = FIXED_MAX;
Printf ("%s\n", GStrings(followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF"));
}
//============================================================================= //=============================================================================
// //
// Updates on Game Tick // Updates on Game Tick
@ -1284,10 +1342,20 @@ void AM_Ticker ()
amclock++; amclock++;
if (followplayer) if (followplayer)
{
AM_doFollowPlayer(); AM_doFollowPlayer();
}
else
{
m_paninc.x = m_paninc.y = 0;
if (Button_AM_PanLeft.bDown) m_paninc.x -= FTOM(F_PANINC);
if (Button_AM_PanRight.bDown) m_paninc.x += FTOM(F_PANINC);
if (Button_AM_PanUp.bDown) m_paninc.y += FTOM(F_PANINC);
if (Button_AM_PanDown.bDown) m_paninc.y -= FTOM(F_PANINC);
}
// Change the zoom if necessary // Change the zoom if necessary
if (ftom_zoommul != MAPUNIT) if (Button_AM_ZoomIn.bDown || Button_AM_ZoomOut.bDown || am_zoomdir != 0)
AM_changeWindowScale(); AM_changeWindowScale();
// Change x,y location // Change x,y location
@ -1545,6 +1613,97 @@ void AM_drawGrid (const AMColor &color)
} }
} }
//=============================================================================
//
// AM_drawSubsectors
//
//=============================================================================
void AM_drawSubsectors()
{
static TArray<FVector2> points;
float scale = float(scale_mtof);
angle_t rotation;
sector_t tempsec;
int floorlight, ceilinglight;
double originx, originy;
FDynamicColormap *colormap;
for (int i = 0; i < numsubsectors; ++i)
{
if (subsectors[i].flags & SSECF_POLYORG)
{
continue;
}
if ((!(subsectors[i].flags & SSECF_DRAWN) || (subsectors[i].render_sector->MoreFlags & SECF_HIDDEN)) && am_cheat == 0)
{
continue;
}
// Fill the points array from the subsector.
points.Resize(subsectors[i].numlines);
for (DWORD j = 0; j < subsectors[i].numlines; ++j)
{
mpoint_t pt = { subsectors[i].firstline[j].v1->x >> FRACTOMAPBITS,
subsectors[i].firstline[j].v1->y >> FRACTOMAPBITS };
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
{
AM_rotatePoint(&pt.x, &pt.y);
}
points[j].X = f_x + ((pt.x - m_x) * scale / float(1 << 24));
points[j].Y = f_y + (f_h - (pt.y - m_y) * scale / float(1 << 24));
}
// For lighting and texture determination
sector_t *sec = R_FakeFlat (subsectors[i].render_sector, &tempsec, &floorlight,
&ceilinglight, false);
// Find texture origin.
mpoint_t originpt = { -sec->GetXOffset(sector_t::floor) >> FRACTOMAPBITS,
sec->GetYOffset(sector_t::floor) >> FRACTOMAPBITS };
rotation = 0 - sec->GetAngle(sector_t::floor);
// Apply the floor's rotation to the texture origin.
if (rotation != 0)
{
AM_rotate(&originpt.x, &originpt.y, rotation);
}
// Apply the automap's rotation to the texture origin.
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
{
rotation += ANG90 - players[consoleplayer].camera->angle;
AM_rotatePoint(&originpt.x, &originpt.y);
}
originx = f_x + ((originpt.x - m_x) * scale / float(1 << 24));
originy = f_y + (f_h - (originpt.y - m_y) * scale / float(1 << 24));
// Coloring for the polygon
colormap = sec->ColorMap;
// If this subsector has not actually been seen yet (because you are cheating
// to see it on the map), tint and desaturate it.
if (!(subsectors[i].flags & SSECF_DRAWN))
{
colormap = GetSpecialLights(
MAKERGB(
(colormap->Color.r + 255) / 2,
(colormap->Color.g + 200) / 2,
(colormap->Color.b + 160) / 2),
colormap->Fade,
255 - (255 - colormap->Desaturate) / 4);
floorlight = (floorlight + 200*15) / 16;
}
// Draw the polygon.
screen->FillSimplePoly(
TexMan(sec->GetTexture(sector_t::floor)),
&points[0], points.Size(),
originx, originy,
scale / (FIXED2FLOAT(sec->GetXScale(sector_t::floor)) * float(1 << MAPBITS)),
scale / (FIXED2FLOAT(sec->GetYScale(sector_t::floor)) * float(1 << MAPBITS)),
rotation,
colormap,
floorlight
);
}
}
//============================================================================= //=============================================================================
// //
// //
@ -1573,6 +1732,80 @@ static bool AM_CheckSecret(line_t *line)
} }
//=============================================================================
//
// Polyobject debug stuff
//
//=============================================================================
void AM_drawSeg(seg_t *seg, const AMColor &color)
{
mline_t l;
l.a.x = seg->v1->x >> FRACTOMAPBITS;
l.a.y = seg->v1->y >> FRACTOMAPBITS;
l.b.x = seg->v2->x >> FRACTOMAPBITS;
l.b.y = seg->v2->y >> FRACTOMAPBITS;
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
{
AM_rotatePoint (&l.a.x, &l.a.y);
AM_rotatePoint (&l.b.x, &l.b.y);
}
AM_drawMline(&l, color);
}
void AM_drawPolySeg(FPolySeg *seg, const AMColor &color)
{
mline_t l;
l.a.x = seg->v1.x >> FRACTOMAPBITS;
l.a.y = seg->v1.y >> FRACTOMAPBITS;
l.b.x = seg->v2.x >> FRACTOMAPBITS;
l.b.y = seg->v2.y >> FRACTOMAPBITS;
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
{
AM_rotatePoint (&l.a.x, &l.a.y);
AM_rotatePoint (&l.b.x, &l.b.y);
}
AM_drawMline(&l, color);
}
void AM_showSS()
{
if (am_showsubsector >= 0 && am_showsubsector < numsubsectors)
{
AMColor yellow;
yellow.FromRGB(255,255,0);
AMColor red;
red.FromRGB(255,0,0);
subsector_t *sub = &subsectors[am_showsubsector];
for (unsigned int i = 0; i < sub->numlines; i++)
{
AM_drawSeg(sub->firstline + i, yellow);
}
PO_LinkToSubsectors();
for (int i = 0; i <po_NumPolyobjs; i++)
{
FPolyObj *po = &polyobjs[i];
FPolyNode *pnode = po->subsectorlinks;
while (pnode != NULL)
{
if (pnode->subsector == sub)
{
for (unsigned j = 0; j < pnode->segs.Size(); j++)
{
AM_drawPolySeg(&pnode->segs[j], red);
}
}
pnode = pnode->snext;
}
}
}
}
//============================================================================= //=============================================================================
// //
// Determines visible lines, draws them. // Determines visible lines, draws them.
@ -1601,7 +1834,12 @@ void AM_drawWalls (bool allmap)
if (am_cheat != 0 || (lines[i].flags & ML_MAPPED)) if (am_cheat != 0 || (lines[i].flags & ML_MAPPED))
{ {
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0) if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
continue; {
if (!am_showallenabled || CheckCheatmode(false))
{
continue;
}
}
if (AM_CheckSecret(&lines[i])) if (AM_CheckSecret(&lines[i]))
{ {
@ -1680,8 +1918,14 @@ void AM_drawWalls (bool allmap)
} }
else if (allmap) else if (allmap)
{ {
if (!(lines[i].flags & ML_DONTDRAW)) if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
AM_drawMline(&l, NotSeenColor); {
if (!am_showallenabled || CheckCheatmode(false))
{
continue;
}
}
AM_drawMline(&l, NotSeenColor);
} }
} }
} }
@ -1694,14 +1938,27 @@ void AM_drawWalls (bool allmap)
// //
//============================================================================= //=============================================================================
void AM_rotate (fixed_t *x, fixed_t *y, angle_t a) void AM_rotate(fixed_t *xp, fixed_t *yp, angle_t a)
{ {
fixed_t tmpx; static angle_t angle_saved = 0;
static double sinrot = 0;
static double cosrot = 1;
a >>= ANGLETOFINESHIFT; if (angle_saved != a)
tmpx = DMulScale16 (*x,finecosine[a],*y,-finesine[a]); {
*y = DMulScale16 (*x,finesine[a],*y,finecosine[a]); angle_saved = a;
*x = tmpx; double rot = (double)a / (double)(1u << 31) * (double)M_PI;
sinrot = sin(rot);
cosrot = cos(rot);
}
double x = FIXED2FLOAT(*xp);
double y = FIXED2FLOAT(*yp);
double tmpx = (x * cosrot) - (y * sinrot);
y = (x * sinrot) + (y * cosrot);
x = tmpx;
*xp = FLOAT2FIXED(x);
*yp = FLOAT2FIXED(y);
} }
//============================================================================= //=============================================================================
@ -1912,11 +2169,40 @@ void AM_drawThings ()
if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = ThingColor_Friend; if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = ThingColor_Friend;
else color = ThingColor_Monster; else color = ThingColor_Monster;
} }
else if (t->flags&MF_SPECIAL) color = ThingColor_Item; else if (t->flags&MF_SPECIAL)
{
// Find the key's own color.
// Only works correctly if single-key locks have lower numbers than any-key locks.
// That is the case for all default keys, however.
if (t->IsKindOf(RUNTIME_CLASS(AKey)))
{
if (am_showkeys)
{
int P_GetMapColorForKey (AInventory * key);
int c = P_GetMapColorForKey(static_cast<AKey *>(t));
AM_drawLineCharacter if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c));
(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, else color = ThingColor_CountItem;
16<<MAPBITS, angle, color, p.x, p.y); AM_drawLineCharacter(key_guy, NUMKEYGUYLINES, 16<<MAPBITS, 0, color, p.x, p.y);
color.Index = -1;
}
else
{
color = ThingColor_Item;
}
}
else if (t->flags&MF_COUNTITEM)
color = ThingColor_CountItem;
else
color = ThingColor_Item;
}
if (color.Index != -1)
{
AM_drawLineCharacter
(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
16<<MAPBITS, angle, color, p.x, p.y);
}
if (am_cheat >= 3) if (am_cheat >= 3)
{ {
@ -2041,7 +2327,11 @@ void AM_drawAuthorMarkers ()
while (marked != NULL) while (marked != NULL)
{ {
if (mark->args[1] == 0 || (mark->args[1] == 1 && marked->Sector->MoreFlags & SECF_DRAWN)) // Use more correct info if we have GL nodes available
if (mark->args[1] == 0 ||
(mark->args[1] == 1 && (hasglnodes ?
marked->subsector->flags & SSECF_DRAWN :
marked->Sector->MoreFlags & SECF_DRAWN)))
{ {
DrawMarker (tex, marked->x >> FRACTOMAPBITS, marked->y >> FRACTOMAPBITS, 0, DrawMarker (tex, marked->x >> FRACTOMAPBITS, marked->y >> FRACTOMAPBITS, 0,
flip, mark->scaleX, mark->scaleY, mark->Translation, flip, mark->scaleX, mark->scaleY, mark->Translation,
@ -2075,7 +2365,7 @@ void AM_Drawer ()
return; return;
bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0; bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0;
bool allthings = allmap && players[consoleplayer].mo->FindInventory<APowerScanner>() != NULL; bool allthings = allmap && players[consoleplayer].mo->FindInventory(RUNTIME_CLASS(APowerScanner), true) != NULL;
AM_initColors (viewactive); AM_initColors (viewactive);
@ -2100,6 +2390,9 @@ void AM_Drawer ()
} }
AM_activateNewScale(); AM_activateNewScale();
if (am_textured && hasglnodes && textured && !viewactive)
AM_drawSubsectors();
if (grid) if (grid)
AM_drawGrid(GridColor); AM_drawGrid(GridColor);
@ -2114,6 +2407,8 @@ void AM_Drawer ()
AM_drawCrosshair(XHairColor); AM_drawCrosshair(XHairColor);
AM_drawMarks(); AM_drawMarks();
AM_showSS();
} }
//============================================================================= //=============================================================================

View file

@ -26,7 +26,7 @@ struct event_t;
class FArchive; class FArchive;
// Called by main loop. // Called by main loop.
bool AM_Responder (event_t* ev); bool AM_Responder (event_t* ev, bool last);
// Called by main loop. // Called by main loop.
void AM_Ticker (void); void AM_Ticker (void);

View file

@ -93,7 +93,16 @@ setupvlineasm:
selfmod premach3a, machvsh8+6 selfmod premach3a, machvsh8+6
ret ret
%ifdef M_TARGET_MACHO
SECTION .text align=64
%else
SECTION .rtext progbits alloc exec write align=64 SECTION .rtext progbits alloc exec write align=64
%endif
%ifdef M_TARGET_MACHO
GLOBAL _rtext_a_start
_rtext_a_start:
%endif
;eax = xscale ;eax = xscale
;ebx = palookupoffse ;ebx = palookupoffse
@ -325,6 +334,7 @@ setupmvlineasm:
mov ecx, dword [esp+4] mov ecx, dword [esp+4]
mov byte [maskmach3a+2], cl mov byte [maskmach3a+2], cl
mov byte [machmv13+2], cl mov byte [machmv13+2], cl
mov byte [machmv14+2], cl mov byte [machmv14+2], cl
mov byte [machmv15+2], cl mov byte [machmv15+2], cl
mov byte [machmv16+2], cl mov byte [machmv16+2], cl
@ -538,3 +548,8 @@ ALIGN 16
mvcase0: jmp beginmvlineasm4 mvcase0: jmp beginmvlineasm4
align 16 align 16
%ifdef M_TARGET_MACHO
GLOBAL _rtext_a_end
_rtext_a_end:
%endif

View file

@ -285,7 +285,16 @@ R_SetSpanSize_ASM:
aret: ret aret: ret
%ifdef M_TARGET_MACHO
SECTION .text align=64
%else
SECTION .rtext progbits alloc exec write align=64 SECTION .rtext progbits alloc exec write align=64
%endif
%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap_start
_rtext_tmap_start:
%endif
rtext_start: rtext_start:
@ -300,6 +309,8 @@ GLOBAL R_DrawSpanP_ASM
; edi: dest ; edi: dest
; ebp: scratch ; ebp: scratch
; esi: count ; esi: count
; [esp]: xstep
; [esp+4]: ystep
align 16 align 16
@ -315,6 +326,7 @@ R_DrawSpanP_ASM:
push edi push edi
push ebp push ebp
push esi push esi
sub esp, 8
mov edi,ecx mov edi,ecx
add edi,[dc_destorg] add edi,[dc_destorg]
@ -326,13 +338,13 @@ dsy1: shl edx,6
dsy3: shr ebp,26 dsy3: shr ebp,26
xor ebx,ebx xor ebx,ebx
lea esi,[eax+1] lea esi,[eax+1]
mov [ds_xstep],edx mov [esp],edx
mov edx,[ds_ystep] mov edx,[ds_ystep]
mov ecx,[ds_xfrac] mov ecx,[ds_xfrac]
dsy4: shr ecx,26 dsy4: shr ecx,26
dsm8: and edx,0xffffffc0 dsm8: and edx,0xffffffc0
or ebp,edx or ebp,edx
mov [ds_ystep],ebp mov [esp+4],ebp
mov ebp,[ds_yfrac] mov ebp,[ds_yfrac]
mov edx,[ds_xfrac] mov edx,[ds_xfrac]
dsy2: shl edx,6 dsy2: shl edx,6
@ -346,8 +358,8 @@ dsm9: and ebp,0xffffffc0
mov ebp,ecx mov ebp,ecx
dsx1: rol ebp,6 dsx1: rol ebp,6
dsm1: and ebp,0xfff dsm1: and ebp,0xfff
add edx,[ds_xstep] add edx,[esp]
adc ecx,[ds_ystep] adc ecx,[esp+4]
spreada mov bl,[ebp+SPACEFILLER4] spreada mov bl,[ebp+SPACEFILLER4]
spmapa mov bl,[ebx+SPACEFILLER4] spmapa mov bl,[ebx+SPACEFILLER4]
mov [edi],bl mov [edi],bl
@ -358,13 +370,13 @@ dseven1 shr esi,1
; do two more pixels ; do two more pixels
mov ebp,ecx mov ebp,ecx
add edx,[ds_xstep] add edx,[esp]
adc ecx,[ds_ystep] adc ecx,[esp+4]
dsm2: and ebp,0xfc00003f dsm2: and ebp,0xfc00003f
dsx2: rol ebp,6 dsx2: rol ebp,6
mov eax,ecx mov eax,ecx
add edx,[ds_xstep] add edx,[esp]
adc ecx,[ds_ystep] adc ecx,[esp+4]
spreadb mov bl,[ebp+SPACEFILLER4] ;read texel1 spreadb mov bl,[ebp+SPACEFILLER4] ;read texel1
dsx3: rol eax,6 dsx3: rol eax,6
dsm6: and eax,0xfff dsm6: and eax,0xfff
@ -383,13 +395,13 @@ dsrest test esi,esi
align 16 align 16
dsloop mov ebp,ecx dsloop mov ebp,ecx
spstep1d add edx,[ds_xstep] spstep1d add edx,[esp]
spstep2d adc ecx,[ds_ystep] spstep2d adc ecx,[esp+4]
dsm3: and ebp,0xfc00003f dsm3: and ebp,0xfc00003f
dsx4: rol ebp,6 dsx4: rol ebp,6
mov eax,ecx mov eax,ecx
spstep1e add edx,[ds_xstep] spstep1e add edx,[esp]
spstep2e adc ecx,[ds_ystep] spstep2e adc ecx,[esp+4]
spreadd mov bl,[ebp+SPACEFILLER4] ;read texel1 spreadd mov bl,[ebp+SPACEFILLER4] ;read texel1
dsx5: rol eax,6 dsx5: rol eax,6
dsm5: and eax,0xfff dsm5: and eax,0xfff
@ -397,8 +409,8 @@ spmapd mov bl,[ebx+SPACEFILLER4] ;map texel1
mov [edi],bl ;store texel1 mov [edi],bl ;store texel1
mov ebp,ecx mov ebp,ecx
spreade mov bl,[eax+SPACEFILLER4] ;read texel2 spreade mov bl,[eax+SPACEFILLER4] ;read texel2
spstep1f add edx,[ds_xstep] spstep1f add edx,[esp]
spstep2f adc ecx,[ds_ystep] spstep2f adc ecx,[esp+4]
dsm4: and ebp,0xfc00003f dsm4: and ebp,0xfc00003f
dsx6: rol ebp,6 dsx6: rol ebp,6
spmape mov bl,[ebx+SPACEFILLER4] ;map texel2 spmape mov bl,[ebx+SPACEFILLER4] ;map texel2
@ -411,14 +423,15 @@ dsx7: rol eax,6
dsm7: and eax,0xfff dsm7: and eax,0xfff
mov [edi-2],bl ;store texel3 mov [edi-2],bl ;store texel3
spreadg mov bl,[eax+SPACEFILLER4] ;read texel4 spreadg mov bl,[eax+SPACEFILLER4] ;read texel4
spstep1g add edx,[ds_xstep] spstep1g add edx,[esp]
spstep2g adc ecx,[ds_ystep] spstep2g adc ecx,[esp+4]
spmapg mov bl,[ebx+SPACEFILLER4] ;map texel4 spmapg mov bl,[ebx+SPACEFILLER4] ;map texel4
dec esi dec esi
mov [edi-1],bl ;store texel4 mov [edi-1],bl ;store texel4
jnz near dsloop jnz near dsloop
dsdone pop esi dsdone add esp,8
pop esi
pop ebp pop ebp
pop edi pop edi
pop ebx pop ebx
@ -439,6 +452,8 @@ GLOBAL R_DrawSpanMaskedP_ASM
; edi: dest ; edi: dest
; ebp: scratch ; ebp: scratch
; esi: count ; esi: count
; [esp]: xstep
; [esp+4]: ystep
align 16 align 16
@ -454,6 +469,7 @@ R_DrawSpanMaskedP_ASM:
push edi push edi
push ebp push ebp
push esi push esi
sub esp,8
mov edi,ecx mov edi,ecx
add edi,[dc_destorg] add edi,[dc_destorg]
@ -465,13 +481,13 @@ dmsy1: shl edx,6
dmsy3: shr ebp,26 dmsy3: shr ebp,26
xor ebx,ebx xor ebx,ebx
lea esi,[eax+1] lea esi,[eax+1]
mov [ds_xstep],edx mov [esp],edx
mov edx,[ds_ystep] mov edx,[ds_ystep]
mov ecx,[ds_xfrac] mov ecx,[ds_xfrac]
dmsy4: shr ecx,26 dmsy4: shr ecx,26
dmsm8: and edx,0xffffffc0 dmsm8: and edx,0xffffffc0
or ebp,edx or ebp,edx
mov [ds_ystep],ebp mov [esp+4],ebp
mov ebp,[ds_yfrac] mov ebp,[ds_yfrac]
mov edx,[ds_xfrac] mov edx,[ds_xfrac]
dmsy2: shl edx,6 dmsy2: shl edx,6
@ -485,8 +501,8 @@ dmsm9: and ebp,0xffffffc0
mov ebp,ecx mov ebp,ecx
dmsx1: rol ebp,6 dmsx1: rol ebp,6
dmsm1: and ebp,0xfff dmsm1: and ebp,0xfff
add edx,[ds_xstep] add edx,[esp]
adc ecx,[ds_ystep] adc ecx,[esp+4]
mspreada mov bl,[ebp+SPACEFILLER4] mspreada mov bl,[ebp+SPACEFILLER4]
cmp bl,0 cmp bl,0
je mspskipa je mspskipa
@ -499,13 +515,13 @@ dmseven1 shr esi,1
; do two more pixels ; do two more pixels
mov ebp,ecx mov ebp,ecx
add edx,[ds_xstep] add edx,[esp]
adc ecx,[ds_ystep] adc ecx,[esp+4]
dmsm2: and ebp,0xfc00003f dmsm2: and ebp,0xfc00003f
dmsx2: rol ebp,6 dmsx2: rol ebp,6
mov eax,ecx mov eax,ecx
add edx,[ds_xstep] add edx,[esp]
adc ecx,[ds_ystep] adc ecx,[esp+4]
mspreadb mov bl,[ebp+SPACEFILLER4] ;read texel1 mspreadb mov bl,[ebp+SPACEFILLER4] ;read texel1
dmsx3: rol eax,6 dmsx3: rol eax,6
dmsm6: and eax,0xfff dmsm6: and eax,0xfff
@ -528,13 +544,13 @@ dmsrest test esi,esi
align 16 align 16
dmsloop mov ebp,ecx dmsloop mov ebp,ecx
mspstep1d add edx,[ds_xstep] mspstep1d add edx,[esp]
mspstep2d adc ecx,[ds_ystep] mspstep2d adc ecx,[esp+4]
dmsm3: and ebp,0xfc00003f dmsm3: and ebp,0xfc00003f
dmsx4: rol ebp,6 dmsx4: rol ebp,6
mov eax,ecx mov eax,ecx
mspstep1e add edx,[ds_xstep] mspstep1e add edx,[esp]
mspstep2e adc ecx,[ds_ystep] mspstep2e adc ecx,[esp+4]
mspreadd mov bl,[ebp+SPACEFILLER4] ;read texel1 mspreadd mov bl,[ebp+SPACEFILLER4] ;read texel1
dmsx5: rol eax,6 dmsx5: rol eax,6
dmsm5: and eax,0xfff dmsm5: and eax,0xfff
@ -544,8 +560,8 @@ dmsm5: and eax,0xfff
mspmapd mov bl,[ebx+SPACEFILLER4] ;map texel1 mspmapd mov bl,[ebx+SPACEFILLER4] ;map texel1
mov [edi],bl ;store texel1 mov [edi],bl ;store texel1
mspreade mov bl,[eax+SPACEFILLER4] ;read texel2 mspreade mov bl,[eax+SPACEFILLER4] ;read texel2
mspstep1f add edx,[ds_xstep] mspstep1f add edx,[esp]
mspstep2f adc ecx,[ds_ystep] mspstep2f adc ecx,[esp+4]
dmsm4: and ebp,0xfc00003f dmsm4: and ebp,0xfc00003f
dmsx6: rol ebp,6 dmsx6: rol ebp,6
cmp bl,0 cmp bl,0
@ -562,8 +578,8 @@ dmsm7: and eax,0xfff
mspmapf mov bl,[ebx+SPACEFILLER4] ;map texel3 mspmapf mov bl,[ebx+SPACEFILLER4] ;map texel3
mov [edi-2],bl ;store texel3 mov [edi-2],bl ;store texel3
mspreadg mov bl,[eax+SPACEFILLER4] ;read texel4 mspreadg mov bl,[eax+SPACEFILLER4] ;read texel4
mspstep1g add edx,[ds_xstep] mspstep1g add edx,[esp]
mspstep2g adc ecx,[ds_ystep] mspstep2g adc ecx,[esp+4]
cmp bl,0 cmp bl,0
je mspskipg je mspskipg
mspmapg mov bl,[ebx+SPACEFILLER4] ;map texel4 mspmapg mov bl,[ebx+SPACEFILLER4] ;map texel4
@ -571,7 +587,8 @@ mspmapg mov bl,[ebx+SPACEFILLER4] ;map texel4
mspskipg dec esi mspskipg dec esi
jnz near dmsloop jnz near dmsloop
dmsdone pop esi dmsdone add esp,8
pop esi
pop ebp pop ebp
pop edi pop edi
pop ebx pop ebx
@ -1738,6 +1755,10 @@ ac4nil: pop edi
ret ret
rtext_end: rtext_end:
%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap_end
_rtext_tmap_end:
%endif
align 16 align 16
;************************ ;************************

View file

@ -216,7 +216,13 @@ SetTiltedSpanSize:
ret ret
%ifndef M_TARGET_MACHO
SECTION .rtext progbits alloc exec write align=64 SECTION .rtext progbits alloc exec write align=64
%else
SECTION .text align=64
GLOBAL _rtext_tmap2_start
_rtext_tmap2_start:
%endif
rtext_start: rtext_start:
@ -628,3 +634,7 @@ fetch10 mov al,[ebp+esi+SPACEFILLER4]
ret ret
rtext_end: rtext_end:
%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap2_end
_rtext_tmap2_end:
%endif

View file

@ -80,7 +80,13 @@ setupvlinetallasm:
selfmod shifter1, shift12+6 selfmod shifter1, shift12+6
ret ret
%ifdef M_TARGET_MACHO
SECTION .text align=64
GLOBAL _rtext_tmap3_start
_rtext_tmap3_start:
%else
SECTION .rtext progbits alloc exec write align=64 SECTION .rtext progbits alloc exec write align=64
%endif
ALIGN 16 ALIGN 16
@ -331,3 +337,8 @@ shift12: shr ecx,16
pop ebx pop ebx
pop ebp pop ebp
ret ret
%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap3_end
_rtext_tmap3_end:
%endif

View file

@ -92,23 +92,23 @@ pm: imulq $320, %rcx
loopit: loopit:
movl %r8d, %edx movl %r8d, %edx
shifter1: shrl $24, %edx shifter1: shrl $24, %edx
step1: addl $0x88888888, %r8d step1: addl $0x44444444, %r8d
movzbl (%rax,%rdx), %edx movzbl (%rax,%rdx), %edx
movl %r9d, %ebx movl %r9d, %ebx
movb (%r12,%rdx), %dl movb (%r12,%rdx), %dl
shifter2: shrl $24, %ebx shifter2: shrl $24, %ebx
step2: addl $0x88888888, %r9d step2: addl $0x44444444, %r9d
source2: movzbl 0x88888888(%rax,%rbx), %ebx source2: movzbl 0x44444444(%rax,%rbx), %ebx
movl %r10d, %ebp movl %r10d, %ebp
movb (%r13,%rbx), %bl movb (%r13,%rbx), %bl
shifter3: shr $24, %ebp shifter3: shr $24, %ebp
step3: addl $0x88888888, %r10d step3: addl $0x44444444, %r10d
source3: movzbl 0x88888888(%rax,%rbp), %ebp source3: movzbl 0x44444444(%rax,%rbp), %ebp
movl %r11d, %esi movl %r11d, %esi
movb (%r14,%rbp), %bpl movb (%r14,%rbp), %bpl
shifter4: shr $24, %esi shifter4: shr $24, %esi
step4: add $0x88888888, %r11d step4: add $0x44444444, %r11d
source4: movzbl 0x88888888(%rax,%rsi), %esi source4: movzbl 0x44444444(%rax,%rsi), %esi
movb %dl, (%rdi,%rcx) movb %dl, (%rdi,%rcx)
movb %bl, 1(%rdi,%rcx) movb %bl, 1(%rdi,%rcx)
movb (%r15,%rsi), %sil movb (%r15,%rsi), %sil

View file

@ -67,8 +67,6 @@ CCMD (removebots)
Net_WriteByte (DEM_KILLBOTS); Net_WriteByte (DEM_KILLBOTS);
} }
extern bool CheckCheatmode ();
CCMD (freeze) CCMD (freeze)
{ {
if (CheckCheatmode ()) if (CheckCheatmode ())

View file

@ -11,8 +11,8 @@
#pragma once #pragma once
#endif #endif
#ifndef _MSC_VER #if defined(__GNUC__) && !defined(__forceinline)
#define __forceinline inline #define __forceinline __inline__ __attribute__((always_inline))
#endif #endif
static __forceinline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) static __forceinline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c)

View file

@ -47,12 +47,6 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
struct FBinding
{
const char *Key;
const char *Bind;
};
/* Default keybindings for Doom (and all other games) /* Default keybindings for Doom (and all other games)
*/ */
static const FBinding DefBindings[] = static const FBinding DefBindings[] =
@ -178,6 +172,29 @@ static const FBinding DefStrifeBindings[] =
// h - use health // h - use health
}; };
static const FBinding DefAutomapBindings[] =
{
{ "f", "am_togglefollow" },
{ "g", "am_togglegrid" },
{ "p", "am_toggletexture" },
{ "m", "am_setmark" },
{ "c", "am_clearmarks" },
{ "0", "am_gobig" },
{ "rightarrow", "+am_panright" },
{ "leftarrow", "+am_panleft" },
{ "uparrow", "+am_panup" },
{ "downarrow", "+am_pandown" },
{ "-", "+am_zoomout" },
{ "=", "+am_zoomin" },
{ "kp-", "+am_zoomout" },
{ "kp+", "+am_zoomin" },
{ "mwheelup", "am_zoom 1.2" },
{ "mwheeldown", "am_zoom -1.2" },
{ NULL }
};
const char *KeyNames[NUM_KEYS] = const char *KeyNames[NUM_KEYS] =
{ {
// This array is dependant on the particular keyboard input // This array is dependant on the particular keyboard input
@ -278,11 +295,19 @@ const char *KeyNames[NUM_KEYS] =
"pad_a", "pad_b", "pad_x", "pad_y" "pad_a", "pad_b", "pad_x", "pad_y"
}; };
static FString Bindings[NUM_KEYS]; FKeyBindings Bindings;
static FString DoubleBindings[NUM_KEYS]; FKeyBindings DoubleBindings;
FKeyBindings AutomapBindings;
static unsigned int DClickTime[NUM_KEYS]; static unsigned int DClickTime[NUM_KEYS];
static BYTE DClicked[(NUM_KEYS+7)/8]; static BYTE DClicked[(NUM_KEYS+7)/8];
//=============================================================================
//
//
//
//=============================================================================
static int GetKeyFromName (const char *name) static int GetKeyFromName (const char *name)
{ {
int i; int i;
@ -302,380 +327,15 @@ static int GetKeyFromName (const char *name)
return 0; return 0;
} }
static const char *KeyName (int key) //=============================================================================
{
static char name[5];
if (KeyNames[key])
return KeyNames[key];
mysnprintf (name, countof(name), "#%d", key);
return name;
}
void C_UnbindAll ()
{
for (int i = 0; i < NUM_KEYS; ++i)
{
Bindings[i] = "";
DoubleBindings[i] = "";
}
}
CCMD (unbindall)
{
C_UnbindAll ();
}
CCMD (unbind)
{
int i;
if (argv.argc() > 1)
{
if ( (i = GetKeyFromName (argv[1])) )
{
Bindings[i] = "";
}
else
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
}
}
CCMD (bind)
{
int i;
if (argv.argc() > 1)
{
i = GetKeyFromName (argv[1]);
if (!i)
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argv.argc() == 2)
{
Printf ("\"%s\" = \"%s\"\n", argv[1], Bindings[i].GetChars());
}
else
{
Bindings[i] = argv[2];
}
}
else
{
Printf ("Current key bindings:\n");
for (i = 0; i < NUM_KEYS; i++)
{
if (!Bindings[i].IsEmpty())
Printf ("%s \"%s\"\n", KeyName (i), Bindings[i].GetChars());
}
}
}
//==========================================================================
// //
// CCMD defaultbind
// //
// Binds a command to a key if that key is not already bound and if
// that command is not already bound to another key.
// //
//========================================================================== //=============================================================================
CCMD (defaultbind) static int GetConfigKeyFromName (const char *key)
{ {
if (argv.argc() < 3) int keynum = GetKeyFromName(key);
{
Printf ("Usage: defaultbind <key> <command>\n");
}
else
{
int key = GetKeyFromName (argv[1]);
if (key == 0)
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (!Bindings[key].IsEmpty())
{ // This key is already bound.
return;
}
for (int i = 0; i < NUM_KEYS; ++i)
{
if (!Bindings[i].IsEmpty() && stricmp (Bindings[i], argv[2]) == 0)
{ // This command is already bound to a key.
return;
}
}
// It is safe to do the bind, so do it.
Bindings[key] = argv[2];
}
}
CCMD (undoublebind)
{
int i;
if (argv.argc() > 1)
{
if ( (i = GetKeyFromName (argv[1])) )
{
DoubleBindings[i] = "";
}
else
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
}
}
CCMD (doublebind)
{
int i;
if (argv.argc() > 1)
{
i = GetKeyFromName (argv[1]);
if (!i)
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argv.argc() == 2)
{
Printf ("\"%s\" = \"%s\"\n", argv[1], DoubleBindings[i].GetChars());
}
else
{
DoubleBindings[i] = argv[2];
}
}
else
{
Printf ("Current key doublebindings:\n");
for (i = 0; i < NUM_KEYS; i++)
{
if (!DoubleBindings[i].IsEmpty())
Printf ("%s \"%s\"\n", KeyName (i), DoubleBindings[i].GetChars());
}
}
}
CCMD (rebind)
{
FString *bindings;
if (key == 0)
{
Printf ("Rebind cannot be used from the console\n");
return;
}
if (key & KEY_DBLCLICKED)
{
bindings = DoubleBindings;
key &= KEY_DBLCLICKED-1;
}
else
{
bindings = Bindings;
}
if (argv.argc() > 1)
{
bindings[key] = argv[1];
}
}
static void SetBinds (const FBinding *array)
{
while (array->Key)
{
C_DoBind (array->Key, array->Bind, false);
array++;
}
}
void C_BindDefaults ()
{
SetBinds (DefBindings);
if (gameinfo.gametype & (GAME_Raven|GAME_Strife))
{
SetBinds (DefRavenBindings);
}
if (gameinfo.gametype == GAME_Heretic)
{
SetBinds (DefHereticBindings);
}
if (gameinfo.gametype == GAME_Hexen)
{
SetBinds (DefHexenBindings);
}
if (gameinfo.gametype == GAME_Strife)
{
SetBinds (DefStrifeBindings);
}
}
CCMD(binddefaults)
{
C_BindDefaults ();
}
void C_SetDefaultBindings ()
{
C_UnbindAll ();
C_BindDefaults ();
}
bool C_DoKey (event_t *ev)
{
FString binding;
bool dclick;
int dclickspot;
BYTE dclickmask;
if (ev->type != EV_KeyDown && ev->type != EV_KeyUp)
return false;
if ((unsigned int)ev->data1 >= NUM_KEYS)
return false;
dclickspot = ev->data1 >> 3;
dclickmask = 1 << (ev->data1 & 7);
dclick = false;
// This used level.time which didn't work outside a level.
if (DClickTime[ev->data1] > I_MSTime() && ev->type == EV_KeyDown)
{
// Key pressed for a double click
binding = DoubleBindings[ev->data1];
DClicked[dclickspot] |= dclickmask;
dclick = true;
}
else
{
if (ev->type == EV_KeyDown)
{ // Key pressed for a normal press
binding = Bindings[ev->data1];
DClickTime[ev->data1] = I_MSTime() + 571;
}
else if (DClicked[dclickspot] & dclickmask)
{ // Key released from a double click
binding = DoubleBindings[ev->data1];
DClicked[dclickspot] &= ~dclickmask;
DClickTime[ev->data1] = 0;
dclick = true;
}
else
{ // Key released from a normal press
binding = Bindings[ev->data1];
}
}
if (binding.IsEmpty())
{
binding = Bindings[ev->data1];
dclick = false;
}
if (!binding.IsEmpty() && (chatmodeon == 0 || ev->data1 < 256))
{
if (ev->type == EV_KeyUp && binding[0] != '+')
{
return false;
}
char *copy = binding.LockBuffer();
if (ev->type == EV_KeyUp)
{
copy[0] = '-';
}
AddCommandString (copy, dclick ? ev->data1 | KEY_DBLCLICKED : ev->data1);
return true;
}
return false;
}
const char *C_ConfigKeyName(int keynum)
{
const char *name = KeyName(keynum);
if (name[1] == 0) // Make sure given name is config-safe
{
if (name[0] == '[')
return "LeftBracket";
else if (name[0] == ']')
return "RightBracket";
else if (name[0] == '=')
return "Equals";
else if (strcmp (name, "kp=") == 0)
return "KP-Equals";
}
return name;
}
// This function is first called for functions in custom key sections.
// In this case, matchcmd is non-NULL, and only keys bound to that command
// are stored. If a match is found, its binding is set to "\1".
// After all custom key sections are saved, it is called one more for the
// normal Bindings and DoubleBindings sections for this game. In this case
// matchcmd is NULL and all keys will be stored. The config section was not
// previously cleared, so all old bindings are still in place. If the binding
// for a key is empty, the corresponding key in the config is removed as well.
// If a binding is "\1", then the binding itself is cleared, but nothing
// happens to the entry in the config.
void C_ArchiveBindings (FConfigFile *f, bool dodouble, const char *matchcmd)
{
FString *bindings;
int i;
bindings = dodouble ? DoubleBindings : Bindings;
for (i = 0; i < NUM_KEYS; i++)
{
if (bindings[i].IsEmpty())
{
if (matchcmd == NULL)
{
f->ClearKey(C_ConfigKeyName(i));
}
}
else if (matchcmd == NULL || stricmp(bindings[i], matchcmd) == 0)
{
if (bindings[i][0] == '\1')
{
bindings[i] = "";
continue;
}
f->SetValueForKey(C_ConfigKeyName(i), bindings[i]);
if (matchcmd != NULL)
{ // If saving a specific command, set a marker so that
// it does not get saved in the general binding list.
bindings[i] = "\1";
}
}
}
}
void C_DoBind (const char *key, const char *bind, bool dodouble)
{
int keynum = GetKeyFromName (key);
if (keynum == 0) if (keynum == 0)
{ {
if (stricmp (key, "LeftBracket") == 0) if (stricmp (key, "LeftBracket") == 0)
@ -695,32 +355,55 @@ void C_DoBind (const char *key, const char *bind, bool dodouble)
keynum = GetKeyFromName ("kp="); keynum = GetKeyFromName ("kp=");
} }
} }
if (keynum != 0) return keynum;
{
(dodouble ? DoubleBindings : Bindings)[keynum] = bind;
}
} }
int C_GetKeysForCommand (char *cmd, int *first, int *second) //=============================================================================
//
//
//
//=============================================================================
static const char *KeyName (int key)
{ {
int c, i; static char name[5];
*first = *second = c = i = 0; if (KeyNames[key])
return KeyNames[key];
while (i < NUM_KEYS && c < 2) mysnprintf (name, countof(name), "#%d", key);
{ return name;
if (stricmp (cmd, Bindings[i]) == 0)
{
if (c++ == 0)
*first = i;
else
*second = i;
}
i++;
}
return c;
} }
//=============================================================================
//
//
//
//=============================================================================
static const char *ConfigKeyName(int keynum)
{
const char *name = KeyName(keynum);
if (name[1] == 0) // Make sure given name is config-safe
{
if (name[0] == '[')
return "LeftBracket";
else if (name[0] == ']')
return "RightBracket";
else if (name[0] == '=')
return "Equals";
else if (strcmp (name, "kp=") == 0)
return "KP-Equals";
}
return name;
}
//=============================================================================
//
//
//
//=============================================================================
void C_NameKeys (char *str, int first, int second) void C_NameKeys (char *str, int first, int second)
{ {
int c = 0; int c = 0;
@ -744,28 +427,471 @@ void C_NameKeys (char *str, int first, int second)
*str = '\0'; *str = '\0';
} }
void C_UnbindACommand (char *str) //=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::DoBind (const char *key, const char *bind)
{
int keynum = GetConfigKeyFromName (key);
if (keynum != 0)
{
Binds[keynum] = bind;
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::SetBinds(const FBinding *binds)
{
while (binds->Key)
{
DoBind (binds->Key, binds->Bind);
binds++;
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindAll ()
{
for (int i = 0; i < NUM_KEYS; ++i)
{
Binds[i] = "";
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindKey(const char *key)
{
int i;
if ( (i = GetKeyFromName (key)) )
{
Binds[i] = "";
}
else
{
Printf ("Unknown key \"%s\"\n", key);
return;
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::PerformBind(FCommandLine &argv, const char *msg)
{
int i;
if (argv.argc() > 1)
{
i = GetKeyFromName (argv[1]);
if (!i)
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argv.argc() == 2)
{
Printf ("\"%s\" = \"%s\"\n", argv[1], Binds[i].GetChars());
}
else
{
Binds[i] = argv[2];
}
}
else
{
Printf ("%s:\n", msg);
for (i = 0; i < NUM_KEYS; i++)
{
if (!Binds[i].IsEmpty())
Printf ("%s \"%s\"\n", KeyName (i), Binds[i].GetChars());
}
}
}
//=============================================================================
//
// This function is first called for functions in custom key sections.
// In this case, matchcmd is non-NULL, and only keys bound to that command
// are stored. If a match is found, its binding is set to "\1".
// After all custom key sections are saved, it is called one more for the
// normal Bindings and DoubleBindings sections for this game. In this case
// matchcmd is NULL and all keys will be stored. The config section was not
// previously cleared, so all old bindings are still in place. If the binding
// for a key is empty, the corresponding key in the config is removed as well.
// If a binding is "\1", then the binding itself is cleared, but nothing
// happens to the entry in the config.
//
//=============================================================================
void FKeyBindings::ArchiveBindings(FConfigFile *f, const char *matchcmd)
{ {
int i; int i;
for (i = 0; i < NUM_KEYS; i++) for (i = 0; i < NUM_KEYS; i++)
{ {
if (!stricmp (str, Bindings[i])) if (Binds[i].IsEmpty())
{ {
Bindings[i] = ""; if (matchcmd == NULL)
{
f->ClearKey(ConfigKeyName(i));
}
}
else if (matchcmd == NULL || stricmp(Binds[i], matchcmd) == 0)
{
if (Binds[i][0] == '\1')
{
Binds[i] = "";
continue;
}
f->SetValueForKey(ConfigKeyName(i), Binds[i]);
if (matchcmd != NULL)
{ // If saving a specific command, set a marker so that
// it does not get saved in the general binding list.
Binds[i] = "\1";
}
} }
} }
} }
void C_ChangeBinding (const char *str, int newone) //=============================================================================
//
//
//
//=============================================================================
int FKeyBindings::GetKeysForCommand (char *cmd, int *first, int *second)
{ {
if ((unsigned int)newone < NUM_KEYS) int c, i;
*first = *second = c = i = 0;
while (i < NUM_KEYS && c < 2)
{ {
Bindings[newone] = str; if (stricmp (cmd, Binds[i]) == 0)
{
if (c++ == 0)
*first = i;
else
*second = i;
}
i++;
}
return c;
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindACommand (char *str)
{
int i;
for (i = 0; i < NUM_KEYS; i++)
{
if (!stricmp (str, Binds[i]))
{
Binds[i] = "";
}
} }
} }
const char *C_GetBinding (int key) //=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::DefaultBind(const char *keyname, const char *cmd)
{ {
return (unsigned int)key < NUM_KEYS ? Bindings[key].GetChars() : NULL; int key = GetKeyFromName (keyname);
if (key == 0)
{
Printf ("Unknown key \"%s\"\n", keyname);
return;
}
if (!Binds[key].IsEmpty())
{ // This key is already bound.
return;
}
for (int i = 0; i < NUM_KEYS; ++i)
{
if (!Binds[i].IsEmpty() && stricmp (Binds[i], cmd) == 0)
{ // This command is already bound to a key.
return;
}
}
// It is safe to do the bind, so do it.
Binds[key] = cmd;
} }
//=============================================================================
//
//
//
//=============================================================================
void C_UnbindAll ()
{
Bindings.UnbindAll();
DoubleBindings.UnbindAll();
AutomapBindings.UnbindAll();
}
CCMD (unbindall)
{
C_UnbindAll ();
}
//=============================================================================
//
//
//
//=============================================================================
CCMD (unbind)
{
if (argv.argc() > 1)
{
Bindings.UnbindKey(argv[1]);
}
}
CCMD (undoublebind)
{
if (argv.argc() > 1)
{
DoubleBindings.UnbindKey(argv[1]);
}
}
CCMD (unmapbind)
{
if (argv.argc() > 1)
{
AutomapBindings.UnbindKey(argv[1]);
}
}
//=============================================================================
//
//
//
//=============================================================================
CCMD (bind)
{
Bindings.PerformBind(argv, "Current key bindings");
}
CCMD (doublebind)
{
DoubleBindings.PerformBind(argv, "Current key doublebindings");
}
CCMD (mapbind)
{
AutomapBindings.PerformBind(argv, "Current automap key bindings");
}
//==========================================================================
//
// CCMD defaultbind
//
// Binds a command to a key if that key is not already bound and if
// that command is not already bound to another key.
//
//==========================================================================
CCMD (defaultbind)
{
if (argv.argc() < 3)
{
Printf ("Usage: defaultbind <key> <command>\n");
}
else
{
Bindings.DefaultBind(argv[1], argv[2]);
}
}
//=============================================================================
//
//
//
//=============================================================================
CCMD (rebind)
{
FKeyBindings *bindings;
if (key == 0)
{
Printf ("Rebind cannot be used from the console\n");
return;
}
if (key & KEY_DBLCLICKED)
{
bindings = &DoubleBindings;
key &= KEY_DBLCLICKED-1;
}
else
{
bindings = &Bindings;
}
if (argv.argc() > 1)
{
bindings->SetBind(key, argv[1]);
}
}
//=============================================================================
//
//
//
//=============================================================================
void C_BindDefaults ()
{
Bindings.SetBinds (DefBindings);
if (gameinfo.gametype & (GAME_Raven|GAME_Strife))
{
Bindings.SetBinds (DefRavenBindings);
}
if (gameinfo.gametype == GAME_Heretic)
{
Bindings.SetBinds (DefHereticBindings);
}
if (gameinfo.gametype == GAME_Hexen)
{
Bindings.SetBinds (DefHexenBindings);
}
if (gameinfo.gametype == GAME_Strife)
{
Bindings.SetBinds (DefStrifeBindings);
}
AutomapBindings.SetBinds(DefAutomapBindings);
}
CCMD(binddefaults)
{
C_BindDefaults ();
}
void C_SetDefaultBindings ()
{
C_UnbindAll ();
C_BindDefaults ();
}
//=============================================================================
//
//
//
//=============================================================================
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds)
{
FString binding;
bool dclick;
int dclickspot;
BYTE dclickmask;
if (ev->type != EV_KeyDown && ev->type != EV_KeyUp)
return false;
if ((unsigned int)ev->data1 >= NUM_KEYS)
return false;
dclickspot = ev->data1 >> 3;
dclickmask = 1 << (ev->data1 & 7);
dclick = false;
// This used level.time which didn't work outside a level.
if (DClickTime[ev->data1] > I_MSTime() && ev->type == EV_KeyDown)
{
// Key pressed for a double click
if (doublebinds != NULL) binding = doublebinds->GetBinding(ev->data1);
DClicked[dclickspot] |= dclickmask;
dclick = true;
}
else
{
if (ev->type == EV_KeyDown)
{ // Key pressed for a normal press
binding = binds->GetBinding(ev->data1);
DClickTime[ev->data1] = I_MSTime() + 571;
}
else if (DClicked[dclickspot] & dclickmask)
{ // Key released from a double click
if (doublebinds != NULL) binding = doublebinds->GetBinding(ev->data1);
DClicked[dclickspot] &= ~dclickmask;
DClickTime[ev->data1] = 0;
dclick = true;
}
else
{ // Key released from a normal press
binding = binds->GetBinding(ev->data1);
}
}
if (binding.IsEmpty())
{
binding = binds->GetBinding(ev->data1);
dclick = false;
}
if (!binding.IsEmpty() && (chatmodeon == 0 || ev->data1 < 256))
{
if (ev->type == EV_KeyUp && binding[0] != '+')
{
return false;
}
char *copy = binding.LockBuffer();
if (ev->type == EV_KeyUp)
{
copy[0] = '-';
}
AddCommandString (copy, dclick ? ev->data1 | KEY_DBLCLICKED : ev->data1);
return true;
}
return false;
}

View file

@ -34,25 +34,65 @@
#ifndef __C_BINDINGS_H__ #ifndef __C_BINDINGS_H__
#define __C_BINDINGS_H__ #define __C_BINDINGS_H__
#include "doomdef.h"
struct event_t; struct event_t;
class FConfigFile; class FConfigFile;
class FCommandLine;
bool C_DoKey (event_t *ev); void C_NameKeys (char *str, int first, int second);
void C_ArchiveBindings (FConfigFile *f, bool dodouble, const char *matchcmd=NULL);
struct FBinding
{
const char *Key;
const char *Bind;
};
class FKeyBindings
{
FString Binds[NUM_KEYS];
public:
void PerformBind(FCommandLine &argv, const char *msg);
void SetBinds(const FBinding *binds);
bool DoKey(event_t *ev);
void ArchiveBindings(FConfigFile *F, const char *matchcmd = NULL);
int GetKeysForCommand (char *cmd, int *first, int *second);
void UnbindACommand (char *str);
void UnbindAll ();
void UnbindKey(const char *key);
void DoBind (const char *key, const char *bind);
void DefaultBind(const char *keyname, const char *cmd);
void SetBind(unsigned int key, const char *bind)
{
if (key < NUM_KEYS) Binds[key] = bind;
}
const FString &GetBinding(unsigned int index) const
{
return Binds[index];
}
const char *GetBind(unsigned int index) const
{
if (index < NUM_KEYS) return Binds[index];
else return NULL;
}
};
extern FKeyBindings Bindings;
extern FKeyBindings DoubleBindings;
extern FKeyBindings AutomapBindings;
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds);
// Stuff used by the customize controls menu // Stuff used by the customize controls menu
int C_GetKeysForCommand (char *cmd, int *first, int *second);
void C_NameKeys (char *str, int first, int second);
void C_UnbindACommand (char *str);
void C_ChangeBinding (const char *str, int newone);
void C_DoBind (const char *key, const char *bind, bool doublebind);
void C_SetDefaultBindings (); void C_SetDefaultBindings ();
void C_UnbindAll (); void C_UnbindAll ();
// Returns string bound to given key (NULL if none)
const char *C_GetBinding (int key);
extern const char *KeyNames[]; extern const char *KeyNames[];
#endif //__C_BINDINGS_H__ #endif //__C_BINDINGS_H__

View file

@ -80,11 +80,11 @@ CCMD (toggleconsole)
C_ToggleConsole(); C_ToggleConsole();
} }
bool CheckCheatmode () bool CheckCheatmode (bool printmsg)
{ {
if ((G_SkillProperty(SKILLP_DisableCheats) || netgame || deathmatch) && (!sv_cheats)) if ((G_SkillProperty(SKILLP_DisableCheats) || netgame || deathmatch) && (!sv_cheats))
{ {
Printf ("sv_cheats must be true to enable this command.\n"); if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
return true; return true;
} }
else else

View file

@ -119,7 +119,9 @@ FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
Button_Forward, Button_Right, Button_Left, Button_MoveDown, Button_Forward, Button_Right, Button_Left, Button_MoveDown,
Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch, Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch,
Button_Zoom, Button_Reload, Button_Zoom, Button_Reload,
Button_User1, Button_User2, Button_User3, Button_User4; Button_User1, Button_User2, Button_User3, Button_User4,
Button_AM_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp,
Button_AM_ZoomIn, Button_AM_ZoomOut;
bool ParsingKeyConf; bool ParsingKeyConf;
@ -131,13 +133,16 @@ bool ParsingKeyConf;
FActionMap ActionMaps[] = FActionMap ActionMaps[] =
{ {
{ 0x0d52d67b, &Button_AM_PanLeft, "am_panleft"},
{ 0x125f5226, &Button_User2, "user2" }, { 0x125f5226, &Button_User2, "user2" },
{ 0x1eefa611, &Button_Jump, "jump" }, { 0x1eefa611, &Button_Jump, "jump" },
{ 0x201f1c55, &Button_Right, "right" }, { 0x201f1c55, &Button_Right, "right" },
{ 0x20ccc4d5, &Button_Zoom, "zoom" }, { 0x20ccc4d5, &Button_Zoom, "zoom" },
{ 0x23a99cd7, &Button_Back, "back" }, { 0x23a99cd7, &Button_Back, "back" },
{ 0x41df90c2, &Button_AM_ZoomIn, "am_zoomin"},
{ 0x426b69e7, &Button_Reload, "reload" }, { 0x426b69e7, &Button_Reload, "reload" },
{ 0x4463f43a, &Button_LookDown, "lookdown" }, { 0x4463f43a, &Button_LookDown, "lookdown" },
{ 0x51f7a334, &Button_AM_ZoomOut, "am_zoomout"},
{ 0x534c30ee, &Button_User4, "user4" }, { 0x534c30ee, &Button_User4, "user4" },
{ 0x5622bf42, &Button_Attack, "attack" }, { 0x5622bf42, &Button_Attack, "attack" },
{ 0x577712d0, &Button_User1, "user1" }, { 0x577712d0, &Button_User1, "user1" },
@ -147,12 +152,15 @@ FActionMap ActionMaps[] =
{ 0x676885b8, &Button_AltAttack, "altattack" }, { 0x676885b8, &Button_AltAttack, "altattack" },
{ 0x6fa41b84, &Button_MoveLeft, "moveleft" }, { 0x6fa41b84, &Button_MoveLeft, "moveleft" },
{ 0x818f08e6, &Button_MoveRight, "moveright" }, { 0x818f08e6, &Button_MoveRight, "moveright" },
{ 0x8197097b, &Button_AM_PanRight, "am_panright"},
{ 0x8d89955e, &Button_AM_PanUp, "am_panup"} ,
{ 0xa2b62d8b, &Button_Mlook, "mlook" }, { 0xa2b62d8b, &Button_Mlook, "mlook" },
{ 0xab2c3e71, &Button_Crouch, "crouch" }, { 0xab2c3e71, &Button_Crouch, "crouch" },
{ 0xb000b483, &Button_Left, "left" }, { 0xb000b483, &Button_Left, "left" },
{ 0xb62b1e49, &Button_LookUp, "lookup" }, { 0xb62b1e49, &Button_LookUp, "lookup" },
{ 0xb6f8fe92, &Button_User3, "user3" }, { 0xb6f8fe92, &Button_User3, "user3" },
{ 0xb7e6a54b, &Button_Strafe, "strafe" }, { 0xb7e6a54b, &Button_Strafe, "strafe" },
{ 0xce301c81, &Button_AM_PanDown, "am_pandown"},
{ 0xd5897c73, &Button_ShowScores, "showscores" }, { 0xd5897c73, &Button_ShowScores, "showscores" },
{ 0xe0ccb317, &Button_Speed, "speed" }, { 0xe0ccb317, &Button_Speed, "speed" },
{ 0xe0cfc260, &Button_Use, "use" }, { 0xe0cfc260, &Button_Use, "use" },
@ -160,6 +168,7 @@ FActionMap ActionMaps[] =
}; };
#define NUM_ACTIONS countof(ActionMaps) #define NUM_ACTIONS countof(ActionMaps)
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
static const char *KeyConfCommands[] = static const char *KeyConfCommands[] =

View file

@ -39,6 +39,8 @@
class FConfigFile; class FConfigFile;
class APlayerPawn; class APlayerPawn;
extern bool CheckCheatmode (bool printmsg = true);
void C_ExecCmdLineParams (); void C_ExecCmdLineParams ();
// Add commands to the console as if they were typed in. Can handle wait // Add commands to the console as if they were typed in. Can handle wait
@ -144,6 +146,7 @@ struct FButtonStatus
bool PressKey (int keynum); // Returns true if this key caused the button to be pressed. bool PressKey (int keynum); // Returns true if this key caused the button to be pressed.
bool ReleaseKey (int keynum); // Returns true if this key is no longer pressed. bool ReleaseKey (int keynum); // Returns true if this key is no longer pressed.
void ResetTriggers () { bWentDown = bWentUp = false; } void ResetTriggers () { bWentDown = bWentUp = false; }
void Reset () { bDown = bWentDown = bWentUp = false; }
}; };
extern FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack, extern FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
@ -152,7 +155,9 @@ extern FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
Button_Forward, Button_Right, Button_Left, Button_MoveDown, Button_Forward, Button_Right, Button_Left, Button_MoveDown,
Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch, Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch,
Button_Zoom, Button_Reload, Button_Zoom, Button_Reload,
Button_User1, Button_User2, Button_User3, Button_User4; Button_User1, Button_User2, Button_User3, Button_User4,
Button_AM_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp,
Button_AM_ZoomIn, Button_AM_ZoomOut;
extern bool ParsingKeyConf; extern bool ParsingKeyConf;
void ResetButtonTriggers (); // Call ResetTriggers for all buttons void ResetButtonTriggers (); // Call ResetTriggers for all buttons

View file

@ -2,10 +2,14 @@
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
#include <io.h>
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#if !defined(__sun)
#include <fts.h>
#endif
#endif #endif
#include "doomtype.h" #include "doomtype.h"
#include "cmdlib.h" #include "cmdlib.h"
@ -90,6 +94,23 @@ char *copystring (const char *s)
return b; return b;
} }
//============================================================================
//
// ncopystring
//
// If the string has no content, returns NULL. Otherwise, returns a copy.
//
//============================================================================
char *ncopystring (const char *string)
{
if (string == NULL || string[0] == 0)
{
return NULL;
}
return copystring (string);
}
//========================================================================== //==========================================================================
// //
// ReplaceString // ReplaceString
@ -868,3 +889,153 @@ FString NicePath(const char *path)
return where; return where;
#endif #endif
} }
#ifdef _WIN32
//==========================================================================
//
// ScanDirectory
//
//==========================================================================
void ScanDirectory(TArray<FFileList> &list, const char *dirpath)
{
struct _finddata_t fileinfo;
intptr_t handle;
FString dirmatch;
dirmatch << dirpath << "*";
if ((handle = _findfirst(dirmatch, &fileinfo)) == -1)
{
I_Error("Could not scan '%s': %s\n", dirpath, strerror(errno));
}
else
{
do
{
if (fileinfo.attrib & _A_HIDDEN)
{
// Skip hidden files and directories. (Prevents SVN bookkeeping
// info from being included.)
continue;
}
if (fileinfo.attrib & _A_SUBDIR)
{
if (fileinfo.name[0] == '.' &&
(fileinfo.name[1] == '\0' ||
(fileinfo.name[1] == '.' && fileinfo.name[2] == '\0')))
{
// Do not record . and .. directories.
continue;
}
FFileList *fl = &list[list.Reserve(1)];
fl->Filename << dirpath << fileinfo.name;
fl->isDirectory = true;
FString newdir = fl->Filename;
newdir << "/";
ScanDirectory(list, newdir);
}
else
{
FFileList *fl = &list[list.Reserve(1)];
fl->Filename << dirpath << fileinfo.name;
fl->isDirectory = false;
}
}
while (_findnext(handle, &fileinfo) == 0);
_findclose(handle);
}
}
#elif defined(__sun) || defined(linux)
//==========================================================================
//
// ScanDirectory
// Solaris version
//
// Given NULL-terminated array of directory paths, create trees for them.
//
//==========================================================================
void ScanDirectory(TArray<FFileList> &list, const char *dirpath)
{
DIR *directory = opendir(dirpath);
if(directory == NULL)
return;
struct dirent *file;
while((file = readdir(directory)) != NULL)
{
if(file->d_name[0] == '.') //File is hidden or ./.. directory so ignore it.
continue;
FFileList *fl = &list[list.Reserve(1)];
fl->Filename << dirpath << file->d_name;
struct stat fileStat;
stat(fl->Filename, &fileStat);
fl->isDirectory = S_ISDIR(fileStat.st_mode);
if(fl->isDirectory)
{
FString newdir = fl->Filename;
newdir += "/";
ScanDirectory(list, newdir);
continue;
}
}
closedir(directory);
}
#else
//==========================================================================
//
// ScanDirectory
// 4.4BSD version
//
//==========================================================================
void ScanDirectory(TArray<FFileList> &list, const char *dirpath)
{
const char **argv[] = {dirpath, NULL };
FTS *fts;
FTSENT *ent;
fts = fts_open(argv, FTS_LOGICAL, NULL);
if (fts == NULL)
{
I_Error("Failed to start directory traversal: %s\n", strerror(errno));
return;
}
while ((ent = fts_read(fts)) != NULL)
{
if (ent->fts_info == FTS_D && ent->fts_name[0] == '.')
{
// Skip hidden directories. (Prevents SVN bookkeeping
// info from being included.)
fts_set(fts, ent, FTS_SKIP);
}
if (ent->fts_info == FTS_D && ent->fts_level == 0)
{
FFileList *fl = &list[list.Reserve(1)];
fl->Filename = ent->fts_path;
fl->isDirectory = true;
}
if (ent->fts_info == FTS_F)
{
// We're only interested in remembering files.
FFileList *fl = &list[list.Reserve(1)];
fl->Filename = ent->fts_path;
fl->isDirectory = false;
}
}
fts_close(fts);
}
#endif

View file

@ -36,6 +36,7 @@ int ParseNum (const char *str);
bool IsNum (const char *str); // [RH] added bool IsNum (const char *str); // [RH] added
char *copystring(const char *s); char *copystring(const char *s);
char *ncopystring(const char *s);
void ReplaceString (char **ptr, const char *str); void ReplaceString (char **ptr, const char *str);
bool CheckWildcards (const char *pattern, const char *text); bool CheckWildcards (const char *pattern, const char *text);
@ -53,4 +54,12 @@ void CreatePath(const char * fn);
FString ExpandEnvVars(const char *searchpathstring); FString ExpandEnvVars(const char *searchpathstring);
FString NicePath(const char *path); FString NicePath(const char *path);
struct FFileList
{
FString Filename;
bool isDirectory;
};
void ScanDirectory(TArray<FFileList> &list, const char *dirpath);
#endif #endif

View file

@ -43,10 +43,13 @@
#include "sc_man.h" #include "sc_man.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "doomdef.h" #include "doomdef.h"
#include "doomdata.h"
#include "doomstat.h" #include "doomstat.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "gi.h" #include "gi.h"
#include "g_level.h" #include "g_level.h"
#include "p_lnspec.h"
#include "r_state.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -59,6 +62,14 @@ struct FCompatOption
int BCompatFlags; int BCompatFlags;
}; };
enum
{
CP_END,
CP_CLEARFLAGS,
CP_SETFLAGS,
CP_SETSPECIAL
};
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -77,7 +88,6 @@ static FCompatOption Options[] =
{ {
{ "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW }, { "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW },
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED }, { "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
{ "spechitoverflow", 0, BCOMPATF_SPECHITOVERFLOW },
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS }, { "vileghosts", 0, BCOMPATF_VILEGHOSTS },
// list copied from g_mapinfo.cpp // list copied from g_mapinfo.cpp
@ -106,9 +116,15 @@ static FCompatOption Options[] =
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 }, { "corpsegibs", COMPATF_CORPSEGIBS, 0 },
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 }, { "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
{ "spritesort", COMPATF_SPRITESORT, 0 }, { "spritesort", COMPATF_SPRITESORT, 0 },
{ "hitscan", COMPATF_HITSCAN, 0 },
{ "lightlevel", COMPATF_LIGHT, 0 },
{ "polyobj", COMPATF_POLYOBJ, 0 },
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
static TArray<int> CompatParams;
static int ii_compatparams;
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
//========================================================================== //==========================================================================
@ -170,12 +186,57 @@ void ParseCompatibility()
} while (!sc.Compare("{")); } while (!sc.Compare("{"));
flags.CompatFlags = 0; flags.CompatFlags = 0;
flags.BCompatFlags = 0; flags.BCompatFlags = 0;
while (sc.MustGetString(), (i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0) flags.ExtCommandIndex = ~0u;
while (sc.GetString())
{ {
flags.CompatFlags |= Options[i].CompatFlags; if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0)
flags.BCompatFlags |= Options[i].BCompatFlags; {
flags.CompatFlags |= Options[i].CompatFlags;
flags.BCompatFlags |= Options[i].BCompatFlags;
}
else if (sc.Compare("clearlineflags"))
{
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
CompatParams.Push(CP_CLEARFLAGS);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
}
else if (sc.Compare("setlineflags"))
{
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
CompatParams.Push(CP_SETFLAGS);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
}
else if (sc.Compare("setlinespecial"))
{
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
CompatParams.Push(CP_SETSPECIAL);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
sc.MustGetString();
CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL));
for(int i=0;i<5;i++)
{
sc.MustGetNumber();
CompatParams.Push(sc.Number);
}
}
else
{
sc.UnGet();
break;
}
}
if (flags.ExtCommandIndex != ~0u)
{
CompatParams.Push(CP_END);
} }
sc.UnGet();
sc.MustGetStringName("}"); sc.MustGetStringName("}");
for (j = 0; j < md5array.Size(); ++j) for (j = 0; j < md5array.Size(); ++j)
{ {
@ -196,12 +257,29 @@ void CheckCompatibility(MapData *map)
FMD5Holder md5; FMD5Holder md5;
FCompatValues *flags; FCompatValues *flags;
// When playing Doom IWAD levels force COMPAT_SHORTTEX. // When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT.
// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt.
// TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD.
if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATSHORTTEX) && !(level.flags & LEVEL_HEXENFORMAT)) if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATSHORTTEX) && !(level.flags & LEVEL_HEXENFORMAT))
{ {
ii_compatflags = COMPATF_SHORTTEX; ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT;
if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX;
ib_compatflags = 0; ib_compatflags = 0;
ii_compatparams = -1;
} }
else if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATPOLY1) && Wads.CheckLumpName(map->lumpnum, "MAP36"))
{
ii_compatflags = COMPATF_POLYOBJ;
ib_compatflags = 0;
ii_compatparams = -1;
}
else if (Wads.GetLumpFile(map->lumpnum) == 2 && (gameinfo.flags & GI_COMPATPOLY2) && Wads.CheckLumpName(map->lumpnum, "MAP47"))
{
ii_compatflags = COMPATF_POLYOBJ;
ib_compatflags = 0;
ii_compatparams = -1;
}
else else
{ {
map->GetChecksum(md5.Bytes); map->GetChecksum(md5.Bytes);
@ -223,17 +301,74 @@ void CheckCompatibility(MapData *map)
{ {
ii_compatflags = flags->CompatFlags; ii_compatflags = flags->CompatFlags;
ib_compatflags = flags->BCompatFlags; ib_compatflags = flags->BCompatFlags;
ii_compatparams = flags->ExtCommandIndex;
} }
else else
{ {
ii_compatflags = 0; ii_compatflags = 0;
ib_compatflags = 0; ib_compatflags = 0;
ii_compatparams = -1;
} }
} }
// Reset i_compatflags // Reset i_compatflags
compatflags.Callback(); compatflags.Callback();
} }
//==========================================================================
//
// SetCompatibilityParams
//
//==========================================================================
void SetCompatibilityParams()
{
if (ii_compatparams != -1)
{
unsigned i = ii_compatparams;
while (CompatParams[i] != CP_END && i < CompatParams.Size())
{
switch (CompatParams[i])
{
case CP_CLEARFLAGS:
{
if (CompatParams[i+1] < numlines)
{
line_t *line = &lines[CompatParams[i+1]];
line->flags &= ~CompatParams[i+2];
}
i+=3;
break;
}
case CP_SETFLAGS:
{
if (CompatParams[i+1] < numlines)
{
line_t *line = &lines[CompatParams[i+1]];
line->flags |= CompatParams[i+2];
}
i+=3;
break;
}
case CP_SETSPECIAL:
{
if (CompatParams[i+1] < numlines)
{
line_t *line = &lines[CompatParams[i+1]];
line->special = CompatParams[i+2];
for(int ii=0;ii<5;ii++)
{
line->args[ii] = CompatParams[i+ii+3];
}
}
i+=8;
break;
}
}
}
}
}
//========================================================================== //==========================================================================
// //
// CCMD mapchecksum // CCMD mapchecksum

View file

@ -16,6 +16,7 @@ struct FCompatValues
{ {
int CompatFlags; int CompatFlags;
int BCompatFlags; int BCompatFlags;
unsigned int ExtCommandIndex;
}; };
struct FMD5HashTraits struct FMD5HashTraits
@ -37,5 +38,6 @@ extern TMap<FMD5Holder, FCompatValues, FMD5HashTraits> BCompatMap;
void ParseCompatibility(); void ParseCompatibility();
void CheckCompatibility(MapData *map); void CheckCompatibility(MapData *map);
void SetCompatibilityParams();
#endif #endif

View file

@ -953,7 +953,7 @@ static int PatchThing (int thingy)
// compatibility, the upper bits are freed, but we have conflicts between the ZDoom bits // compatibility, the upper bits are freed, but we have conflicts between the ZDoom bits
// and the MBF bits. The only such flag exposed to DEHSUPP, though, is STEALTH -- the others // and the MBF bits. The only such flag exposed to DEHSUPP, though, is STEALTH -- the others
// are not available through mnemonics, and aren't available either through their bit value. // are not available through mnemonics, and aren't available either through their bit value.
// So if we find the STEALTH keyword, it's a ZDoom mod, otherwise assume assume FRIEND. // So if we find the STEALTH keyword, it's a ZDoom mod, otherwise assume FRIEND.
bool zdoomflags = false; bool zdoomflags = false;
char *strval; char *strval;
@ -1355,8 +1355,8 @@ static int PatchFrame (int frameNum)
} }
info->Tics = tics; info->Tics = tics;
info->Misc1 = misc1; info->Misc1 = misc1;
info->Frame = (frame & 0x3f) | info->Frame = frame & 0x3f;
(frame & 0x8000 ? SF_FULLBRIGHT : 0); info->Fullbright = frame & 0x8000 ? true : false;
} }
return result; return result;
@ -2106,13 +2106,13 @@ static int PatchText (int oldSize)
// This must be done because the map is scanned using a binary search. // This must be done because the map is scanned using a binary search.
while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0) while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0)
{ {
swap (DehSpriteMappings[i-1], DehSpriteMappings[i]); swapvalues (DehSpriteMappings[i-1], DehSpriteMappings[i]);
--i; --i;
} }
while ((size_t)i < countof(DehSpriteMappings)-1 && while ((size_t)i < countof(DehSpriteMappings)-1 &&
strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0) strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0)
{ {
swap (DehSpriteMappings[i+1], DehSpriteMappings[i]); swapvalues (DehSpriteMappings[i+1], DehSpriteMappings[i]);
++i; ++i;
} }
break; break;

View file

@ -58,10 +58,10 @@ EIWADType gameiwad;
const IWADInfo IWADInfos[NUM_IWAD_TYPES] = const IWADInfo IWADInfos[NUM_IWAD_TYPES] =
{ {
// banner text, autoname, fg color, bg color // banner text, autoname, fg color, bg color
{ "Final Doom: TNT - Evilution", "TNT", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/tnt.txt", GI_MAPxx | GI_COMPATSHORTTEX }, { "Final Doom: TNT - Evilution", "TNT", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/tnt.txt", GI_MAPxx | GI_COMPATSHORTTEX | GI_COMPATSTAIRS },
{ "Final Doom: Plutonia Experiment", "Plutonia", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/plutonia.txt", GI_MAPxx | GI_COMPATSHORTTEX }, { "Final Doom: Plutonia Experiment", "Plutonia", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/plutonia.txt", GI_MAPxx | GI_COMPATSHORTTEX },
{ "Hexen: Beyond Heretic", NULL, MAKERGB(240,240,240), MAKERGB(107,44,24), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx }, { "Hexen: Beyond Heretic", NULL, MAKERGB(240,240,240), MAKERGB(107,44,24), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx | GI_COMPATPOLY1 },
{ "Hexen: Deathkings of the Dark Citadel", "HexenDK", MAKERGB(240,240,240), MAKERGB(139,68,9), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx }, { "Hexen: Deathkings of the Dark Citadel", "HexenDK", MAKERGB(240,240,240), MAKERGB(139,68,9), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx | GI_COMPATPOLY1 | GI_COMPATPOLY2 },
{ "Hexen: Demo Version", "HexenDemo",MAKERGB(240,240,240), MAKERGB(107,44,24), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx | GI_SHAREWARE }, { "Hexen: Demo Version", "HexenDemo",MAKERGB(240,240,240), MAKERGB(107,44,24), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx | GI_SHAREWARE },
{ "DOOM 2: Hell on Earth", "Doom2", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx | GI_COMPATSHORTTEX }, { "DOOM 2: Hell on Earth", "Doom2", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx | GI_COMPATSHORTTEX },
{ "Heretic Shareware", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0), GAME_Heretic, "mapinfo/hereticsw.txt",GI_SHAREWARE }, { "Heretic Shareware", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0), GAME_Heretic, "mapinfo/hereticsw.txt",GI_SHAREWARE },

View file

@ -38,7 +38,7 @@
#endif #endif
#include <float.h> #include <float.h>
#ifdef unix #if defined(unix) || defined(__APPLE__)
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -104,6 +104,7 @@
#include "compatibility.h" #include "compatibility.h"
#include "m_joy.h" #include "m_joy.h"
#include "sc_man.h" #include "sc_man.h"
#include "po_man.h"
#include "resourcefiles/resourcefile.h" #include "resourcefiles/resourcefile.h"
EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Bool, hud_althud)
@ -120,7 +121,6 @@ extern void M_SetDefaultMode ();
extern void R_ExecuteSetViewSize (); extern void R_ExecuteSetViewSize ();
extern void G_NewInit (); extern void G_NewInit ();
extern void SetupPlayerClasses (); extern void SetupPlayerClasses ();
extern bool CheckCheatmode ();
const IWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad); const IWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad);
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -201,6 +201,7 @@ gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe
bool PageBlank; bool PageBlank;
FTexture *Page; FTexture *Page;
FTexture *Advisory; FTexture *Advisory;
bool nospriterename;
cycle_t FrameCycles; cycle_t FrameCycles;
@ -459,6 +460,8 @@ CVAR (Flag, sv_disallowspying, dmflags2, DF2_DISALLOW_SPYING);
CVAR (Flag, sv_chasecam, dmflags2, DF2_CHASECAM); CVAR (Flag, sv_chasecam, dmflags2, DF2_CHASECAM);
CVAR (Flag, sv_disallowsuicide, dmflags2, DF2_NOSUICIDE); CVAR (Flag, sv_disallowsuicide, dmflags2, DF2_NOSUICIDE);
CVAR (Flag, sv_noautoaim, dmflags2, DF2_NOAUTOAIM); CVAR (Flag, sv_noautoaim, dmflags2, DF2_NOAUTOAIM);
CVAR (Flag, sv_dontcheckammo, dmflags2, DF2_DONTCHECKAMMO);
CVAR (Flag, sv_killbossmonst, dmflags2, DF2_KILLBOSSMONST);
//========================================================================== //==========================================================================
// //
@ -479,7 +482,12 @@ static int GetCompatibility(int mask)
CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
{ {
int old = i_compatflags;
i_compatflags = GetCompatibility(self) | ii_compatflags; i_compatflags = GetCompatibility(self) | ii_compatflags;
if ((old ^i_compatflags) & COMPATF_POLYOBJ)
{
FPolyObj::ClearAllSubsectorLinks();
}
} }
CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL) CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
@ -495,28 +503,35 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
case 1: // Doom2.exe compatible with a few relaxed settings case 1: // Doom2.exe compatible with a few relaxed settings
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT| v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_DEHHEALTH|COMPATF_CROSSDROPOFF; COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_DEHHEALTH|COMPATF_CROSSDROPOFF|
COMPATF_LIGHT;
break; break;
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set) case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT| v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN| COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS; COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|
COMPATF_WALLRUN|COMPATF_NOTOSSDROPS|COMPATF_LIGHT;
break; break;
case 3: // Boom compat mode case 3: // Boom compat mode
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL; v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP;
break; break;
case 4: // Old ZDoom compat mode case 4: // Old ZDoom compat mode
v = COMPATF_SOUNDTARGET; v = COMPATF_SOUNDTARGET|COMPATF_LIGHT;
break; break;
case 5: // MBF compat mode case 5: // MBF compat mode
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MUSHROOM| v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_MUSHROOM|
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS; COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
break; break;
case 6: // Boom with some added settings to reenable spme 'broken' behavior
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_NO_PASSMOBJ|
COMPATF_INVISIBILITY|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
break;
} }
compatflags = v; compatflags = v;
} }
@ -549,6 +564,9 @@ CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS); CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS); CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
CVAR (Flag, compat_spritesort, compatflags,COMPATF_SPRITESORT); CVAR (Flag, compat_spritesort, compatflags,COMPATF_SPRITESORT);
CVAR (Flag, compat_hitscan, compatflags,COMPATF_HITSCAN);
CVAR (Flag, compat_light, compatflags,COMPATF_LIGHT);
CVAR (Flag, compat_polyobj, compatflags,COMPATF_POLYOBJ);
//========================================================================== //==========================================================================
// //
@ -1199,8 +1217,11 @@ void D_DoAdvanceDemo (void)
case 2: case 2:
pagetic = (int)(gameinfo.pageTime * TICRATE); pagetic = (int)(gameinfo.pageTime * TICRATE);
gamestate = GS_DEMOSCREEN; gamestate = GS_DEMOSCREEN;
pagename = gameinfo.creditPages[pagecount]; if (gameinfo.creditPages.Size() > 0)
pagecount = (pagecount+1) % gameinfo.creditPages.Size(); {
pagename = gameinfo.creditPages[pagecount];
pagecount = (pagecount+1) % gameinfo.creditPages.Size();
}
demosequence = 1; demosequence = 1;
break; break;
} }
@ -1658,6 +1679,10 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
} }
while (sc.CheckToken(',')); while (sc.CheckToken(','));
} }
else if (!nextKey.CompareNoCase("NOSPRITERENAME"))
{
nospriterename = true;
}
} }
return iwad; return iwad;
} }
@ -1754,6 +1779,9 @@ void D_DoomMain (void)
#endif #endif
#endif #endif
// Check response files before coalescing file parameters.
M_FindResponseFile ();
PClass::StaticInit(); PClass::StaticInit();
PType::StaticInit(); PType::StaticInit();
@ -1772,7 +1800,6 @@ void D_DoomMain (void)
rngseed = I_MakeRNGSeed(); rngseed = I_MakeRNGSeed();
FRandom::StaticClearRandom (); FRandom::StaticClearRandom ();
M_FindResponseFile ();
Printf ("M_LoadDefaults: Load system defaults.\n"); Printf ("M_LoadDefaults: Load system defaults.\n");
M_LoadDefaults (); // load before initing other systems M_LoadDefaults (); // load before initing other systems
@ -2274,6 +2301,14 @@ void FStartupScreen::AppendStatusLine(const char *status)
// //
//========================================================================== //==========================================================================
//==========================================================================
//
// STAT fps
//
// Displays statistics about rendering times
//
//==========================================================================
ADD_STAT (fps) ADD_STAT (fps)
{ {
FString out; FString out;
@ -2282,6 +2317,24 @@ ADD_STAT (fps)
return out; return out;
} }
static double f_acc, w_acc,p_acc,m_acc;
static int acc_c;
ADD_STAT (fps_accumulated)
{
f_acc += FrameCycles.TimeMS();
w_acc += WallCycles.TimeMS();
p_acc += PlaneCycles.TimeMS();
m_acc += MaskedCycles.TimeMS();
acc_c++;
FString out;
out.Format("frame=%04.1f ms walls=%04.1f ms planes=%04.1f ms masked=%04.1f ms %d counts",
f_acc/acc_c, w_acc/acc_c, p_acc/acc_c, m_acc/acc_c, acc_c);
Printf(PRINT_LOG, "%s\n", out.GetChars());
return out;
}
//========================================================================== //==========================================================================
// //
// STAT wallcycles // STAT wallcycles

View file

@ -1917,6 +1917,22 @@ BYTE *FDynamicBuffer::GetData (int *len)
} }
static int KillAll(const PClass *cls)
{
AActor *actor;
int killcount = 0;
TThinkerIterator<AActor> iterator(cls);
while ( (actor = iterator.Next ()) )
{
if (actor->IsA(cls))
{
if (!(actor->flags2 & MF2_DORMANT) && (actor->flags3 & MF3_ISMONSTER))
killcount += actor->Massacre ();
}
}
return killcount;
}
// [RH] Execute a special "ticcmd". The type byte should // [RH] Execute a special "ticcmd". The type byte should
// have already been read, and the stream is positioned // have already been read, and the stream is positioned
// at the beginning of the command's actual data. // at the beginning of the command's actual data.
@ -2021,7 +2037,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
// Using LEVEL_NOINTERMISSION tends to throw the game out of sync. // Using LEVEL_NOINTERMISSION tends to throw the game out of sync.
// That was a long time ago. Maybe it works now? // That was a long time ago. Maybe it works now?
level.flags |= LEVEL_CHANGEMAPCHEAT; level.flags |= LEVEL_CHANGEMAPCHEAT;
G_ChangeLevel(s, pos, false); G_ChangeLevel(s, pos, 0);
break; break;
case DEM_SUICIDE: case DEM_SUICIDE:
@ -2348,22 +2364,25 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_KILLCLASSCHEAT: case DEM_KILLCLASSCHEAT:
{ {
AActor *actor;
TThinkerIterator<AActor> iterator;
char *classname = ReadString (stream); char *classname = ReadString (stream);
int killcount = 0; int killcount = 0;
PClassActor *cls = PClass::FindActor(classname);
while ( (actor = iterator.Next ()) ) if (cls != NULL)
{ {
if (!stricmp (actor->GetClass ()->TypeName.GetChars (), classname)) killcount = KillAll(cls);
const PClass *cls_rep = cls->GetReplacement();
if (cls != cls_rep)
{ {
if (!(actor->flags2 & MF2_DORMANT) && (actor->flags3 & MF3_ISMONSTER)) killcount += KillAll(cls_rep);
killcount += actor->Massacre ();
} }
Printf ("Killed %d monsters of type %s.\n",killcount, classname);
}
else
{
Printf ("%s is not an actor class.\n", classname);
} }
Printf ("Killed %d monsters of type %s.\n",killcount, classname);
} }
break; break;

View file

@ -772,10 +772,6 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
// Rebuild translation in case the new skin uses a different range // Rebuild translation in case the new skin uses a different range
// than the old one. // than the old one.
R_BuildPlayerTranslation (i); R_BuildPlayerTranslation (i);
if (StatusBar != NULL && i == StatusBar->GetPlayer())
{
StatusBar->SetFace (&skins[info->skin]);
}
break; break;
case INFO_Gender: case INFO_Gender:

View file

@ -320,7 +320,7 @@ public:
short fixedlightlevel; short fixedlightlevel;
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
int morphTics; // player is a chicken/pig if > 0 int morphTics; // player is a chicken/pig if > 0
BYTE MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed PClassPlayerPawn *MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed
int MorphStyle; // which effects to apply for this player instance when morphed int MorphStyle; // which effects to apply for this player instance when morphed
PClassActor *MorphExitFlash; // flash to apply when demorphing (cache of value given to P_MorphPlayer) PClassActor *MorphExitFlash; // flash to apply when demorphing (cache of value given to P_MorphPlayer)
TObjPtr<AWeapon> PremorphWeapon; // ready weapon before morphing TObjPtr<AWeapon> PremorphWeapon; // ready weapon before morphing

View file

@ -403,7 +403,7 @@ void FDecalLib::ReadDecals(FScanner &sc)
} }
else else
{ {
sc.MustGetStringName(NULL); sc.ScriptError("Unknown decaldef keyword '%s'", sc.String);
} }
} }
} }

View file

@ -60,6 +60,40 @@ ClassReg DObject::RegistrationInfo =
}; };
_DECLARE_TI(DObject) _DECLARE_TI(DObject)
CCMD (dumpactors)
{
const char *const filters[32] =
{
"0:All", "1:Doom", "2:Heretic", "3:DoomHeretic", "4:Hexen", "5:DoomHexen", "6:Raven", "7:IdRaven",
"8:Strife", "9:DoomStrife", "10:HereticStrife", "11:DoomHereticStrife", "12:HexenStrife",
"13:DoomHexenStrife", "14:RavenStrife", "15:NotChex", "16:Chex", "17:DoomChex", "18:HereticChex",
"19:DoomHereticChex", "20:HexenChex", "21:DoomHexenChex", "22:RavenChex", "23:NotStrife", "24:StrifeChex",
"25:DoomStrifeChex", "26:HereticStrifeChex", "27:NotHexen", "28:HexenStrifeChex", "29:NotHeretic",
"30:NotDoom", "31:All",
};
Printf("%i object class types total\nActor\tEd Num\tSpawnID\tFilter\tSource\n", PClass::AllClasses.Size());
for (unsigned int i = 0; i < PClass::AllClasses.Size(); i++)
{
PClass *cls = PClass::AllClasses[i];
PClassActor *acls = dyn_cast<PClassActor>(cls);
if (acls != NULL)
{
Printf("%s\t%i\t%i\t%s\t%s\n",
acls->TypeName.GetChars(), acls->DoomEdNum,
acls->SpawnID, filters[acls->GameFilter & 31],
acls->SourceLumpName.GetChars());
}
else if (cls != NULL)
{
Printf("%s\tn/a\tn/a\tn/a\tEngine (not an actor type)\n", cls->TypeName.GetChars());
}
else
{
Printf("Type %i is not an object class\n", i);
}
}
}
CCMD (dumpclasses) CCMD (dumpclasses)
{ {
// This is by no means speed-optimized. But it's an informational console // This is by no means speed-optimized. But it's an informational console

View file

@ -71,6 +71,7 @@
#include "r_interpolate.h" #include "r_interpolate.h"
#include "doomstat.h" #include "doomstat.h"
#include "m_argv.h" #include "m_argv.h"
#include "po_man.h"
#include "autosegs.h" #include "autosegs.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------

View file

@ -29,6 +29,7 @@
// Some global defines, that configure the game. // Some global defines, that configure the game.
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h"
// //
// Map level types. // Map level types.
@ -138,7 +139,7 @@ enum ELineFlags
ML_ADDTRANS = 0x00000400, // additive translucency (can only be set internally) ML_ADDTRANS = 0x00000400, // additive translucency (can only be set internally)
// Extended flags // Extended flags
ML_MONSTERSCANACTIVATE = 0x00002000, // [RH] Monsters (as well as players) can active the line ML_MONSTERSCANACTIVATE = 0x00002000, // [RH] Monsters (as well as players) can activate the line
ML_BLOCK_PLAYERS = 0x00004000, ML_BLOCK_PLAYERS = 0x00004000,
ML_BLOCKEVERYTHING = 0x00008000, // [RH] Line blocks everything ML_BLOCKEVERYTHING = 0x00008000, // [RH] Line blocks everything
ML_ZONEBOUNDARY = 0x00010000, ML_ZONEBOUNDARY = 0x00010000,
@ -168,8 +169,9 @@ enum SPAC
SPAC_AnyCross = 1<<7, // when anything without the MF2_TELEPORT flag crosses the line SPAC_AnyCross = 1<<7, // when anything without the MF2_TELEPORT flag crosses the line
SPAC_MUse = 1<<8, // monsters can use SPAC_MUse = 1<<8, // monsters can use
SPAC_MPush = 1<<9, // monsters can push SPAC_MPush = 1<<9, // monsters can push
SPAC_UseBack = 1<<10, // Can be used from the backside
SPAC_PlayerActivate = (SPAC_Cross|SPAC_Use|SPAC_Impact|SPAC_Push|SPAC_AnyCross|SPAC_UseThrough), SPAC_PlayerActivate = (SPAC_Cross|SPAC_Use|SPAC_Impact|SPAC_Push|SPAC_AnyCross|SPAC_UseThrough|SPAC_UseBack),
}; };
enum EMapLineFlags // These are flags that use different values internally enum EMapLineFlags // These are flags that use different values internally
@ -220,6 +222,13 @@ struct mapsubsector_t
WORD firstseg; // index of first one, segs are stored sequentially WORD firstseg; // index of first one, segs are stored sequentially
}; };
#pragma pack(1)
struct mapsubsector4_t
{
WORD numsegs;
DWORD firstseg; // index of first one, segs are stored sequentially
};
#pragma pack()
// LineSeg, generated by splitting LineDefs // LineSeg, generated by splitting LineDefs
// using partition lines selected by BSP builder. // using partition lines selected by BSP builder.
@ -231,6 +240,22 @@ struct mapseg_t
WORD linedef; WORD linedef;
SWORD side; SWORD side;
SWORD offset; SWORD offset;
int V1() { return LittleShort(v1); }
int V2() { return LittleShort(v2); }
};
struct mapseg4_t
{
SDWORD v1;
SDWORD v2;
SWORD angle;
WORD linedef;
SWORD side;
SWORD offset;
int V1() { return LittleLong(v1); }
int V2() { return LittleLong(v2); }
}; };
@ -238,18 +263,40 @@ struct mapseg_t
// BSP node structure. // BSP node structure.
// Indicate a leaf. // Indicate a leaf.
#define NF_SUBSECTOR 0x8000
struct mapnode_t struct mapnode_t
{ {
enum
{
NF_SUBSECTOR = 0x8000,
NF_LUMPOFFSET = 0
};
SWORD x,y,dx,dy; // partition line SWORD x,y,dx,dy; // partition line
SWORD bbox[2][4]; // bounding box for each child SWORD bbox[2][4]; // bounding box for each child
// If NF_SUBSECTOR is or'ed in, it's a subsector, // If NF_SUBSECTOR is or'ed in, it's a subsector,
// else it's a node of another subtree. // else it's a node of another subtree.
WORD children[2]; WORD children[2];
DWORD Child(int num) { return LittleShort(children[num]); }
}; };
struct mapnode4_t
{
enum
{
NF_SUBSECTOR = 0x80000000,
NF_LUMPOFFSET = 8
};
SWORD x,y,dx,dy; // partition line
SWORD bbox[2][4]; // bounding box for each child
// If NF_SUBSECTOR is or'ed in, it's a subsector,
// else it's a node of another subtree.
DWORD children[2];
DWORD Child(int num) { return LittleLong(children[num]); }
};
// Thing definition, position, orientation and type, // Thing definition, position, orientation and type,
@ -293,6 +340,7 @@ struct FMapThing
DWORD flags; DWORD flags;
int special; int special;
int args[5]; int args[5];
int Conversation;
void Serialize (FArchive &); void Serialize (FArchive &);
}; };

View file

@ -290,8 +290,10 @@ enum
DF2_NO_AUTOMAP_ALLIES = 1 << 19, // Allies can been seen on the automap. DF2_NO_AUTOMAP_ALLIES = 1 << 19, // Allies can been seen on the automap.
DF2_DISALLOW_SPYING = 1 << 20, // You can spy on your allies. DF2_DISALLOW_SPYING = 1 << 20, // You can spy on your allies.
DF2_CHASECAM = 1 << 21, // Players can use the chasecam cheat. DF2_CHASECAM = 1 << 21, // Players can use the chasecam cheat.
DF2_NOSUICIDE = 1 << 22, // Players are allowed to suicide. DF2_NOSUICIDE = 1 << 22, // Players are not allowed to suicide.
DF2_NOAUTOAIM = 1 << 23, // Players cannot use autoaim. DF2_NOAUTOAIM = 1 << 23, // Players cannot use autoaim.
DF2_DONTCHECKAMMO = 1 << 24, // Don't Check ammo when switching weapons.
DF2_KILLBOSSMONST = 1 << 25, // Kills all monsters spawned by a boss cube when the boss dies
}; };
// [RH] Compatibility flags. // [RH] Compatibility flags.
@ -325,6 +327,9 @@ enum
COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs. COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs.
COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines. COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines.
COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance
COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code.
COMPATF_LIGHT = 1 << 29, // Find neighboring light level like Doom
COMPATF_POLYOBJ = 1 << 30, // Draw polyobjects the old fashioned way
}; };
// Emulate old bugs for select maps. These are not exposed by a cvar // Emulate old bugs for select maps. These are not exposed by a cvar
@ -333,8 +338,7 @@ enum
{ {
BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow
BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps
BCOMPATF_SPECHITOVERFLOW = 1 << 2, // Emulate spechit overflow (e.g. Strain MAP07) BCOMPATF_VILEGHOSTS = 1 << 2, // Monsters' radius and height aren't restored properly when resurrected.
BCOMPATF_VILEGHOSTS = 1 << 3, // Monsters' radius and height aren't restored properly when resurrected.
}; };
// phares 3/20/98: // phares 3/20/98:

View file

@ -44,12 +44,6 @@
// Since this file is included by everything, it seems an appropriate place // Since this file is included by everything, it seems an appropriate place
// to check the NOASM/USEASM macros. // to check the NOASM/USEASM macros.
#if defined(__APPLE__)
// The assembly code needs to be tweaked for Mach-O before enabled on Macs.
#ifndef NOASM
#define NOASM
#endif
#endif
// There are three assembly-related macros: // There are three assembly-related macros:
// //

View file

@ -723,7 +723,7 @@ bool F_CastResponder (event_t* ev)
if (ev->type != EV_KeyDown) if (ev->type != EV_KeyDown)
return false; return false;
const char *cmd = C_GetBinding (ev->data1); const char *cmd = Bindings.GetBind (ev->data1);
if (cmd != NULL && !stricmp (cmd, "toggleconsole")) if (cmd != NULL && !stricmp (cmd, "toggleconsole"))
return false; return false;
@ -1226,7 +1226,7 @@ void F_Drawer (void)
FTextureID picnum = TexMan.CheckForTexture (FinaleFlat, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable); FTextureID picnum = TexMan.CheckForTexture (FinaleFlat, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
if (picnum.isValid()) if (picnum.isValid())
{ {
screen->FlatFill (0,0, SCREENWIDTH, SCREENHEIGHT, TexMan(picnum)); screen->FlatFill (0,0, SCREENWIDTH, SCREENHEIGHT, TexMan[picnum]);
} }
else else
{ {
@ -1322,15 +1322,15 @@ void F_Drawer (void)
if (multiplayer) if (multiplayer)
{ {
screen->DrawTexture (TexMan["CHESSALL"], 20, 0, screen->DrawTexture (TexMan["CHESSALL"], 20, 0,
DTA_VirtualWidth, w, DTA_VirtualWidthF, w,
DTA_VirtualHeight, h, TAG_DONE); DTA_VirtualHeightF, h, TAG_DONE);
} }
else if (players[consoleplayer].CurrentPlayerClass > 0) else if (players[consoleplayer].CurrentPlayerClass > 0)
{ {
picname = players[consoleplayer].CurrentPlayerClass == 1 ? "CHESSC" : "CHESSM"; picname = players[consoleplayer].CurrentPlayerClass == 1 ? "CHESSC" : "CHESSM";
screen->DrawTexture (TexMan[picname], 60, 0, screen->DrawTexture (TexMan[picname], 60, 0,
DTA_VirtualWidth, w, DTA_VirtualWidthF, w,
DTA_VirtualHeight, h, TAG_DONE); DTA_VirtualHeightF, h, TAG_DONE);
} }
} }
} }

View file

@ -282,6 +282,10 @@ template<> inline FArchive &operator<< <FFont> (FArchive &arc, FFont* &font)
return SerializeFFontPtr (arc, font); return SerializeFFontPtr (arc, font);
} }
struct FStrifeDialogueNode;
template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node);
template<class T,class TT> template<class T,class TT>
inline FArchive &operator<< (FArchive &arc, TArray<T,TT> &self) inline FArchive &operator<< (FArchive &arc, TArray<T,TT> &self)

View file

@ -132,6 +132,8 @@ long FileReader::Seek (long offset, int origin)
long FileReader::Read (void *buffer, long len) long FileReader::Read (void *buffer, long len)
{ {
assert(len >= 0);
if (len <= 0) return 0;
if (FilePos + len > StartPos + Length) if (FilePos + len > StartPos + Length)
{ {
len = Length - FilePos + StartPos; len = Length - FilePos + StartPos;

View file

@ -8,7 +8,56 @@
#include "doomtype.h" #include "doomtype.h"
#include "m_swap.h" #include "m_swap.h"
class FileReader class FileReaderBase
{
public:
virtual ~FileReaderBase() {}
virtual long Read (void *buffer, long len) = 0;
FileReaderBase &operator>> (BYTE &v)
{
Read (&v, 1);
return *this;
}
FileReaderBase &operator>> (SBYTE &v)
{
Read (&v, 1);
return *this;
}
FileReaderBase &operator>> (WORD &v)
{
Read (&v, 2);
v = LittleShort(v);
return *this;
}
FileReaderBase &operator>> (SWORD &v)
{
Read (&v, 2);
v = LittleShort(v);
return *this;
}
FileReaderBase &operator>> (DWORD &v)
{
Read (&v, 4);
v = LittleLong(v);
return *this;
}
FileReaderBase &operator>> (fixed_t &v)
{
Read (&v, 4);
v = LittleLong(v);
return *this;
}
};
class FileReader : public FileReaderBase
{ {
public: public:
FileReader (); FileReader ();
@ -82,13 +131,13 @@ protected:
}; };
// Wraps around a FileReader to decompress a zlib stream // Wraps around a FileReader to decompress a zlib stream
class FileReaderZ class FileReaderZ : public FileReaderBase
{ {
public: public:
FileReaderZ (FileReader &file, bool zip=false); FileReaderZ (FileReader &file, bool zip=false);
~FileReaderZ (); ~FileReaderZ ();
long Read (void *buffer, long len); virtual long Read (void *buffer, long len);
FileReaderZ &operator>> (BYTE &v) FileReaderZ &operator>> (BYTE &v)
{ {
@ -144,7 +193,7 @@ private:
}; };
// Wraps around a FileReader to decompress a bzip2 stream // Wraps around a FileReader to decompress a bzip2 stream
class FileReaderBZ2 class FileReaderBZ2 : public FileReaderBase
{ {
public: public:
FileReaderBZ2 (FileReader &file); FileReaderBZ2 (FileReader &file);
@ -206,7 +255,7 @@ private:
}; };
// Wraps around a FileReader to decompress a lzma stream // Wraps around a FileReader to decompress a lzma stream
class FileReaderLZMA class FileReaderLZMA : public FileReaderBase
{ {
public: public:
FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip); FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip);

View file

@ -85,6 +85,21 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainDie)
if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT)) if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT))
return 0; return 0;
// New dmflag: Kill all boss spawned monsters before ending the level.
if (dmflags2 & DF2_KILLBOSSMONST)
{
TThinkerIterator<AActor> it;
AActor *mo;
while ((mo = it.Next()))
{
if (mo->flags4 & MF4_BOSSSPAWNED)
{
P_DamageMobj(mo, self, self, mo->health, NAME_None,
DMG_NO_ARMOR|DMG_FORCED|DMG_THRUSTLESS|DMG_NO_FACTOR);
}
}
}
G_ExitLevel (0, false); G_ExitLevel (0, false);
return 0; return 0;
} }
@ -261,6 +276,7 @@ static void SpawnFly(AActor *self, PClassActor *spawntype, FSoundID sound)
// telefrag anything in this spot // telefrag anything in this spot
P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true); P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true);
} }
newmobj->flags4 |= MF4_BOSSSPAWNED;
} }
} }

View file

@ -54,7 +54,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
angle += pr_punch.Random2() << 18; angle += pr_punch.Random2() << 18;
pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &linetarget);
// turn to face target // turn to face target
if (linetarget) if (linetarget)
@ -105,15 +106,30 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
// //
// A_Saw // A_Saw
// //
enum SAW_Flags
{
SF_NORANDOM = 1,
SF_RANDOMLIGHTMISS = 2,
SF_RANDOMLIGHTHIT = 4,
SF_NOUSEAMMOMISS = 8,
SF_NOUSEAMMO = 16,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; } PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; }
PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; } PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; }
PARAM_INT_OPT (damage) { damage = 2; } PARAM_INT_OPT (damage) { damage = 2; }
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; }
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (range) { range = 0; }
PARAM_ANGLE_OPT (spread_xy) { spread_xy = angle_t(2.8125 * (ANGLE_90 / 90.0)); }
PARAM_ANGLE_OPT (spread_z) { spread_z = 0; }
PARAM_FIXED_OPT (lifesteal) { lifesteal = 0; }
angle_t angle; angle_t angle;
angle_t slope;
player_t *player; player_t *player;
AActor *linetarget; AActor *linetarget;
@ -122,13 +138,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
return 0; return 0;
} }
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
if (pufftype == NULL) if (pufftype == NULL)
{ {
pufftype = PClass::FindActor(NAME_BulletPuff); pufftype = PClass::FindActor(NAME_BulletPuff);
@ -137,21 +146,61 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
{ {
damage = 2; damage = 2;
} }
if (!(flags & SF_NORANDOM))
{
damage *= (pr_saw()%10+1);
}
if (range == 0)
{ // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states)
range = MELEERANGE+1;
}
damage *= (pr_saw()%10 + 1); angle = self->angle + (pr_saw.Random2() * (spread_xy / 255));
angle = self->angle; slope = P_AimLineAttack (self, angle, range, &linetarget) + (pr_saw.Random2() * (spread_z / 255));
angle += pr_saw.Random2() << 18;
// use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) P_LineAttack (self, angle, range,
P_LineAttack (self, angle, MELEERANGE+1, slope, damage,
P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage,
NAME_None, pufftype); NAME_None, pufftype);
AWeapon *weapon = self->player->ReadyWeapon;
if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!linetarget && (flags & SF_NOUSEAMMOMISS)))
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
if (!linetarget) if (!linetarget)
{ {
if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64))
{
player->extralight = !player->extralight;
}
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
return 0; return 0;
} }
if (flags & SF_RANDOMLIGHTHIT)
{
int randVal = pr_saw();
if (randVal < 64)
{
player->extralight = 0;
}
else if (randVal < 160)
{
player->extralight = 1;
}
else
{
player->extralight = 2;
}
}
if (lifesteal)
{
P_GiveBody (self, (damage * lifesteal) >> FRACBITS);
}
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
// turn to face target // turn to face target

View file

@ -17,9 +17,9 @@
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_INT(doortag); PARAM_INT_OPT(doortag) { doortag = 666; }
CALL_ACTION(A_NoBlocking, self); A_Unblock(self, false);
// scan the remaining thinkers to see if all Keens are dead // scan the remaining thinkers to see if all Keens are dead
AActor *other; AActor *other;

View file

@ -179,7 +179,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie)
self->flags &= ~MF_FRIENDLY; self->flags &= ~MF_FRIENDLY;
} }
PClassActor *spawntype = GetSpawnType(numparam > NAP ? &param[NAP] : NULL); PClassActor *spawntype = GetSpawnType(numparam > NAP ? &param[NAP] : NULL);
CALL_ACTION(A_NoBlocking, self); A_Unblock(self, true);
A_PainShootSkull (self, self->angle + ANG90, spawntype); A_PainShootSkull (self, self->angle + ANG90, spawntype);
A_PainShootSkull (self, self->angle + ANG180, spawntype); A_PainShootSkull (self, self->angle + ANG180, spawntype);
A_PainShootSkull (self, self->angle + ANG270, spawntype); A_PainShootSkull (self, self->angle + ANG270, spawntype);

View file

@ -283,7 +283,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
P_LineAttack (self, angle, MELEERANGE+1, P_LineAttack (self, angle, MELEERANGE+1,
P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage, P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage,
NAME_Melee, pufftype); NAME_Melee, pufftype, false, &linetarget);
if (!linetarget) if (!linetarget)
{ {
@ -338,7 +338,7 @@ static void MarinePunch(AActor *self, int damagemul)
A_FaceTarget (self); A_FaceTarget (self);
angle = self->angle + (pr_m_punch.Random2() << 18); angle = self->angle + (pr_m_punch.Random2() << 18);
pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true); P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &linetarget);
// turn to face target // turn to face target
if (linetarget) if (linetarget)

View file

@ -116,13 +116,13 @@ EXTERN_CVAR (Float, con_midtime);
// //
// CVAR displaynametags // CVAR displaynametags
// //
// Selects whether to display name tags or not when changing weapons // Selects whether to display name tags or not when changing weapons/items
// //
//========================================================================== //==========================================================================
CUSTOM_CVAR (Bool, displaynametags, 0, CVAR_ARCHIVE) CUSTOM_CVAR (Int, displaynametags, 0, CVAR_ARCHIVE)
{ {
if (self != 0 && self != 1) if (self < 0 || self > 3)
{ {
self = 0; self = 0;
} }
@ -288,7 +288,8 @@ CCMD (slot)
if (slot < NUM_WEAPON_SLOTS) if (slot < NUM_WEAPON_SLOTS)
{ {
SendItemUse = players[consoleplayer].weapons.Slots[slot].PickWeapon (&players[consoleplayer]); SendItemUse = players[consoleplayer].weapons.Slots[slot].PickWeapon (&players[consoleplayer],
!(dmflags2 & DF2_DONTCHECKAMMO));
} }
} }
} }
@ -321,11 +322,23 @@ CCMD (turn180)
CCMD (weapnext) CCMD (weapnext)
{ {
SendItemUse = players[consoleplayer].weapons.PickNextWeapon (&players[consoleplayer]); SendItemUse = players[consoleplayer].weapons.PickNextWeapon (&players[consoleplayer]);
// [BC] Option to display the name of the weapon being cycled to.
if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
{
StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, SendItemUse->GetTag(),
1.5f, 0.90f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' ));
}
} }
CCMD (weapprev) CCMD (weapprev)
{ {
SendItemUse = players[consoleplayer].weapons.PickPrevWeapon (&players[consoleplayer]); SendItemUse = players[consoleplayer].weapons.PickPrevWeapon (&players[consoleplayer]);
// [BC] Option to display the name of the weapon being cycled to.
if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
{
StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, SendItemUse->GetTag(),
1.5f, 0.90f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' ));
}
} }
CCMD (invnext) CCMD (invnext)
@ -353,10 +366,9 @@ CCMD (invnext)
who->InvSel = who->Inventory; who->InvSel = who->Inventory;
} }
} }
if (displaynametags && StatusBar && SmallFont if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel)
&& gamestate == GS_LEVEL && level.time > con_midtime && who->InvSel) StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(),
StatusBar->AttachMessage (new DHUDMessage (SmallFont, who->InvSel->GetTag(), 1.5f, 0.80f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
2.5f, 0.375f, 0, 0, CR_YELLOW, con_midtime), MAKE_ID('S','I','N','V'));
} }
who->player->inventorytics = 5*TICRATE; who->player->inventorytics = 5*TICRATE;
} }
@ -384,10 +396,9 @@ CCMD (invprev)
} }
who->InvSel = item; who->InvSel = item;
} }
if (displaynametags && StatusBar && SmallFont if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel)
&& gamestate == GS_LEVEL && level.time > con_midtime && who->InvSel) StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(),
StatusBar->AttachMessage (new DHUDMessage (SmallFont, who->InvSel->GetTag(), 1.5f, 0.80f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
2.5f, 0.375f, 0, 0, CR_YELLOW, con_midtime), MAKE_ID('S','I','N','V'));
} }
who->player->inventorytics = 5*TICRATE; who->player->inventorytics = 5*TICRATE;
} }
@ -871,7 +882,7 @@ bool G_Responder (event_t *ev)
if (gameaction == ga_nothing && if (gameaction == ga_nothing &&
(demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL)) (demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL))
{ {
const char *cmd = C_GetBinding (ev->data1); const char *cmd = Bindings.GetBind (ev->data1);
if (ev->type == EV_KeyDown) if (ev->type == EV_KeyDown)
{ {
@ -894,11 +905,11 @@ bool G_Responder (event_t *ev)
} }
else else
{ {
return C_DoKey (ev); return C_DoKey (ev, &Bindings, &DoubleBindings);
} }
} }
if (cmd && cmd[0] == '+') if (cmd && cmd[0] == '+')
return C_DoKey (ev); return C_DoKey (ev, &Bindings, &DoubleBindings);
return false; return false;
} }
@ -910,7 +921,7 @@ bool G_Responder (event_t *ev)
{ {
if (ST_Responder (ev)) if (ST_Responder (ev))
return true; // status window ate it return true; // status window ate it
if (!viewactive && AM_Responder (ev)) if (!viewactive && AM_Responder (ev, false))
return true; // automap ate it return true; // automap ate it
} }
else if (gamestate == GS_FINALE) else if (gamestate == GS_FINALE)
@ -922,12 +933,12 @@ bool G_Responder (event_t *ev)
switch (ev->type) switch (ev->type)
{ {
case EV_KeyDown: case EV_KeyDown:
if (C_DoKey (ev)) if (C_DoKey (ev, &Bindings, &DoubleBindings))
return true; return true;
break; break;
case EV_KeyUp: case EV_KeyUp:
C_DoKey (ev); C_DoKey (ev, &Bindings, &DoubleBindings);
break; break;
// [RH] mouse buttons are sent as key up/down events // [RH] mouse buttons are sent as key up/down events
@ -941,7 +952,7 @@ bool G_Responder (event_t *ev)
// the events *last* so that any bound keys get precedence. // the events *last* so that any bound keys get precedence.
if (gamestate == GS_LEVEL && viewactive) if (gamestate == GS_LEVEL && viewactive)
return AM_Responder (ev); return AM_Responder (ev, true);
return (ev->type == EV_KeyDown || return (ev->type == EV_KeyDown ||
ev->type == EV_Mouse); ev->type == EV_Mouse);
@ -1165,7 +1176,9 @@ void G_Ticker ()
// G_PlayerFinishLevel // G_PlayerFinishLevel
// Called when a player completes a level. // Called when a player completes a level.
// //
void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory) // flags is checked for RESETINVENTORY and RESETHEALTH only.
void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags)
{ {
AInventory *item, *next; AInventory *item, *next;
player_t *p; player_t *p;
@ -1237,8 +1250,14 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory
P_UndoPlayerMorph (p, p, 0, true); P_UndoPlayerMorph (p, p, 0, true);
} }
// Resets player health to default
if (flags & CHANGELEVEL_RESETHEALTH)
{
p->health = p->mo->health = p->mo->SpawnHealth();
}
// Clears the entire inventory and gives back the defaults for starting a game // Clears the entire inventory and gives back the defaults for starting a game
if (resetinventory) if (flags & CHANGELEVEL_RESETINVENTORY)
{ {
AInventory *inv = p->mo->Inventory; AInventory *inv = p->mo->Inventory;
@ -2044,11 +2063,11 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
M_AppendPNGChunk (stdfile, MAKE_ID('s','n','X','t'), &next, 1); M_AppendPNGChunk (stdfile, MAKE_ID('s','n','X','t'), &next, 1);
} }
M_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
M_FinishPNG (stdfile); M_FinishPNG (stdfile);
fclose (stdfile); fclose (stdfile);
M_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
// Check whether the file is ok. // Check whether the file is ok.
bool success = false; bool success = false;
stdfile = fopen (filename.GetChars(), "rb"); stdfile = fopen (filename.GetChars(), "rb");

View file

@ -71,7 +71,7 @@ enum EFinishLevelType
FINISH_NoHub FINISH_NoHub
}; };
void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory); void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags);
void G_DoReborn (int playernum, bool freshbot); void G_DoReborn (int playernum, bool freshbot);

View file

@ -186,7 +186,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
damage = 1 + (pr_beakatkpl1()&3); damage = 1 + (pr_beakatkpl1()&3);
angle = player->mo->angle; angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget); slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true); P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
if (linetarget) if (linetarget)
{ {
player->mo->angle = R_PointToAngle2 (player->mo->x, player->mo->angle = R_PointToAngle2 (player->mo->x,
@ -222,7 +222,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
damage = pr_beakatkpl2.HitDice (4); damage = pr_beakatkpl2.HitDice (4);
angle = player->mo->angle; angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget); slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true); P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
if (linetarget) if (linetarget)
{ {
player->mo->angle = R_PointToAngle2 (player->mo->x, player->mo->angle = R_PointToAngle2 (player->mo->x,

View file

@ -151,7 +151,7 @@ void P_DSparilTeleport (AActor *actor)
DSpotState *state = DSpotState::GetSpotState(); DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return; if (state == NULL) return;
spot = state->GetSpotWithMinDistance(PClass::FindClass("BossSpot"), actor->x, actor->y, 128*FRACUNIT); spot = state->GetSpotWithMinMaxDistance(PClass::FindClass("BossSpot"), actor->x, actor->y, 128*FRACUNIT, 0);
if (spot == NULL) return; if (spot == NULL) return;
prevX = actor->x; prevX = actor->x;

View file

@ -89,7 +89,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
angle = self->angle; angle = self->angle;
angle += pr_sap.Random2() << 18; angle += pr_sap.Random2() << 18;
slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
P_LineAttack (self, angle, MELEERANGE, slope, damage, NAME_Melee, puff, true); P_LineAttack (self, angle, MELEERANGE, slope, damage, NAME_Melee, puff, true, &linetarget);
if (linetarget) if (linetarget)
{ {
//S_StartSound(player->mo, sfx_stfhit); //S_StartSound(player->mo, sfx_stfhit);
@ -291,7 +291,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
pufftype = PClass::FindActor("GauntletPuff1"); pufftype = PClass::FindActor("GauntletPuff1");
} }
slope = P_AimLineAttack (self, angle, dist, &linetarget); slope = P_AimLineAttack (self, angle, dist, &linetarget);
P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype); P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &linetarget);
if (!linetarget) if (!linetarget)
{ {
if (pr_gatk() > 64) if (pr_gatk() > 64)

View file

@ -1,795 +0,0 @@
#include <assert.h>
#include "doomtype.h"
#include "doomstat.h"
#include "v_font.h"
#include "sbar.h"
#include "r_defs.h"
#include "w_wad.h"
#include "m_random.h"
#include "d_player.h"
#include "st_stuff.h"
#include "v_video.h"
#include "r_draw.h"
#include "templates.h"
#include "a_keys.h"
#include "r_translate.h"
#include "g_level.h"
#include "v_palette.h"
static FRandom pr_chainwiggle;
// This texture is used to shade each end of the health chain
class FHereticShader : public FTexture
{
public:
FHereticShader ();
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
const BYTE *GetPixels ();
void Unload ();
private:
static const BYTE Pixels[10*16];
static const Span DummySpan[2];
};
static FHereticShader ChainShade;
const FTexture::Span FHereticShader::DummySpan[2] = { { 0, 10 }, { 0, 0 } };
const BYTE FHereticShader::Pixels[10*16] =
{
254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
};
FHereticShader::FHereticShader ()
{
Width = 16;
Height = 10;
WidthBits = 4;
HeightBits = 4;
WidthMask = 15;
}
void FHereticShader::Unload ()
{
}
const BYTE *FHereticShader::GetColumn (unsigned int column, const Span **spans_out)
{
if (spans_out != NULL)
{
*spans_out = DummySpan;
}
return Pixels + 10*(column & 15);
}
const BYTE *FHereticShader::GetPixels ()
{
return Pixels;
}
class DHereticStatusBar : public DBaseStatusBar
{
DECLARE_CLASS(DHereticStatusBar, DBaseStatusBar)
HAS_OBJECT_POINTERS
public:
DHereticStatusBar () : DBaseStatusBar (42)
{
static const char *hereticLumpNames[NUM_HERETICSB_IMAGES] =
{
"LTFACE", "RTFACE", "BARBACK", "INVBAR", "CHAIN",
NULL, "LIFEGEM2", "LTFCTOP", "RTFCTOP", "SELECTBO",
"INVGEML1", "INVGEML2", "INVGEMR1", "INVGEMR2", "BLACKSQ",
"ARMCLEAR", "CHAINBACK","GOD1", "GOD2", "USEARTIA",
"USEARTIB", "USEARTIC", "USEARTID", "YKEYICON", "GKEYICON",
"BKEYICON", "ARTIBOX", "PTN1A0", "PTN1B0", "PTN1C0"
};
static const char *sharedLumpNames[] =
{
"LAME", "NEGNUM", "IN0", "IN1", "IN2",
"IN3", "IN4", "IN5", "IN6", "IN7",
"IN8", "IN9", "FONTB13", "FONTB16", "FONTB17",
"FONTB18", "FONTB19", "FONTB20", "FONTB21", "FONTB22",
"FONTB23", "FONTB24", "FONTB25", "SMALLIN0", "SMALLIN1",
"SMALLIN2", "SMALLIN3", "SMALLIN4", "SMALLIN5", "SMALLIN6",
"SMALLIN7", "SMALLIN8", "SMALLIN9"
};
if (deathmatch)
{
hereticLumpNames[5] = "STATBAR";
}
else
{
hereticLumpNames[5] = "LIFEBAR";
}
DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES);
Images.Init (hereticLumpNames, NUM_HERETICSB_IMAGES);
oldarti = NULL;
oldammo1 = oldammo2 = NULL;
oldammocount1 = oldammocount2 = -1;
oldartiCount = 0;
oldfrags = -9999;
oldarmor = -1;
oldhealth = -1;
oldlife = -1;
oldkeys = -1;
HealthMarker = 0;
ChainWiggle = 0;
ArtifactFlash = 0;
}
~DHereticStatusBar ()
{
}
void Tick ()
{
int curHealth;
DBaseStatusBar::Tick ();
if (level.time & 1)
{
ChainWiggle = pr_chainwiggle() & 1;
}
curHealth = CPlayer->health;
if (curHealth < 0)
{
curHealth = 0;
}
if (curHealth < HealthMarker)
{
HealthMarker -= clamp ((HealthMarker - curHealth) >> 2, 1, 8);
}
else if (curHealth > HealthMarker)
{
HealthMarker += clamp ((curHealth - HealthMarker) >> 2, 1, 8);
}
if (ArtifactFlash > 0)
{
if (--ArtifactFlash == 0)
{
ArtiRefresh = screen->GetPageCount ();
}
}
}
void Draw (EHudState state)
{
DBaseStatusBar::Draw (state);
if (state == HUD_Fullscreen)
{
DrawFullScreenStuff ();
SB_state = screen->GetPageCount ();
}
else if (state == HUD_StatusBar)
{
if (SB_state > 0)
{
DrawImage (Images[imgBARBACK], 0, 0);
if (CPlayer->cheats&CF_GODMODE)
{
DrawImage (Images[imgGOD1], 16, 9);
DrawImage (Images[imgGOD2], 287, 9);
}
oldhealth = -1;
}
DrawCommonBar ();
if (CPlayer->inventorytics == 0)
{
if (SB_state < 0)
{
SB_state = screen->GetPageCount ();
}
if (SB_state != 0)
{
// Main interface
SB_state--;
DrawImage (Images[imgSTATBAR], 34, 2);
oldarti = NULL;
oldammo1 = oldammo2 = NULL;
oldammocount1 = oldammocount2 = -1;
oldarmor = -1;
oldfrags = -9999; //can't use -1, 'cuz of negative frags
oldlife = -1;
oldkeys = -1;
oldhealth = -1;
ArtiRefresh = 0;
}
DrawMainBar ();
}
else
{
if (SB_state > -1)
{
SB_state = -screen->GetPageCount () - 1;
}
if (SB_state < -1)
{
SB_state++;
DrawImage (Images[imgINVBAR], 34, 2);
}
DrawInventoryBar ();
}
}
}
private:
//---------------------------------------------------------------------------
//
// PROC DrawCommonBar
//
//---------------------------------------------------------------------------
void DrawCommonBar ()
{
int chainY;
int healthPos;
DrawImage (Images[imgLTFCTOP], 0, -10);
//DrawImage (Images[imgRTFCTOP], 290, -10);
screen->DrawTexture (Images[imgRTFCTOP], ST_X+290, ST_Y,
DTA_Bottom320x200, Scaled,
DTA_TopOffset, Images[imgRTFCTOP]->GetHeight(),
TAG_DONE);
if (oldhealth != HealthMarker)
{
oldhealth = HealthMarker;
HealthRefresh = screen->GetPageCount ();
}
if (HealthRefresh)
{
HealthRefresh--;
healthPos = HealthMarker;
if (healthPos < 0)
{
healthPos = 0;
}
if (healthPos > 100)
{
healthPos = 100;
}
healthPos = (healthPos * 256) / 100;
chainY = (HealthMarker == (CPlayer->health > 0 ? CPlayer->health : 0)) ? 33 : 33 + ChainWiggle;
DrawImage (Images[imgCHAINBACK], 0, 32);
DrawImage (Images[imgCHAIN], 2+(healthPos%17), chainY);
DrawImage (Images[imgLIFEGEM], 17+healthPos, chainY, multiplayer ?
translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)] : NULL);
DrawImage (Images[imgLTFACE], 0, 32);
DrawImage (Images[imgRTFACE], 276, 32);
screen->DrawTexture (&ChainShade, ST_X+19, ST_Y+32,
DTA_Bottom320x200, Scaled,
DTA_AlphaChannel, true,
DTA_FillColor, 0,
TAG_DONE);
screen->DrawTexture (&ChainShade, ST_X+277, ST_Y+32,
DTA_Bottom320x200, Scaled,
DTA_AlphaChannel, true,
DTA_FillColor, 0,
DTA_FlipX, true,
TAG_DONE);
}
}
//---------------------------------------------------------------------------
//
// PROC DrawMainBar
//
//---------------------------------------------------------------------------
void DrawMainBar ()
{
AInventory *item;
AAmmo *ammo1, *ammo2;
int ammocount1, ammocount2;
int temp;
int playerkeys;
// Ready artifact
if (ArtifactFlash)
{
DrawImage (Images[imgBLACKSQ], 180, 3);
DrawImage (Images[imgUSEARTIA + ArtifactFlash], 182, 3);
oldarti = NULL; // so that the correct artifact fills in after the flash
}
else if (oldarti != CPlayer->mo->InvSel
|| (oldarti != NULL && oldartiCount != oldarti->Amount))
{
oldarti = CPlayer->mo->InvSel;
GC::WriteBarrier(this, oldarti);
oldartiCount = oldarti != NULL ? oldarti->Amount : 0;
ArtiRefresh = screen->GetPageCount ();
}
if (ArtiRefresh)
{
ArtiRefresh--;
DrawImage (Images[imgBLACKSQ], 180, 3);
if (oldarti != NULL)
{
DrawDimImage (TexMan(oldarti->Icon), 179, 2, oldarti->Amount <= 0);
if (oldartiCount != 1)
{
DrSmallNumber (oldartiCount, 197, 24);
}
}
}
// Frags
if (deathmatch)
{
temp = CPlayer->fragcount;
if (temp != oldfrags)
{
oldfrags = temp;
FragHealthRefresh = screen->GetPageCount ();
}
if (FragHealthRefresh)
{
FragHealthRefresh--;
DrawImage (Images[imgARMCLEAR], 57, 13);
DrINumber (temp, 61, 12);
}
}
else
{
temp = MAX(0, HealthMarker);
if (oldlife != temp)
{
oldlife = temp;
FragHealthRefresh = screen->GetPageCount ();
}
if (FragHealthRefresh)
{
FragHealthRefresh--;
DrawImage (Images[imgARMCLEAR], 57, 13);
DrINumber (temp, 61, 12);
}
}
// Keys
playerkeys = 0;
for (item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory)
{
if (item->IsKindOf (RUNTIME_CLASS(AKey)))
{
int keynum = static_cast<AKey*>(item)->KeyNumber;
if (keynum >= 1 && keynum <= 3)
{
playerkeys |= 1 << (keynum-1);
}
}
}
if (oldkeys != playerkeys)
{
oldkeys = playerkeys;
KeysRefresh = screen->GetPageCount ();
}
if (KeysRefresh)
{
KeysRefresh--;
// [RH] Erase the key images so the player can drop keys
// and see the status update.
screen->DrawTexture (Images[imgSTATBAR], ST_X+34, ST_Y+2,
DTA_WindowLeft, 119,
DTA_WindowRight, 129,
DTA_Bottom320x200, Scaled,
TAG_DONE);
if (playerkeys & 4)
{
DrawImage (Images[imgYKEYICON], 153, 6);
}
if (playerkeys & 1)
{
DrawImage (Images[imgGKEYICON], 153, 14);
}
if (playerkeys & 2)
{
DrawImage (Images[imgBKEYICON], 153, 22);
}
}
// Ammo
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
if (ammo1 == ammo2)
{
// Don't show the same ammo twice.
ammo2 = NULL;
}
if (oldammo1 != ammo1 || oldammo2 != ammo2 ||
oldammocount1 != ammocount1 || oldammocount2 != ammocount2)
{
oldammo1 = ammo1;
oldammo2 = ammo2;
oldammocount1 = ammocount1;
oldammocount2 = ammocount2;
GC::WriteBarrier(this, ammo1);
GC::WriteBarrier(this, ammo2);
AmmoRefresh = screen->GetPageCount ();
}
if (AmmoRefresh)
{
AmmoRefresh--;
DrawImage (Images[imgBLACKSQ], 108, 3);
if (ammo2 != NULL)
{ // Draw both ammos
screen->DrawTexture (TexMan[ammo1->Icon], 115+ST_X, 11+ST_Y,
DTA_CenterOffset, true,
DTA_Bottom320x200, Scaled,
TAG_DONE);
DrSmallNumber (ammo1->Amount, 124, 7);
screen->DrawTexture (TexMan[ammo2->Icon], 115+ST_X, 22+ST_Y,
DTA_CenterOffset, true,
DTA_Bottom320x200, Scaled,
TAG_DONE);
DrSmallNumber (ammo2->Amount, 124, 19);
}
else if (ammo1 != NULL)
{ // Draw just one ammo
DrINumber (ammo1->Amount, 109, 4);
screen->DrawTexture (TexMan[ammo1->Icon], 123+ST_X, 22+ST_Y,
DTA_CenterOffset, true,
DTA_Bottom320x200, Scaled,
TAG_DONE);
}
}
// Armor
AInventory *armor = CPlayer->mo->FindInventory<ABasicArmor>();
int armorpoints = armor != NULL ? armor->Amount : 0;
if (oldarmor != armorpoints)
{
oldarmor = armorpoints;
ArmorRefresh = screen->GetPageCount ();
}
if (ArmorRefresh)
{
ArmorRefresh--;
DrawImage (Images[imgARMCLEAR], 224, 13);
DrINumber (armorpoints, 228, 12);
}
}
//---------------------------------------------------------------------------
//
// PROC DrawInventoryBar
//
//---------------------------------------------------------------------------
void DrawInventoryBar ()
{
AInventory *item;
int i;
DrawImage (Images[imgINVBAR], 34, 2);
CPlayer->mo->InvFirst = ValidateInvFirst (7);
if (CPlayer->mo->InvFirst != NULL)
{
for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i)
{
DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0);
if (item->Amount != 1)
{
DrSmallNumber (item->Amount, 65+i*31, 24);
}
if (item == CPlayer->mo->InvSel)
{
DrawImage (Images[imgSELECTBOX], 50+i*31, 31);
}
}
// Is there something to the left?
if (CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
{
DrawImage (Images[!(gametic & 4) ?
imgINVLFGEM1 : imgINVLFGEM2], 38, 1);
}
// Is there something to the right?
if (item != NULL)
{
DrawImage (Images[!(gametic & 4) ?
imgINVRTGEM1 : imgINVRTGEM2], 269, 1);
}
}
}
//---------------------------------------------------------------------------
//
// PROC DrawFullScreenStuff
//
//---------------------------------------------------------------------------
void DrawFullScreenStuff ()
{
AInventory *item;
FTexture *pic;
int i;
// Draw health
if (CPlayer->mo->health > 0)
{
pic = Images[imgPTN1 + gametic/3%3];
screen->DrawTexture (pic, 48, -3,
DTA_HUDRules, HUD_Normal,
DTA_LeftOffset, pic->GetWidth()/2,
DTA_TopOffset, pic->GetHeight(),
TAG_DONE);
DrBNumberOuter (CPlayer->mo->health, 5, -21);
}
else
{
DrBNumberOuter (0, 5, -20);
}
// Draw armor
ABasicArmor *armor = CPlayer->mo->FindInventory<ABasicArmor>();
if (armor != NULL && armor->Amount != 0)
{
pic = TexMan(armor->Icon);
if (pic != NULL)
{
screen->DrawTexture (pic, 56, -24,
DTA_HUDRules, HUD_Normal,
DTA_LeftOffset, pic->GetWidth()/2,
DTA_TopOffset, pic->GetHeight(),
TAG_DONE);
}
DrBNumberOuter (armor->Amount, 5, -43);
}
if (deathmatch)
{
// Draw frag count
DrINumberOuter (CPlayer->fragcount, 45, -16);
}
else
{
// Draw keys
int playerkeys = 0;
for (item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory)
{
if (item->IsKindOf (RUNTIME_CLASS(AKey)))
{
int keynum = static_cast<const AKey*>(item)->KeyNumber;
if (keynum >= 1 && keynum <= 3)
{
playerkeys |= 1 << (keynum-1);
}
}
}
i = -7;
if (playerkeys & 2)
{
screen->DrawTexture (Images[imgBKEYICON], 54, i,
DTA_HUDRules, HUD_Normal,
TAG_DONE);
i -= 8;
}
if (playerkeys & 1)
{
screen->DrawTexture (Images[imgGKEYICON], 54, i,
DTA_HUDRules, HUD_Normal,
TAG_DONE);
i -= 8;
}
if (playerkeys & 4)
{
screen->DrawTexture (Images[imgYKEYICON], 54, i,
DTA_HUDRules, HUD_Normal,
TAG_DONE);
}
}
// Draw ammo
AAmmo *ammo1, *ammo2;
int ammocount1, ammocount2;
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
if (ammo1 != NULL)
{
// Draw primary ammo in the bottom-right corner
DrINumberOuter (ammo1->Amount, -29, -15);
screen->DrawTexture (TexMan(ammo1->Icon), -14, -22,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
TAG_DONE);
if (ammo2 != NULL && ammo2!=ammo1)
{
// Draw secondary ammo just above the primary ammo
DrINumberOuter (ammo2->Amount, -29, -56);
screen->DrawTexture (TexMan(ammo2->Icon), -14, -63,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
TAG_DONE);
}
}
// Draw inventory
if (CPlayer->inventorytics == 0)
{
if (ArtifactFlash)
{
screen->DrawTexture (Images[imgARTIBOX], -61, -31,
DTA_HUDRules, HUD_Normal,
DTA_Alpha, TRANSLUC50,
TAG_DONE);
screen->DrawTexture (Images[imgUSEARTIA + ArtifactFlash], -61, -31,
DTA_HUDRules, HUD_Normal,
TAG_DONE);
}
else if (CPlayer->mo->InvSel != NULL)
{
screen->DrawTexture (Images[imgARTIBOX], -61, -31,
DTA_HUDRules, HUD_Normal,
DTA_Alpha, TRANSLUC50,
TAG_DONE);
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -61, -31,
DTA_HUDRules, HUD_Normal,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (CPlayer->mo->InvSel->Amount != 1)
{
DrSmallNumberOuter (CPlayer->mo->InvSel->Amount, -46, -9, false);
}
}
}
else
{
CPlayer->mo->InvFirst = ValidateInvFirst (7);
i = 0;
if (CPlayer->mo->InvFirst != NULL)
{
for (item = CPlayer->mo->InvFirst; item != NULL && i < 7; item = item->NextInv(), ++i)
{
screen->DrawTexture (Images[imgARTIBOX], -100+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_Alpha, HX_SHADOW,
TAG_DONE);
screen->DrawTexture (TexMan(item->Icon), -100+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (item->Amount != 1)
{
DrSmallNumberOuter (item->Amount, -84+i*31, -10, true);
}
if (item == CPlayer->mo->InvSel)
{
screen->DrawTexture (Images[imgSELECTBOX], -100+i*31, -3,
DTA_HUDRules, HUD_HorizCenter,
TAG_DONE);
}
}
// Is there something to the left?
if (CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
{
screen->DrawTexture (Images[!(gametic & 4) ?
imgINVLFGEM1 : imgINVLFGEM2], -112, -33,
DTA_HUDRules, HUD_HorizCenter, TAG_DONE);
}
// Is there something to the right?
if (item != NULL)
{
screen->DrawTexture (Images[!(gametic & 4) ?
imgINVRTGEM1 : imgINVRTGEM2], 119, -33,
DTA_HUDRules, HUD_HorizCenter, TAG_DONE);
}
}
for (; i < 7; i++)
{
screen->DrawTexture (Images[imgARTIBOX], -100+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_Alpha, HX_SHADOW,
TAG_DONE);
}
}
}
//---------------------------------------------------------------------------
//
// PROC FlashItem
//
//---------------------------------------------------------------------------
void FlashItem (const PClass *itemtype)
{
ArtifactFlash = 4;
}
static const char patcharti[][10];
static const char ammopic[][10];
TObjPtr<AInventory> oldarti;
TObjPtr<AAmmo> oldammo1, oldammo2;
int oldammocount1, oldammocount2;
int oldartiCount;
int oldfrags;
int oldarmor;
int oldhealth;
int oldlife;
int oldkeys;
enum
{
imgLTFACE,
imgRTFACE,
imgBARBACK,
imgINVBAR,
imgCHAIN,
imgSTATBAR,
imgLIFEGEM,
imgLTFCTOP,
imgRTFCTOP,
imgSELECTBOX,
imgINVLFGEM1,
imgINVLFGEM2,
imgINVRTGEM1,
imgINVRTGEM2,
imgBLACKSQ,
imgARMCLEAR,
imgCHAINBACK,
imgGOD1,
imgGOD2,
imgUSEARTIA,
imgUSEARTIB,
imgUSEARTIC,
imgUSEARTID,
imgYKEYICON,
imgGKEYICON,
imgBKEYICON,
imgARTIBOX,
imgPTN1,
imgPTN2,
imgPTN3,
NUM_HERETICSB_IMAGES
};
FImageCollection Images;
int HealthMarker;
int ChainWiggle;
int ArtifactFlash;
char HealthRefresh;
char ArtiRefresh;
char FragHealthRefresh;
char KeysRefresh;
char AmmoRefresh;
char ArmorRefresh;
};
IMPLEMENT_POINTY_CLASS(DHereticStatusBar)
DECLARE_POINTER(oldarti)
DECLARE_POINTER(oldammo1)
DECLARE_POINTER(oldammo2)
END_POINTERS
DBaseStatusBar *CreateHereticStatusBar ()
{
return new DHereticStatusBar;
}

View file

@ -31,6 +31,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack)
return 0; return 0;
} }
PClassActor *hammertime = PClass::FindActor("HammerPuff");
damage = 25+(pr_maceatk()&15); damage = 25+(pr_maceatk()&15);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
@ -38,21 +40,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack)
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE, &linetarget); slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE, &linetarget);
if (linetarget) if (linetarget)
{ {
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("HammerPuff"), true); P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
AdjustPlayerAngle (player->mo, linetarget); if (linetarget != NULL)
// player->mo->angle = R_PointToAngle2(player->mo->x, {
// player->mo->y, linetarget->x, linetarget->y); AdjustPlayerAngle (player->mo, linetarget);
goto macedone; goto macedone;
}
} }
angle = player->mo->angle-i*(ANG45/16); angle = player->mo->angle-i*(ANG45/16);
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE, &linetarget); slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE, &linetarget);
if (linetarget) if (linetarget)
{ {
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("HammerPuff"), true); P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
AdjustPlayerAngle (player->mo, linetarget); if (linetarget != NULL)
// player->mo->angle = R_PointToAngle2(player->mo->x, {
// player->mo->y, linetarget->x, linetarget->y); AdjustPlayerAngle (player->mo, linetarget);
goto macedone; goto macedone;
}
} }
} }
// didn't find any creatures, so try to strike any walls // didn't find any creatures, so try to strike any walls
@ -60,7 +64,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack)
angle = player->mo->angle; angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget); slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("HammerPuff")); P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, hammertime);
macedone: macedone:
return 0; return 0;
} }

View file

@ -56,6 +56,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
int i; int i;
player_t *player; player_t *player;
AActor *linetarget; AActor *linetarget;
PClassActor *puff;
if (NULL == (player = self->player)) if (NULL == (player = self->player))
{ {
@ -66,13 +67,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
pmo = player->mo; pmo = player->mo;
damage = 20+(pr_staffcheck()&15); damage = 20+(pr_staffcheck()&15);
max = pmo->GetMaxHealth(); max = pmo->GetMaxHealth();
puff = PClass::FindActor("CStaffPuff");
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
angle = pmo->angle+i*(ANG45/16); angle = pmo->angle+i*(ANG45/16);
slope = P_AimLineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D); slope = P_AimLineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindActor("CStaffPuff")); P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, pmo->angle = R_PointToAngle2 (pmo->x, pmo->y,
linetarget->x, linetarget->y); linetarget->x, linetarget->y);
if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER) if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
@ -96,7 +98,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
slope = P_AimLineAttack (player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D); slope = P_AimLineAttack (player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindActor("CStaffPuff")); P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, pmo->angle = R_PointToAngle2 (pmo->x, pmo->y,
linetarget->x, linetarget->y); linetarget->x, linetarget->y);
if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER) if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)

View file

@ -242,27 +242,33 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack)
slope = P_AimLineAttack (pmo, angle, AXERANGE, &linetarget); slope = P_AimLineAttack (pmo, angle, AXERANGE, &linetarget);
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true); P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player) if (linetarget != NULL)
{ {
P_ThrustMobj (linetarget, angle, power); if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
{
P_ThrustMobj (linetarget, angle, power);
}
AdjustPlayerAngle (pmo, linetarget);
useMana++;
goto axedone;
} }
AdjustPlayerAngle (pmo, linetarget);
useMana++;
goto axedone;
} }
angle = pmo->angle-i*(ANG45/16); angle = pmo->angle-i*(ANG45/16);
slope = P_AimLineAttack (pmo, angle, AXERANGE, &linetarget); slope = P_AimLineAttack (pmo, angle, AXERANGE, &linetarget);
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true); P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
if (linetarget->flags3&MF3_ISMONSTER) if (linetarget != NULL)
{ {
P_ThrustMobj (linetarget, angle, power); if (linetarget->flags3&MF3_ISMONSTER)
{
P_ThrustMobj (linetarget, angle, power);
}
AdjustPlayerAngle (pmo, linetarget);
useMana++;
goto axedone;
} }
AdjustPlayerAngle (pmo, linetarget);
useMana++;
goto axedone;
} }
} }
// didn't find any creatures, so try to strike any walls // didn't find any creatures, so try to strike any walls

View file

@ -51,29 +51,35 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
{ {
angle = pmo->angle + i*(ANG45/32); angle = pmo->angle + i*(ANG45/32);
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D); slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
if (linetarget) if (linetarget != NULL)
{ {
P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true); P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
AdjustPlayerAngle(pmo, linetarget); if (linetarget != NULL)
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
{ {
P_ThrustMobj (linetarget, angle, power); AdjustPlayerAngle(pmo, linetarget);
if (linetarget->flags3 & MF3_ISMONSTER || linetarget->player)
{
P_ThrustMobj(linetarget, angle, power);
}
pmo->special1 = false; // Don't throw a hammer
goto hammerdone;
} }
pmo->special1 = false; // Don't throw a hammer
goto hammerdone;
} }
angle = pmo->angle-i*(ANG45/32); angle = pmo->angle-i*(ANG45/32);
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D); slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
if(linetarget) if (linetarget != NULL)
{ {
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true); P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
AdjustPlayerAngle(pmo, linetarget); if (linetarget != NULL)
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
{ {
P_ThrustMobj(linetarget, angle, power); AdjustPlayerAngle(pmo, linetarget);
if (linetarget->flags3 & MF3_ISMONSTER || linetarget->player)
{
P_ThrustMobj(linetarget, angle, power);
}
pmo->special1 = false; // Don't throw a hammer
goto hammerdone;
} }
pmo->special1 = false; // Don't throw a hammer
goto hammerdone;
} }
} }
// didn't find any targets in meleerange, so set to throw out a hammer // didn't find any targets in meleerange, so set to throw out a hammer

View file

@ -167,13 +167,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack)
power = 6*FRACUNIT; power = 6*FRACUNIT;
pufftype = PClass::FindActor("HammerPuff"); pufftype = PClass::FindActor("HammerPuff");
} }
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true); P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player) if (linetarget != NULL)
{ {
P_ThrustMobj (linetarget, angle, power); if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
{
P_ThrustMobj (linetarget, angle, power);
}
AdjustPlayerAngle (pmo, linetarget);
goto punchdone;
} }
AdjustPlayerAngle (pmo, linetarget);
goto punchdone;
} }
angle = pmo->angle-i * (ANG45/16); angle = pmo->angle-i * (ANG45/16);
slope = P_AimLineAttack (pmo, angle, 2*MELEERANGE, &linetarget); slope = P_AimLineAttack (pmo, angle, 2*MELEERANGE, &linetarget);
@ -186,13 +189,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack)
power = 6*FRACUNIT; power = 6*FRACUNIT;
pufftype = PClass::FindActor("HammerPuff"); pufftype = PClass::FindActor("HammerPuff");
} }
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true); P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player) if (linetarget != NULL)
{ {
P_ThrustMobj (linetarget, angle, power); if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
{
P_ThrustMobj (linetarget, angle, power);
}
AdjustPlayerAngle (pmo, linetarget);
goto punchdone;
} }
AdjustPlayerAngle (pmo, linetarget);
goto punchdone;
} }
} }
// didn't find any creatures, so try to strike any walls // didn't find any creatures, so try to strike any walls

View file

@ -83,7 +83,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FogMove)
if (self->args[3]-- <= 0) if (self->args[3]-- <= 0)
{ {
self->SetStateNF (self->FindState(NAME_Death)); self->SetState (self->FindState(NAME_Death), true);
return 0; return 0;
} }

View file

@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack)
damage = 3+(pr_snoutattack()&3); damage = 3+(pr_snoutattack()&3);
angle = player->mo->angle; angle = player->mo->angle;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE, &linetarget); slope = P_AimLineAttack(player->mo, angle, MELEERANGE, &linetarget);
puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true); puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true, &linetarget);
S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM); S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
if(linetarget) if(linetarget)
{ {

View file

@ -115,9 +115,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise)
{ // Reached it's target height { // Reached it's target height
actor->args[0] = 1; actor->args[0] = 1;
if (actor->args[1]) if (actor->args[1])
actor->SetStateNF (actor->FindState ("BloodThrustInit2")); actor->SetState (actor->FindState ("BloodThrustInit2"), true);
else else
actor->SetStateNF (actor->FindState ("ThrustInit2")); actor->SetState (actor->FindState ("ThrustInit2"), true);
} }
// Lose the dirt clump // Lose the dirt clump
@ -142,9 +142,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower)
{ {
self->args[0] = 0; self->args[0] = 0;
if (self->args[1]) if (self->args[1])
self->SetStateNF (self->FindState ("BloodThrustInit1")); self->SetState (self->FindState ("BloodThrustInit1"), true);
else else
self->SetStateNF (self->FindState ("ThrustInit1")); self->SetState (self->FindState ("ThrustInit1"), true);
} }
return 0; return 0;
} }

File diff suppressed because it is too large Load diff

View file

@ -419,15 +419,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
int cstype = SBarInfoScript[SCRIPT_CUSTOM]->GetGameType(); int cstype = SBarInfoScript[SCRIPT_CUSTOM]->GetGameType();
//Did the user specify a "base" //Did the user specify a "base"
if(cstype == GAME_Heretic) if(cstype == GAME_Strife)
{
StatusBar = CreateHereticStatusBar();
}
else if(cstype == GAME_Hexen)
{
StatusBar = CreateHexenStatusBar();
}
else if(cstype == GAME_Strife)
{ {
StatusBar = CreateStrifeStatusBar(); StatusBar = CreateStrifeStatusBar();
} }
@ -442,18 +434,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
} }
if (StatusBar == NULL) if (StatusBar == NULL)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.gametype & (GAME_DoomChex|GAME_Heretic|GAME_Hexen))
{ {
StatusBar = CreateCustomStatusBar (SCRIPT_DEFAULT); StatusBar = CreateCustomStatusBar (SCRIPT_DEFAULT);
} }
else if (gameinfo.gametype == GAME_Heretic)
{
StatusBar = CreateHereticStatusBar ();
}
else if (gameinfo.gametype == GAME_Hexen)
{
StatusBar = CreateHexenStatusBar ();
}
else if (gameinfo.gametype == GAME_Strife) else if (gameinfo.gametype == GAME_Strife)
{ {
StatusBar = CreateStrifeStatusBar (); StatusBar = CreateStrifeStatusBar ();
@ -545,10 +529,8 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
static FString nextlevel; static FString nextlevel;
static int startpos; // [RH] Support for multiple starts per level static int startpos; // [RH] Support for multiple starts per level
extern int NoWipe; // [RH] Don't wipe when travelling in hubs extern int NoWipe; // [RH] Don't wipe when travelling in hubs
static bool startkeepfacing; // [RH] Support for keeping your facing angle static int changeflags;
static bool resetinventory; // Reset the inventory to the player's default for the next level
static bool unloading; static bool unloading;
static bool g_nomonsters;
//========================================================================== //==========================================================================
// //
@ -559,8 +541,7 @@ static bool g_nomonsters;
//========================================================================== //==========================================================================
void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nextSkill, void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill)
bool nointermission, bool resetinv, bool nomonsters)
{ {
level_info_t *nextinfo = NULL; level_info_t *nextinfo = NULL;
@ -589,25 +570,32 @@ void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nex
if (nextSkill != -1) if (nextSkill != -1)
NextSkill = nextSkill; NextSkill = nextSkill;
g_nomonsters = nomonsters; if (flags & CHANGELEVEL_NOINTERMISSION)
{
if (nointermission) level.flags |= LEVEL_NOINTERMISSION; level.flags |= LEVEL_NOINTERMISSION;
}
cluster_info_t *thiscluster = FindClusterInfo (level.cluster); cluster_info_t *thiscluster = FindClusterInfo (level.cluster);
cluster_info_t *nextcluster = nextinfo? FindClusterInfo (nextinfo->cluster) : NULL; cluster_info_t *nextcluster = nextinfo? FindClusterInfo (nextinfo->cluster) : NULL;
startpos = position; startpos = position;
startkeepfacing = keepFacing;
gameaction = ga_completed; gameaction = ga_completed;
resetinventory = resetinv;
if (nextinfo != NULL) if (nextinfo != NULL)
{ {
if (thiscluster != nextcluster || (thiscluster && !(thiscluster->flags & CLUSTER_HUB))) if (thiscluster != nextcluster || (thiscluster && !(thiscluster->flags & CLUSTER_HUB)))
{ {
resetinventory |= !!(nextinfo->flags2 & LEVEL2_RESETINVENTORY); if (nextinfo->flags2 & LEVEL2_RESETINVENTORY)
{
flags |= CHANGELEVEL_RESETINVENTORY;
}
if (nextinfo->flags2 & LEVEL2_RESETHEALTH)
{
flags |= CHANGELEVEL_RESETHEALTH;
}
} }
} }
changeflags = flags;
bglobal.End(); //Added by MC: bglobal.End(); //Added by MC:
@ -683,12 +671,12 @@ const char *G_GetSecretExitMap()
void G_ExitLevel (int position, bool keepFacing) void G_ExitLevel (int position, bool keepFacing)
{ {
G_ChangeLevel(G_GetExitMap(), position, keepFacing); G_ChangeLevel(G_GetExitMap(), position, keepFacing ? CHANGELEVEL_KEEPFACING : 0);
} }
void G_SecretExitLevel (int position) void G_SecretExitLevel (int position)
{ {
G_ChangeLevel(G_GetSecretExitMap(), position, false); G_ChangeLevel(G_GetSecretExitMap(), position, 0);
} }
//========================================================================== //==========================================================================
@ -802,7 +790,7 @@ void G_DoCompleted (void)
{ {
if (playeringame[i]) if (playeringame[i])
{ // take away appropriate inventory { // take away appropriate inventory
G_PlayerFinishLevel (i, mode, resetinventory); G_PlayerFinishLevel (i, mode, changeflags);
} }
} }
@ -943,7 +931,7 @@ void G_DoLoadLevel (int position, bool autosave)
players[i].fragcount = 0; players[i].fragcount = 0;
} }
if (g_nomonsters) if (changeflags & CHANGELEVEL_NOMONSTERS)
{ {
level.flags2 |= LEVEL2_NOMONSTERS; level.flags2 |= LEVEL2_NOMONSTERS;
} }
@ -1180,7 +1168,7 @@ void G_FinishTravel ()
// The player being spawned here is a short lived dummy and // The player being spawned here is a short lived dummy and
// must not start any ENTER script or big problems will happen. // must not start any ENTER script or big problems will happen.
pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], true); pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], true);
if (!startkeepfacing) if (!changeflags & CHANGELEVEL_KEEPFACING)
{ {
pawn->angle = pawndup->angle; pawn->angle = pawndup->angle;
pawn->pitch = pawndup->pitch; pawn->pitch = pawndup->pitch;
@ -1476,8 +1464,8 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
P_SerializeThinkers (arc, hubLoad); P_SerializeThinkers (arc, hubLoad);
P_SerializeWorld (arc); P_SerializeWorld (arc);
P_SerializePolyobjs (arc); P_SerializePolyobjs (arc);
P_SerializeSubsectors(arc);
StatusBar->Serialize (arc); StatusBar->Serialize (arc);
//SerializeInterpolations (arc);
arc << level.total_monsters << level.total_items << level.total_secrets; arc << level.total_monsters << level.total_items << level.total_secrets;

View file

@ -127,6 +127,7 @@ enum ELevelFlags
LEVEL_SPECLOWERFLOOR = 0x00000100, LEVEL_SPECLOWERFLOOR = 0x00000100,
LEVEL_SPECOPENDOOR = 0x00000200, LEVEL_SPECOPENDOOR = 0x00000200,
LEVEL_SPECLOWERFLOORTOHIGHEST= 0x00000300,
LEVEL_SPECACTIONSMASK = 0x00000300, LEVEL_SPECACTIONSMASK = 0x00000300,
LEVEL_MONSTERSTELEFRAG = 0x00000400, LEVEL_MONSTERSTELEFRAG = 0x00000400,
@ -198,6 +199,7 @@ enum ELevelFlags
LEVEL2_SMOOTHLIGHTING = 0x01000000, // Level uses the smooth lighting feature. LEVEL2_SMOOTHLIGHTING = 0x01000000, // Level uses the smooth lighting feature.
LEVEL2_POLYGRIND = 0x02000000, // Polyobjects grind corpses to gibs. LEVEL2_POLYGRIND = 0x02000000, // Polyobjects grind corpses to gibs.
LEVEL2_RESETINVENTORY = 0x04000000, // Resets player inventory when starting this level (unless in a hub) LEVEL2_RESETINVENTORY = 0x04000000, // Resets player inventory when starting this level (unless in a hub)
LEVEL2_RESETHEALTH = 0x08000000, // Resets player health when starting this level (unless in a hub)
}; };
@ -236,6 +238,7 @@ struct FOptionalMapinfoDataPtr
}; };
typedef TMap<FName, FOptionalMapinfoDataPtr> FOptData; typedef TMap<FName, FOptionalMapinfoDataPtr> FOptData;
typedef TMap<int, FName> FMusicMap;
struct level_info_t struct level_info_t
{ {
@ -295,6 +298,7 @@ struct level_info_t
float teamdamage; float teamdamage;
FOptData optdata; FOptData optdata;
FMusicMap MusicMap;
TArray<FSpecialAction> specialactions; TArray<FSpecialAction> specialactions;
@ -486,8 +490,17 @@ void G_SecretExitLevel (int position);
const char *G_GetExitMap(); const char *G_GetExitMap();
const char *G_GetSecretExitMap(); const char *G_GetSecretExitMap();
void G_ChangeLevel(const char * levelname, int position, bool keepFacing, int nextSkill=-1, enum
bool nointermission=false, bool resetinventory=false, bool nomonsters=false); {
CHANGELEVEL_KEEPFACING = 1,
CHANGELEVEL_RESETINVENTORY = 2,
CHANGELEVEL_NOMONSTERS = 4,
CHANGELEVEL_CHANGESKILL = 8,
CHANGELEVEL_NOINTERMISSION = 16,
CHANGELEVEL_RESETHEALTH = 32,
};
void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill=-1);
void G_SetForEndGame (char *nextmap); void G_SetForEndGame (char *nextmap);
@ -533,9 +546,11 @@ enum ESkillProperty
SKILLP_ACSReturn, SKILLP_ACSReturn,
SKILLP_MonsterHealth, SKILLP_MonsterHealth,
SKILLP_FriendlyHealth, SKILLP_FriendlyHealth,
SKILLP_NoPain SKILLP_NoPain,
SKILLP_ArmorFactor
}; };
int G_SkillProperty(ESkillProperty prop); int G_SkillProperty(ESkillProperty prop);
const char * G_SkillName();
typedef TMap<FName, FString> SkillMenuNames; typedef TMap<FName, FString> SkillMenuNames;
@ -556,8 +571,8 @@ struct FSkillInfo
int SpawnFilter; int SpawnFilter;
int ACSReturn; int ACSReturn;
FString MenuName; FString MenuName;
FString PicName;
SkillMenuNames MenuNamesForPlayerClass; SkillMenuNames MenuNamesForPlayerClass;
bool MenuNameIsLump;
bool MustConfirm; bool MustConfirm;
FString MustConfirmText; FString MustConfirmText;
char Shortcut; char Shortcut;
@ -567,6 +582,7 @@ struct FSkillInfo
fixed_t MonsterHealth; fixed_t MonsterHealth;
fixed_t FriendlyHealth; fixed_t FriendlyHealth;
bool NoPain; bool NoPain;
fixed_t ArmorFactor;
FSkillInfo() {} FSkillInfo() {}
FSkillInfo(const FSkillInfo &other) FSkillInfo(const FSkillInfo &other)

View file

@ -51,6 +51,8 @@
#include "doomstat.h" #include "doomstat.h"
#include "d_player.h" #include "d_player.h"
#include "autosegs.h" #include "autosegs.h"
#include "version.h"
#include "v_text.h"
int FindEndSequence (int type, const char *picname); int FindEndSequence (int type, const char *picname);
@ -1324,6 +1326,7 @@ MapFlagHandlers[] =
{ "specialaction_exitlevel", MITYPE_SCFLAGS, 0, ~LEVEL_SPECACTIONSMASK }, { "specialaction_exitlevel", MITYPE_SCFLAGS, 0, ~LEVEL_SPECACTIONSMASK },
{ "specialaction_opendoor", MITYPE_SCFLAGS, LEVEL_SPECOPENDOOR, ~LEVEL_SPECACTIONSMASK }, { "specialaction_opendoor", MITYPE_SCFLAGS, LEVEL_SPECOPENDOOR, ~LEVEL_SPECACTIONSMASK },
{ "specialaction_lowerfloor", MITYPE_SCFLAGS, LEVEL_SPECLOWERFLOOR, ~LEVEL_SPECACTIONSMASK }, { "specialaction_lowerfloor", MITYPE_SCFLAGS, LEVEL_SPECLOWERFLOOR, ~LEVEL_SPECACTIONSMASK },
{ "specialaction_lowerfloortohighest",MITYPE_SCFLAGS,LEVEL_SPECLOWERFLOORTOHIGHEST, ~LEVEL_SPECACTIONSMASK },
{ "specialaction_killmonsters", MITYPE_SETFLAG, LEVEL_SPECKILLMONSTERS, 0 }, { "specialaction_killmonsters", MITYPE_SETFLAG, LEVEL_SPECKILLMONSTERS, 0 },
{ "lightning", MITYPE_SETFLAG, LEVEL_STARTLIGHTNING, 0 }, { "lightning", MITYPE_SETFLAG, LEVEL_STARTLIGHTNING, 0 },
{ "smoothlighting", MITYPE_SETFLAG2, LEVEL2_SMOOTHLIGHTING, 0 }, { "smoothlighting", MITYPE_SETFLAG2, LEVEL2_SMOOTHLIGHTING, 0 },
@ -1372,6 +1375,7 @@ MapFlagHandlers[] =
{ "grinding_polyobj", MITYPE_SETFLAG2, LEVEL2_POLYGRIND, 0 }, { "grinding_polyobj", MITYPE_SETFLAG2, LEVEL2_POLYGRIND, 0 },
{ "no_grinding_polyobj", MITYPE_CLRFLAG2, LEVEL2_POLYGRIND, 0 }, { "no_grinding_polyobj", MITYPE_CLRFLAG2, LEVEL2_POLYGRIND, 0 },
{ "resetinventory", MITYPE_SETFLAG2, LEVEL2_RESETINVENTORY, 0 }, { "resetinventory", MITYPE_SETFLAG2, LEVEL2_RESETINVENTORY, 0 },
{ "resethealth", MITYPE_SETFLAG2, LEVEL2_RESETHEALTH, 0 },
{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2, LEVEL2_CONV_SINGLE_UNFREEZE, 0 }, { "unfreezesingleplayerconversations",MITYPE_SETFLAG2, LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes { "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
{ "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX}, { "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX},
@ -1399,6 +1403,8 @@ MapFlagHandlers[] =
{ "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS}, { "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS},
{ "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS}, { "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS},
{ "compat_spritesort", MITYPE_COMPATFLAG, COMPATF_SPRITESORT}, { "compat_spritesort", MITYPE_COMPATFLAG, COMPATF_SPRITESORT},
{ "compat_light", MITYPE_COMPATFLAG, COMPATF_LIGHT},
{ "compat_polyobj", MITYPE_COMPATFLAG, COMPATF_POLYOBJ},
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 }, { "cd_start_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end2_track", MITYPE_EATNEXT, 0, 0 },
@ -1799,6 +1805,7 @@ void FMapInfoParser::ParseEpisodeInfo ()
EpisodeMenu[i].fulltext = !picisgfx; EpisodeMenu[i].fulltext = !picisgfx;
EpisodeNoSkill[i] = noskill; EpisodeNoSkill[i] = noskill;
strncpy (EpisodeMaps[i], map, 8); strncpy (EpisodeMaps[i], map, 8);
EpisodeMaps[i][8] = 0;
} }
} }
@ -1861,6 +1868,15 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i
{ {
sc.ScriptError("include file '%s' not found", sc.String); sc.ScriptError("include file '%s' not found", sc.String);
} }
if (Wads.GetLumpFile(sc.LumpNum) != Wads.GetLumpFile(inclump))
{
// Do not allow overriding includes from the default MAPINFO
if (Wads.GetLumpFile(sc.LumpNum) == 0)
{
I_FatalError("File %s is overriding core lump %s.",
Wads.GetWadFullName(Wads.GetLumpFile(inclump)), sc.String);
}
}
FScanner saved_sc = sc; FScanner saved_sc = sc;
ParseMapInfo(inclump, gamedefaults, defaultinfo); ParseMapInfo(inclump, gamedefaults, defaultinfo);
sc = saved_sc; sc = saved_sc;
@ -1952,12 +1968,18 @@ void G_ParseMapInfo (const char *basemapinfo)
atterm(ClearEpisodes); atterm(ClearEpisodes);
// Parse the default MAPINFO for the current game. // Parse the default MAPINFO for the current game. This lump *MUST* come from zdoom.pk3.
if (basemapinfo != NULL) if (basemapinfo != NULL)
{ {
FMapInfoParser parse; FMapInfoParser parse;
level_info_t defaultinfo; level_info_t defaultinfo;
parse.ParseMapInfo(Wads.GetNumForFullName(basemapinfo), gamedefaults, defaultinfo); int baselump = Wads.GetNumForFullName(basemapinfo);
if (Wads.GetLumpFile(baselump) > 0)
{
I_FatalError("File %s is overriding core lump %s.",
Wads.GetWadFullName(Wads.GetLumpFile(baselump)), basemapinfo);
}
parse.ParseMapInfo(baselump, gamedefaults, defaultinfo);
} }
static const char *mapinfonames[] = { "MAPINFO", "ZMAPINFO", NULL }; static const char *mapinfonames[] = { "MAPINFO", "ZMAPINFO", NULL };

View file

@ -200,7 +200,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
&& pr_minotaurdecide() < 150) && pr_minotaurdecide() < 150)
{ // Charge attack { // Charge attack
// Don't call the state function right away // Don't call the state function right away
self->SetStateNF (self->FindState ("Charge")); self->SetState (self->FindState ("Charge"), true);
self->flags |= MF_SKULLFLY; self->flags |= MF_SKULLFLY;
if (!friendly) if (!friendly)
{ // Heretic's Minotaur is invulnerable during charge attack { // Heretic's Minotaur is invulnerable during charge attack
@ -473,9 +473,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurRoam)
{ {
// Turn // Turn
if (pr_minotaurroam() & 1) if (pr_minotaurroam() & 1)
self->movedir = (++self->movedir)%8; self->movedir = (self->movedir + 1) % 8;
else else
self->movedir = (self->movedir+7)%8; self->movedir = (self->movedir + 7) % 8;
FaceMovementDirection (self); FaceMovementDirection (self);
} }
return 0; return 0;
@ -552,11 +552,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
if (self->target) if (self->target)
{ {
self->SetStateNF (self->SeeState); self->SetState (self->SeeState, true);
} }
else else
{ {
self->SetStateNF (self->FindState ("Roam")); self->SetState (self->FindState ("Roam"), true);
} }
return 0; return 0;
} }

View file

@ -57,10 +57,8 @@ IMPLEMENT_CLASS (ASwitchingDecoration)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking) void A_Unblock(AActor *self, bool drop)
{ {
PARAM_ACTION_PROLOGUE;
// [RH] Andy Baker's stealth monsters // [RH] Andy Baker's stealth monsters
if (self->flags & MF_STEALTH) if (self->flags & MF_STEALTH)
{ {
@ -70,18 +68,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
self->flags &= ~MF_SOLID; self->flags &= ~MF_SOLID;
// If the self has a conversation that sets an item to drop, drop that. // If the actor has a conversation that sets an item to drop, drop that.
if (self->Conversation != NULL && self->Conversation->DropType != NULL) if (self->Conversation != NULL && self->Conversation->DropType != NULL)
{ {
P_DropItem (self, self->Conversation->DropType, -1, 256); P_DropItem (self, self->Conversation->DropType, -1, 256);
self->Conversation = NULL; self->Conversation = NULL;
return 0; return;
} }
self->Conversation = NULL; self->Conversation = NULL;
// If the self has attached metadata for items to drop, drop those. // If the actor has attached metadata for items to drop, drop those.
if (!self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB] if (drop && !self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
{ {
DDropItem *di = self->GetDropItems(); DDropItem *di = self->GetDropItems();
@ -101,14 +99,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
} }
} }
} }
}
DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
{
PARAM_ACTION_PROLOGUE;
A_Unblock(self, true);
return 0; return 0;
} }
DEFINE_ACTION_FUNCTION(AActor, A_Fall) DEFINE_ACTION_FUNCTION(AActor, A_Fall)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
A_Unblock(self, true);
CALL_ACTION(A_NoBlocking, self);
return 0; return 0;
} }
@ -332,7 +335,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
{ {
CALL_ACTION(A_BossDeath, self); CALL_ACTION(A_BossDeath, self);
} }
CALL_ACTION(A_NoBlocking, self); A_Unblock(self, true);
self->SetState(self->FindState(NAME_Null)); self->SetState(self->FindState(NAME_Null));
return 0; return 0;

View file

@ -5,6 +5,7 @@
#include "r_data.h" #include "r_data.h"
#include "a_pickups.h" #include "a_pickups.h"
#include "templates.h" #include "templates.h"
#include "g_level.h"
IMPLEMENT_CLASS (AArmor) IMPLEMENT_CLASS (AArmor)
@ -84,6 +85,18 @@ bool ABasicArmor::HandlePickup (AInventory *item)
// You shouldn't be picking up BasicArmor anyway. // You shouldn't be picking up BasicArmor anyway.
return true; return true;
} }
if (item->IsKindOf(RUNTIME_CLASS(ABasicArmorBonus)) && !(item->ItemFlags & IF_IGNORESKILL))
{
ABasicArmorBonus *armor = static_cast<ABasicArmorBonus*>(item);
armor->SaveAmount = FixedMul(armor->SaveAmount, G_SkillProperty(SKILLP_ArmorFactor));
}
else if (item->IsKindOf(RUNTIME_CLASS(ABasicArmorPickup)) && !(item->ItemFlags & IF_IGNORESKILL))
{
ABasicArmorPickup *armor = static_cast<ABasicArmorPickup*>(item);
armor->SaveAmount = FixedMul(armor->SaveAmount, G_SkillProperty(SKILLP_ArmorFactor));
}
if (Inventory != NULL) if (Inventory != NULL)
{ {
return Inventory->HandlePickup (item); return Inventory->HandlePickup (item);
@ -198,10 +211,17 @@ void ABasicArmorPickup::Serialize (FArchive &arc)
AInventory *ABasicArmorPickup::CreateCopy (AActor *other) AInventory *ABasicArmorPickup::CreateCopy (AActor *other)
{ {
ABasicArmorPickup *copy = static_cast<ABasicArmorPickup *> (Super::CreateCopy (other)); ABasicArmorPickup *copy = static_cast<ABasicArmorPickup *> (Super::CreateCopy (other));
if (!(ItemFlags & IF_IGNORESKILL))
{
SaveAmount = FixedMul(SaveAmount, G_SkillProperty(SKILLP_ArmorFactor));
}
copy->SavePercent = SavePercent; copy->SavePercent = SavePercent;
copy->SaveAmount = SaveAmount; copy->SaveAmount = SaveAmount;
copy->MaxAbsorb = MaxAbsorb; copy->MaxAbsorb = MaxAbsorb;
copy->MaxFullAbsorb = MaxFullAbsorb; copy->MaxFullAbsorb = MaxFullAbsorb;
return copy; return copy;
} }
@ -272,6 +292,12 @@ void ABasicArmorBonus::Serialize (FArchive &arc)
AInventory *ABasicArmorBonus::CreateCopy (AActor *other) AInventory *ABasicArmorBonus::CreateCopy (AActor *other)
{ {
ABasicArmorBonus *copy = static_cast<ABasicArmorBonus *> (Super::CreateCopy (other)); ABasicArmorBonus *copy = static_cast<ABasicArmorBonus *> (Super::CreateCopy (other));
if (!(ItemFlags & IF_IGNORESKILL))
{
SaveAmount = FixedMul(SaveAmount, G_SkillProperty(SKILLP_ArmorFactor));
}
copy->SavePercent = SavePercent; copy->SavePercent = SavePercent;
copy->SaveAmount = SaveAmount; copy->SaveAmount = SaveAmount;
copy->MaxSaveAmount = MaxSaveAmount; copy->MaxSaveAmount = MaxSaveAmount;
@ -279,6 +305,7 @@ AInventory *ABasicArmorBonus::CreateCopy (AActor *other)
copy->BonusMax = BonusMax; copy->BonusMax = BonusMax;
copy->MaxAbsorb = MaxAbsorb; copy->MaxAbsorb = MaxAbsorb;
copy->MaxFullAbsorb = MaxFullAbsorb; copy->MaxFullAbsorb = MaxFullAbsorb;
return copy; return copy;
} }

View file

@ -750,10 +750,6 @@ void APowerIronFeet::AbsorbDamage (int damage, FName damageType, int &newdamage)
if (damageType == NAME_Drowning) if (damageType == NAME_Drowning)
{ {
newdamage = 0; newdamage = 0;
if (Owner->player != NULL)
{
Owner->player->mo->ResetAirSupply ();
}
} }
else if (Inventory != NULL) else if (Inventory != NULL)
{ {
@ -761,6 +757,21 @@ void APowerIronFeet::AbsorbDamage (int damage, FName damageType, int &newdamage)
} }
} }
//===========================================================================
//
// APowerIronFeet :: DoEffect
//
//===========================================================================
void APowerIronFeet::DoEffect ()
{
if (Owner->player != NULL)
{
Owner->player->mo->ResetAirSupply ();
}
}
// Strife Environment Suit Powerup ------------------------------------------- // Strife Environment Suit Powerup -------------------------------------------
IMPLEMENT_CLASS (APowerMask) IMPLEMENT_CLASS (APowerMask)
@ -993,6 +1004,12 @@ void APowerFlight::EndEffect ()
bool APowerFlight::DrawPowerup (int x, int y) bool APowerFlight::DrawPowerup (int x, int y)
{ {
// If this item got a valid icon use that instead of the default spinning wings.
if (Icon.isValid())
{
return Super::DrawPowerup(x, y);
}
if (EffectTics > BLINKTHRESHOLD || !(EffectTics & 16)) if (EffectTics > BLINKTHRESHOLD || !(EffectTics & 16))
{ {
FTextureID picnum = TexMan.CheckForTexture ("SPFLY0", FTexture::TEX_MiscPatch); FTextureID picnum = TexMan.CheckForTexture ("SPFLY0", FTexture::TEX_MiscPatch);

View file

@ -86,6 +86,7 @@ class APowerIronFeet : public APowerup
DECLARE_CLASS (APowerIronFeet, APowerup) DECLARE_CLASS (APowerIronFeet, APowerup)
public: public:
void AbsorbDamage (int damage, FName damageType, int &newdamage); void AbsorbDamage (int damage, FName damageType, int &newdamage);
void DoEffect ();
}; };
class APowerMask : public APowerIronFeet class APowerMask : public APowerIronFeet

View file

@ -72,7 +72,7 @@ void AFastProjectile::Tick ()
tm.LastRipped = NULL; // [RH] Do rip damage each step, like Hexen tm.LastRipped = NULL; // [RH] Do rip damage each step, like Hexen
} }
if (!P_TryMove (this, x + xfrac,y + yfrac, true, false, tm)) if (!P_TryMove (this, x + xfrac,y + yfrac, true, NULL, tm))
{ // Blocked move { // Blocked move
if (!(flags3 & MF3_SKYEXPLODE)) if (!(flags3 & MF3_SKYEXPLODE))
{ {
@ -158,10 +158,13 @@ void AFastProjectile::Effect()
if (name != NAME_None) if (name != NAME_None)
{ {
fixed_t hitz = z-8*FRACUNIT; fixed_t hitz = z-8*FRACUNIT;
if (hitz < floorz) if (hitz < floorz)
{ {
hitz = floorz; hitz = floorz;
} }
// Do not clip this offset to the floor.
hitz += GetClass()->MissileHeight;
PClassActor *trail = PClass::FindActor(name); PClassActor *trail = PClass::FindActor(name);
if (trail != NULL) if (trail != NULL)

View file

@ -19,7 +19,12 @@ struct OneKey
bool check(AActor *owner) bool check(AActor *owner)
{ {
return !!owner->FindInventory(key); // P_GetMapColorForKey() checks the key directly
if (owner->IsKindOf (RUNTIME_CLASS(AKey)))
return owner->IsA(key);
// Other calls check an actor that may have a key in its inventory.
else
return !!owner->FindInventory(key);
} }
}; };

View file

@ -99,15 +99,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
p->morphTics = (duration) ? duration : MORPHTICS; p->morphTics = (duration) ? duration : MORPHTICS;
// [MH] Used by SBARINFO to speed up face drawing // [MH] Used by SBARINFO to speed up face drawing
p->MorphedPlayerClass = 0; p->MorphedPlayerClass = spawntype;
for (unsigned int i = 1; i < PlayerClasses.Size(); i++)
{
if (PlayerClasses[i].Type == spawntype)
{
p->MorphedPlayerClass = i;
break;
}
}
p->MorphStyle = style; p->MorphStyle = style;
p->MorphExitFlash = (exit_flash) ? exit_flash : RUNTIME_CLASS(ATeleportFog); p->MorphExitFlash = (exit_flash) ? exit_flash : RUNTIME_CLASS(ATeleportFog);
@ -149,19 +141,6 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
p->camera = morphed; p->camera = morphed;
} }
morphed->ScoreIcon = actor->ScoreIcon; // [GRB] morphed->ScoreIcon = actor->ScoreIcon; // [GRB]
// [MH]
// If the player that was morphed is the one
// taking events, set up the face, if any;
// this is only needed for old-skool skins
// and for the original DOOM status bar.
if (p == &players[consoleplayer])
{
if (spawntype->Face.IsNotEmpty() && strcmp(spawntype->Face, "None") != 0)
{
StatusBar->SetFace(&skins[p->MorphedPlayerClass]);
}
}
return true; return true;
} }
@ -307,7 +286,6 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
} }
} }
} }
StatusBar->SetFace(&skins[skinindex]);
} }
} }

View file

@ -401,6 +401,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition)
self->z += FloatBobOffsets[(self->FloatBobPhase + level.maptime) & 63]; self->z += FloatBobOffsets[(self->FloatBobPhase + level.maptime) & 63];
} }
} }
self->SetOrigin (self->x, self->y, self->z);
return 0; return 0;
} }
@ -935,7 +936,7 @@ void AInventory::Touch (AActor *toucher)
{ {
const char * message = PickupMessage (); const char * message = PickupMessage ();
if (toucher->CheckLocalView (consoleplayer) if (message != NULL && *message != 0 && toucher->CheckLocalView (consoleplayer)
&& (StaticLastMessageTic != gametic || StaticLastMessage != message)) && (StaticLastMessageTic != gametic || StaticLastMessage != message))
{ {
StaticLastMessageTic = gametic; StaticLastMessageTic = gametic;

View file

@ -23,7 +23,7 @@ public:
bool AddWeapon (const char *type); bool AddWeapon (const char *type);
bool AddWeapon (PClassWeapon *type); bool AddWeapon (PClassWeapon *type);
void AddWeaponList (const char *list, bool clear); void AddWeaponList (const char *list, bool clear);
AWeapon *PickWeapon (player_t *player); AWeapon *PickWeapon (player_t *player, bool checkammo = false);
int Size () const { return (int)Weapons.Size(); } int Size () const { return (int)Weapons.Size(); }
int LocateWeapon (PClassWeapon *type); int LocateWeapon (PClassWeapon *type);

View file

@ -124,6 +124,7 @@ class ARandomSpawner : public AActor
{ {
// copy everything relevant // copy everything relevant
newmobj->SpawnAngle = newmobj->angle = angle; newmobj->SpawnAngle = newmobj->angle = angle;
newmobj->SpawnPoint[2] = SpawnPoint[2];
newmobj->special = special; newmobj->special = special;
newmobj->args[0] = args[0]; newmobj->args[0] = args[0];
newmobj->args[1] = args[1]; newmobj->args[1] = args[1];
@ -147,10 +148,10 @@ class ARandomSpawner : public AActor
// a health set to -2 after spawning, for internal reasons. // a health set to -2 after spawning, for internal reasons.
if (health != SpawnHealth()) newmobj->health = health; if (health != SpawnHealth()) newmobj->health = health;
if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED; if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED;
// Handle special altitude flags // Handle special altitude flags
if (newmobj->flags & MF_SPAWNCEILING) if (newmobj->flags & MF_SPAWNCEILING)
{ {
newmobj->z = newmobj->ceilingz - newmobj->height; newmobj->z = newmobj->ceilingz - newmobj->height - SpawnPoint[2];
} }
else if (newmobj->flags2 & MF2_SPAWNFLOAT) else if (newmobj->flags2 & MF2_SPAWNFLOAT)
{ {
@ -160,6 +161,7 @@ class ARandomSpawner : public AActor
space -= 40*FRACUNIT; space -= 40*FRACUNIT;
newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT; newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT;
} }
newmobj->z += SpawnPoint[2];
} }
if (newmobj->flags & MF_MISSILE) if (newmobj->flags & MF_MISSILE)
P_CheckMissileSpawn(newmobj); P_CheckMissileSpawn(newmobj);

View file

@ -147,14 +147,20 @@ struct FSpotList
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ASpecialSpot *GetSpotWithMinDistance(fixed_t x, fixed_t y, fixed_t distance) ASpecialSpot *GetSpotWithMinMaxDistance(fixed_t x, fixed_t y, fixed_t mindist, fixed_t maxdist)
{ {
if (Spots.Size() == 0) return NULL; if (Spots.Size() == 0) return NULL;
int i = pr_spot() % Spots.Size(); int i = pr_spot() % Spots.Size();
int initial = i; int initial = i;
while (P_AproxDistance(Spots[i]->x - x, Spots[i]->y - y) < distance) fixed_t distance;
while (true)
{ {
distance = P_AproxDistance(Spots[i]->x - x, Spots[i]->y - y);
if ((distance >= mindist) && ((maxdist == 0) || (distance <= maxdist))) break;
i = (i+1) % Spots.Size(); i = (i+1) % Spots.Size();
if (i == initial) return NULL; if (i == initial) return NULL;
} }
@ -329,10 +335,10 @@ ASpecialSpot *DSpotState::GetNextInList(const PClass *type, int skipcounter)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ASpecialSpot *DSpotState::GetSpotWithMinDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t distance) ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t mindist, fixed_t maxdist)
{ {
FSpotList *list = FindSpotList(type); FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetSpotWithMinDistance(x, y, distance); if (list != NULL) return list->GetSpotWithMinMaxDistance(x, y, mindist, maxdist);
return NULL; return NULL;
} }

View file

@ -36,7 +36,7 @@ public:
bool RemoveSpot(ASpecialSpot *spot); bool RemoveSpot(ASpecialSpot *spot);
void Serialize(FArchive &arc); void Serialize(FArchive &arc);
ASpecialSpot *GetNextInList(const PClass *type, int skipcounter); ASpecialSpot *GetNextInList(const PClass *type, int skipcounter);
ASpecialSpot *GetSpotWithMinDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t distance); ASpecialSpot *GetSpotWithMinMaxDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t mindist, fixed_t maxdist);
ASpecialSpot *GetRandomSpot(const PClass *type, bool onlyonce = false); ASpecialSpot *GetRandomSpot(const PClass *type, bool onlyonce = false);
}; };

View file

@ -771,7 +771,7 @@ int FWeaponSlot::LocateWeapon(PClassWeapon *type)
// //
//=========================================================================== //===========================================================================
AWeapon *FWeaponSlot::PickWeapon(player_t *player) AWeapon *FWeaponSlot::PickWeapon(player_t *player, bool checkammo)
{ {
int i, j; int i, j;
@ -795,9 +795,12 @@ AWeapon *FWeaponSlot::PickWeapon(player_t *player)
{ {
AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory(Weapons[j].Type)); AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory(Weapons[j].Type));
if (weap != NULL && weap->IsKindOf(RUNTIME_CLASS(AWeapon)) && weap->CheckAmmo(AWeapon::EitherFire, false)) if (weap != NULL && weap->IsKindOf(RUNTIME_CLASS(AWeapon)))
{ {
return weap; if (!checkammo || weap->CheckAmmo(AWeapon::EitherFire, false))
{
return weap;
}
} }
} }
} }
@ -807,9 +810,12 @@ AWeapon *FWeaponSlot::PickWeapon(player_t *player)
{ {
AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory(Weapons[i].Type)); AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory(Weapons[i].Type));
if (weap != NULL && weap->IsKindOf(RUNTIME_CLASS(AWeapon)) && weap->CheckAmmo(AWeapon::EitherFire, false)) if (weap != NULL && weap->IsKindOf(RUNTIME_CLASS(AWeapon)))
{ {
return weap; if (!checkammo || weap->CheckAmmo(AWeapon::EitherFire, false))
{
return weap;
}
} }
} }
return player->ReadyWeapon; return player->ReadyWeapon;

View file

@ -165,7 +165,7 @@ struct FMugShotFrame
FMugShotFrame(); FMugShotFrame();
~FMugShotFrame(); ~FMugShotFrame();
FTexture *GetTexture(const char *default_face, FPlayerSkin *skin, int random, int level=0, FTexture *GetTexture(const char *default_face, const char *skin_face, int random, int level=0,
int direction=0, bool usesLevels=false, bool health2=false, bool healthspecial=false, int direction=0, bool usesLevels=false, bool health2=false, bool healthspecial=false,
bool directional=false); bool directional=false);
}; };
@ -189,9 +189,9 @@ struct FMugShotState
void Tick(); void Tick();
void Reset(); void Reset();
FMugShotFrame &GetCurrentFrame() { return Frames[Position]; } FMugShotFrame &GetCurrentFrame() { return Frames[Position]; }
FTexture *GetCurrentFrameTexture(const char *default_face, FPlayerSkin *skin, int level=0, int direction=0) FTexture *GetCurrentFrameTexture(const char *default_face, const char *skin_face, int level=0, int direction=0)
{ {
return GetCurrentFrame().GetTexture(default_face, skin, Random, level, direction, bUsesLevels, bHealth2, bHealthSpecial, bDirectional); return GetCurrentFrame().GetTexture(default_face, skin_face, Random, level, direction, bUsesLevels, bHealth2, bHealthSpecial, bDirectional);
} }
private: private:
FMugShotState(); FMugShotState();
@ -215,6 +215,7 @@ class FMugShot
FMugShot(); FMugShot();
void Grin(bool grin=true) { bEvilGrin = grin; } void Grin(bool grin=true) { bEvilGrin = grin; }
void Reset();
void Tick(player_t *player); void Tick(player_t *player);
bool SetState(const char *state_name, bool wait_till_done=false, bool reset=false); bool SetState(const char *state_name, bool wait_till_done=false, bool reset=false);
int UpdateState(player_t *player, StateFlags stateflags=STANDARD); int UpdateState(player_t *player, StateFlags stateflags=STANDARD);
@ -275,7 +276,7 @@ public:
ST_DEADFACE = ST_GODFACE + 1 ST_DEADFACE = ST_GODFACE + 1
}; };
DBaseStatusBar (int reltop); DBaseStatusBar (int reltop, int hres=320, int vres=200);
void Destroy (); void Destroy ();
void SetScaled (bool scale, bool force=false); void SetScaled (bool scale, bool force=false);
@ -300,8 +301,6 @@ public:
virtual void AttachToPlayer (player_t *player); virtual void AttachToPlayer (player_t *player);
virtual void FlashCrosshair (); virtual void FlashCrosshair ();
virtual void BlendView (float blend[4]); virtual void BlendView (float blend[4]);
virtual void SetFace (void *skn); // Takes a FPlayerSkin as input
virtual void AddFaceToImageCollection (void *skn, FImageCollection *images); // Takes a FPlayerSkin as input
virtual void NewGame (); virtual void NewGame ();
virtual void ScreenSizeChanged (); virtual void ScreenSizeChanged ();
virtual void MultiplayerChanged (); virtual void MultiplayerChanged ();
@ -334,14 +333,13 @@ protected:
void GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const; void GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const;
void AddFaceToImageCollectionActual (void *skn, FImageCollection *images, bool isDoom);
public: public:
AInventory *ValidateInvFirst (int numVisible) const; AInventory *ValidateInvFirst (int numVisible) const;
void DrawCrosshair (); void DrawCrosshair ();
int ST_X, ST_Y; int ST_X, ST_Y;
int RelTop; int RelTop;
int HorizontalResolution, VirticalResolution;
bool Scaled; bool Scaled;
bool Centering; bool Centering;
bool FixedOrigin; bool FixedOrigin;
@ -378,8 +376,6 @@ extern DBaseStatusBar *StatusBar;
// Status bar factories ----------------------------------------------------- // Status bar factories -----------------------------------------------------
DBaseStatusBar *CreateHereticStatusBar();
DBaseStatusBar *CreateHexenStatusBar();
DBaseStatusBar *CreateStrifeStatusBar(); DBaseStatusBar *CreateStrifeStatusBar();
DBaseStatusBar *CreateCustomStatusBar(int script=0); DBaseStatusBar *CreateCustomStatusBar(int script=0);

View file

@ -76,7 +76,7 @@ FMugShotFrame::~FMugShotFrame()
// //
//=========================================================================== //===========================================================================
FTexture *FMugShotFrame::GetTexture(const char *default_face, FPlayerSkin *skin, int random, int level, FTexture *FMugShotFrame::GetTexture(const char *default_face, const char *skin_face, int random, int level,
int direction, bool uses_levels, bool health2, bool healthspecial, bool directional) int direction, bool uses_levels, bool health2, bool healthspecial, bool directional)
{ {
int index = !directional ? random % Graphic.Size() : direction; int index = !directional ? random % Graphic.Size() : direction;
@ -84,7 +84,7 @@ FTexture *FMugShotFrame::GetTexture(const char *default_face, FPlayerSkin *skin,
{ {
index = Graphic.Size() - 1; index = Graphic.Size() - 1;
} }
FString sprite(skin->face[0] != 0 ? skin->face : default_face, 3); FString sprite(skin_face != NULL && skin_face[0] != 0 ? skin_face : default_face, 3);
sprite += Graphic[index]; sprite += Graphic[index];
if (uses_levels) //change the last character to the level if (uses_levels) //change the last character to the level
{ {
@ -221,6 +221,17 @@ int FindMugShotStateIndex(FName state)
//=========================================================================== //===========================================================================
FMugShot::FMugShot() FMugShot::FMugShot()
{
Reset();
}
//===========================================================================
//
// FMugShot :: Reset
//
//===========================================================================
void FMugShot::Reset()
{ {
FaceHealth = -1; FaceHealth = -1;
bEvilGrin = false; bEvilGrin = false;
@ -492,8 +503,8 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
} }
if (CurrentState != NULL) if (CurrentState != NULL)
{ {
FPlayerSkin *skin = &skins[player->morphTics ? player->MorphedPlayerClass : player->userinfo.skin]; const char *skin_face = player->morphTics ? player->MorphedPlayerClass->Face : skins[player->userinfo.skin].face;
return CurrentState->GetCurrentFrameTexture(default_face, skin, level, angle); return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
} }
return NULL; return NULL;
} }

View file

@ -57,16 +57,8 @@
#include "g_level.h" #include "g_level.h"
#include "v_palette.h" #include "v_palette.h"
#include "p_acs.h" #include "p_acs.h"
#include "gstrings.h"
#define ADJUST_RELCENTER(x, y, outX, outY) \ #include "version.h"
if(x.RelCenter()) \
outX = *x + SCREENWIDTH/(hud_scale ? CleanXfac*2 : 2); \
else \
outX = *x; \
if(y.RelCenter()) \
outY = *y + SCREENHEIGHT/(hud_scale ? CleanYfac*2 : 2); \
else \
outY = *y;
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6) #define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
enum enum
@ -189,8 +181,8 @@ class SBarInfoCommand
} }
} }
if(!fullScreenOffsets) //if(!fullScreenOffsets)
y.SetCoord((negative ? -sc.Number : sc.Number) - (200 - script->height)); // y.SetCoord((negative ? -sc.Number : sc.Number) - (200 - script->height));
} }
EColorRange GetTranslation(FScanner &sc) EColorRange GetTranslation(FScanner &sc)
{ {
@ -213,60 +205,107 @@ class SBarInfoCommand
class SBarInfoCommandFlowControl : public SBarInfoCommand class SBarInfoCommandFlowControl : public SBarInfoCommand
{ {
public: public:
SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script) {} SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script), truth(false) {}
~SBarInfoCommandFlowControl() ~SBarInfoCommandFlowControl()
{ {
for(unsigned int i = 0;i < commands.Size();i++) for(unsigned int i = 0;i < 2;i++)
delete commands[i]; {
for(unsigned int j = 0;j < commands[i].Size();j++)
delete commands[i][j];
}
} }
void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar)
{ {
for(unsigned int i = 0;i < commands.Size();i++) for(unsigned int i = 0;i < commands[truth].Size();i++)
commands[i]->Draw(block, statusBar); commands[truth][i]->Draw(block, statusBar);
} }
int NumCommands() const { return commands.Size(); } int NumCommands() const { return commands[truth].Size(); }
void Parse(FScanner &sc, bool fullScreenOffsets) void Parse(FScanner &sc, bool fullScreenOffsets)
{ {
sc.MustGetToken('{'); bool elseBlock = false;
SBarInfoCommand *cmd = NULL; SBarInfoCommand *cmd = NULL;
while((cmd = NextCommand(sc)) != NULL) // Should loop no more than twice.
while(true)
{ {
cmd->Parse(sc, fullScreenOffsets); if(sc.CheckToken('{'))
commands.Push(cmd); {
while((cmd = NextCommand(sc)) != NULL)
{
cmd->Parse(sc, fullScreenOffsets);
commands[!elseBlock].Push(cmd);
}
}
else
{
if((cmd = NextCommand(sc)) != NULL)
{
cmd->Parse(sc, fullScreenOffsets);
commands[!elseBlock].Push(cmd);
}
else
sc.ScriptError("Missing command for flow control statement.");
}
if(!elseBlock && sc.CheckToken(TK_Else))
{
elseBlock = true;
continue;
}
break;
} }
} }
void Reset() void Reset()
{ {
for(unsigned int i = 0;i < commands.Size();i++) for(unsigned int i = 0;i < 2;i++)
commands[i]->Reset(); {
for(unsigned int j = 0;j < commands[i].Size();j++)
commands[i][j]->Reset();
}
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
for(unsigned int i = 0;i < commands.Size();i++) for(unsigned int i = 0;i < commands[truth].Size();i++)
commands[i]->Tick(block, statusBar, hudChanged); commands[truth][i]->Tick(block, statusBar, hudChanged);
}
protected:
void SetTruth(bool truth, const SBarInfoMainBlock *block, const DSBarInfo *statusBar)
{
// If there is no change we don't need to do anything. Do note
// that this should not change more than once per tick. If it does
// there may be cosmetic problems.
if(this->truth == truth)
return;
this->truth = truth;
if(block != NULL)
Tick(block, statusBar, true);
} }
private: private:
SBarInfoCommand *NextCommand(FScanner &sc); SBarInfoCommand *NextCommand(FScanner &sc);
TArray<SBarInfoCommand *> commands; bool truth;
TArray<SBarInfoCommand *> commands[2];
}; };
class SBarInfoMainBlock : public SBarInfoCommandFlowControl class SBarInfoMainBlock : public SBarInfoCommandFlowControl
{ {
public: public:
SBarInfoMainBlock(SBarInfo *script) : SBarInfoCommandFlowControl(script), SBarInfoMainBlock(SBarInfo *script) : SBarInfoCommandFlowControl(script),
alpha(FRACUNIT), forceScaled(false), fullScreenOffsets(false) alpha(FRACUNIT), currentAlpha(FRACUNIT), forceScaled(false),
fullScreenOffsets(false)
{ {
SetTruth(true, NULL, NULL);
} }
int Alpha() const { return alpha; } int Alpha() const { return currentAlpha; }
void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, int xOffset, int yOffset, int alpha) void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, int xOffset, int yOffset, int alpha)
{ {
this->xOffset = xOffset; this->xOffset = xOffset;
this->yOffset = yOffset; this->yOffset = yOffset;
this->alpha = alpha; this->currentAlpha = fixed_t((((double) this->alpha / (double) FRACUNIT) * ((double) alpha / (double) FRACUNIT)) * FRACUNIT);
SBarInfoCommandFlowControl::Draw(this, statusBar); SBarInfoCommandFlowControl::Draw(this, statusBar);
} }
bool ForceScaled() const { return forceScaled; } bool ForceScaled() const { return forceScaled; }
@ -299,8 +338,9 @@ class SBarInfoMainBlock : public SBarInfoCommandFlowControl
int XOffset() const { return xOffset; } int XOffset() const { return xOffset; }
int YOffset() const { return yOffset; } int YOffset() const { return yOffset; }
private: protected:
int alpha; int alpha;
int currentAlpha;
bool forceScaled; bool forceScaled;
bool fullScreenOffsets; bool fullScreenOffsets;
int xOffset; int xOffset;
@ -320,6 +360,7 @@ enum //Key words
SBARINFO_COMPLETEBORDER, SBARINFO_COMPLETEBORDER,
SBARINFO_MONOSPACEFONTS, SBARINFO_MONOSPACEFONTS,
SBARINFO_LOWERHEALTHCAP, SBARINFO_LOWERHEALTHCAP,
SBARINFO_RESOLUTION,
SBARINFO_STATUSBAR, SBARINFO_STATUSBAR,
SBARINFO_MUGSHOT, SBARINFO_MUGSHOT,
SBARINFO_CREATEPOPUP, SBARINFO_CREATEPOPUP,
@ -347,6 +388,7 @@ static const char *SBarInfoTopLevel[] =
"completeborder", "completeborder",
"monospacefonts", "monospacefonts",
"lowerhealthcap", "lowerhealthcap",
"resolution",
"statusbar", "statusbar",
"mugshot", "mugshot",
"createpopup", "createpopup",
@ -428,6 +470,7 @@ void SBarInfo::ParseSBarInfo(int lump)
ParseSBarInfo(lump); ParseSBarInfo(lump);
continue; continue;
} }
int baselump = -2;
switch(sc.MustMatchString(SBarInfoTopLevel)) switch(sc.MustMatchString(SBarInfoTopLevel))
{ {
case SBARINFO_BASE: case SBARINFO_BASE:
@ -436,21 +479,36 @@ void SBarInfo::ParseSBarInfo(int lump)
sc.MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
if(sc.Compare("Doom")) if(sc.Compare("Doom"))
{ {
int lump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true); baselump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true);
if(lump == -1)
sc.ScriptError("Standard Doom Status Bar not found.");
ParseSBarInfo(lump);
} }
else if(sc.Compare("Heretic")) else if(sc.Compare("Heretic"))
gameType = GAME_Heretic; {
baselump = Wads.CheckNumForFullName("sbarinfo/heretic.txt", true);
}
else if(sc.Compare("Hexen")) else if(sc.Compare("Hexen"))
gameType = GAME_Hexen; {
baselump = Wads.CheckNumForFullName("sbarinfo/hexen.txt", true);
}
else if(sc.Compare("Strife")) else if(sc.Compare("Strife"))
gameType = GAME_Strife; gameType = GAME_Strife;
else if(sc.Compare("None")) else if(sc.Compare("None"))
gameType = GAME_Any; gameType = GAME_Any;
else else
sc.ScriptError("Bad game name: %s", sc.String); sc.ScriptError("Bad game name: %s", sc.String);
// If one of the standard status bar should be loaded, baselump has been set to a different value.
if (baselump != -2)
{
if(baselump == -1)
{
sc.ScriptError("Standard %s status bar not found.", sc.String);
}
else if (Wads.GetLumpFile(baselump) > 0)
{
I_FatalError("File %s is overriding core lump sbarinfo/%s.txt.",
Wads.GetWadFullName(Wads.GetLumpFile(baselump)), sc.String);
}
ParseSBarInfo(baselump);
}
sc.MustGetToken(';'); sc.MustGetToken(';');
break; break;
case SBARINFO_HEIGHT: case SBARINFO_HEIGHT:
@ -518,6 +576,19 @@ void SBarInfo::ParseSBarInfo(int lump)
sc.MustGetToken(','); sc.MustGetToken(',');
sc.MustGetToken(TK_StringConst); //Don't tell anyone we're just ignoring this ;) sc.MustGetToken(TK_StringConst); //Don't tell anyone we're just ignoring this ;)
} }
if(sc.CheckToken(','))
{
// Character alignment
sc.MustGetToken(TK_Identifier);
if(sc.Compare("left"))
spacingAlignment = ALIGN_LEFT;
else if(sc.Compare("center"))
spacingAlignment = ALIGN_CENTER;
else if(sc.Compare("right"))
spacingAlignment = ALIGN_RIGHT;
else
sc.ScriptError("Unknown alignment '%s'.", sc.String);
}
sc.MustGetToken(';'); sc.MustGetToken(';');
break; break;
case SBARINFO_LOWERHEALTHCAP: case SBARINFO_LOWERHEALTHCAP:
@ -532,6 +603,14 @@ void SBarInfo::ParseSBarInfo(int lump)
} }
sc.MustGetToken(';'); sc.MustGetToken(';');
break; break;
case SBARINFO_RESOLUTION:
sc.MustGetToken(TK_IntConst);
resW = sc.Number;
sc.MustGetToken(',');
sc.MustGetToken(TK_IntConst);
resH = sc.Number;
sc.MustGetToken(';');
break;
case SBARINFO_STATUSBAR: case SBARINFO_STATUSBAR:
{ {
if(!baseSet) //If the user didn't explicitly define a base, do so now. if(!baseSet) //If the user didn't explicitly define a base, do so now.
@ -615,6 +694,13 @@ void SBarInfo::ParseSBarInfo(int lump)
sc.MustGetToken(TK_IntConst); sc.MustGetToken(TK_IntConst);
popup.speed = sc.Number; popup.speed = sc.Number;
} }
else if(sc.Compare("pushup"))
{
popup.transition = Popup::TRANSITION_PUSHUP;
sc.MustGetToken(',');
sc.MustGetToken(TK_IntConst);
popup.speed = sc.Number;
}
else if(sc.Compare("fade")) else if(sc.Compare("fade"))
{ {
popup.transition = Popup::TRANSITION_FADE; popup.transition = Popup::TRANSITION_FADE;
@ -707,6 +793,9 @@ void SBarInfo::Init()
armorInterpolationSpeed = 8; armorInterpolationSpeed = 8;
height = 0; height = 0;
spacingCharacter = '\0'; spacingCharacter = '\0';
spacingAlignment = ALIGN_CENTER;
resW = 320;
resH = 200;
for(unsigned int i = 0;i < NUMHUDS;i++) for(unsigned int i = 0;i < NUMHUDS;i++)
huds[i] = new SBarInfoMainBlock(this); huds[i] = new SBarInfoMainBlock(this);
@ -722,78 +811,79 @@ SBarInfo::~SBarInfo()
} }
//Popup //Popup
Popup::Popup() Popup::Popup() : transition(TRANSITION_NONE), opened(false), moving(false),
height(320), width(200), speed(0), speed2(0), alpha(FRACUNIT), x(320),
y(200), displacementX(0), displacementY(0)
{ {
transition = TRANSITION_NONE;
height = 320;
width = 200;
speed = 0;
x = 320;
y = 200;
alpha = FRACUNIT;
opened = false;
moving = false;
} }
void Popup::init() void Popup::init()
{ {
x = width; x = width;
y = height; y = height;
if(transition == TRANSITION_SLIDEINBOTTOM) switch(transition)
{ {
x = 0; case TRANSITION_SLIDEINBOTTOM:
} case TRANSITION_PUSHUP:
else if(transition == TRANSITION_FADE) x = 0;
{ break;
alpha = 0; case TRANSITION_FADE:
x = 0; alpha = 0;
y = 0; x = 0;
y = 0;
break;
default:
break;
} }
} }
void Popup::tick() void Popup::tick()
{ {
if(transition == TRANSITION_SLIDEINBOTTOM) switch(transition)
{ {
if(moving) case TRANSITION_SLIDEINBOTTOM:
{ case TRANSITION_PUSHUP:
if(opened) if(moving)
y -= clamp(height + (y - height), 1, speed); {
int oldY = y;
if(opened)
y -= clamp(height + (y - height), 1, speed);
else
y += clamp(height - y, 1, speed);
if(transition == TRANSITION_PUSHUP)
displacementY += y - oldY;
}
if(y != 0 && y != height)
moving = true;
else else
y += clamp(height - y, 1, speed); moving = false;
} break;
if(y != 0 && y != height) case TRANSITION_FADE:
moving = true; if(moving)
else {
moving = false; if(opened)
} alpha = clamp(alpha + speed, 0, FRACUNIT);
else if(transition == TRANSITION_FADE) else
{ alpha = clamp(alpha - speed2, 0, FRACUNIT);
if(moving) }
{ if(alpha == 0 || alpha == FRACUNIT)
if(opened) moving = false;
alpha = clamp(alpha + speed, 0, FRACUNIT);
else else
alpha = clamp(alpha - speed2, 0, FRACUNIT); moving = true;
} break;
if(alpha == 0 || alpha == FRACUNIT) default:
if(opened)
{
y = 0;
x = 0;
}
else
{
y = height;
x = width;
}
moving = false; moving = false;
else break;
moving = true;
}
else
{
if(opened)
{
y = 0;
x = 0;
}
else
{
y = height;
x = width;
}
moving = false;
} }
} }
@ -819,6 +909,16 @@ int Popup::getAlpha(int maxAlpha)
return fixed_t((a * b) * FRACUNIT); return fixed_t((a * b) * FRACUNIT);
} }
int Popup::getXDisplacement()
{
return displacementX;
}
int Popup::getYDisplacement()
{
return displacementY;
}
void Popup::open() void Popup::open()
{ {
opened = true; opened = true;
@ -833,11 +933,23 @@ void Popup::close()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
inline void adjustRelCenter(bool relX, bool relY, const double &x, const double &y, double &outX, double &outY, const double &xScale, const double &yScale)
{
if(relX)
outX = x + (SCREENWIDTH/(hud_scale ? xScale*2 : 2));
else
outX = x;
if(relY)
outY = y + (SCREENHEIGHT/(hud_scale ? yScale*2 : 2));
else
outY = y;
}
class DSBarInfo : public DBaseStatusBar class DSBarInfo : public DBaseStatusBar
{ {
DECLARE_CLASS(DSBarInfo, DBaseStatusBar) DECLARE_CLASS(DSBarInfo, DBaseStatusBar)
public: public:
DSBarInfo (SBarInfo *script=NULL) : DBaseStatusBar(script->height), DSBarInfo (SBarInfo *script=NULL) : DBaseStatusBar(script->height, script->resW, script->resH),
ammo1(NULL), ammo2(NULL), ammocount1(0), ammocount2(0), armor(NULL), ammo1(NULL), ammo2(NULL), ammocount1(0), ammocount2(0), armor(NULL),
pendingPopup(POP_None), currentPopup(POP_None), lastHud(-1), pendingPopup(POP_None), currentPopup(POP_None), lastHud(-1),
lastInventoryBar(NULL), lastPopup(NULL) lastInventoryBar(NULL), lastPopup(NULL)
@ -861,10 +973,6 @@ public:
{ {
patchnames[i+script->Images.Size()] = InventoryBarLumps[i]; patchnames[i+script->Images.Size()] = InventoryBarLumps[i];
} }
for (i = 0;i < numskins;i++)
{
AddFaceToImageCollection (&skins[i], &Images);
}
invBarOffset = script->Images.Size(); invBarOffset = script->Images.Size();
Images.Init(&patchnames[0], patchnames.Size()); Images.Init(&patchnames[0], patchnames.Size());
} }
@ -918,8 +1026,13 @@ public:
armor = CPlayer->mo->FindInventory<ABasicArmor>(); armor = CPlayer->mo->FindInventory<ABasicArmor>();
if(hud != lastHud) if(hud != lastHud)
script->huds[hud]->Tick(NULL, this, true); script->huds[hud]->Tick(NULL, this, true);
script->huds[hud]->Draw(NULL, this, 0, 0, FRACUNIT);
if(currentPopup != POP_None && !script->huds[hud]->FullScreenOffsets())
script->huds[hud]->Draw(NULL, this, script->popups[currentPopup-1].getXDisplacement(), script->popups[currentPopup-1].getYDisplacement(), FRACUNIT);
else
script->huds[hud]->Draw(NULL, this, 0, 0, FRACUNIT);
lastHud = hud; lastHud = hud;
if(CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR) && (state == HUD_StatusBar || state == HUD_Fullscreen)) if(CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR) && (state == HUD_StatusBar || state == HUD_Fullscreen))
{ {
SBarInfoMainBlock *inventoryBar = state == HUD_StatusBar ? script->huds[STBAR_INVENTORY] : script->huds[STBAR_INVENTORYFULLSCREEN]; SBarInfoMainBlock *inventoryBar = state == HUD_StatusBar ? script->huds[STBAR_INVENTORY] : script->huds[STBAR_INVENTORYFULLSCREEN];
@ -1030,53 +1143,58 @@ public:
if (texture == NULL) if (texture == NULL)
return; return;
double dx = *x;
double dy = *y;
if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER) if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER)
{ {
x -= (texture->GetScaledWidth()/2)-texture->LeftOffset; dx -= (texture->GetScaledWidthDouble()/2.0)-texture->LeftOffset;
y -= (texture->GetScaledHeight()/2)-texture->TopOffset; dy -= (texture->GetScaledHeightDouble()/2.0)-texture->TopOffset;
} }
x += xOffset; dx += xOffset;
y += yOffset; dy += yOffset;
int w, h; double w, h;
if(!fullScreenOffsets) if(!fullScreenOffsets)
{ {
fixed_t tmp = 0; double tmp = 0;
// I'll handle the conversion from fixed to int myself for more control dx += ST_X;
fixed_t fx = (x + ST_X).Coordinate() << FRACBITS; dy += ST_Y - (Scaled ? script->resH : 200) + script->height;
fixed_t fy = (y + ST_Y).Coordinate() << FRACBITS; w = forceWidth < 0 ? texture->GetScaledWidthDouble() : forceWidth;
fixed_t fw = (forceWidth <= -1 ? texture->GetScaledWidth() : forceWidth) << FRACBITS; h = forceHeight < 0 ? texture->GetScaledHeightDouble() : forceHeight;
fixed_t fh = (forceHeight <= -1 ? texture->GetScaledHeight() : forceHeight) << FRACBITS; double dcx = cx == 0 ? 0 : dx + ((double) cx / FRACUNIT) - texture->GetScaledLeftOffsetDouble();
fixed_t fcx = cx == 0 ? 0 : fx + cx - (texture->GetScaledLeftOffset() << FRACBITS); double dcy = cy == 0 ? 0 : dy + ((double) cy / FRACUNIT) - texture->GetScaledTopOffsetDouble();
fixed_t fcy = cy == 0 ? 0 : fy + cy - (texture->GetScaledTopOffset() << FRACBITS); double dcr = cr == 0 ? INT_MAX : dx + w - ((double) cr / FRACUNIT);
fixed_t fcr = fx + fw - cr; double dcb = cb == 0 ? INT_MAX : dy + h - ((double) cb / FRACUNIT);
fixed_t fcb = fy + fh - cb;
if(Scaled) if(Scaled)
{ {
if(cx != 0 || cy != 0) if(cx != 0 || cy != 0)
screen->VirtualToRealCoordsFixed(fcx, fcy, tmp, tmp, 320, 200, true); screen->VirtualToRealCoords(dcx, dcy, tmp, tmp, script->resW, script->resH, true);
if(cr != 0 || cb != 0 || clearDontDraw) if(cr != 0 || cb != 0 || clearDontDraw)
screen->VirtualToRealCoordsFixed(fcr, fcb, tmp, tmp, 320, 200, true); screen->VirtualToRealCoords(dcr, dcb, tmp, tmp, script->resW, script->resH, true);
screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true); screen->VirtualToRealCoords(dx, dy, w, h, script->resW, script->resH, true);
} }
// Round to nearest else
w = (fw + (FRACUNIT>>1)) >> FRACBITS; {
h = (fh + (FRACUNIT>>1)) >> FRACBITS; dy += 200 - script->resH;
cr = cr != 0 ? fcr >> FRACBITS : INT_MAX; dcy += 200 - script->resH;
cb = cb != 0 ? fcb >> FRACBITS : INT_MAX; dcb += 200 - script->resH;
}
if(clearDontDraw) if(clearDontDraw)
screen->Clear(MAX<fixed_t>(fx, fcx)>>FRACBITS, MAX<fixed_t>(fy, fcy)>>FRACBITS, fcr>>FRACBITS, fcb>>FRACBITS, GPalette.BlackIndex, 0); screen->Clear(static_cast<int>(MAX<double>(dx, dcx)), static_cast<int>(MAX<double>(dy, dcy)), static_cast<int>(dcr), static_cast<int>(dcb), GPalette.BlackIndex, 0);
else else
{ {
if(alphaMap) if(alphaMap)
{ {
screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS), screen->DrawTexture(texture, dx, dy,
DTA_DestWidth, w, DTA_DestWidthF, w,
DTA_DestHeight, h, DTA_DestHeightF, h,
DTA_ClipLeft, fcx>>FRACBITS, DTA_ClipLeft, static_cast<int>(dcx),
DTA_ClipTop, fcy>>FRACBITS, DTA_ClipTop, static_cast<int>(dcy),
DTA_ClipRight, cr, DTA_ClipRight, static_cast<int>(MIN<double>(INT_MAX, dcr)),
DTA_ClipBottom, cb, DTA_ClipBottom, static_cast<int>(MIN<double>(INT_MAX, dcb)),
DTA_Translation, translate ? GetTranslation() : 0, DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
@ -1087,13 +1205,13 @@ public:
} }
else else
{ {
screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS), screen->DrawTexture(texture, dx, dy,
DTA_DestWidth, w, DTA_DestWidthF, w,
DTA_DestHeight, h, DTA_DestHeightF, h,
DTA_ClipLeft, fcx>>FRACBITS, DTA_ClipLeft, static_cast<int>(dcx),
DTA_ClipTop, fcy>>FRACBITS, DTA_ClipTop, static_cast<int>(dcy),
DTA_ClipRight, cr, DTA_ClipRight, static_cast<int>(MIN<double>(INT_MAX, dcr)),
DTA_ClipBottom, cb, DTA_ClipBottom, static_cast<int>(MIN<double>(INT_MAX, dcb)),
DTA_Translation, translate ? GetTranslation() : 0, DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
@ -1104,69 +1222,87 @@ public:
} }
else else
{ {
int rx, ry, rcx=0, rcy=0, rcr=INT_MAX, rcb=INT_MAX; double rx, ry, rcx=0, rcy=0, rcr=INT_MAX, rcb=INT_MAX;
ADJUST_RELCENTER(x,y,rx,ry)
w = (forceWidth <= -1 ? texture->GetScaledWidth() : forceWidth); double xScale = !hud_scale ? 1.0 : (double) CleanXfac*320.0/(double) script->resW;//(double) SCREENWIDTH/(double) script->resW;
h = (forceHeight <= -1 ? texture->GetScaledHeight() : forceHeight); double yScale = !hud_scale ? 1.0 : (double) CleanYfac*200.0/(double) script->resH;//(double) SCREENHEIGHT/(double) script->resH;
adjustRelCenter(x.RelCenter(), y.RelCenter(), dx, dy, rx, ry, xScale, yScale);
// We can't use DTA_HUDRules since it forces a width and height.
// Translation: No high res.
bool xright = rx < 0;
bool ybot = ry < 0;
w = (forceWidth < 0 ? texture->GetScaledWidthDouble() : forceWidth);
h = (forceHeight < 0 ? texture->GetScaledHeightDouble() : forceHeight);
if(vid_fps && rx < 0 && ry >= 0) if(vid_fps && rx < 0 && ry >= 0)
ry += 10; ry += 10;
if(hud_scale)
{
rx *= xScale;
ry *= yScale;
w *= xScale;
h *= yScale;
}
if(xright)
rx = SCREENWIDTH + rx;
if(ybot)
ry = SCREENHEIGHT + ry;
// Check for clipping // Check for clipping
if(cx != 0 || cy != 0 || cr != 0 || cb != 0) if(cx != 0 || cy != 0 || cr != 0 || cb != 0)
{ {
rcx = cx == 0 ? 0 : rx+(cx>>FRACBITS); rcx = cx == 0 ? 0 : rx+(((double) cx/FRACUNIT)*xScale);
rcy = cy == 0 ? 0 : ry+(cy>>FRACBITS); rcy = cy == 0 ? 0 : ry+(((double) cy/FRACUNIT)*yScale);
rcr = cr == 0 ? INT_MAX : rx+w-(cr>>FRACBITS); rcr = cr == 0 ? INT_MAX : rx+w-(((double) cr/FRACUNIT)*xScale);
rcb = cb == 0 ? INT_MAX : ry+h-(cb>>FRACBITS); rcb = cb == 0 ? INT_MAX : ry+h-(((double) cb/FRACUNIT)*yScale);
// Fix the clipping for fullscreenoffsets. // Fix the clipping for fullscreenoffsets.
if(ry < 0) /*if(ry < 0)
{ {
if(rcy != 0) if(rcy != 0)
rcy = hud_scale ? SCREENHEIGHT + (rcy*CleanYfac) : SCREENHEIGHT + rcy; rcy = hud_scale ? SCREENHEIGHT + (int) (rcy*CleanYfac*200.0/script->resH) : SCREENHEIGHT + rcy;
if(rcb != INT_MAX) if(rcb != INT_MAX)
rcb = hud_scale ? SCREENHEIGHT + (rcb*CleanYfac) : SCREENHEIGHT + rcb; rcb = hud_scale ? SCREENHEIGHT + (int) (rcb*CleanYfac*200.0/script->resH) : SCREENHEIGHT + rcb;
} }
else if(hud_scale) else if(hud_scale)
{ {
rcy *= CleanYfac; rcy *= (int) (CleanYfac*200.0/script->resH);
if(rcb != INT_MAX) if(rcb != INT_MAX)
rcb *= CleanYfac; rcb *= (int) (CleanYfac*200.0/script->resH);
} }
if(rx < 0) if(rx < 0)
{ {
if(rcx != 0) if(rcx != 0)
rcx = hud_scale ? SCREENWIDTH + (rcx*CleanXfac) : SCREENWIDTH + rcx; rcx = hud_scale ? SCREENWIDTH + (int) (rcx*CleanXfac*320.0/script->resW) : SCREENWIDTH + rcx;
if(rcr != INT_MAX) if(rcr != INT_MAX)
rcr = hud_scale ? SCREENWIDTH + (rcr*CleanXfac) : SCREENWIDTH + rcr; rcr = hud_scale ? SCREENWIDTH + (int) (rcr*CleanXfac*320.0/script->resW) : SCREENWIDTH + rcr;
} }
else if(hud_scale) else if(hud_scale)
{ {
rcx *= CleanXfac; rcx *= (int) (CleanXfac*320.0/script->resW);
if(rcr != INT_MAX) if(rcr != INT_MAX)
rcr *= CleanXfac; rcr *= (int) (CleanXfac*320.0/script->resW);
} }*/
} }
if(clearDontDraw) if(clearDontDraw)
{ screen->Clear(static_cast<int>(rcx), static_cast<int>(rcy), static_cast<int>(MIN<double>(rcr, rcx+w)), static_cast<int>(MIN<double>(rcb, rcy+h)), GPalette.BlackIndex, 0);
screen->Clear(rcx, rcy, MIN<int>(rcr, w*(hud_scale ? CleanXfac : 1)), MIN<int>(rcb, h*(hud_scale ? CleanYfac : 1)), GPalette.BlackIndex, 0);
}
else else
{ {
if(alphaMap) if(alphaMap)
{ {
screen->DrawTexture(texture, rx, ry, screen->DrawTexture(texture, rx, ry,
DTA_DestWidth, w, DTA_DestWidthF, w,
DTA_DestHeight, h, DTA_DestHeightF, h,
DTA_ClipLeft, rcx, DTA_ClipLeft, static_cast<int>(rcx),
DTA_ClipTop, rcy, DTA_ClipTop, static_cast<int>(rcy),
DTA_ClipRight, rcr, DTA_ClipRight, static_cast<int>(rcr),
DTA_ClipBottom, rcb, DTA_ClipBottom, static_cast<int>(rcb),
DTA_Translation, translate ? GetTranslation() : 0, DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
DTA_HUDRules, HUD_Normal,
DTA_Alpha, alpha, DTA_Alpha, alpha,
DTA_AlphaChannel, alphaMap, DTA_AlphaChannel, alphaMap,
DTA_FillColor, 0, DTA_FillColor, 0,
@ -1175,16 +1311,15 @@ public:
else else
{ {
screen->DrawTexture(texture, rx, ry, screen->DrawTexture(texture, rx, ry,
DTA_DestWidth, w, DTA_DestWidthF, w,
DTA_DestHeight, h, DTA_DestHeightF, h,
DTA_ClipLeft, rcx, DTA_ClipLeft, static_cast<int>(rcx),
DTA_ClipTop, rcy, DTA_ClipTop, static_cast<int>(rcy),
DTA_ClipRight, rcr, DTA_ClipRight, static_cast<int>(rcr),
DTA_ClipBottom, rcb, DTA_ClipBottom, static_cast<int>(rcb),
DTA_Translation, translate ? GetTranslation() : 0, DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
DTA_HUDRules, HUD_Normal,
DTA_Alpha, alpha, DTA_Alpha, alpha,
TAG_DONE); TAG_DONE);
} }
@ -1192,20 +1327,32 @@ public:
} }
} }
void DrawString(FFont *font, const char* str, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool drawshadow=false) const void DrawString(FFont *font, const char* str, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool drawshadow=false, int shadowX=2, int shadowY=2) const
{ {
x += spacing; x += spacing;
int ax = *x; double ax = *x;
int ay = *y; double ay = *y;
double xScale = 1.0;
double yScale = 1.0;
if(fullScreenOffsets) if(fullScreenOffsets)
{ {
ADJUST_RELCENTER(x,y,ax,ay) if(hud_scale)
{
xScale = (double) CleanXfac*320.0/(double) script->resW;//(double) SCREENWIDTH/(double) script->resW;
yScale = (double) CleanYfac*200.0/(double) script->resH;//(double) SCREENWIDTH/(double) script->resW;
}
adjustRelCenter(x.RelCenter(), y.RelCenter(), *x, *y, ax, ay, xScale, yScale);
} }
while(*str != '\0') while(*str != '\0')
{ {
if(*str == ' ') if(*str == ' ')
{ {
ax += font->GetSpaceWidth(); if(script->spacingCharacter == '\0')
ax += font->GetSpaceWidth();
else
ax += font->GetCharWidth((int) script->spacingCharacter);
str++; str++;
continue; continue;
} }
@ -1223,65 +1370,77 @@ public:
if(script->spacingCharacter == '\0') //If we are monospaced lets use the offset if(script->spacingCharacter == '\0') //If we are monospaced lets use the offset
ax += (character->LeftOffset+1); //ignore x offsets since we adapt to character size ax += (character->LeftOffset+1); //ignore x offsets since we adapt to character size
int rx, ry, rw, rh; double rx, ry, rw, rh;
rx = ax + xOffset; rx = ax + xOffset;
ry = ay + yOffset; ry = ay + yOffset;
rw = character->GetScaledWidth(); rw = character->GetScaledWidthDouble();
rh = character->GetScaledHeight(); rh = character->GetScaledHeightDouble();
if(script->spacingCharacter != '\0')
{
double spacingSize = font->GetCharWidth((int) script->spacingCharacter);
switch(script->spacingAlignment)
{
default:
break;
case SBarInfo::ALIGN_CENTER:
rx += (spacingSize/2)-(rw/2);
break;
case SBarInfo::ALIGN_RIGHT:
rx += spacingSize-rw;
break;
}
}
if(!fullScreenOffsets) if(!fullScreenOffsets)
{ {
rx += ST_X; rx += ST_X;
ry += ST_Y; ry += ST_Y - (Scaled ? script->resH : 200) + script->height;
if(Scaled) if(Scaled)
screen->VirtualToRealCoordsInt(rx, ry, rw, rh, 320, 200, true); screen->VirtualToRealCoords(rx, ry, rw, rh, script->resW, script->resH, true);
else
{
ry += (200 - script->resH);
}
} }
else else
{ {
if(vid_fps && ax < 0 && ay >= 0) if(vid_fps && ax < 0 && ay >= 0)
ry += 10; ry += 10;
bool xright = rx < 0;
bool ybot = ry < 0;
if(hud_scale)
{
rx *= xScale;
ry *= yScale;
rw *= xScale;
rh *= yScale;
}
if(xright)
rx = SCREENWIDTH + rx;
if(ybot)
ry = SCREENHEIGHT + ry;
} }
if(drawshadow) if(drawshadow)
{ {
int salpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) HR_SHADOW / (double) FRACUNIT) * FRACUNIT); int salpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) HR_SHADOW / (double) FRACUNIT) * FRACUNIT);
if(!fullScreenOffsets) double srx = rx + (shadowX*xScale);
{ double sry = ry + (shadowY*yScale);
screen->DrawTexture(character, rx+2, ry+2, screen->DrawTexture(character, srx, sry,
DTA_DestWidth, rw, DTA_DestWidthF, rw,
DTA_DestHeight, rh, DTA_DestHeightF, rh,
DTA_Alpha, salpha, DTA_Alpha, salpha,
DTA_FillColor, 0, DTA_FillColor, 0,
TAG_DONE);
}
else
{
screen->DrawTexture(character, rx+2, ry+2,
DTA_DestWidth, rw,
DTA_DestHeight, rh,
DTA_Alpha, salpha,
DTA_HUDRules, HUD_Normal,
DTA_FillColor, 0,
TAG_DONE);
}
}
if(!fullScreenOffsets)
{
screen->DrawTexture(character, rx, ry,
DTA_DestWidth, rw,
DTA_DestHeight, rh,
DTA_Translation, font->GetColorTranslation(translation),
DTA_Alpha, alpha,
TAG_DONE);
}
else
{
screen->DrawTexture(character, rx, ry,
DTA_DestWidth, rw,
DTA_DestHeight, rh,
DTA_Translation, font->GetColorTranslation(translation),
DTA_Alpha, alpha,
DTA_HUDRules, HUD_Normal,
TAG_DONE); TAG_DONE);
} }
screen->DrawTexture(character, rx, ry,
DTA_DestWidthF, rw,
DTA_DestHeightF, rh,
DTA_Translation, font->GetColorTranslation(translation),
DTA_Alpha, alpha,
TAG_DONE);
if(script->spacingCharacter == '\0') if(script->spacingCharacter == '\0')
ax += width + spacing - (character->LeftOffset+1); ax += width + spacing - (character->LeftOffset+1);
else //width gets changed at the call to GetChar() else //width gets changed at the call to GetChar()

View file

@ -52,6 +52,7 @@ struct Popup
{ {
TRANSITION_NONE, TRANSITION_NONE,
TRANSITION_SLIDEINBOTTOM, TRANSITION_SLIDEINBOTTOM,
TRANSITION_PUSHUP,
TRANSITION_FADE, TRANSITION_FADE,
}; };
@ -65,6 +66,8 @@ struct Popup
int alpha; int alpha;
int x; int x;
int y; int y;
int displacementX;
int displacementY;
Popup(); Popup();
void init(); void init();
@ -75,10 +78,19 @@ struct Popup
int getXOffset(); int getXOffset();
int getYOffset(); int getYOffset();
int getAlpha(int maxAlpha=FRACUNIT); int getAlpha(int maxAlpha=FRACUNIT);
int getXDisplacement();
int getYDisplacement();
}; };
struct SBarInfo struct SBarInfo
{ {
enum MonospaceAlignment
{
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT
};
TArray<FString> Images; TArray<FString> Images;
SBarInfoMainBlock *huds[NUMHUDS]; SBarInfoMainBlock *huds[NUMHUDS];
Popup popups[NUMPOPUPS]; Popup popups[NUMPOPUPS];
@ -88,11 +100,14 @@ struct SBarInfo
bool completeBorder; bool completeBorder;
bool lowerHealthCap; bool lowerHealthCap;
char spacingCharacter; char spacingCharacter;
MonospaceAlignment spacingAlignment;
int interpolationSpeed; int interpolationSpeed;
int armorInterpolationSpeed; int armorInterpolationSpeed;
int height; int height;
int gameType; int gameType;
FMugShot MugShot; FMugShot MugShot;
int resW;
int resH;
int GetGameType() { return gameType; } int GetGameType() { return gameType; }
void ParseSBarInfo(int lump); void ParseSBarInfo(int lump);

File diff suppressed because it is too large Load diff

View file

@ -175,7 +175,7 @@ void ST_LoadCrosshair(bool alwaysload)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
DBaseStatusBar::DBaseStatusBar (int reltop) DBaseStatusBar::DBaseStatusBar (int reltop, int hres, int vres)
{ {
Centering = false; Centering = false;
FixedOrigin = false; FixedOrigin = false;
@ -185,6 +185,8 @@ DBaseStatusBar::DBaseStatusBar (int reltop)
Displacement = 0; Displacement = 0;
CPlayer = NULL; CPlayer = NULL;
ShowLog = false; ShowLog = false;
HorizontalResolution = hres;
VirticalResolution = vres;
SetScaled (st_scale); SetScaled (st_scale);
} }
@ -216,18 +218,20 @@ void DBaseStatusBar::Destroy ()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//[BL] Added force argument to have forcescaled mean forcescaled. //[BL] Added force argument to have forcescaled mean forcescaled.
// - Also, if the VirticalResolution is something other than the default (200)
// We should always obey the value of scale.
void DBaseStatusBar::SetScaled (bool scale, bool force) void DBaseStatusBar::SetScaled (bool scale, bool force)
{ {
Scaled = (RelTop != 0 || force) && (SCREENWIDTH != 320 && scale); Scaled = (RelTop != 0 || force) && ((SCREENWIDTH != 320 || HorizontalResolution != 320) && scale);
if (!Scaled) if (!Scaled)
{ {
ST_X = (SCREENWIDTH - 320) / 2; ST_X = (SCREENWIDTH - HorizontalResolution) / 2;
ST_Y = SCREENHEIGHT - RelTop; ST_Y = SCREENHEIGHT - RelTop;
::ST_Y = ST_Y; ::ST_Y = ST_Y;
if (RelTop > 0) if (RelTop > 0)
{ {
Displacement = ((ST_Y * 200 / SCREENHEIGHT) - (200 - RelTop))*FRACUNIT/RelTop; Displacement = ((ST_Y * VirticalResolution / SCREENHEIGHT) - (VirticalResolution - RelTop))*FRACUNIT/RelTop;
} }
else else
{ {
@ -237,14 +241,14 @@ void DBaseStatusBar::SetScaled (bool scale, bool force)
else else
{ {
ST_X = 0; ST_X = 0;
ST_Y = 200 - RelTop; ST_Y = VirticalResolution - RelTop;
if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) != 4) if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) != 4)
{ // Normal resolution { // Normal resolution
::ST_Y = Scale (ST_Y, SCREENHEIGHT, 200); ::ST_Y = Scale (ST_Y, SCREENHEIGHT, VirticalResolution);
} }
else else
{ // 5:4 resolution { // 5:4 resolution
::ST_Y = Scale(ST_Y - 100, SCREENHEIGHT*3, BaseRatioSizes[4][1]) + SCREENHEIGHT/2 ::ST_Y = Scale(ST_Y - VirticalResolution/2, SCREENHEIGHT*3, Scale(VirticalResolution, BaseRatioSizes[4][1], 200)) + SCREENHEIGHT/2
+ (SCREENHEIGHT - SCREENHEIGHT * BaseRatioSizes[4][3] / 48) / 2; + (SCREENHEIGHT - SCREENHEIGHT * BaseRatioSizes[4][3] / 48) / 2;
} }
Displacement = 0; Displacement = 0;
@ -1000,7 +1004,7 @@ void DBaseStatusBar::RefreshBackground () const
if (x > 0) if (x > 0)
{ {
y = x == ST_X ? ST_Y : ::ST_Y; y = x == ST_X ? ST_Y : ::ST_Y;
x2 = !(ratio & 3) || !Scaled ? ST_X+320 : x2 = !(ratio & 3) || !Scaled ? ST_X+HorizontalResolution :
SCREENWIDTH - (SCREENWIDTH*(48-BaseRatioSizes[ratio][3])+48*2-1)/(48*2); SCREENWIDTH - (SCREENWIDTH*(48-BaseRatioSizes[ratio][3])+48*2-1)/(48*2);
R_DrawBorder (0, y, x, SCREENHEIGHT); R_DrawBorder (0, y, x, SCREENHEIGHT);
R_DrawBorder (x2, y, SCREENWIDTH, SCREENHEIGHT); R_DrawBorder (x2, y, SCREENWIDTH, SCREENHEIGHT);
@ -1500,18 +1504,23 @@ void DBaseStatusBar::BlendView (float blend[4])
if (CPlayer->bonuscount) if (CPlayer->bonuscount)
{ {
cnt = CPlayer->bonuscount << 3; cnt = CPlayer->bonuscount << 3;
AddBlend (0.8431f, 0.7333f, 0.2706f, cnt > 128 ? 0.5f : cnt / 255.f, blend);
AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f,
BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend);
} }
cnt = DamageToAlpha[MIN (113, CPlayer->damagecount)]; if (CPlayer->mo->DamageFade.a != 0)
if (cnt)
{ {
if (cnt > 228) cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * CPlayer->mo->DamageFade.a / 255)];
cnt = 228;
APlayerPawn *mo = players[consoleplayer].mo; if (cnt)
AddBlend (mo->DamageFade.r / 255.f, mo->DamageFade.g / 255.f, mo->DamageFade.b / 255.f, cnt / 255.f, blend); {
if (cnt > 228)
cnt = 228;
APlayerPawn *mo = CPlayer->mo;
AddBlend (mo->DamageFade.r / 255.f, mo->DamageFade.g / 255.f, mo->DamageFade.b / 255.f, cnt / 255.f, blend);
}
} }
// Unlike Doom, I did not have any utility source to look at to find the // Unlike Doom, I did not have any utility source to look at to find the
@ -1591,15 +1600,6 @@ void DBaseStatusBar::FlashItem (const PClass *itemtype)
{ {
} }
void DBaseStatusBar::SetFace (void *skn)
{
}
void DBaseStatusBar::AddFaceToImageCollection (void *skn, FImageCollection *images)
{
AddFaceToImageCollectionActual (skn, images, false);
}
void DBaseStatusBar::NewGame () void DBaseStatusBar::NewGame ()
{ {
} }
@ -1635,72 +1635,6 @@ void DBaseStatusBar::ScreenSizeChanged ()
} }
} }
//---------------------------------------------------------------------------
//
// AddFaceToImageCollectionActual
//
// Adds face graphics for specified skin to the specified image collection.
// If not in DOOM statusbar and no face in current skin, do NOT default STF*
//
//---------------------------------------------------------------------------
void DBaseStatusBar::AddFaceToImageCollectionActual (void *skn, FImageCollection *images, bool isDoom)
{
const char *nameptrs[ST_NUMFACES];
char names[ST_NUMFACES][9];
char prefix[4];
int i, j;
int namespc;
int facenum;
FPlayerSkin *skin = (FPlayerSkin *)skn;
if ((skin->face[0] == 0) && !isDoom)
{
return;
}
for (i = 0; i < ST_NUMFACES; i++)
{
nameptrs[i] = names[i];
}
if (skin->face[0] != 0)
{
prefix[0] = skin->face[0];
prefix[1] = skin->face[1];
prefix[2] = skin->face[2];
prefix[3] = 0;
namespc = skin->namespc;
}
else
{
prefix[0] = 'S';
prefix[1] = 'T';
prefix[2] = 'F';
prefix[3] = 0;
namespc = ns_global;
}
facenum = 0;
for (i = 0; i < ST_NUMPAINFACES; i++)
{
for (j = 0; j < ST_NUMSTRAIGHTFACES; j++)
{
mysnprintf (names[facenum++], countof(names[0]), "%sST%d%d", prefix, i, j);
}
mysnprintf (names[facenum++], countof(names[0]), "%sTR%d0", prefix, i); // turn right
mysnprintf (names[facenum++], countof(names[0]), "%sTL%d0", prefix, i); // turn left
mysnprintf (names[facenum++], countof(names[0]), "%sOUCH%d", prefix, i); // ouch!
mysnprintf (names[facenum++], countof(names[0]), "%sEVL%d", prefix, i); // evil grin ;)
mysnprintf (names[facenum++], countof(names[0]), "%sKILL%d", prefix, i); // pissed off
}
mysnprintf (names[facenum++], countof(names[0]), "%sGOD0", prefix);
mysnprintf (names[facenum++], countof(names[0]), "%sDEAD0", prefix);
images->Add (nameptrs, ST_NUMFACES, namespc);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// ValidateInvFirst // ValidateInvFirst

View file

@ -35,12 +35,14 @@
#include <ctype.h> #include <ctype.h>
#include "doomstat.h" #include "doomstat.h"
#include "d_player.h"
#include "g_level.h" #include "g_level.h"
#include "g_game.h" #include "g_game.h"
#include "gi.h" #include "gi.h"
#include "templates.h" #include "templates.h"
#include "v_font.h" #include "v_font.h"
#include "m_fixed.h" #include "m_fixed.h"
#include "gstrings.h"
TArray<FSkillInfo> AllSkills; TArray<FSkillInfo> AllSkills;
int DefaultSkill = -1; int DefaultSkill = -1;
@ -70,7 +72,6 @@ void FMapInfoParser::ParseSkill ()
skill.Aggressiveness = FRACUNIT; skill.Aggressiveness = FRACUNIT;
skill.SpawnFilter = 0; skill.SpawnFilter = 0;
skill.ACSReturn = 0; skill.ACSReturn = 0;
skill.MenuNameIsLump = false;
skill.MustConfirm = false; skill.MustConfirm = false;
skill.Shortcut = 0; skill.Shortcut = 0;
skill.TextColor = ""; skill.TextColor = "";
@ -79,6 +80,7 @@ void FMapInfoParser::ParseSkill ()
skill.MonsterHealth = FRACUNIT; skill.MonsterHealth = FRACUNIT;
skill.FriendlyHealth = FRACUNIT; skill.FriendlyHealth = FRACUNIT;
skill.NoPain = false; skill.NoPain = false;
skill.ArmorFactor = FRACUNIT;
sc.MustGetString(); sc.MustGetString();
skill.Name = sc.String; skill.Name = sc.String;
@ -185,7 +187,6 @@ void FMapInfoParser::ParseSkill ()
ParseAssign(); ParseAssign();
sc.MustGetString (); sc.MustGetString ();
skill.MenuName = sc.String; skill.MenuName = sc.String;
skill.MenuNameIsLump = false;
} }
else if (sc.Compare("PlayerClassName")) else if (sc.Compare("PlayerClassName"))
{ {
@ -200,8 +201,7 @@ void FMapInfoParser::ParseSkill ()
{ {
ParseAssign(); ParseAssign();
sc.MustGetString (); sc.MustGetString ();
skill.MenuName = sc.String; skill.PicName = sc.String;
skill.MenuNameIsLump = true;
} }
else if (sc.Compare("MustConfirm")) else if (sc.Compare("MustConfirm"))
{ {
@ -250,6 +250,12 @@ void FMapInfoParser::ParseSkill ()
{ {
skill.NoPain = true; skill.NoPain = true;
} }
else if (sc.Compare("ArmorFactor"))
{
ParseAssign();
sc.MustGetFloat();
skill.ArmorFactor = FLOAT2FIXED(sc.Float);
}
else if (sc.Compare("DefaultSkill")) else if (sc.Compare("DefaultSkill"))
{ {
if (DefaultSkill >= 0) if (DefaultSkill >= 0)
@ -359,11 +365,37 @@ int G_SkillProperty(ESkillProperty prop)
case SKILLP_NoPain: case SKILLP_NoPain:
return AllSkills[gameskill].NoPain; return AllSkills[gameskill].NoPain;
case SKILLP_ArmorFactor:
return AllSkills[gameskill].ArmorFactor;
} }
} }
return 0; return 0;
} }
//==========================================================================
//
//
//
//==========================================================================
const char * G_SkillName()
{
const char *name = AllSkills[gameskill].MenuName;
player_t *player = &players[consoleplayer];
const char *playerclass = player->mo->GetClass()->DisplayName;
if (playerclass != NULL)
{
FString * pmnm = AllSkills[gameskill].MenuNamesForPlayerClass.CheckKey(playerclass);
if (pmnm != NULL) name = *pmnm;
}
if (*name == '$') name = GStrings(name+1);
return name;
}
//========================================================================== //==========================================================================
// //
@ -402,8 +434,8 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other)
SpawnFilter = other.SpawnFilter; SpawnFilter = other.SpawnFilter;
ACSReturn = other.ACSReturn; ACSReturn = other.ACSReturn;
MenuName = other.MenuName; MenuName = other.MenuName;
PicName = other.PicName;
MenuNamesForPlayerClass = other.MenuNamesForPlayerClass; MenuNamesForPlayerClass = other.MenuNamesForPlayerClass;
MenuNameIsLump = other.MenuNameIsLump;
MustConfirm = other.MustConfirm; MustConfirm = other.MustConfirm;
MustConfirmText = other.MustConfirmText; MustConfirmText = other.MustConfirmText;
Shortcut = other.Shortcut; Shortcut = other.Shortcut;
@ -413,6 +445,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other)
MonsterHealth = other.MonsterHealth; MonsterHealth = other.MonsterHealth;
FriendlyHealth = other.FriendlyHealth; FriendlyHealth = other.FriendlyHealth;
NoPain = other.NoPain; NoPain = other.NoPain;
ArmorFactor = other.ArmorFactor;
return *this; return *this;
} }

View file

@ -93,7 +93,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath)
int log; int log;
int i; int i;
CALL_ACTION(A_NoBlocking, self); // [RH] Need this for Sigil rewarding A_Unblock(self, true); // [RH] Need this for Sigil rewarding
if (!CheckBossDeath (self)) if (!CheckBossDeath (self))
{ {
return 0; return 0;

View file

@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger)
angle = self->angle + (pr_jabdagger.Random2() << 18); angle = self->angle + (pr_jabdagger.Random2() << 18);
pitch = P_AimLineAttack (self, angle, 80*FRACUNIT, &linetarget); pitch = P_AimLineAttack (self, angle, 80*FRACUNIT, &linetarget);
P_LineAttack (self, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, "StrifeSpark", true); P_LineAttack (self, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, "StrifeSpark", true, &linetarget);
// turn to face target // turn to face target
if (linetarget) if (linetarget)

View file

@ -399,29 +399,38 @@ void FGameConfigFile::DoGameSetup (const char *gamename)
ReadCVars (0); ReadCVars (0);
} }
strncpy (subsection, "Bindings", sublen); if (!bMigrating)
if (!SetSection (section))
{ // Config has no bindings for the given game
if (!bMigrating)
{
C_SetDefaultBindings ();
}
}
else
{ {
C_UnbindAll (); C_SetDefaultBindings ();
}
strncpy (subsection, "Bindings", sublen);
if (SetSection (section))
{
Bindings.UnbindAll();
while (NextInSection (key, value)) while (NextInSection (key, value))
{ {
C_DoBind (key, value, false); Bindings.DoBind (key, value);
} }
} }
strncpy (subsection, "DoubleBindings", sublen); strncpy (subsection, "DoubleBindings", sublen);
if (SetSection (section)) if (SetSection (section))
{ {
DoubleBindings.UnbindAll();
while (NextInSection (key, value)) while (NextInSection (key, value))
{ {
C_DoBind (key, value, true); DoubleBindings.DoBind (key, value);
}
}
strncpy (subsection, "AutomapBindings", sublen);
if (SetSection (section))
{
AutomapBindings.UnbindAll();
while (NextInSection (key, value))
{
AutomapBindings.DoBind (key, value);
} }
} }
@ -512,11 +521,15 @@ void FGameConfigFile::ArchiveGameData (const char *gamename)
strcpy (subsection, "Bindings"); strcpy (subsection, "Bindings");
SetSection (section, true); SetSection (section, true);
C_ArchiveBindings (this, false); Bindings.ArchiveBindings (this);
strncpy (subsection, "DoubleBindings", sublen); strncpy (subsection, "DoubleBindings", sublen);
SetSection (section, true); SetSection (section, true);
C_ArchiveBindings (this, true); DoubleBindings.ArchiveBindings (this);
strncpy (subsection, "AutomapBindings", sublen);
SetSection (section, true);
AutomapBindings.ArchiveBindings (this);
} }
void FGameConfigFile::ArchiveGlobalData () void FGameConfigFile::ArchiveGlobalData ()

View file

@ -266,6 +266,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_INT(defKickback, "defKickback") GAMEINFOKEY_INT(defKickback, "defKickback")
GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8) GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8)
GAMEINFOKEY_STRING(translator, "translator") GAMEINFOKEY_STRING(translator, "translator")
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor") GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor")
GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor") GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor")
GAMEINFOKEY_STRING(backpacktype, "backpacktype") GAMEINFOKEY_STRING(backpacktype, "backpacktype")

View file

@ -43,6 +43,9 @@
#define GI_MENUHACK_EXTENDED 0x00000004 // (Heretic) #define GI_MENUHACK_EXTENDED 0x00000004 // (Heretic)
#define GI_TEASER2 0x00000008 // Alternate version of the Strife Teaser #define GI_TEASER2 0x00000008 // Alternate version of the Strife Teaser
#define GI_COMPATSHORTTEX 0x00000010 // always force COMPAT_SHORTTEX for IWAD maps. #define GI_COMPATSHORTTEX 0x00000010 // always force COMPAT_SHORTTEX for IWAD maps.
#define GI_COMPATSTAIRS 0x00000020 // same for stairbuilding
#define GI_COMPATPOLY1 0x00000040 // Hexen's MAP36 needs old polyobject drawing
#define GI_COMPATPOLY2 0x00000080 // so does HEXDD's MAP47
#include "gametype.h" #include "gametype.h"
@ -105,6 +108,7 @@ struct gameinfo_t
int defaultrespawntime; int defaultrespawntime;
int defaultdropstyle; int defaultdropstyle;
int player5start; int player5start;
DWORD pickupcolor;
const char *GetFinalePage(unsigned int num) const; const char *GetFinalePage(unsigned int num) const;
}; };

View file

@ -269,8 +269,16 @@ void PacketGet (void)
if (err == WSAECONNRESET) if (err == WSAECONNRESET)
{ // The remote node aborted unexpectedly, so pretend it sent an exit packet { // The remote node aborted unexpectedly, so pretend it sent an exit packet
StartScreen->NetMessage ("The connection from %s was dropped.\n", if (StartScreen != NULL)
players[sendplayer[node]].userinfo.netname); {
StartScreen->NetMessage ("The connection from %s was dropped.\n",
players[sendplayer[node]].userinfo.netname);
}
else
{
Printf("The connection from %s was dropped.\n",
players[sendplayer[node]].userinfo.netname);
}
doomcom.data[0] = 0x80; // NCMD_EXIT doomcom.data[0] = 0x80; // NCMD_EXIT
c = 1; c = 1;

View file

@ -134,6 +134,10 @@ void PClassActor::StaticInit()
// Sprite 1 is always ---- // Sprite 1 is always ----
memcpy (temp.name, "----", 5); memcpy (temp.name, "----", 5);
sprites.Push (temp); sprites.Push (temp);
// Sprite 2 is always ####
memcpy (temp.name, "####", 5);
sprites.Push (temp);
} }
Printf ("LoadActors: Load actor definitions.\n"); Printf ("LoadActors: Load actor definitions.\n");
@ -625,7 +629,6 @@ CCMD (dumpmapthings)
FDoomEdMap::DumpMapThings (); FDoomEdMap::DumpMapThings ();
} }
bool CheckCheatmode ();
static void SummonActor (int command, int command2, FCommandLine argv) static void SummonActor (int command, int command2, FCommandLine argv)
{ {

View file

@ -46,20 +46,28 @@
#include "vm.h" #include "vm.h"
#include "s_sound.h" #include "s_sound.h"
const BYTE SF_FULLBRIGHT = 0x40;
struct Baggage; struct Baggage;
class FScanner; class FScanner;
struct FActorInfo; struct FActorInfo;
class FArchive; class FArchive;
// Sprites that are fixed in position because they can have special meanings.
enum
{
SPR_TNT1, // The empty sprite
SPR_FIXED, // Do not change sprite or frame
SPR_NOCHANGE, // Do not change sprite (frame change is okay)
};
struct FState struct FState
{ {
WORD sprite; WORD sprite;
SWORD Tics; SWORD Tics;
long Misc1; // Was changed to SBYTE, reverted to long for MBF compat int Misc1; // Was changed to SBYTE, reverted to long for MBF compat
long Misc2; // Was changed to BYTE, reverted to long for MBF compat int Misc2; // Was changed to BYTE, reverted to long for MBF compat
BYTE Frame; BYTE Frame:6;
BYTE Fullbright:1; // State is fullbright
BYTE SameFrame:1; // Ignore Frame (except when spawning actor)
BYTE DefineFlags; // Unused byte so let's use it during state creation. BYTE DefineFlags; // Unused byte so let's use it during state creation.
short Light; short Light;
FState *NextState; FState *NextState;
@ -67,11 +75,15 @@ struct FState
inline int GetFrame() const inline int GetFrame() const
{ {
return Frame & ~(SF_FULLBRIGHT); return Frame;
}
inline bool GetSameFrame() const
{
return SameFrame;
} }
inline int GetFullbright() const inline int GetFullbright() const
{ {
return Frame & SF_FULLBRIGHT ? 0x10 /*RF_FULLBRIGHT*/ : 0; return Fullbright ? 0x10 /*RF_FULLBRIGHT*/ : 0;
} }
inline int GetTics() const inline int GetTics() const
{ {
@ -91,7 +103,7 @@ struct FState
} }
inline void SetFrame(BYTE frame) inline void SetFrame(BYTE frame)
{ {
Frame = (Frame & SF_FULLBRIGHT) | (frame-'A'); Frame = frame - 'A';
} }
void SetAction(VMFunction *func) { ActionFunc = func; } void SetAction(VMFunction *func) { ActionFunc = func; }
bool CallAction(AActor *self, AActor *stateowner, StateCallData *statecall = NULL); bool CallAction(AActor *self, AActor *stateowner, StateCallData *statecall = NULL);
@ -185,6 +197,7 @@ public:
FName BloodType3; // AxeBlood replacement type FName BloodType3; // AxeBlood replacement type
DDropItem *DropItems; DDropItem *DropItems;
FString SourceLumpName;
// Old Decorate compatibility stuff // Old Decorate compatibility stuff
bool DontHurtShooter; bool DontHurtShooter;

View file

@ -302,6 +302,19 @@ void DArgs::AppendArgs(int argc, const FString *argv)
} }
} }
//===========================================================================
//
// DArgs :: RemoveArg
//
// Removes a single argument from argv.
//
//===========================================================================
void DArgs::RemoveArg(int argindex)
{
Argv.Delete(argindex);
}
//=========================================================================== //===========================================================================
// //
// DArgs :: CollectFiles // DArgs :: CollectFiles

View file

@ -53,6 +53,7 @@ public:
void AppendArg(FString arg); void AppendArg(FString arg);
void AppendArgs(int argc, const FString *argv); void AppendArgs(int argc, const FString *argv);
void RemoveArg(int argindex);
void SetArgs(int argc, char **argv); void SetArgs(int argc, char **argv);
void CollectFiles(const char *param, const char *extension); void CollectFiles(const char *param, const char *extension);
DArgs *GatherFiles(const char *param) const; DArgs *GatherFiles(const char *param) const;

View file

@ -91,8 +91,3 @@ int FBoundingBox::BoxOnLineSide (const line_t *ld) const
return (p1 == p2) ? p1 : -1; return (p1 == p2) ? p1 : -1;
} }

View file

@ -25,6 +25,7 @@
#include "doomtype.h" #include "doomtype.h"
struct line_t; struct line_t;
struct node_t;
class FBoundingBox class FBoundingBox
{ {

View file

@ -601,7 +601,7 @@ void GiveSpawner (player_t *player, PClassInventory *type, int amount)
void cht_Give (player_t *player, const char *name, int amount) void cht_Give (player_t *player, const char *name, int amount)
{ {
bool giveall; enum { ALL_NO, ALL_YES, ALL_YESYES } giveall;
int i; int i;
PClassActor *type; PClassActor *type;
@ -613,9 +613,17 @@ void cht_Give (player_t *player, const char *name, int amount)
return; return;
} }
giveall = (stricmp (name, "all") == 0); giveall = ALL_NO;
if (stricmp (name, "all") == 0)
{
giveall = ALL_YES;
}
else if (stricmp (name, "everything") == 0)
{
giveall = ALL_YESYES;
}
if (giveall || stricmp (name, "health") == 0) if (stricmp (name, "health") == 0)
{ {
if (amount > 0) if (amount > 0)
{ {
@ -640,9 +648,6 @@ void cht_Give (player_t *player, const char *name, int amount)
player->health = deh.GodHealth; player->health = deh.GodHealth;
} }
} }
if (!giveall)
return;
} }
if (giveall || stricmp (name, "backpack") == 0) if (giveall || stricmp (name, "backpack") == 0)
@ -757,7 +762,7 @@ void cht_Give (player_t *player, const char *name, int amount)
player->weapons.LocateWeapon(static_cast<PClassWeapon *>(type), NULL, NULL)) player->weapons.LocateWeapon(static_cast<PClassWeapon *>(type), NULL, NULL))
{ {
AWeapon *def = (AWeapon*)GetDefaultByType (type); AWeapon *def = (AWeapon*)GetDefaultByType (type);
if (!(def->WeaponFlags & WIF_CHEATNOTWEAPON)) if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON))
{ {
GiveSpawner (player, static_cast<PClassInventory *>(type), 1); GiveSpawner (player, static_cast<PClassInventory *>(type), 1);
} }
@ -783,7 +788,7 @@ void cht_Give (player_t *player, const char *name, int amount)
!type->IsDescendantOf (RUNTIME_CLASS(APowerup)) && !type->IsDescendantOf (RUNTIME_CLASS(APowerup)) &&
!type->IsDescendantOf (RUNTIME_CLASS(AArmor))) !type->IsDescendantOf (RUNTIME_CLASS(AArmor)))
{ {
GiveSpawner (player, static_cast<PClassInventory *>(type), 1); GiveSpawner (player, static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount);
} }
} }
} }
@ -801,7 +806,7 @@ void cht_Give (player_t *player, const char *name, int amount)
AInventory *def = (AInventory*)GetDefaultByType (type); AInventory *def = (AInventory*)GetDefaultByType (type);
if (def->Icon.isValid()) if (def->Icon.isValid())
{ {
GiveSpawner (player, static_cast<PClassInventory *>(type), 1); GiveSpawner (player, static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount);
} }
} }
} }
@ -1063,7 +1068,6 @@ void cht_Suicide (player_t *plyr)
} }
} }
bool CheckCheatmode ();
CCMD (mdk) CCMD (mdk)
{ {

Some files were not shown because too many files have changed in this diff Show more