- 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_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
if( CMAKE_COMPILER_IS_GNUCXX AND PROFILE )
set( CMAKE_C_FLAGS_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( CMAKE_COMPILER_IS_GNUCXX AND PROFILE )
if( ZLIB_FOUND )
option(FORCE_INTERNAL_ZLIB "Use internal zlib")
option(FORCE_INTERNAL_JPEG "Use internal jpeg")
option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
message( STATUS "Using system zlib" )
else( ZLIB_FOUND )
else( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
message( STATUS "Using internal zlib" )
add_subdirectory( zlib )
set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib )
set( ZLIB_LIBRARIES 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" )
else( JPEG_FOUND )
else( JPEG_FOUND AND NOT FORCE_INTERNAL_JPEG )
message( STATUS "Using internal jpeg library" )
add_subdirectory( jpeg-6b )
set( JPEG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/jpeg-6b )
set( JPEG_LIBRARIES 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" )
else( BZIP2_FOUND )
else( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 )
message( STATUS "Using internal bzip2 library" )
add_subdirectory( bzip2 )
set( BZIP2_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bzip2" )
set( BZIP2_LIBRARIES 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" )

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.
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.
@ -38,7 +38,8 @@ between the TEXTMAP and ENDMAP lumps:
BEHAVIOR = contains compiled ACS code
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.
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
renderstyle = <string>; // Render style, can be "translucent" or "add",
// default is "translucent".
playeruseback = <bool>; // New SPAC flag, true = player can use from back side.
anycross = <bool>; // New SPAC flag, true = any non-projectile
// crossing will 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
dropactors = <bool>; // Actors drop with instantly moving floors (*)
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
@ -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.
// 8 is the maximum amount of classes the class
// 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
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
===============================================================================

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( CheckFunctionExists )
include( CheckCXXCompilerFlag )
include( FindPkgConfig )
option( NO_ASM "Disable assembly code" )
if( CMAKE_COMPILER_IS_GNUCXX )
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 )
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" )
if( CMAKE_SIZEOF_VOID_P MATCHES "8" )
set( X64 64 )
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
# 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.
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"
"15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03"
"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" )
foreach( majver ${MAJOR_VERSIONS} )
foreach( minver ${MINOR_VERSIONS} )
@ -230,14 +242,11 @@ else( FMOD_LIBRARY )
endif( FMOD_LIBRARY )
# Search for NASM
# Search for FluidSynth
if( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc )
if( NOT NO_ASM )
message( STATUS "Disabling assembly code for PowerPC." )
set( NO_ASM ON )
endif( NOT NO_ASM )
endif( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc )
include( ../FindFluidSynth.cmake )
# Search for NASM
if( NOT NO_ASM )
if( UNIX AND X64 )
@ -297,7 +306,12 @@ if( NOT NO_ASM )
set( ASM_FLAGS )
set( ASM_SOURCE_EXTENSION .s )
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 )
endif( X64 )
else( UNIX )
@ -327,9 +341,52 @@ if( NOT NO_ASM )
ENDMACRO( ADD_ASM_FILE )
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
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" )
if( NOT PROFILE )
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
@ -375,6 +432,13 @@ if( NOT STRNICMP_EXISTS )
add_definitions( -Dstrnicmp=strncasecmp )
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 )
add_definitions( -D__forceinline=inline )
endif( NOT MSVC )
@ -408,6 +472,12 @@ if( NOT HAS_VA_COPY )
endif( HAS___VA_COPY )
endif( NOT HAS_VA_COPY )
# Flags
if( BACKPATCH )
add_definitions( -DBACKPATCH )
endif( BACKPATCH )
# Update svnrevision.h
add_custom_target( revision_check ALL
@ -417,8 +487,16 @@ add_custom_target( revision_check ALL
# Libraries ZDoom needs
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
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
@ -466,7 +544,7 @@ else( WIN32 )
sdl/sdlvideo.cpp
sdl/st_start.cpp )
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( WIN32 )
@ -507,12 +585,23 @@ add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h
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( NOT_X86 ON )
else( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc )
set( X86_SOURCES nodebuild_classify_sse2.cpp )
endif( CMAKE_SYSTEM_PROCESSOR MATCHES powerpc )
endif( SSE_MATTERS )
if( DYN_FLUIDSYNTH )
add_definitions( -DHAVE_FLUIDSYNTH -DDYN_FLUIDSYNTH )
elseif( FLUIDSYNTH_FOUND )
add_definitions( -DHAVE_FLUIDSYNTH )
endif( DYN_FLUIDSYNTH )
add_executable( zdoom WIN32
autostart.cpp
@ -578,7 +667,6 @@ add_executable( zdoom WIN32
m_png.cpp
m_random.cpp
md5.cpp
mus2midi.cpp
name.cpp
nodebuild.cpp
nodebuild_classify_nosse2.cpp
@ -596,6 +684,7 @@ add_executable( zdoom WIN32
p_effect.cpp
p_enemy.cpp
p_floor.cpp
p_glnodes.cpp
p_interaction.cpp
p_lights.cpp
p_linkedsectors.cpp
@ -620,6 +709,7 @@ add_executable( zdoom WIN32
p_tick.cpp
p_trace.cpp
p_udmf.cpp
p_usdf.cpp
p_user.cpp
p_writemap.cpp
p_xlat.cpp
@ -663,9 +753,7 @@ add_executable( zdoom WIN32
zstring.cpp
g_doom/a_doommisc.cpp
g_heretic/a_hereticmisc.cpp
g_heretic/heretic_sbar.cpp
g_hexen/a_hexenmisc.cpp
g_hexen/hexen_sbar.cpp
g_raven/a_artitele.cpp
g_raven/a_minotaur.cpp
g_strife/a_strifestuff.cpp
@ -729,13 +817,16 @@ add_executable( zdoom WIN32
sound/music_cd.cpp
sound/music_dumb.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_midi_base.cpp
sound/music_midi_midiout.cpp
sound/music_midi_timidity.cpp
sound/music_mus_midiout.cpp
sound/music_mus_opl.cpp
sound/music_stream.cpp
sound/music_fluidsynth_mididevice.cpp
sound/music_softsynth_mididevice.cpp
sound/music_timidity_mididevice.cpp
sound/music_win_mididevice.cpp
textures/automaptexture.cpp
@ -824,21 +915,12 @@ if( NOT WIN32 )
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
endif( NOT WIN32 )
if( CMAKE_COMPILER_IS_GNUCXX )
# GCC misoptimizes this file
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.
if( NOT NOT_X86 )
if( SSE_MATTERS )
set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
endif( NOT NOT_X86 )
endif( SSE_MATTERS )
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_SetTextureScale, 56, 5, 5, 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_Stop, 61, 1, 1, 1)
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(TeleportGroup, 77, 5, 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_Suspend, 81, 2, 2, 2)
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2, 2)
DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5, 5)
DEFINE_SPECIAL(ACS_ExecuteWithResult, 84, 1, 4, 4)
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_RotateRight, 91, 3, 3, 3)
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(Radius_Quake, 120, 5, 5, 5) // Earthquake
DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5)
DEFINE_SPECIAL(Thing_Move, 125, 2, 3, 3)
DEFINE_SPECIAL(Thing_SetSpecial, 127, 5, 5, 5)
DEFINE_SPECIAL(ThrustThingZ, 128, 4, 4, 4)
DEFINE_SPECIAL(UsePuzzleItem, 129, 2, 5, 5)

View file

@ -40,6 +40,7 @@
#include "r_blend.h"
#include "s_sound.h"
struct subsector_t;
class PClassAmmo;
//
@ -262,7 +263,7 @@ enum
MF4_NOEXTREMEDEATH = 0x10000000, // this projectile or weapon never gibs its victim
MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
/* = 0x80000000, */
MF4_BOSSSPAWNED = 0x80000000, // Spawned by a boss spawn cube
// --- mobj.flags5 ---
@ -321,6 +322,9 @@ enum
MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions
MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering
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 ---
@ -616,7 +620,7 @@ public:
bool CheckLocalView (int playernum) const;
// Finds the first item of a particular type.
AInventory *FindInventory (PClassActor *type);
AInventory *FindInventory (PClassActor *type, bool subclass=false);
AInventory *FindInventory (FName type);
template<class T> T *FindInventory ()
{
@ -695,22 +699,29 @@ public:
PClassActor *GetBloodType(int type = 0) const
{
PClassActor *bloodcls;
if (type == 0)
{
return PClass::FindActor(GetClass()->BloodType);
bloodcls = PClass::FindActor(GetClass()->BloodType);
}
else if (type == 1)
{
return PClass::FindActor(GetClass()->BloodType2);
bloodcls = PClass::FindActor(GetClass()->BloodType2);
}
else if (type == 2)
{
return PClass::FindActor(GetClass()->BloodType3);
bloodcls = PClass::FindActor(GetClass()->BloodType3);
}
else
{
return NULL;
}
if (bloodcls != NULL)
{
bloodcls = bloodcls->GetReplacement();
}
return bloodcls;
}
// Calculate amount of missile damage
@ -742,6 +753,7 @@ public:
fixed_t pitch, roll;
FBlockNode *BlockNode; // links in blocks (if needed)
struct sector_t *Sector;
subsector_t * subsector;
fixed_t floorz, ceilingz; // closest together of contacted secs
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
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
struct msecnode_t *touching_sectorlist; // phares 3/14/98
@ -859,8 +880,9 @@ public:
FState *MeleeState;
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.
FDecalBase *DecalGenerator;
@ -890,8 +912,7 @@ public:
void SetOrigin (fixed_t x, fixed_t y, fixed_t z);
bool InStateSequence(FState * newstate, FState * basestate);
int GetTics(FState * newstate);
bool SetState (FState *newstate);
bool SetStateNF (FState *newstate);
bool SetState (FState *newstate, bool nofunction=false);
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
bool isFast();
void SetIdle();

View file

@ -36,6 +36,9 @@
#include "r_translate.h"
#include "d_event.h"
#include "gi.h"
#include "r_bsp.h"
#include "p_setup.h"
#include "c_bind.h"
#include "m_cheat.h"
#include "i_system.h"
@ -58,6 +61,8 @@
#include "am_map.h"
#include "a_artifacts.h"
#include "po_man.h"
#include "a_keys.h"
struct AMColor
{
@ -79,7 +84,7 @@ struct AMColor
static AMColor Background, YourColor, WallColor, TSWallColor,
FDWallColor, CDWallColor, ThingColor,
ThingColor_Item, ThingColor_Monster, ThingColor_Friend,
ThingColor_Item, ThingColor_CountItem, ThingColor_Monster, ThingColor_Friend,
SecretWallColor, GridColor, XHairColor,
NotSeenColor,
LockedColor,
@ -170,27 +175,66 @@ CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE);
CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE);
CVAR (Int, am_map_secrets, 1, 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_monster, 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_monster, 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
@ -202,10 +246,10 @@ CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE);
#define F_PANINC (140/TICRATE)
// how much zoom-in per tic
// 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
// 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
#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 } }
};
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
mline_t player_arrow_raven[] = {
{ { -R+R/4, 0 }, { 0, 0} }, // center line.
{ { -R+R/4, R/8 }, { R, 0} }, // blade
{ { -R+R/4, -R/8 }, { R, 0 } },
{ { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece
{ { -R+R/8, -R/4 }, { -R+R/8, R/4 } },
{ { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors
{ { -R+R/8, R/4 }, { -R+R/4, R/4} },
{ { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel
{ { -R-R/4, R/8 }, { -R+R/8, R/8 } },
{ { -R-R/4, -R/8}, { -R+R/8, -R/8 } }
};
#undef R
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
{ { -R+R/4, 0 }, { 0, 0} }, // center line.
{ { -R+R/4, R/8 }, { R, 0} }, // blade
{ { -R+R/4, -R/8 }, { R, 0 } },
{ { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece
{ { -R+R/8, -R/4 }, { -R+R/8, R/4 } },
{ { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors
{ { -R+R/8, R/4 }, { -R+R/4, R/4} },
{ { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel
{ { -R-R/4, R/8 }, { -R+R/8, R/8 } },
{ { -R-R/4, -R/8}, { -R+R/8, -R/8 } }
};
#define NUMPLYRLINES_RAVEN (sizeof(player_arrow_raven)/sizeof(mline_t))
#define R ((8*PLAYERRADIUS)/7)
mline_t cheat_player_arrow[] = {
{ { -R+R/8, 0 }, { R, 0 } }, // -----
{ { 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/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
};
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
#undef R
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
#define R (MAPUNIT)
// [RH] Avoid lots of warnings without compiler-specific #pragmas
@ -309,9 +350,37 @@ mline_t thintriangle_guy[] = {
L (1,0, -.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 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 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_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_rotate (fixed_t *x, fixed_t *y, angle_t an);
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
// segment in map coordinates (with the upright y-axis n' all) so
@ -702,11 +833,19 @@ void AM_initVariables ()
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;
amclock = 0;
m_paninc.x = m_paninc.y = 0;
ftom_zoommul = MAPUNIT;
mtof_zoommul = MAPUNIT;
m_w = FTOM(SCREENWIDTH);
@ -774,6 +913,7 @@ static void AM_initColors (bool overlayed)
SecretWallColor = WallColor;
SecretSectorColor.FromCVar (am_ovsecretsectorcolor);
ThingColor_Item.FromCVar (am_ovthingcolor_item);
ThingColor_CountItem.FromCVar (am_ovthingcolor_citem);
ThingColor_Friend.FromCVar (am_ovthingcolor_friend);
ThingColor_Monster.FromCVar (am_ovthingcolor_monster);
ThingColor.FromCVar (am_ovthingcolor);
@ -797,6 +937,7 @@ static void AM_initColors (bool overlayed)
FDWallColor.FromCVar (am_fdwallcolor);
CDWallColor.FromCVar (am_cdwallcolor);
ThingColor_Item.FromCVar (am_thingcolor_item);
ThingColor_CountItem.FromCVar (am_thingcolor_citem);
ThingColor_Friend.FromCVar (am_thingcolor_friend);
ThingColor_Monster.FromCVar (am_thingcolor_monster);
ThingColor.FromCVar (am_thingcolor);
@ -946,6 +1087,8 @@ void AM_LevelInit ()
if (scale_mtof > max_scale_mtof)
scale_mtof = min_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;
static int cheatstate = 0;
static int bigstate = 0;
rc = false;
if (automapactive && ev->type == EV_KeyDown)
if (automapactive && (ev->type == EV_KeyDown || ev->type == EV_KeyUp))
{
rc = true;
switch (ev->data1)
if (followplayer)
{
case AM_PANRIGHTKEY: // pan right
if (!followplayer)
m_paninc.x = FTOM(F_PANINC);
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;
}
// check for am_pan* and ignore in follow mode
const char *defbind = AutomapBindings.GetBind(ev->data1);
if (!strnicmp(defbind, "+am_pan", 7)) return 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 ()
{
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
scale_mtof = MapMul(scale_mtof, mtof_zoommul);
scale_ftom = MapDiv(MAPUNIT, scale_mtof);
@ -1223,6 +1287,13 @@ void AM_changeWindowScale ()
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
@ -1284,10 +1342,20 @@ void AM_Ticker ()
amclock++;
if (followplayer)
{
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
if (ftom_zoommul != MAPUNIT)
if (Button_AM_ZoomIn.bDown || Button_AM_ZoomOut.bDown || am_zoomdir != 0)
AM_changeWindowScale();
// 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.
@ -1601,7 +1834,12 @@ void AM_drawWalls (bool allmap)
if (am_cheat != 0 || (lines[i].flags & ML_MAPPED))
{
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
continue;
{
if (!am_showallenabled || CheckCheatmode(false))
{
continue;
}
}
if (AM_CheckSecret(&lines[i]))
{
@ -1680,8 +1918,14 @@ void AM_drawWalls (bool allmap)
}
else if (allmap)
{
if (!(lines[i].flags & ML_DONTDRAW))
AM_drawMline(&l, NotSeenColor);
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
{
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;
tmpx = DMulScale16 (*x,finecosine[a],*y,-finesine[a]);
*y = DMulScale16 (*x,finesine[a],*y,finecosine[a]);
*x = tmpx;
if (angle_saved != a)
{
angle_saved = a;
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;
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
(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
16<<MAPBITS, angle, color, p.x, p.y);
if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c));
else color = ThingColor_CountItem;
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)
{
@ -2041,7 +2327,11 @@ void AM_drawAuthorMarkers ()
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,
flip, mark->scaleX, mark->scaleY, mark->Translation,
@ -2075,7 +2365,7 @@ void AM_Drawer ()
return;
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);
@ -2100,6 +2390,9 @@ void AM_Drawer ()
}
AM_activateNewScale();
if (am_textured && hasglnodes && textured && !viewactive)
AM_drawSubsectors();
if (grid)
AM_drawGrid(GridColor);
@ -2114,6 +2407,8 @@ void AM_Drawer ()
AM_drawCrosshair(XHairColor);
AM_drawMarks();
AM_showSS();
}
//=============================================================================

View file

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

View file

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

View file

@ -216,7 +216,13 @@ SetTiltedSpanSize:
ret
%ifndef M_TARGET_MACHO
SECTION .rtext progbits alloc exec write align=64
%else
SECTION .text align=64
GLOBAL _rtext_tmap2_start
_rtext_tmap2_start:
%endif
rtext_start:
@ -628,3 +634,7 @@ fetch10 mov al,[ebp+esi+SPACEFILLER4]
ret
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
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
%endif
ALIGN 16
@ -331,3 +337,8 @@ shift12: shr ecx,16
pop ebx
pop ebp
ret
%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap3_end
_rtext_tmap3_end:
%endif

View file

@ -1,28 +1,28 @@
#%include "valgrind.inc"
#%include "valgrind.inc"
.section .text
.section .text
.globl ASM_PatchPitch
ASM_PatchPitch:
.globl ASM_PatchPitch
ASM_PatchPitch:
movl dc_pitch(%rip), %ecx
movl %ecx, pm+3(%rip)
movl %ecx, vltpitch+3(%rip)
# selfmod pm, vltpitch+6
ret
.align 16
movl %ecx, vltpitch+3(%rip)
# selfmod pm, vltpitch+6
ret
.align 16
.globl setupvlinetallasm
.globl setupvlinetallasm
setupvlinetallasm:
movb %dil, shifter1+2(%rip)
movb %dil, shifter2+2(%rip)
movb %dil, shifter3+2(%rip)
movb %dil, shifter4+2(%rip)
# selfmod shifter1, shifter4+3
movb %dil, shifter4+2(%rip)
# selfmod shifter1, shifter4+3
ret
.align 16
.section .rtext,"awx"
.align 16
.section .rtext,"awx"
.globl vlinetallasm4
.type vlinetallasm4,@function
vlinetallasm4:
@ -38,18 +38,18 @@ vlinetallasm4:
subq $8, %rsp # Does the stack need to be 16-byte aligned for Linux?
.cfi_adjust_cfa_offset 8
# rax = bufplce base address
# rbx =
# rcx = offset from rdi/count (negative)
# edx/rdx = scratch
# rdi = bottom of columns to write to
# r8d-r11d = column offsets
# r12-r15 = palookupoffse[0] - palookupoffse[4]
# rax = bufplce base address
# rbx =
# rcx = offset from rdi/count (negative)
# edx/rdx = scratch
# rdi = bottom of columns to write to
# r8d-r11d = column offsets
# r12-r15 = palookupoffse[0] - palookupoffse[4]
movl dc_count(%rip), %ecx
movq dc_dest(%rip), %rdi
testl %ecx, %ecx
jle vltepilog # count must be positive
jle vltepilog # count must be positive
movq bufplce(%rip), %rax
movq bufplce+8(%rip), %r8
@ -60,14 +60,14 @@ vlinetallasm4:
subq %rax, %r10
movl %r8d, source2+4(%rip)
movl %r9d, source3+4(%rip)
movl %r10d, source4+4(%rip)
movl %r10d, source4+4(%rip)
pm: imulq $320, %rcx
pm: imulq $320, %rcx
movq palookupoffse(%rip), %r12
movq palookupoffse+8(%rip), %r13
movq palookupoffse+16(%rip), %r14
movq palookupoffse+24(%rip), %r15
movq palookupoffse+24(%rip), %r15
movl vince(%rip), %r8d
movl vince+4(%rip), %r9d
@ -76,53 +76,53 @@ pm: imulq $320, %rcx
movl %r8d, step1+3(%rip)
movl %r9d, step2+3(%rip)
movl %r10d, step3+3(%rip)
movl %r11d, step4+3(%rip)
movl %r11d, step4+3(%rip)
addq %rcx, %rdi
negq %rcx
negq %rcx
movl vplce(%rip), %r8d
movl vplce+4(%rip), %r9d
movl vplce+8(%rip), %r10d
movl vplce+12(%rip), %r11d
# selfmod loopit, vltepilog
jmp loopit
jmp loopit
.align 16
.align 16
loopit:
movl %r8d, %edx
shifter1: shrl $24, %edx
step1: addl $0x88888888, %r8d
step1: addl $0x44444444, %r8d
movzbl (%rax,%rdx), %edx
movl %r9d, %ebx
movb (%r12,%rdx), %dl
shifter2: shrl $24, %ebx
step2: addl $0x88888888, %r9d
source2: movzbl 0x88888888(%rax,%rbx), %ebx
step2: addl $0x44444444, %r9d
source2: movzbl 0x44444444(%rax,%rbx), %ebx
movl %r10d, %ebp
movb (%r13,%rbx), %bl
shifter3: shr $24, %ebp
step3: addl $0x88888888, %r10d
source3: movzbl 0x88888888(%rax,%rbp), %ebp
step3: addl $0x44444444, %r10d
source3: movzbl 0x44444444(%rax,%rbp), %ebp
movl %r11d, %esi
movb (%r14,%rbp), %bpl
shifter4: shr $24, %esi
step4: add $0x88888888, %r11d
source4: movzbl 0x88888888(%rax,%rsi), %esi
step4: add $0x44444444, %r11d
source4: movzbl 0x44444444(%rax,%rsi), %esi
movb %dl, (%rdi,%rcx)
movb %bl, 1(%rdi,%rcx)
movb (%r15,%rsi), %sil
movb %bpl, 2(%rdi,%rcx)
movb %sil, 3(%rdi,%rcx)
vltpitch: addq $320, %rcx
jl loopit
vltpitch: addq $320, %rcx
jl loopit
movl %r8d, vplce(%rip)
movl %r9d, vplce+4(%rip)
movl %r10d, vplce+8(%rip)
movl %r11d, vplce+12(%rip)
movl %r11d, vplce+12(%rip)
vltepilog:
addq $8, %rsp
.cfi_adjust_cfa_offset -8
@ -137,5 +137,5 @@ vltepilog:
ret
.cfi_endproc
.align 16

View file

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

View file

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

View file

@ -47,12 +47,6 @@
#include <math.h>
#include <stdlib.h>
struct FBinding
{
const char *Key;
const char *Bind;
};
/* Default keybindings for Doom (and all other games)
*/
static const FBinding DefBindings[] =
@ -178,6 +172,29 @@ static const FBinding DefStrifeBindings[] =
// 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] =
{
// 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"
};
static FString Bindings[NUM_KEYS];
static FString DoubleBindings[NUM_KEYS];
FKeyBindings Bindings;
FKeyBindings DoubleBindings;
FKeyBindings AutomapBindings;
static unsigned int DClickTime[NUM_KEYS];
static BYTE DClicked[(NUM_KEYS+7)/8];
//=============================================================================
//
//
//
//=============================================================================
static int GetKeyFromName (const char *name)
{
int i;
@ -302,380 +327,15 @@ static int GetKeyFromName (const char *name)
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)
{
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);
int keynum = GetKeyFromName(key);
if (keynum == 0)
{
if (stricmp (key, "LeftBracket") == 0)
@ -695,32 +355,55 @@ void C_DoBind (const char *key, const char *bind, bool dodouble)
keynum = GetKeyFromName ("kp=");
}
}
if (keynum != 0)
{
(dodouble ? DoubleBindings : Bindings)[keynum] = bind;
}
return keynum;
}
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)
{
if (stricmp (cmd, Bindings[i]) == 0)
{
if (c++ == 0)
*first = i;
else
*second = i;
}
i++;
}
return c;
mysnprintf (name, countof(name), "#%d", key);
return name;
}
//=============================================================================
//
//
//
//=============================================================================
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)
{
int c = 0;
@ -744,28 +427,471 @@ void C_NameKeys (char *str, int first, int second)
*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;
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__
#define __C_BINDINGS_H__
#include "doomdef.h"
struct event_t;
class FConfigFile;
class FCommandLine;
bool C_DoKey (event_t *ev);
void C_ArchiveBindings (FConfigFile *f, bool dodouble, const char *matchcmd=NULL);
void C_NameKeys (char *str, int first, int second);
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
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_UnbindAll ();
// Returns string bound to given key (NULL if none)
const char *C_GetBinding (int key);
extern const char *KeyNames[];
#endif //__C_BINDINGS_H__

View file

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

View file

@ -39,6 +39,8 @@
class FConfigFile;
class APlayerPawn;
extern bool CheckCheatmode (bool printmsg = true);
void C_ExecCmdLineParams ();
// 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 ReleaseKey (int keynum); // Returns true if this key is no longer pressed.
void ResetTriggers () { bWentDown = bWentUp = false; }
void Reset () { bDown = bWentDown = bWentUp = false; }
};
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_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch,
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;
void ResetButtonTriggers (); // Call ResetTriggers for all buttons

View file

@ -2,10 +2,14 @@
#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#if !defined(__sun)
#include <fts.h>
#endif
#endif
#include "doomtype.h"
#include "cmdlib.h"
@ -90,6 +94,23 @@ char *copystring (const char *s)
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
@ -868,3 +889,153 @@ FString NicePath(const char *path)
return where;
#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
char *copystring(const char *s);
char *ncopystring(const char *s);
void ReplaceString (char **ptr, const char *str);
bool CheckWildcards (const char *pattern, const char *text);
@ -53,4 +54,12 @@ void CreatePath(const char * fn);
FString ExpandEnvVars(const char *searchpathstring);
FString NicePath(const char *path);
struct FFileList
{
FString Filename;
bool isDirectory;
};
void ScanDirectory(TArray<FFileList> &list, const char *dirpath);
#endif

View file

@ -43,10 +43,13 @@
#include "sc_man.h"
#include "cmdlib.h"
#include "doomdef.h"
#include "doomdata.h"
#include "doomstat.h"
#include "c_dispatch.h"
#include "gi.h"
#include "g_level.h"
#include "p_lnspec.h"
#include "r_state.h"
// MACROS ------------------------------------------------------------------
@ -59,6 +62,14 @@ struct FCompatOption
int BCompatFlags;
};
enum
{
CP_END,
CP_CLEARFLAGS,
CP_SETFLAGS,
CP_SETSPECIAL
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -77,7 +88,6 @@ static FCompatOption Options[] =
{
{ "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW },
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
{ "spechitoverflow", 0, BCOMPATF_SPECHITOVERFLOW },
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
// list copied from g_mapinfo.cpp
@ -106,9 +116,15 @@ static FCompatOption Options[] =
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 },
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
{ "spritesort", COMPATF_SPRITESORT, 0 },
{ "hitscan", COMPATF_HITSCAN, 0 },
{ "lightlevel", COMPATF_LIGHT, 0 },
{ "polyobj", COMPATF_POLYOBJ, 0 },
{ NULL, 0, 0 }
};
static TArray<int> CompatParams;
static int ii_compatparams;
// CODE --------------------------------------------------------------------
//==========================================================================
@ -170,12 +186,57 @@ void ParseCompatibility()
} while (!sc.Compare("{"));
flags.CompatFlags = 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;
flags.BCompatFlags |= Options[i].BCompatFlags;
if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0)
{
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("}");
for (j = 0; j < md5array.Size(); ++j)
{
@ -196,12 +257,29 @@ void CheckCompatibility(MapData *map)
FMD5Holder md5;
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))
{
ii_compatflags = COMPATF_SHORTTEX;
ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT;
if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX;
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
{
map->GetChecksum(md5.Bytes);
@ -223,17 +301,74 @@ void CheckCompatibility(MapData *map)
{
ii_compatflags = flags->CompatFlags;
ib_compatflags = flags->BCompatFlags;
ii_compatparams = flags->ExtCommandIndex;
}
else
{
ii_compatflags = 0;
ib_compatflags = 0;
ii_compatparams = -1;
}
}
// Reset i_compatflags
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

View file

@ -16,6 +16,7 @@ struct FCompatValues
{
int CompatFlags;
int BCompatFlags;
unsigned int ExtCommandIndex;
};
struct FMD5HashTraits
@ -37,5 +38,6 @@ extern TMap<FMD5Holder, FCompatValues, FMD5HashTraits> BCompatMap;
void ParseCompatibility();
void CheckCompatibility(MapData *map);
void SetCompatibilityParams();
#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
// 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.
// 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;
char *strval;
@ -1355,8 +1355,8 @@ static int PatchFrame (int frameNum)
}
info->Tics = tics;
info->Misc1 = misc1;
info->Frame = (frame & 0x3f) |
(frame & 0x8000 ? SF_FULLBRIGHT : 0);
info->Frame = frame & 0x3f;
info->Fullbright = frame & 0x8000 ? true : false;
}
return result;
@ -2106,13 +2106,13 @@ static int PatchText (int oldSize)
// This must be done because the map is scanned using a binary search.
while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0)
{
swap (DehSpriteMappings[i-1], DehSpriteMappings[i]);
swapvalues (DehSpriteMappings[i-1], DehSpriteMappings[i]);
--i;
}
while ((size_t)i < countof(DehSpriteMappings)-1 &&
strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0)
{
swap (DehSpriteMappings[i+1], DehSpriteMappings[i]);
swapvalues (DehSpriteMappings[i+1], DehSpriteMappings[i]);
++i;
}
break;

View file

@ -58,10 +58,10 @@ EIWADType gameiwad;
const IWADInfo IWADInfos[NUM_IWAD_TYPES] =
{
// 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 },
{ "Hexen: Beyond Heretic", NULL, MAKERGB(240,240,240), MAKERGB(107,44,24), 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 },
{ "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 | 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 },
{ "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 },

View file

@ -38,7 +38,7 @@
#endif
#include <float.h>
#ifdef unix
#if defined(unix) || defined(__APPLE__)
#include <unistd.h>
#endif
@ -104,6 +104,7 @@
#include "compatibility.h"
#include "m_joy.h"
#include "sc_man.h"
#include "po_man.h"
#include "resourcefiles/resourcefile.h"
EXTERN_CVAR(Bool, hud_althud)
@ -120,7 +121,6 @@ extern void M_SetDefaultMode ();
extern void R_ExecuteSetViewSize ();
extern void G_NewInit ();
extern void SetupPlayerClasses ();
extern bool CheckCheatmode ();
const IWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -201,6 +201,7 @@ gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe
bool PageBlank;
FTexture *Page;
FTexture *Advisory;
bool nospriterename;
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_disallowsuicide, dmflags2, DF2_NOSUICIDE);
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)
{
int old = i_compatflags;
i_compatflags = GetCompatibility(self) | ii_compatflags;
if ((old ^i_compatflags) & COMPATF_POLYOBJ)
{
FPolyObj::ClearAllSubsectorLinks();
}
}
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
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;
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|
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;
case 3: // Boom compat mode
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL;
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP;
break;
case 4: // Old ZDoom compat mode
v = COMPATF_SOUNDTARGET;
v = COMPATF_SOUNDTARGET|COMPATF_LIGHT;
break;
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;
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;
}
@ -549,6 +564,9 @@ CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
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:
pagetic = (int)(gameinfo.pageTime * TICRATE);
gamestate = GS_DEMOSCREEN;
pagename = gameinfo.creditPages[pagecount];
pagecount = (pagecount+1) % gameinfo.creditPages.Size();
if (gameinfo.creditPages.Size() > 0)
{
pagename = gameinfo.creditPages[pagecount];
pagecount = (pagecount+1) % gameinfo.creditPages.Size();
}
demosequence = 1;
break;
}
@ -1658,6 +1679,10 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
}
while (sc.CheckToken(','));
}
else if (!nextKey.CompareNoCase("NOSPRITERENAME"))
{
nospriterename = true;
}
}
return iwad;
}
@ -1754,6 +1779,9 @@ void D_DoomMain (void)
#endif
#endif
// Check response files before coalescing file parameters.
M_FindResponseFile ();
PClass::StaticInit();
PType::StaticInit();
@ -1772,7 +1800,6 @@ void D_DoomMain (void)
rngseed = I_MakeRNGSeed();
FRandom::StaticClearRandom ();
M_FindResponseFile ();
Printf ("M_LoadDefaults: Load system defaults.\n");
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)
{
FString out;
@ -2282,6 +2317,24 @@ ADD_STAT (fps)
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

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
// have already been read, and the stream is positioned
// 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.
// That was a long time ago. Maybe it works now?
level.flags |= LEVEL_CHANGEMAPCHEAT;
G_ChangeLevel(s, pos, false);
G_ChangeLevel(s, pos, 0);
break;
case DEM_SUICIDE:
@ -2348,22 +2364,25 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_KILLCLASSCHEAT:
{
AActor *actor;
TThinkerIterator<AActor> iterator;
char *classname = ReadString (stream);
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 += actor->Massacre ();
killcount += KillAll(cls_rep);
}
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;

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
// than the old one.
R_BuildPlayerTranslation (i);
if (StatusBar != NULL && i == StatusBar->GetPlayer())
{
StatusBar->SetFace (&skins[info->skin]);
}
break;
case INFO_Gender:

View file

@ -320,7 +320,7 @@ public:
short fixedlightlevel;
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
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
PClassActor *MorphExitFlash; // flash to apply when demorphing (cache of value given to P_MorphPlayer)
TObjPtr<AWeapon> PremorphWeapon; // ready weapon before morphing

View file

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

View file

@ -60,6 +60,40 @@ ClassReg DObject::RegistrationInfo =
};
_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)
{
// This is by no means speed-optimized. But it's an informational console

View file

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

View file

@ -29,6 +29,7 @@
// Some global defines, that configure the game.
#include "doomdef.h"
#include "m_swap.h"
//
// Map level types.
@ -138,7 +139,7 @@ enum ELineFlags
ML_ADDTRANS = 0x00000400, // additive translucency (can only be set internally)
// 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_BLOCKEVERYTHING = 0x00008000, // [RH] Line blocks everything
ML_ZONEBOUNDARY = 0x00010000,
@ -168,8 +169,9 @@ enum SPAC
SPAC_AnyCross = 1<<7, // when anything without the MF2_TELEPORT flag crosses the line
SPAC_MUse = 1<<8, // monsters can use
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
@ -220,6 +222,13 @@ struct mapsubsector_t
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
// using partition lines selected by BSP builder.
@ -231,6 +240,22 @@ struct mapseg_t
WORD linedef;
SWORD side;
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.
// Indicate a leaf.
#define NF_SUBSECTOR 0x8000
struct mapnode_t
{
enum
{
NF_SUBSECTOR = 0x8000,
NF_LUMPOFFSET = 0
};
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.
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,
@ -293,6 +340,7 @@ struct FMapThing
DWORD flags;
int special;
int args[5];
int Conversation;
void Serialize (FArchive &);
};

View file

@ -290,8 +290,10 @@ enum
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_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_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.
@ -325,6 +327,9 @@ enum
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_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
@ -333,8 +338,7 @@ enum
{
BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow
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 << 3, // Monsters' radius and height aren't restored properly when resurrected.
BCOMPATF_VILEGHOSTS = 1 << 2, // Monsters' radius and height aren't restored properly when resurrected.
};
// phares 3/20/98:

View file

@ -44,12 +44,6 @@
// Since this file is included by everything, it seems an appropriate place
// 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:
//

View file

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

View file

@ -282,6 +282,10 @@ template<> inline FArchive &operator<< <FFont> (FArchive &arc, FFont* &font)
return SerializeFFontPtr (arc, font);
}
struct FStrifeDialogueNode;
template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node);
template<class T,class TT>
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)
{
assert(len >= 0);
if (len <= 0) return 0;
if (FilePos + len > StartPos + Length)
{
len = Length - FilePos + StartPos;

View file

@ -8,7 +8,56 @@
#include "doomtype.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:
FileReader ();
@ -82,13 +131,13 @@ protected:
};
// Wraps around a FileReader to decompress a zlib stream
class FileReaderZ
class FileReaderZ : public FileReaderBase
{
public:
FileReaderZ (FileReader &file, bool zip=false);
~FileReaderZ ();
long Read (void *buffer, long len);
virtual long Read (void *buffer, long len);
FileReaderZ &operator>> (BYTE &v)
{
@ -144,7 +193,7 @@ private:
};
// Wraps around a FileReader to decompress a bzip2 stream
class FileReaderBZ2
class FileReaderBZ2 : public FileReaderBase
{
public:
FileReaderBZ2 (FileReader &file);
@ -206,7 +255,7 @@ private:
};
// Wraps around a FileReader to decompress a lzma stream
class FileReaderLZMA
class FileReaderLZMA : public FileReaderBase
{
public:
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))
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);
return 0;
}
@ -261,6 +276,7 @@ static void SpawnFly(AActor *self, PClassActor *spawntype, FSoundID sound)
// telefrag anything in this spot
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;
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
if (linetarget)
@ -105,15 +106,30 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
//
// 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)
{
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_INT_OPT (damage) { damage = 2; }
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;
AActor *linetarget;
@ -122,13 +138,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
return 0;
}
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
if (pufftype == NULL)
{
pufftype = PClass::FindActor(NAME_BulletPuff);
@ -137,21 +146,61 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
{
damage = 2;
}
damage *= (pr_saw()%10 + 1);
angle = self->angle;
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, MELEERANGE+1,
P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage,
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;
}
angle = self->angle + (pr_saw.Random2() * (spread_xy / 255));
slope = P_AimLineAttack (self, angle, range, &linetarget) + (pr_saw.Random2() * (spread_z / 255));
P_LineAttack (self, angle, range,
slope, damage,
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 ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64))
{
player->extralight = !player->extralight;
}
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
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);
// turn to face target

View file

@ -17,9 +17,9 @@
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie)
{
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
AActor *other;

View file

@ -179,7 +179,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie)
self->flags &= ~MF_FRIENDLY;
}
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 + ANG180, 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_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage,
NAME_Melee, pufftype);
NAME_Melee, pufftype, false, &linetarget);
if (!linetarget)
{
@ -338,7 +338,7 @@ static void MarinePunch(AActor *self, int damagemul)
A_FaceTarget (self);
angle = self->angle + (pr_m_punch.Random2() << 18);
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
if (linetarget)

View file

@ -116,13 +116,13 @@ EXTERN_CVAR (Float, con_midtime);
//
// 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;
}
@ -288,7 +288,8 @@ CCMD (slot)
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)
{
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)
{
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)
@ -353,10 +366,9 @@ CCMD (invnext)
who->InvSel = who->Inventory;
}
}
if (displaynametags && StatusBar && SmallFont
&& gamestate == GS_LEVEL && level.time > con_midtime && who->InvSel)
StatusBar->AttachMessage (new DHUDMessage (SmallFont, who->InvSel->GetTag(),
2.5f, 0.375f, 0, 0, CR_YELLOW, con_midtime), MAKE_ID('S','I','N','V'));
if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel)
StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(),
1.5f, 0.80f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
}
who->player->inventorytics = 5*TICRATE;
}
@ -384,10 +396,9 @@ CCMD (invprev)
}
who->InvSel = item;
}
if (displaynametags && StatusBar && SmallFont
&& gamestate == GS_LEVEL && level.time > con_midtime && who->InvSel)
StatusBar->AttachMessage (new DHUDMessage (SmallFont, who->InvSel->GetTag(),
2.5f, 0.375f, 0, 0, CR_YELLOW, con_midtime), MAKE_ID('S','I','N','V'));
if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel)
StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(),
1.5f, 0.80f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
}
who->player->inventorytics = 5*TICRATE;
}
@ -871,7 +882,7 @@ bool G_Responder (event_t *ev)
if (gameaction == ga_nothing &&
(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)
{
@ -894,11 +905,11 @@ bool G_Responder (event_t *ev)
}
else
{
return C_DoKey (ev);
return C_DoKey (ev, &Bindings, &DoubleBindings);
}
}
if (cmd && cmd[0] == '+')
return C_DoKey (ev);
return C_DoKey (ev, &Bindings, &DoubleBindings);
return false;
}
@ -910,7 +921,7 @@ bool G_Responder (event_t *ev)
{
if (ST_Responder (ev))
return true; // status window ate it
if (!viewactive && AM_Responder (ev))
if (!viewactive && AM_Responder (ev, false))
return true; // automap ate it
}
else if (gamestate == GS_FINALE)
@ -922,12 +933,12 @@ bool G_Responder (event_t *ev)
switch (ev->type)
{
case EV_KeyDown:
if (C_DoKey (ev))
if (C_DoKey (ev, &Bindings, &DoubleBindings))
return true;
break;
case EV_KeyUp:
C_DoKey (ev);
C_DoKey (ev, &Bindings, &DoubleBindings);
break;
// [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.
if (gamestate == GS_LEVEL && viewactive)
return AM_Responder (ev);
return AM_Responder (ev, true);
return (ev->type == EV_KeyDown ||
ev->type == EV_Mouse);
@ -1165,7 +1176,9 @@ void G_Ticker ()
// G_PlayerFinishLevel
// 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;
player_t *p;
@ -1237,8 +1250,14 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory
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
if (resetinventory)
if (flags & CHANGELEVEL_RESETINVENTORY)
{
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_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
M_FinishPNG (stdfile);
fclose (stdfile);
M_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
// Check whether the file is ok.
bool success = false;
stdfile = fopen (filename.GetChars(), "rb");

View file

@ -71,7 +71,7 @@ enum EFinishLevelType
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);

View file

@ -186,7 +186,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
damage = 1 + (pr_beakatkpl1()&3);
angle = player->mo->angle;
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)
{
player->mo->angle = R_PointToAngle2 (player->mo->x,
@ -222,7 +222,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
damage = pr_beakatkpl2.HitDice (4);
angle = player->mo->angle;
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)
{
player->mo->angle = R_PointToAngle2 (player->mo->x,

View file

@ -151,7 +151,7 @@ void P_DSparilTeleport (AActor *actor)
DSpotState *state = DSpotState::GetSpotState();
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;
prevX = actor->x;

View file

@ -89,7 +89,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
angle = self->angle;
angle += pr_sap.Random2() << 18;
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)
{
//S_StartSound(player->mo, sfx_stfhit);
@ -291,7 +291,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
pufftype = PClass::FindActor("GauntletPuff1");
}
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 (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;
}
PClassActor *hammertime = PClass::FindActor("HammerPuff");
damage = 25+(pr_maceatk()&15);
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);
if (linetarget)
{
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("HammerPuff"), true);
AdjustPlayerAngle (player->mo, linetarget);
// player->mo->angle = R_PointToAngle2(player->mo->x,
// player->mo->y, linetarget->x, linetarget->y);
goto macedone;
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
{
AdjustPlayerAngle (player->mo, linetarget);
goto macedone;
}
}
angle = player->mo->angle-i*(ANG45/16);
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE, &linetarget);
if (linetarget)
{
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("HammerPuff"), true);
AdjustPlayerAngle (player->mo, linetarget);
// player->mo->angle = R_PointToAngle2(player->mo->x,
// player->mo->y, linetarget->x, linetarget->y);
goto macedone;
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
{
AdjustPlayerAngle (player->mo, linetarget);
goto macedone;
}
}
}
// 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;
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:
return 0;
}

View file

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

View file

@ -51,29 +51,35 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
{
angle = pmo->angle + i*(ANG45/32);
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);
AdjustPlayerAngle(pmo, linetarget);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
{
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);
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);
AdjustPlayerAngle(pmo, linetarget);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
{
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

View file

@ -167,13 +167,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack)
power = 6*FRACUNIT;
pufftype = PClass::FindActor("HammerPuff");
}
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
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);
slope = P_AimLineAttack (pmo, angle, 2*MELEERANGE, &linetarget);
@ -186,13 +189,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack)
power = 6*FRACUNIT;
pufftype = PClass::FindActor("HammerPuff");
}
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
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

View file

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

View file

@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack)
damage = 3+(pr_snoutattack()&3);
angle = player->mo->angle;
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);
if(linetarget)
{

View file

@ -115,9 +115,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise)
{ // Reached it's target height
actor->args[0] = 1;
if (actor->args[1])
actor->SetStateNF (actor->FindState ("BloodThrustInit2"));
actor->SetState (actor->FindState ("BloodThrustInit2"), true);
else
actor->SetStateNF (actor->FindState ("ThrustInit2"));
actor->SetState (actor->FindState ("ThrustInit2"), true);
}
// Lose the dirt clump
@ -142,9 +142,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower)
{
self->args[0] = 0;
if (self->args[1])
self->SetStateNF (self->FindState ("BloodThrustInit1"));
self->SetState (self->FindState ("BloodThrustInit1"), true);
else
self->SetStateNF (self->FindState ("ThrustInit1"));
self->SetState (self->FindState ("ThrustInit1"), true);
}
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();
//Did the user specify a "base"
if(cstype == GAME_Heretic)
{
StatusBar = CreateHereticStatusBar();
}
else if(cstype == GAME_Hexen)
{
StatusBar = CreateHexenStatusBar();
}
else if(cstype == GAME_Strife)
if(cstype == GAME_Strife)
{
StatusBar = CreateStrifeStatusBar();
}
@ -442,18 +434,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
}
if (StatusBar == NULL)
{
if (gameinfo.gametype & GAME_DoomChex)
if (gameinfo.gametype & (GAME_DoomChex|GAME_Heretic|GAME_Hexen))
{
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)
{
StatusBar = CreateStrifeStatusBar ();
@ -545,10 +529,8 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
static FString nextlevel;
static int startpos; // [RH] Support for multiple starts per level
extern int NoWipe; // [RH] Don't wipe when travelling in hubs
static bool startkeepfacing; // [RH] Support for keeping your facing angle
static bool resetinventory; // Reset the inventory to the player's default for the next level
static int changeflags;
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,
bool nointermission, bool resetinv, bool nomonsters)
void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill)
{
level_info_t *nextinfo = NULL;
@ -589,25 +570,32 @@ void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nex
if (nextSkill != -1)
NextSkill = nextSkill;
g_nomonsters = nomonsters;
if (nointermission) level.flags |= LEVEL_NOINTERMISSION;
if (flags & CHANGELEVEL_NOINTERMISSION)
{
level.flags |= LEVEL_NOINTERMISSION;
}
cluster_info_t *thiscluster = FindClusterInfo (level.cluster);
cluster_info_t *nextcluster = nextinfo? FindClusterInfo (nextinfo->cluster) : NULL;
startpos = position;
startkeepfacing = keepFacing;
gameaction = ga_completed;
resetinventory = resetinv;
if (nextinfo != NULL)
{
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:
@ -683,12 +671,12 @@ const char *G_GetSecretExitMap()
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)
{
G_ChangeLevel(G_GetSecretExitMap(), position, false);
G_ChangeLevel(G_GetSecretExitMap(), position, 0);
}
//==========================================================================
@ -802,7 +790,7 @@ void G_DoCompleted (void)
{
if (playeringame[i])
{ // 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;
}
if (g_nomonsters)
if (changeflags & CHANGELEVEL_NOMONSTERS)
{
level.flags2 |= LEVEL2_NOMONSTERS;
}
@ -1180,7 +1168,7 @@ void G_FinishTravel ()
// The player being spawned here is a short lived dummy and
// must not start any ENTER script or big problems will happen.
pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], true);
if (!startkeepfacing)
if (!changeflags & CHANGELEVEL_KEEPFACING)
{
pawn->angle = pawndup->angle;
pawn->pitch = pawndup->pitch;
@ -1476,8 +1464,8 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
P_SerializeThinkers (arc, hubLoad);
P_SerializeWorld (arc);
P_SerializePolyobjs (arc);
P_SerializeSubsectors(arc);
StatusBar->Serialize (arc);
//SerializeInterpolations (arc);
arc << level.total_monsters << level.total_items << level.total_secrets;

View file

@ -127,6 +127,7 @@ enum ELevelFlags
LEVEL_SPECLOWERFLOOR = 0x00000100,
LEVEL_SPECOPENDOOR = 0x00000200,
LEVEL_SPECLOWERFLOORTOHIGHEST= 0x00000300,
LEVEL_SPECACTIONSMASK = 0x00000300,
LEVEL_MONSTERSTELEFRAG = 0x00000400,
@ -198,6 +199,7 @@ enum ELevelFlags
LEVEL2_SMOOTHLIGHTING = 0x01000000, // Level uses the smooth lighting feature.
LEVEL2_POLYGRIND = 0x02000000, // Polyobjects grind corpses to gibs.
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<int, FName> FMusicMap;
struct level_info_t
{
@ -295,6 +298,7 @@ struct level_info_t
float teamdamage;
FOptData optdata;
FMusicMap MusicMap;
TArray<FSpecialAction> specialactions;
@ -486,8 +490,17 @@ void G_SecretExitLevel (int position);
const char *G_GetExitMap();
const char *G_GetSecretExitMap();
void G_ChangeLevel(const char * levelname, int position, bool keepFacing, int nextSkill=-1,
bool nointermission=false, bool resetinventory=false, bool nomonsters=false);
enum
{
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);
@ -533,9 +546,11 @@ enum ESkillProperty
SKILLP_ACSReturn,
SKILLP_MonsterHealth,
SKILLP_FriendlyHealth,
SKILLP_NoPain
SKILLP_NoPain,
SKILLP_ArmorFactor
};
int G_SkillProperty(ESkillProperty prop);
const char * G_SkillName();
typedef TMap<FName, FString> SkillMenuNames;
@ -556,8 +571,8 @@ struct FSkillInfo
int SpawnFilter;
int ACSReturn;
FString MenuName;
FString PicName;
SkillMenuNames MenuNamesForPlayerClass;
bool MenuNameIsLump;
bool MustConfirm;
FString MustConfirmText;
char Shortcut;
@ -567,6 +582,7 @@ struct FSkillInfo
fixed_t MonsterHealth;
fixed_t FriendlyHealth;
bool NoPain;
fixed_t ArmorFactor;
FSkillInfo() {}
FSkillInfo(const FSkillInfo &other)

View file

@ -51,6 +51,8 @@
#include "doomstat.h"
#include "d_player.h"
#include "autosegs.h"
#include "version.h"
#include "v_text.h"
int FindEndSequence (int type, const char *picname);
@ -1324,6 +1326,7 @@ MapFlagHandlers[] =
{ "specialaction_exitlevel", MITYPE_SCFLAGS, 0, ~LEVEL_SPECACTIONSMASK },
{ "specialaction_opendoor", MITYPE_SCFLAGS, LEVEL_SPECOPENDOOR, ~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 },
{ "lightning", MITYPE_SETFLAG, LEVEL_STARTLIGHTNING, 0 },
{ "smoothlighting", MITYPE_SETFLAG2, LEVEL2_SMOOTHLIGHTING, 0 },
@ -1372,6 +1375,7 @@ MapFlagHandlers[] =
{ "grinding_polyobj", MITYPE_SETFLAG2, LEVEL2_POLYGRIND, 0 },
{ "no_grinding_polyobj", MITYPE_CLRFLAG2, LEVEL2_POLYGRIND, 0 },
{ "resetinventory", MITYPE_SETFLAG2, LEVEL2_RESETINVENTORY, 0 },
{ "resethealth", MITYPE_SETFLAG2, LEVEL2_RESETHEALTH, 0 },
{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2, LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
{ "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX},
@ -1399,6 +1403,8 @@ MapFlagHandlers[] =
{ "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS},
{ "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS},
{ "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_end1_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },
@ -1799,6 +1805,7 @@ void FMapInfoParser::ParseEpisodeInfo ()
EpisodeMenu[i].fulltext = !picisgfx;
EpisodeNoSkill[i] = noskill;
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);
}
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;
ParseMapInfo(inclump, gamedefaults, defaultinfo);
sc = saved_sc;
@ -1952,12 +1968,18 @@ void G_ParseMapInfo (const char *basemapinfo)
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)
{
FMapInfoParser parse;
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 };

View file

@ -200,7 +200,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
&& pr_minotaurdecide() < 150)
{ // Charge attack
// Don't call the state function right away
self->SetStateNF (self->FindState ("Charge"));
self->SetState (self->FindState ("Charge"), true);
self->flags |= MF_SKULLFLY;
if (!friendly)
{ // Heretic's Minotaur is invulnerable during charge attack
@ -473,9 +473,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurRoam)
{
// Turn
if (pr_minotaurroam() & 1)
self->movedir = (++self->movedir)%8;
self->movedir = (self->movedir + 1) % 8;
else
self->movedir = (self->movedir+7)%8;
self->movedir = (self->movedir + 7) % 8;
FaceMovementDirection (self);
}
return 0;
@ -552,11 +552,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
if (self->target)
{
self->SetStateNF (self->SeeState);
self->SetState (self->SeeState, true);
}
else
{
self->SetStateNF (self->FindState ("Roam"));
self->SetState (self->FindState ("Roam"), true);
}
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
if (self->flags & MF_STEALTH)
{
@ -70,18 +68,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
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)
{
P_DropItem (self, self->Conversation->DropType, -1, 256);
self->Conversation = NULL;
return 0;
return;
}
self->Conversation = NULL;
// If the self has attached metadata for items to drop, drop those.
if (!self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
// If the actor has attached metadata for items to drop, drop those.
if (drop && !self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
{
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;
}
DEFINE_ACTION_FUNCTION(AActor, A_Fall)
{
PARAM_ACTION_PROLOGUE;
CALL_ACTION(A_NoBlocking, self);
A_Unblock(self, true);
return 0;
}
@ -332,7 +335,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
{
CALL_ACTION(A_BossDeath, self);
}
CALL_ACTION(A_NoBlocking, self);
A_Unblock(self, true);
self->SetState(self->FindState(NAME_Null));
return 0;

View file

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

View file

@ -750,10 +750,6 @@ void APowerIronFeet::AbsorbDamage (int damage, FName damageType, int &newdamage)
if (damageType == NAME_Drowning)
{
newdamage = 0;
if (Owner->player != NULL)
{
Owner->player->mo->ResetAirSupply ();
}
}
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 -------------------------------------------
IMPLEMENT_CLASS (APowerMask)
@ -993,6 +1004,12 @@ void APowerFlight::EndEffect ()
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))
{
FTextureID picnum = TexMan.CheckForTexture ("SPFLY0", FTexture::TEX_MiscPatch);

View file

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

View file

@ -72,7 +72,7 @@ void AFastProjectile::Tick ()
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
if (!(flags3 & MF3_SKYEXPLODE))
{
@ -158,10 +158,13 @@ void AFastProjectile::Effect()
if (name != NAME_None)
{
fixed_t hitz = z-8*FRACUNIT;
if (hitz < floorz)
{
hitz = floorz;
}
// Do not clip this offset to the floor.
hitz += GetClass()->MissileHeight;
PClassActor *trail = PClass::FindActor(name);
if (trail != NULL)

View file

@ -19,7 +19,12 @@ struct OneKey
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;
// [MH] Used by SBARINFO to speed up face drawing
p->MorphedPlayerClass = 0;
for (unsigned int i = 1; i < PlayerClasses.Size(); i++)
{
if (PlayerClasses[i].Type == spawntype)
{
p->MorphedPlayerClass = i;
break;
}
}
p->MorphedPlayerClass = spawntype;
p->MorphStyle = style;
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;
}
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;
}
@ -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->SetOrigin (self->x, self->y, self->z);
return 0;
}
@ -935,7 +936,7 @@ void AInventory::Touch (AActor *toucher)
{
const char * message = PickupMessage ();
if (toucher->CheckLocalView (consoleplayer)
if (message != NULL && *message != 0 && toucher->CheckLocalView (consoleplayer)
&& (StaticLastMessageTic != gametic || StaticLastMessage != message))
{
StaticLastMessageTic = gametic;

View file

@ -23,7 +23,7 @@ public:
bool AddWeapon (const char *type);
bool AddWeapon (PClassWeapon *type);
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 LocateWeapon (PClassWeapon *type);

View file

@ -124,6 +124,7 @@ class ARandomSpawner : public AActor
{
// copy everything relevant
newmobj->SpawnAngle = newmobj->angle = angle;
newmobj->SpawnPoint[2] = SpawnPoint[2];
newmobj->special = special;
newmobj->args[0] = args[0];
newmobj->args[1] = args[1];
@ -147,10 +148,10 @@ class ARandomSpawner : public AActor
// a health set to -2 after spawning, for internal reasons.
if (health != SpawnHealth()) newmobj->health = health;
if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED;
// Handle special altitude flags
// Handle special altitude flags
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)
{
@ -160,6 +161,7 @@ class ARandomSpawner : public AActor
space -= 40*FRACUNIT;
newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT;
}
newmobj->z += SpawnPoint[2];
}
if (newmobj->flags & MF_MISSILE)
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;
int i = pr_spot() % Spots.Size();
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();
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);
if (list != NULL) return list->GetSpotWithMinDistance(x, y, distance);
if (list != NULL) return list->GetSpotWithMinMaxDistance(x, y, mindist, maxdist);
return NULL;
}

View file

@ -36,7 +36,7 @@ public:
bool RemoveSpot(ASpecialSpot *spot);
void Serialize(FArchive &arc);
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);
};

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;
@ -795,9 +795,12 @@ AWeapon *FWeaponSlot::PickWeapon(player_t *player)
{
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));
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;

View file

@ -165,7 +165,7 @@ struct 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,
bool directional=false);
};
@ -189,9 +189,9 @@ struct FMugShotState
void Tick();
void Reset();
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:
FMugShotState();
@ -215,6 +215,7 @@ class FMugShot
FMugShot();
void Grin(bool grin=true) { bEvilGrin = grin; }
void Reset();
void Tick(player_t *player);
bool SetState(const char *state_name, bool wait_till_done=false, bool reset=false);
int UpdateState(player_t *player, StateFlags stateflags=STANDARD);
@ -275,7 +276,7 @@ public:
ST_DEADFACE = ST_GODFACE + 1
};
DBaseStatusBar (int reltop);
DBaseStatusBar (int reltop, int hres=320, int vres=200);
void Destroy ();
void SetScaled (bool scale, bool force=false);
@ -300,8 +301,6 @@ public:
virtual void AttachToPlayer (player_t *player);
virtual void FlashCrosshair ();
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 ScreenSizeChanged ();
virtual void MultiplayerChanged ();
@ -334,14 +333,13 @@ protected:
void GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const;
void AddFaceToImageCollectionActual (void *skn, FImageCollection *images, bool isDoom);
public:
AInventory *ValidateInvFirst (int numVisible) const;
void DrawCrosshair ();
int ST_X, ST_Y;
int RelTop;
int HorizontalResolution, VirticalResolution;
bool Scaled;
bool Centering;
bool FixedOrigin;
@ -378,8 +376,6 @@ extern DBaseStatusBar *StatusBar;
// Status bar factories -----------------------------------------------------
DBaseStatusBar *CreateHereticStatusBar();
DBaseStatusBar *CreateHexenStatusBar();
DBaseStatusBar *CreateStrifeStatusBar();
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 index = !directional ? random % Graphic.Size() : direction;
@ -84,7 +84,7 @@ FTexture *FMugShotFrame::GetTexture(const char *default_face, FPlayerSkin *skin,
{
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];
if (uses_levels) //change the last character to the level
{
@ -221,6 +221,17 @@ int FindMugShotStateIndex(FName state)
//===========================================================================
FMugShot::FMugShot()
{
Reset();
}
//===========================================================================
//
// FMugShot :: Reset
//
//===========================================================================
void FMugShot::Reset()
{
FaceHealth = -1;
bEvilGrin = false;
@ -492,8 +503,8 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
}
if (CurrentState != NULL)
{
FPlayerSkin *skin = &skins[player->morphTics ? player->MorphedPlayerClass : player->userinfo.skin];
return CurrentState->GetCurrentFrameTexture(default_face, skin, level, angle);
const char *skin_face = player->morphTics ? player->MorphedPlayerClass->Face : skins[player->userinfo.skin].face;
return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
}
return NULL;
}

View file

@ -57,16 +57,8 @@
#include "g_level.h"
#include "v_palette.h"
#include "p_acs.h"
#define ADJUST_RELCENTER(x, y, outX, outY) \
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;
#include "gstrings.h"
#include "version.h"
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
enum
@ -189,8 +181,8 @@ class SBarInfoCommand
}
}
if(!fullScreenOffsets)
y.SetCoord((negative ? -sc.Number : sc.Number) - (200 - script->height));
//if(!fullScreenOffsets)
// y.SetCoord((negative ? -sc.Number : sc.Number) - (200 - script->height));
}
EColorRange GetTranslation(FScanner &sc)
{
@ -213,60 +205,107 @@ class SBarInfoCommand
class SBarInfoCommandFlowControl : public SBarInfoCommand
{
public:
SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script) {}
SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script), truth(false) {}
~SBarInfoCommandFlowControl()
{
for(unsigned int i = 0;i < commands.Size();i++)
delete commands[i];
for(unsigned int i = 0;i < 2;i++)
{
for(unsigned int j = 0;j < commands[i].Size();j++)
delete commands[i][j];
}
}
void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar)
{
for(unsigned int i = 0;i < commands.Size();i++)
commands[i]->Draw(block, statusBar);
for(unsigned int i = 0;i < commands[truth].Size();i++)
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)
{
sc.MustGetToken('{');
bool elseBlock = false;
SBarInfoCommand *cmd = NULL;
while((cmd = NextCommand(sc)) != NULL)
// Should loop no more than twice.
while(true)
{
cmd->Parse(sc, fullScreenOffsets);
commands.Push(cmd);
if(sc.CheckToken('{'))
{
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()
{
for(unsigned int i = 0;i < commands.Size();i++)
commands[i]->Reset();
for(unsigned int i = 0;i < 2;i++)
{
for(unsigned int j = 0;j < commands[i].Size();j++)
commands[i][j]->Reset();
}
}
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{
for(unsigned int i = 0;i < commands.Size();i++)
commands[i]->Tick(block, statusBar, hudChanged);
for(unsigned int i = 0;i < commands[truth].Size();i++)
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:
SBarInfoCommand *NextCommand(FScanner &sc);
TArray<SBarInfoCommand *> commands;
bool truth;
TArray<SBarInfoCommand *> commands[2];
};
class SBarInfoMainBlock : public SBarInfoCommandFlowControl
{
public:
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)
{
this->xOffset = xOffset;
this->yOffset = yOffset;
this->alpha = alpha;
this->currentAlpha = fixed_t((((double) this->alpha / (double) FRACUNIT) * ((double) alpha / (double) FRACUNIT)) * FRACUNIT);
SBarInfoCommandFlowControl::Draw(this, statusBar);
}
bool ForceScaled() const { return forceScaled; }
@ -299,8 +338,9 @@ class SBarInfoMainBlock : public SBarInfoCommandFlowControl
int XOffset() const { return xOffset; }
int YOffset() const { return yOffset; }
private:
protected:
int alpha;
int currentAlpha;
bool forceScaled;
bool fullScreenOffsets;
int xOffset;
@ -320,6 +360,7 @@ enum //Key words
SBARINFO_COMPLETEBORDER,
SBARINFO_MONOSPACEFONTS,
SBARINFO_LOWERHEALTHCAP,
SBARINFO_RESOLUTION,
SBARINFO_STATUSBAR,
SBARINFO_MUGSHOT,
SBARINFO_CREATEPOPUP,
@ -347,6 +388,7 @@ static const char *SBarInfoTopLevel[] =
"completeborder",
"monospacefonts",
"lowerhealthcap",
"resolution",
"statusbar",
"mugshot",
"createpopup",
@ -428,6 +470,7 @@ void SBarInfo::ParseSBarInfo(int lump)
ParseSBarInfo(lump);
continue;
}
int baselump = -2;
switch(sc.MustMatchString(SBarInfoTopLevel))
{
case SBARINFO_BASE:
@ -436,21 +479,36 @@ void SBarInfo::ParseSBarInfo(int lump)
sc.MustGetToken(TK_Identifier);
if(sc.Compare("Doom"))
{
int lump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true);
if(lump == -1)
sc.ScriptError("Standard Doom Status Bar not found.");
ParseSBarInfo(lump);
baselump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true);
}
else if(sc.Compare("Heretic"))
gameType = GAME_Heretic;
{
baselump = Wads.CheckNumForFullName("sbarinfo/heretic.txt", true);
}
else if(sc.Compare("Hexen"))
gameType = GAME_Hexen;
{
baselump = Wads.CheckNumForFullName("sbarinfo/hexen.txt", true);
}
else if(sc.Compare("Strife"))
gameType = GAME_Strife;
else if(sc.Compare("None"))
gameType = GAME_Any;
else
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(';');
break;
case SBARINFO_HEIGHT:
@ -518,6 +576,19 @@ void SBarInfo::ParseSBarInfo(int lump)
sc.MustGetToken(',');
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(';');
break;
case SBARINFO_LOWERHEALTHCAP:
@ -532,6 +603,14 @@ void SBarInfo::ParseSBarInfo(int lump)
}
sc.MustGetToken(';');
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:
{
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);
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"))
{
popup.transition = Popup::TRANSITION_FADE;
@ -707,6 +793,9 @@ void SBarInfo::Init()
armorInterpolationSpeed = 8;
height = 0;
spacingCharacter = '\0';
spacingAlignment = ALIGN_CENTER;
resW = 320;
resH = 200;
for(unsigned int i = 0;i < NUMHUDS;i++)
huds[i] = new SBarInfoMainBlock(this);
@ -722,78 +811,79 @@ SBarInfo::~SBarInfo()
}
//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()
{
x = width;
y = height;
if(transition == TRANSITION_SLIDEINBOTTOM)
switch(transition)
{
x = 0;
}
else if(transition == TRANSITION_FADE)
{
alpha = 0;
x = 0;
y = 0;
case TRANSITION_SLIDEINBOTTOM:
case TRANSITION_PUSHUP:
x = 0;
break;
case TRANSITION_FADE:
alpha = 0;
x = 0;
y = 0;
break;
default:
break;
}
}
void Popup::tick()
{
if(transition == TRANSITION_SLIDEINBOTTOM)
switch(transition)
{
if(moving)
{
if(opened)
y -= clamp(height + (y - height), 1, speed);
case TRANSITION_SLIDEINBOTTOM:
case TRANSITION_PUSHUP:
if(moving)
{
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
y += clamp(height - y, 1, speed);
}
if(y != 0 && y != height)
moving = true;
else
moving = false;
}
else if(transition == TRANSITION_FADE)
{
if(moving)
{
if(opened)
alpha = clamp(alpha + speed, 0, FRACUNIT);
moving = false;
break;
case TRANSITION_FADE:
if(moving)
{
if(opened)
alpha = clamp(alpha + speed, 0, FRACUNIT);
else
alpha = clamp(alpha - speed2, 0, FRACUNIT);
}
if(alpha == 0 || alpha == FRACUNIT)
moving = false;
else
alpha = clamp(alpha - speed2, 0, FRACUNIT);
}
if(alpha == 0 || alpha == FRACUNIT)
moving = true;
break;
default:
if(opened)
{
y = 0;
x = 0;
}
else
{
y = height;
x = width;
}
moving = false;
else
moving = true;
}
else
{
if(opened)
{
y = 0;
x = 0;
}
else
{
y = height;
x = width;
}
moving = false;
break;
}
}
@ -819,6 +909,16 @@ int Popup::getAlpha(int maxAlpha)
return fixed_t((a * b) * FRACUNIT);
}
int Popup::getXDisplacement()
{
return displacementX;
}
int Popup::getYDisplacement()
{
return displacementY;
}
void Popup::open()
{
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
{
DECLARE_CLASS(DSBarInfo, DBaseStatusBar)
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),
pendingPopup(POP_None), currentPopup(POP_None), lastHud(-1),
lastInventoryBar(NULL), lastPopup(NULL)
@ -861,10 +973,6 @@ public:
{
patchnames[i+script->Images.Size()] = InventoryBarLumps[i];
}
for (i = 0;i < numskins;i++)
{
AddFaceToImageCollection (&skins[i], &Images);
}
invBarOffset = script->Images.Size();
Images.Init(&patchnames[0], patchnames.Size());
}
@ -918,8 +1026,13 @@ public:
armor = CPlayer->mo->FindInventory<ABasicArmor>();
if(hud != lastHud)
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;
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];
@ -1030,53 +1143,58 @@ public:
if (texture == NULL)
return;
double dx = *x;
double dy = *y;
if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER)
{
x -= (texture->GetScaledWidth()/2)-texture->LeftOffset;
y -= (texture->GetScaledHeight()/2)-texture->TopOffset;
dx -= (texture->GetScaledWidthDouble()/2.0)-texture->LeftOffset;
dy -= (texture->GetScaledHeightDouble()/2.0)-texture->TopOffset;
}
x += xOffset;
y += yOffset;
int w, h;
dx += xOffset;
dy += yOffset;
double w, h;
if(!fullScreenOffsets)
{
fixed_t tmp = 0;
// I'll handle the conversion from fixed to int myself for more control
fixed_t fx = (x + ST_X).Coordinate() << FRACBITS;
fixed_t fy = (y + ST_Y).Coordinate() << FRACBITS;
fixed_t fw = (forceWidth <= -1 ? texture->GetScaledWidth() : forceWidth) << FRACBITS;
fixed_t fh = (forceHeight <= -1 ? texture->GetScaledHeight() : forceHeight) << FRACBITS;
fixed_t fcx = cx == 0 ? 0 : fx + cx - (texture->GetScaledLeftOffset() << FRACBITS);
fixed_t fcy = cy == 0 ? 0 : fy + cy - (texture->GetScaledTopOffset() << FRACBITS);
fixed_t fcr = fx + fw - cr;
fixed_t fcb = fy + fh - cb;
double tmp = 0;
dx += ST_X;
dy += ST_Y - (Scaled ? script->resH : 200) + script->height;
w = forceWidth < 0 ? texture->GetScaledWidthDouble() : forceWidth;
h = forceHeight < 0 ? texture->GetScaledHeightDouble() : forceHeight;
double dcx = cx == 0 ? 0 : dx + ((double) cx / FRACUNIT) - texture->GetScaledLeftOffsetDouble();
double dcy = cy == 0 ? 0 : dy + ((double) cy / FRACUNIT) - texture->GetScaledTopOffsetDouble();
double dcr = cr == 0 ? INT_MAX : dx + w - ((double) cr / FRACUNIT);
double dcb = cb == 0 ? INT_MAX : dy + h - ((double) cb / FRACUNIT);
if(Scaled)
{
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)
screen->VirtualToRealCoordsFixed(fcr, fcb, tmp, tmp, 320, 200, true);
screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true);
screen->VirtualToRealCoords(dcr, dcb, tmp, tmp, script->resW, script->resH, true);
screen->VirtualToRealCoords(dx, dy, w, h, script->resW, script->resH, true);
}
// Round to nearest
w = (fw + (FRACUNIT>>1)) >> FRACBITS;
h = (fh + (FRACUNIT>>1)) >> FRACBITS;
cr = cr != 0 ? fcr >> FRACBITS : INT_MAX;
cb = cb != 0 ? fcb >> FRACBITS : INT_MAX;
else
{
dy += 200 - script->resH;
dcy += 200 - script->resH;
dcb += 200 - script->resH;
}
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
{
if(alphaMap)
{
screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS),
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_ClipLeft, fcx>>FRACBITS,
DTA_ClipTop, fcy>>FRACBITS,
DTA_ClipRight, cr,
DTA_ClipBottom, cb,
screen->DrawTexture(texture, dx, dy,
DTA_DestWidthF, w,
DTA_DestHeightF, h,
DTA_ClipLeft, static_cast<int>(dcx),
DTA_ClipTop, static_cast<int>(dcy),
DTA_ClipRight, static_cast<int>(MIN<double>(INT_MAX, dcr)),
DTA_ClipBottom, static_cast<int>(MIN<double>(INT_MAX, dcb)),
DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
@ -1087,13 +1205,13 @@ public:
}
else
{
screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS),
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_ClipLeft, fcx>>FRACBITS,
DTA_ClipTop, fcy>>FRACBITS,
DTA_ClipRight, cr,
DTA_ClipBottom, cb,
screen->DrawTexture(texture, dx, dy,
DTA_DestWidthF, w,
DTA_DestHeightF, h,
DTA_ClipLeft, static_cast<int>(dcx),
DTA_ClipTop, static_cast<int>(dcy),
DTA_ClipRight, static_cast<int>(MIN<double>(INT_MAX, dcr)),
DTA_ClipBottom, static_cast<int>(MIN<double>(INT_MAX, dcb)),
DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
@ -1104,69 +1222,87 @@ public:
}
else
{
int rx, ry, rcx=0, rcy=0, rcr=INT_MAX, rcb=INT_MAX;
ADJUST_RELCENTER(x,y,rx,ry)
double rx, ry, rcx=0, rcy=0, rcr=INT_MAX, rcb=INT_MAX;
w = (forceWidth <= -1 ? texture->GetScaledWidth() : forceWidth);
h = (forceHeight <= -1 ? texture->GetScaledHeight() : forceHeight);
double xScale = !hud_scale ? 1.0 : (double) CleanXfac*320.0/(double) script->resW;//(double) SCREENWIDTH/(double) script->resW;
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)
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
if(cx != 0 || cy != 0 || cr != 0 || cb != 0)
{
rcx = cx == 0 ? 0 : rx+(cx>>FRACBITS);
rcy = cy == 0 ? 0 : ry+(cy>>FRACBITS);
rcr = cr == 0 ? INT_MAX : rx+w-(cr>>FRACBITS);
rcb = cb == 0 ? INT_MAX : ry+h-(cb>>FRACBITS);
rcx = cx == 0 ? 0 : rx+(((double) cx/FRACUNIT)*xScale);
rcy = cy == 0 ? 0 : ry+(((double) cy/FRACUNIT)*yScale);
rcr = cr == 0 ? INT_MAX : rx+w-(((double) cr/FRACUNIT)*xScale);
rcb = cb == 0 ? INT_MAX : ry+h-(((double) cb/FRACUNIT)*yScale);
// Fix the clipping for fullscreenoffsets.
if(ry < 0)
/*if(ry < 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)
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)
{
rcy *= CleanYfac;
rcy *= (int) (CleanYfac*200.0/script->resH);
if(rcb != INT_MAX)
rcb *= CleanYfac;
rcb *= (int) (CleanYfac*200.0/script->resH);
}
if(rx < 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)
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)
{
rcx *= CleanXfac;
rcx *= (int) (CleanXfac*320.0/script->resW);
if(rcr != INT_MAX)
rcr *= CleanXfac;
}
rcr *= (int) (CleanXfac*320.0/script->resW);
}*/
}
if(clearDontDraw)
{
screen->Clear(rcx, rcy, MIN<int>(rcr, w*(hud_scale ? CleanXfac : 1)), MIN<int>(rcb, h*(hud_scale ? CleanYfac : 1)), GPalette.BlackIndex, 0);
}
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);
else
{
if(alphaMap)
{
screen->DrawTexture(texture, rx, ry,
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_ClipLeft, rcx,
DTA_ClipTop, rcy,
DTA_ClipRight, rcr,
DTA_ClipBottom, rcb,
DTA_DestWidthF, w,
DTA_DestHeightF, h,
DTA_ClipLeft, static_cast<int>(rcx),
DTA_ClipTop, static_cast<int>(rcy),
DTA_ClipRight, static_cast<int>(rcr),
DTA_ClipBottom, static_cast<int>(rcb),
DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
DTA_HUDRules, HUD_Normal,
DTA_Alpha, alpha,
DTA_AlphaChannel, alphaMap,
DTA_FillColor, 0,
@ -1175,16 +1311,15 @@ public:
else
{
screen->DrawTexture(texture, rx, ry,
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_ClipLeft, rcx,
DTA_ClipTop, rcy,
DTA_ClipRight, rcr,
DTA_ClipBottom, rcb,
DTA_DestWidthF, w,
DTA_DestHeightF, h,
DTA_ClipLeft, static_cast<int>(rcx),
DTA_ClipTop, static_cast<int>(rcy),
DTA_ClipRight, static_cast<int>(rcr),
DTA_ClipBottom, static_cast<int>(rcb),
DTA_Translation, translate ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? DIM_OVERLAY : 0,
DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM,
DTA_HUDRules, HUD_Normal,
DTA_Alpha, alpha,
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;
int ax = *x;
int ay = *y;
double ax = *x;
double ay = *y;
double xScale = 1.0;
double yScale = 1.0;
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')
{
if(*str == ' ')
{
ax += font->GetSpaceWidth();
if(script->spacingCharacter == '\0')
ax += font->GetSpaceWidth();
else
ax += font->GetCharWidth((int) script->spacingCharacter);
str++;
continue;
}
@ -1223,65 +1370,77 @@ public:
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
int rx, ry, rw, rh;
double rx, ry, rw, rh;
rx = ax + xOffset;
ry = ay + yOffset;
rw = character->GetScaledWidth();
rh = character->GetScaledHeight();
rw = character->GetScaledWidthDouble();
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)
{
rx += ST_X;
ry += ST_Y;
ry += ST_Y - (Scaled ? script->resH : 200) + script->height;
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
{
if(vid_fps && ax < 0 && ay >= 0)
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)
{
int salpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) HR_SHADOW / (double) FRACUNIT) * FRACUNIT);
if(!fullScreenOffsets)
{
screen->DrawTexture(character, rx+2, ry+2,
DTA_DestWidth, rw,
DTA_DestHeight, rh,
DTA_Alpha, salpha,
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,
double srx = rx + (shadowX*xScale);
double sry = ry + (shadowY*yScale);
screen->DrawTexture(character, srx, sry,
DTA_DestWidthF, rw,
DTA_DestHeightF, rh,
DTA_Alpha, salpha,
DTA_FillColor, 0,
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')
ax += width + spacing - (character->LeftOffset+1);
else //width gets changed at the call to GetChar()

View file

@ -52,6 +52,7 @@ struct Popup
{
TRANSITION_NONE,
TRANSITION_SLIDEINBOTTOM,
TRANSITION_PUSHUP,
TRANSITION_FADE,
};
@ -65,6 +66,8 @@ struct Popup
int alpha;
int x;
int y;
int displacementX;
int displacementY;
Popup();
void init();
@ -75,10 +78,19 @@ struct Popup
int getXOffset();
int getYOffset();
int getAlpha(int maxAlpha=FRACUNIT);
int getXDisplacement();
int getYDisplacement();
};
struct SBarInfo
{
enum MonospaceAlignment
{
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT
};
TArray<FString> Images;
SBarInfoMainBlock *huds[NUMHUDS];
Popup popups[NUMPOPUPS];
@ -88,11 +100,14 @@ struct SBarInfo
bool completeBorder;
bool lowerHealthCap;
char spacingCharacter;
MonospaceAlignment spacingAlignment;
int interpolationSpeed;
int armorInterpolationSpeed;
int height;
int gameType;
FMugShot MugShot;
int resW;
int resH;
int GetGameType() { return gameType; }
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;
FixedOrigin = false;
@ -185,6 +185,8 @@ DBaseStatusBar::DBaseStatusBar (int reltop)
Displacement = 0;
CPlayer = NULL;
ShowLog = false;
HorizontalResolution = hres;
VirticalResolution = vres;
SetScaled (st_scale);
}
@ -216,18 +218,20 @@ void DBaseStatusBar::Destroy ()
//---------------------------------------------------------------------------
//[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)
{
Scaled = (RelTop != 0 || force) && (SCREENWIDTH != 320 && scale);
Scaled = (RelTop != 0 || force) && ((SCREENWIDTH != 320 || HorizontalResolution != 320) && scale);
if (!Scaled)
{
ST_X = (SCREENWIDTH - 320) / 2;
ST_X = (SCREENWIDTH - HorizontalResolution) / 2;
ST_Y = SCREENHEIGHT - RelTop;
::ST_Y = ST_Y;
if (RelTop > 0)
{
Displacement = ((ST_Y * 200 / SCREENHEIGHT) - (200 - RelTop))*FRACUNIT/RelTop;
Displacement = ((ST_Y * VirticalResolution / SCREENHEIGHT) - (VirticalResolution - RelTop))*FRACUNIT/RelTop;
}
else
{
@ -237,14 +241,14 @@ void DBaseStatusBar::SetScaled (bool scale, bool force)
else
{
ST_X = 0;
ST_Y = 200 - RelTop;
ST_Y = VirticalResolution - RelTop;
if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) != 4)
{ // Normal resolution
::ST_Y = Scale (ST_Y, SCREENHEIGHT, 200);
::ST_Y = Scale (ST_Y, SCREENHEIGHT, VirticalResolution);
}
else
{ // 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;
}
Displacement = 0;
@ -1000,7 +1004,7 @@ void DBaseStatusBar::RefreshBackground () const
if (x > 0)
{
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);
R_DrawBorder (0, y, x, SCREENHEIGHT);
R_DrawBorder (x2, y, SCREENWIDTH, SCREENHEIGHT);
@ -1500,18 +1504,23 @@ void DBaseStatusBar::BlendView (float blend[4])
if (CPlayer->bonuscount)
{
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 (cnt)
if (CPlayer->mo->DamageFade.a != 0)
{
if (cnt > 228)
cnt = 228;
cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * CPlayer->mo->DamageFade.a / 255)];
if (cnt)
{
if (cnt > 228)
cnt = 228;
APlayerPawn *mo = players[consoleplayer].mo;
AddBlend (mo->DamageFade.r / 255.f, mo->DamageFade.g / 255.f, mo->DamageFade.b / 255.f, cnt / 255.f, blend);
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
@ -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 ()
{
}
@ -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

View file

@ -35,12 +35,14 @@
#include <ctype.h>
#include "doomstat.h"
#include "d_player.h"
#include "g_level.h"
#include "g_game.h"
#include "gi.h"
#include "templates.h"
#include "v_font.h"
#include "m_fixed.h"
#include "gstrings.h"
TArray<FSkillInfo> AllSkills;
int DefaultSkill = -1;
@ -70,7 +72,6 @@ void FMapInfoParser::ParseSkill ()
skill.Aggressiveness = FRACUNIT;
skill.SpawnFilter = 0;
skill.ACSReturn = 0;
skill.MenuNameIsLump = false;
skill.MustConfirm = false;
skill.Shortcut = 0;
skill.TextColor = "";
@ -79,6 +80,7 @@ void FMapInfoParser::ParseSkill ()
skill.MonsterHealth = FRACUNIT;
skill.FriendlyHealth = FRACUNIT;
skill.NoPain = false;
skill.ArmorFactor = FRACUNIT;
sc.MustGetString();
skill.Name = sc.String;
@ -185,7 +187,6 @@ void FMapInfoParser::ParseSkill ()
ParseAssign();
sc.MustGetString ();
skill.MenuName = sc.String;
skill.MenuNameIsLump = false;
}
else if (sc.Compare("PlayerClassName"))
{
@ -200,8 +201,7 @@ void FMapInfoParser::ParseSkill ()
{
ParseAssign();
sc.MustGetString ();
skill.MenuName = sc.String;
skill.MenuNameIsLump = true;
skill.PicName = sc.String;
}
else if (sc.Compare("MustConfirm"))
{
@ -250,6 +250,12 @@ void FMapInfoParser::ParseSkill ()
{
skill.NoPain = true;
}
else if (sc.Compare("ArmorFactor"))
{
ParseAssign();
sc.MustGetFloat();
skill.ArmorFactor = FLOAT2FIXED(sc.Float);
}
else if (sc.Compare("DefaultSkill"))
{
if (DefaultSkill >= 0)
@ -358,12 +364,38 @@ int G_SkillProperty(ESkillProperty prop)
return AllSkills[gameskill].FriendlyHealth;
case SKILLP_NoPain:
return AllSkills[gameskill].NoPain;
return AllSkills[gameskill].NoPain;
case SKILLP_ArmorFactor:
return AllSkills[gameskill].ArmorFactor;
}
}
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;
ACSReturn = other.ACSReturn;
MenuName = other.MenuName;
PicName = other.PicName;
MenuNamesForPlayerClass = other.MenuNamesForPlayerClass;
MenuNameIsLump = other.MenuNameIsLump;
MustConfirm = other.MustConfirm;
MustConfirmText = other.MustConfirmText;
Shortcut = other.Shortcut;
@ -413,6 +445,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other)
MonsterHealth = other.MonsterHealth;
FriendlyHealth = other.FriendlyHealth;
NoPain = other.NoPain;
ArmorFactor = other.ArmorFactor;
return *this;
}

View file

@ -93,7 +93,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath)
int log;
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))
{
return 0;

View file

@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger)
angle = self->angle + (pr_jabdagger.Random2() << 18);
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
if (linetarget)

View file

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

View file

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

View file

@ -43,6 +43,9 @@
#define GI_MENUHACK_EXTENDED 0x00000004 // (Heretic)
#define GI_TEASER2 0x00000008 // Alternate version of the Strife Teaser
#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"
@ -105,6 +108,7 @@ struct gameinfo_t
int defaultrespawntime;
int defaultdropstyle;
int player5start;
DWORD pickupcolor;
const char *GetFinalePage(unsigned int num) const;
};

View file

@ -269,8 +269,16 @@ void PacketGet (void)
if (err == WSAECONNRESET)
{ // The remote node aborted unexpectedly, so pretend it sent an exit packet
StartScreen->NetMessage ("The connection from %s was dropped.\n",
players[sendplayer[node]].userinfo.netname);
if (StartScreen != NULL)
{
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
c = 1;

View file

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

View file

@ -46,20 +46,28 @@
#include "vm.h"
#include "s_sound.h"
const BYTE SF_FULLBRIGHT = 0x40;
struct Baggage;
class FScanner;
struct FActorInfo;
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
{
WORD sprite;
SWORD Tics;
long Misc1; // Was changed to SBYTE, reverted to long for MBF compat
long Misc2; // Was changed to BYTE, reverted to long for MBF compat
BYTE Frame;
int Misc1; // Was changed to SBYTE, reverted to long for MBF compat
int Misc2; // Was changed to BYTE, reverted to long for MBF compat
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.
short Light;
FState *NextState;
@ -67,11 +75,15 @@ struct FState
inline int GetFrame() const
{
return Frame & ~(SF_FULLBRIGHT);
return Frame;
}
inline bool GetSameFrame() const
{
return SameFrame;
}
inline int GetFullbright() const
{
return Frame & SF_FULLBRIGHT ? 0x10 /*RF_FULLBRIGHT*/ : 0;
return Fullbright ? 0x10 /*RF_FULLBRIGHT*/ : 0;
}
inline int GetTics() const
{
@ -91,7 +103,7 @@ struct FState
}
inline void SetFrame(BYTE frame)
{
Frame = (Frame & SF_FULLBRIGHT) | (frame-'A');
Frame = frame - 'A';
}
void SetAction(VMFunction *func) { ActionFunc = func; }
bool CallAction(AActor *self, AActor *stateowner, StateCallData *statecall = NULL);
@ -185,6 +197,7 @@ public:
FName BloodType3; // AxeBlood replacement type
DDropItem *DropItems;
FString SourceLumpName;
// Old Decorate compatibility stuff
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

View file

@ -53,6 +53,7 @@ public:
void AppendArg(FString arg);
void AppendArgs(int argc, const FString *argv);
void RemoveArg(int argindex);
void SetArgs(int argc, char **argv);
void CollectFiles(const char *param, const char *extension);
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;
}

View file

@ -25,6 +25,7 @@
#include "doomtype.h"
struct line_t;
struct node_t;
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)
{
bool giveall;
enum { ALL_NO, ALL_YES, ALL_YESYES } giveall;
int i;
PClassActor *type;
@ -613,9 +613,17 @@ void cht_Give (player_t *player, const char *name, int amount)
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)
{
@ -640,9 +648,6 @@ void cht_Give (player_t *player, const char *name, int amount)
player->health = deh.GodHealth;
}
}
if (!giveall)
return;
}
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))
{
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);
}
@ -783,7 +788,7 @@ void cht_Give (player_t *player, const char *name, int amount)
!type->IsDescendantOf (RUNTIME_CLASS(APowerup)) &&
!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);
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)
{

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