Merge remote-tracking branch 'origin/next' into http-mserv

This commit is contained in:
James R 2020-08-08 15:05:03 -07:00
commit 54e446199d
68 changed files with 8174 additions and 624 deletions

View File

@ -1,5 +1,17 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
# Enable CCache early
set(SRB2_USE_CCACHE OFF CACHE BOOL "Use CCache")
if (${SRB2_USE_CCACHE})
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
message(STATUS "Found CCache: ${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
else()
message(WARNING "You have specified to use CCACHE but it was not found. Object files will not be cached.")
endif()
endif()
file(STRINGS src/version.h SRB2_VERSION) file(STRINGS src/version.h SRB2_VERSION)
string(REGEX MATCH "[0-9]+\\.[0-9.]+" SRB2_VERSION ${SRB2_VERSION}) string(REGEX MATCH "[0-9]+\\.[0-9.]+" SRB2_VERSION ${SRB2_VERSION})
@ -13,6 +25,10 @@ if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
message(FATAL_ERROR "In-source builds will bring you a world of pain. Please make a separate directory to invoke CMake from.") message(FATAL_ERROR "In-source builds will bring you a world of pain. Please make a separate directory to invoke CMake from.")
endif() endif()
if ((${SRB2_USE_CCACHE}) AND (${CMAKE_C_COMPILER} MATCHES "clang"))
message(WARNING "Using clang and CCache: You may want to set environment variable CCACHE_CPP2=yes to prevent include errors during compile.")
endif()
# Set up CMAKE path # Set up CMAKE path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
@ -117,16 +133,19 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINAR
##### PACKAGE CONFIGURATION ##### ##### PACKAGE CONFIGURATION #####
if(${CMAKE_SYSTEM} MATCHES "Windows") set(SRB2_CPACK_GENERATOR "" CACHE STRING "Generator to use for making a package. E.g., ZIP, TGZ, DragNDrop (OSX only). Leave blank for default generator.")
set(CPACK_GENERATOR "ZIP")
endif() if("${SRB2_CPACK_GENERATOR}" STREQUAL "")
if(${CMAKE_SYSTEM} MATCHES "Linux") if(${CMAKE_SYSTEM} MATCHES "Windows")
set(CPACK_GENERATOR "TGZ") set(SRB2_CPACK_GENERATOR "ZIP")
endif() elseif(${CMAKE_SYSTEM} MATCHES "Linux")
if(${CMAKE_SYSTEM} MATCHES "Darwin") set(SRB2_CPACK_GENERATOR "TGZ")
set(CPACK_GENERATOR "DragNDrop") elseif(${CMAKE_SYSTEM} MATCHES "Darwin")
set(SRB2_CPACK_GENERATOR "TGZ")
endif()
endif() endif()
set(CPACK_GENERATOR ${SRB2_CPACK_GENERATOR})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Sonic Robo Blast 2" CACHE STRING "Program name for display purposes") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Sonic Robo Blast 2" CACHE STRING "Program name for display purposes")
set(CPACK_PACKAGE_VENDOR "Sonic Team Jr." CACHE STRING "Vendor name for display purposes") set(CPACK_PACKAGE_VENDOR "Sonic Team Jr." CACHE STRING "Vendor name for display purposes")
#set(CPACK_PACKAGE_DESCRIPTION_FILE ) #set(CPACK_PACKAGE_DESCRIPTION_FILE )
@ -135,4 +154,5 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${SRB2_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${SRB2_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_MINOR ${SRB2_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${SRB2_VERSION_PATCH}) set(CPACK_PACKAGE_VERSION_PATCH ${SRB2_VERSION_PATCH})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMAKE_VERSION_MAJOR}.${CMAKE_VERSION_MINOR}") set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMAKE_VERSION_MAJOR}.${CMAKE_VERSION_MINOR}")
SET(CPACK_OUTPUT_FILE_PREFIX package)
include(CPack) include(CPack)

View File

@ -12,6 +12,9 @@ ENDFUNCTION(PREPEND)
set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer" set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer"
CACHE STRING "Path to directory that contains all asset files for the installer.") CACHE STRING "Path to directory that contains all asset files for the installer.")
set(SRB2_ASSET_INSTALL ON
CACHE BOOL "Insert asset files into the install directory or package.")
#################### ####################
# POST-V2.2 NOTE: Do not forget to add patch.pk3 to the end of this list! # POST-V2.2 NOTE: Do not forget to add patch.pk3 to the end of this list!
#################### ####################
@ -43,20 +46,27 @@ endforeach()
if(${CMAKE_SYSTEM} MATCHES Darwin) if(${CMAKE_SYSTEM} MATCHES Darwin)
get_target_property(outname SRB2SDL2 OUTPUT_NAME) get_target_property(outname SRB2SDL2 OUTPUT_NAME)
install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/" if(${SRB2_ASSET_INSTALL})
DESTINATION "${outname}.app/Contents/Resources" install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/"
) DESTINATION "${outname}.app/Contents/Resources"
)
endif()
# Always install the doc files, even in non-asset packages.
install(FILES ${SRB2_ASSET_DOCS} install(FILES ${SRB2_ASSET_DOCS}
DESTINATION . DESTINATION .
OPTIONAL OPTIONAL
) )
else() else()
install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/" if(${SRB2_ASSET_INSTALL})
DESTINATION . install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/"
) DESTINATION .
# Docs are assumed to be located in SRB2_ASSET_DIRECTORY, so don't install again )
#install(FILES ${SRB2_ASSET_DOCS} # Docs are assumed to be located in SRB2_ASSET_DIRECTORY, so don't install them in their own call.
# DESTINATION . else()
# OPTIONAL # Always install the doc files, even in non-asset packages.
#) install(FILES ${SRB2_ASSET_DOCS}
DESTINATION .
OPTIONAL
)
endif()
endif() endif()

3
cmake/launch-c.in Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$@"

3
cmake/launch-cxx.in Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$@"

View File

@ -0,0 +1,77 @@
// Default lump name for new map
defaultlumpname = "MAP01";
//GZDB specific. Don't try to load lumps that don't exist.
basegame = "Doom";
//Sky textures for vanilla maps
defaultskytextures
{
SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0";
SKY2 = "MAPM7,MAPMB";
SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1";
SKY6 = "MAP05,MAP51,MAPMA";
SKY7 = "MAPM2,MAPM5";
SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1";
SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3";
SKY11 = "MAP11,MAPF7";
SKY13 = "MAP13,MAP64";
SKY14 = "MAP14";
SKY15 = "MAP15,MAP54";
SKY17 = "MAP70";
SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5";
SKY21 = "MAPM4";
SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6";
SKY30 = "MAP30";
SKY31 = "MAP31";
SKY35 = "MAP42";
SKY40 = "MAP41,MAP71,MAPM9";
SKY55 = "MAPF3,MAPM8";
SKY68 = "MAPF8";
SKY99 = "MAP57,MAPZ0";
SKY159 = "MAP16";
SKY172 = "MAP40";
SKY300 = "MAP72";
SKY301 = "MAP73";
}
// Skill levels
skills
{
1 = "Normal";
}
// Skins
skins
{
Sonic;
Tails;
Knuckles;
Amy;
Fang;
Metalsonic;
}
// Gametypes
gametypes
{
-1 = "Single Player";
0 = "Co-op";
1 = "Competition";
2 = "Race";
3 = "Match";
4 = "Team Match";
5 = "Tag";
6 = "Hide and Seek";
7 = "CTF";
}
// Texture loading options
defaultwalltexture = "GFZROCK";
defaultfloortexture = "GFZFLR01";
defaultceilingtexture = "F_SKY1";
// Default texture sets
// (these are not required, but useful for new users)
texturesets
{
}

View File

@ -0,0 +1,297 @@
common
{
// Simulate Doom brightness levels (turn this off for linear lighting)
doomlightlevels = true;
// Enables support for long (> 8 chars) texture names
// WARNING: this should only be enabled for UDMF game configurations!
// WARNING: enabling this will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3!
longtexturenames = false;
// These directory names are ignored when loading PK3/PK7/Directory resources
ignoreddirectories = ".svn .git";
// Files with these extensions are ignored when loading PK3/PK7/Directory resources
ignoredextensions = "wad pk3 pk7 bak backup1 backup2 backup3 zip rar 7z";
// Default testing parameters
testparameters = "-file \"%AP\" \"%F\" -warp %L";
testshortpaths = true;
// Action special help
actionspecialhelp = "https://wiki.srb2.org/wiki/Linedef_type_%K";
// Generalized actions
generalizedlinedefs = false;
generalizedsectors = true;
// Maximum safe map size check (0 means skip check)
safeboundary = 1;
// Map boundaries. Map objects can only be placed within these boundaries
leftboundary = -32768;
rightboundary = 32767;
topboundary = 32767;
bottomboundary = -32768;
// Texture loading options
mixtexturesflats = true;
defaulttexturescale = 1.0f;
defaultflatscale = 1.0f;
scaledtextureoffsets = true;
// Thing number for start position in 3D Mode
start3dmode = 3328;
// Texture sources
textures
{
include("SRB222_misc.cfg", "textures");
}
// Patch sources
patches
{
include("SRB222_misc.cfg", "patches");
}
// Sprite sources
sprites
{
include("SRB222_misc.cfg", "sprites");
}
// Flat sources
flats
{
include("SRB222_misc.cfg", "flats");
}
}
mapformat_doom
{
// The format interface handles the map data format
formatinterface = "DoomMapSetIO";
// Default nodebuilder configurations
defaultsavecompiler = "zennode_normal";
defaulttestcompiler = "zennode_fast";
/*
GAME DETECT PATTERN
Used to guess the game for which a WAD file is made.
1 = One of these lumps must exist
2 = None of these lumps must exist
3 = All of these lumps must exist
*/
gamedetect
{
EXTENDED = 2;
BEHAVIOR = 2;
E#M# = 2;
MAP?? = 1;
}
/*
MAP LUMP NAMES
Map lumps are loaded with the map as long as they are right after each other. When the editor
meets a lump which is not defined in this list it will ignore the map if not satisfied.
The order of items defines the order in which lumps will be written to WAD file on save.
To indicate the map header lump, use ~MAP
Legenda:
required = Lump is required to exist.
blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use)
nodebuild = The nodebuilder generates this lump.
allowempty = The nodebuilder is allowed to leave this lump empty.
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
maplumpnames
{
include("SRB222_misc.cfg", "doommaplumpnames");
}
// When this is set to true, sectors with the same tag will light up when a line is highlighted
linetagindicatesectors = true;
// Special linedefs
include("SRB222_misc.cfg", "speciallinedefs");
// Default flags for first new thing
defaultthingflags
{
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
include("SRB222_misc.cfg", "sectorbrightness");
}
// SECTOR TYPES
sectortypes
{
include("SRB222_sectors.cfg", "sectortypes");
}
// GENERALISED SECTOR TYPES
gen_sectortypes
{
include("SRB222_sectors.cfg", "gen_sectortypes");
}
// LINEDEF FLAGS
linedefflags
{
include("SRB222_misc.cfg", "linedefflags");
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
linedefflagstranslation
{
include("SRB222_misc.cfg", "linedefflagstranslation");
}
// LINEDEF ACTIVATIONS
linedefactivations
{
}
// LINEDEF TYPES
linedeftypes
{
include("SRB222_linedefs.cfg", "doom");
}
// THING FLAGS
thingflags
{
include("SRB222_misc.cfg", "thingflags");
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
include("SRB222_misc.cfg", "thingflagstranslation");
}
// THING FLAGS ERROR MASK
// Mask for the thing flags which indicates the options
// that make the same thing appear in the same modes
thingflagsmask1 = 7; // 1 + 2 + 4
thingflagsmask2 = 0;
}
mapformat_udmf
{
// The format interface handles the map data format
formatinterface = "UniversalMapSetIO";
// Default nodebuilder configurations
defaultsavecompiler = "zdbsp_udmf_normal";
defaulttestcompiler = "zdbsp_udmf_fast";
// Determines the textmap namespace
engine = "srb2";
maplumpnames
{
include("UDMF_misc.cfg", "udmfmaplumpnames_begin");
include("SRB222_misc.cfg", "udmfmaplumpnames");
include("UDMF_misc.cfg", "udmfmaplumpnames_end");
}
universalfields
{
include("SRB222_misc.cfg", "universalfields");
}
// When this is set to true, sectors with the same tag will light up when a line is highlighted
linetagindicatesectors = false;
// Special linedefs
include("SRB222_misc.cfg", "speciallinedefs_udmf");
// Default flags for first new thing
defaultthingflags
{
}
// SECTOR FLAGS
sectorflags
{
include("SRB222_misc.cfg", "sectorflags");
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
include("SRB222_misc.cfg", "sectorbrightness");
}
// SECTOR TYPES
sectortypes
{
include("SRB222_sectors.cfg", "sectortypes");
}
// GENERALISED SECTOR TYPES
gen_sectortypes
{
include("SRB222_sectors.cfg", "gen_sectortypes");
}
// LINEDEF FLAGS
linedefflags
{
include("SRB222_misc.cfg", "linedefflags_udmf");
}
linedefflagstranslation
{
include("SRB222_misc.cfg", "linedefflagstranslation");
}
// LINEDEF RENDERSTYLES
/*linedefrenderstyles
{
include("SRB222_misc.cfg", "linedefrenderstyles");
}*/
// THING FLAGS
thingflags
{
include("SRB222_misc.cfg", "thingflags_udmf");
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
include("SRB222_misc.cfg", "thingflagstranslation");
}
// How to compare thing flags (for the stuck things error checker)
thingflagscompare
{
include("UDMF_misc.cfg", "thingflagscompare");
}
// LINEDEF TYPES
linedeftypes
{
include("SRB222_linedefs.cfg", "udmf");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,625 @@
linedefflags
{
1 = "[0] Impassable";
2 = "[1] Block Enemies";
4 = "[2] Double-Sided";
8 = "[3] Upper Unpegged";
16 = "[4] Lower Unpegged";
32 = "[5] Slope Skew (E1)";
64 = "[6] Not Climbable";
128 = "[7] No Midtexture Skew (E2)";
256 = "[8] Peg Midtexture (E3)";
512 = "[9] Solid Midtexture (E4)";
1024 = "[10] Repeat Midtexture (E5)";
2048 = "[11] Netgame Only";
4096 = "[12] No Netgame";
8192 = "[13] Effect 6";
16384 = "[14] Bouncy Wall";
32768 = "[15] Transfer Line";
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
linedefflagstranslation
{
1 = "blocking";
2 = "blockmonsters";
4 = "twosided";
8 = "dontpegtop";
16 = "dontpegbottom";
32 = "skewtd";
64 = "noclimb";
128 = "noskew";
256 = "midpeg";
512 = "midsolid";
1024 = "wrapmidtex";
2048 = "netonly";
4096 = "nonet";
8192 = "effect6";
16384 = "bouncy";
32768 = "transfer";
}
linedefflags_udmf
{
blocking = "Impassable";
blockmonsters = "Block Enemies";
twosided = "Double-Sided";
dontpegtop = "Upper Unpegged";
dontpegbottom = "Lower Unpegged";
skewtd = "Slope Skew";
noclimb = "Not Climbable";
noskew = "No Midtexture Skew";
midpeg = "Peg Midtexture";
midsolid = "Solid Midtexture";
wrapmidtex = "Repeat Midtexture";
netonly = "Netgame Only";
nonet = "No Netgame";
effect6 = "Effect 6";
bouncy = "Bouncy Wall";
transfer = "Transfer Line";
}
/*linedefrenderstyles
{
translucent = "Translucent";
fog = "Fog";
}*/
sectorflags
{
colormapfog = "Fog Planes in Colormap";
colormapfadesprites = "Fade Fullbright in Colormap";
colormapprotected = "Protected Colormap";
}
thingflags
{
1 = "[1] Extra";
2 = "[2] Flip";
4 = "[4] Special";
8 = "[8] Ambush";
}
// THING FLAGS
thingflags_udmf
{
extra = "Extra";
flip = "Flip";
special = "Special";
ambush = "Ambush";
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
1 = "extra";
2 = "flip";
4 = "special";
8 = "ambush";
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
255;
248;
240;
232;
224;
216;
208;
200;
192;
184;
176;
168;
160;
152;
144;
136;
128;
120;
112;
104;
96;
88;
80;
72;
64;
56;
48;
40;
32;
24;
16;
8;
0;
}
/*
TEXTURES AND FLAT SOURCES
This tells Doom Builder where to find the information for textures
and flats in the IWAD file, Addition WAD file and Map WAD file.
Start and end lumps must be given in a structure (of which the
key name doesnt matter) and any textures or flats in between them
are loaded in either the textures category or flats category.
For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default.
*/
textures
{
zdoom1
{
start = "TX_START";
end = "TX_END";
}
}
/*
ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS
Only add fields here that Doom Builder does not edit with its own user-interface!
The "default" field must match the UDMF specifications!
Field data types:
0 = integer *
1 = float
2 = string
3 = bool
4 = linedef action (integer) *
5 = sector effect (integer) *
6 = texture (string)
7 = flat (string)
8 = angle in degrees (integer)
9 = angle in radians (float)
10 = XXRRGGBB color (integer)
11 = enum option (integer) *
12 = enum bits (integer) *
13 = sector tag (integer) *
14 = thing tag (integer) *
15 = linedef tag (integer) *
16 = enum option (string)
17 = angle in degrees (float)
22 = byte angle (integer)
*/
universalfields
{
sector
{
lightalpha
{
type = 0;
default = 25;
}
fadealpha
{
type = 0;
default = 25;
}
fadestart
{
type = 0;
default = 0;
}
fadeend
{
type = 0;
default = 33;
}
foglighting
{
type = 3;
default = false;
}
}
linedef
{
arg5
{
type = 0;
default = 0;
}
stringarg0
{
type = 2;
default = "";
}
stringarg1
{
type = 2;
default = "";
}
executordelay
{
type = 0;
default = 0;
}
}
sidedef
{
repeatcnt
{
type = 0;
default = 0;
}
}
thing
{
}
}
/*
MAP LUMP NAMES
Map lumps are loaded with the map as long as they are right after each other. When the editor
meets a lump which is not defined in this list it will ignore the map if not satisfied.
The order of items defines the order in which lumps will be written to WAD file on save.
To indicate the map header lump, use ~MAP
Legenda:
required = Lump is required to exist.
blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use)
nodebuild = The nodebuilder generates this lump.
allowempty = The nodebuilder is allowed to leave this lump empty.
scriptbuild = This lump is a text-based script, which should be compiled using current script compiler;
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
doommaplumpnames
{
~MAP
{
required = true;
blindcopy = true;
nodebuild = false;
}
THINGS
{
required = true;
nodebuild = true;
allowempty = true;
}
LINEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
SIDEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
VERTEXES
{
required = true;
nodebuild = true;
allowempty = false;
}
SEGS
{
required = false;
nodebuild = true;
allowempty = false;
}
SSECTORS
{
required = false;
nodebuild = true;
allowempty = false;
}
NODES
{
required = false;
nodebuild = true;
allowempty = false;
}
SECTORS
{
required = true;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
udmfmaplumpnames
{
ZNODES
{
required = false;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
// ENUMERATIONS
// These are enumerated lists for linedef types and UDMF fields.
// Reserved names are: angledeg, anglerad, color, texture, flat
enums
{
falsetrue
{
0 = "False";
1 = "True";
}
yesno
{
0 = "Yes";
1 = "No";
}
noyes
{
0 = "No";
1 = "Yes";
}
onoff
{
0 = "On";
1 = "Off";
}
offon
{
0 = "Off";
1 = "On";
}
updown
{
0 = "Up";
1 = "Down";
}
downup
{
0 = "Down";
1 = "Up";
}
frontback
{
0 = "None";
1 = "Front";
2 = "Back";
}
tangibility
{
1 = "Intangible from top";
2 = "Intangible from bottom";
4 = "Don't block players";
8 = "Don't block non-players";
}
}
//Default things filters
thingsfilters
{
filter0
{
name = "Player starts";
category = "starts";
type = -1;
}
filter1
{
name = "Enemies";
category = "enemies";
type = -1;
}
filter2
{
name = "NiGHTS Track";
category = "nightstrk";
type = -1;
}
filter3
{
name = "Normal Gravity";
category = "";
type = -1;
fields
{
2 = false;
}
}
filter4
{
name = "Reverse Gravity";
category = "";
type = -1;
fields
{
2 = true;
}
}
}
// Special linedefs
speciallinedefs
{
soundlinedefflag = 64; // See linedefflags
singlesidedflag = 1; // See linedefflags
doublesidedflag = 4; // See linedefflags
impassableflag = 1;
upperunpeggedflag = 8;
lowerunpeggedflag = 16;
repeatmidtextureflag = 1024;
pegmidtextureflag = 256;
}
speciallinedefs_udmf
{
soundlinedefflag = "noclimb";
singlesidedflag = "blocking";
doublesidedflag = "twosided";
impassableflag = "blocking";
upperunpeggedflag = "dontpegtop";
lowerunpeggedflag = "dontpegbottom";
repeatmidtextureflag = "wrapmidtex";
pegmidtextureflag = "midpeg";
}
scriptlumpnames
{
MAINCFG
{
script = "SOC.cfg";
}
OBJCTCFG
{
script = "SOC.cfg";
}
SOC_
{
script = "SOC.cfg";
isprefix = true;
}
LUA_
{
script = "Lua.cfg";
isprefix = true;
}
}
// Texture sources
textures
{
zdoom1
{
start = "TX_START";
end = "TX_END";
}
}
// Patch sources
patches
{
standard1
{
start = "P_START";
end = "P_END";
}
standard2
{
start = "PP_START";
end = "PP_END";
}
}
// Sprite sources
sprites
{
standard1
{
start = "S_START";
end = "S_END";
}
standard2
{
start = "SS_START";
end = "SS_END";
}
}
// Flat sources
flats
{
standard1
{
start = "F_START";
end = "F_END";
}
standard2
{
start = "FF_START";
end = "FF_END";
}
standard3
{
start = "FF_START";
end = "F_END";
}
standard4
{
start = "F_START";
end = "FF_END";
}
}

View File

@ -0,0 +1,109 @@
sectortypes
{
0 = "Normal";
1 = "Damage";
2 = "Damage (Water)";
3 = "Damage (Fire)";
4 = "Damage (Electrical)";
5 = "Spikes";
6 = "Death Pit (Camera Tilt)";
7 = "Death Pit (No Camera Tilt)";
8 = "Instant Kill";
9 = "Ring Drainer (Floor Touch)";
10 = "Ring Drainer (Anywhere in Sector)";
11 = "Special Stage Damage";
12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF";
16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)";
112 = "Trigger Line Ex. (NiGHTS Mare)";
128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters";
176 = "Custom Global Gravity";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad";
4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag";
12288 = "CTF Red Team Base";
16384 = "CTF Blue Team Base";
20480 = "Fan Sector";
24576 = "Super Sonic Transform";
28672 = "Force Spin";
32768 = "Zoom Tube Start";
36864 = "Zoom Tube End";
40960 = "Circuit Finish Line";
45056 = "Rope Hang";
49152 = "Intangible to the Camera";
}
gen_sectortypes
{
first
{
0 = "Normal";
1 = "Damage";
2 = "Damage (Water)";
3 = "Damage (Fire)";
4 = "Damage (Electrical)";
5 = "Spikes";
6 = "Death Pit (Camera Tilt)";
7 = "Death Pit (No Camera Tilt)";
8 = "Instant Kill";
9 = "Ring Drainer (Floor Touch)";
10 = "Ring Drainer (Anywhere in Sector)";
11 = "Special Stage Damage";
12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF";
}
second
{
0 = "Normal";
16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)";
112 = "Trigger Line Ex. (NiGHTS Mare)";
128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters";
176 = "Custom Global Gravity";
}
third
{
0 = "Normal";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad";
}
fourth
{
0 = "Normal";
4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag";
12288 = "CTF Red Team Base";
16384 = "CTF Blue Team Base";
20480 = "Fan Sector";
24576 = "Super Sonic Transform";
28672 = "Force Spin";
32768 = "Zoom Tube Start";
36864 = "Zoom Tube End";
40960 = "Circuit Finish Line";
45056 = "Rope Hang";
49152 = "Intangible to the Camera";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
/************************************************************************\
Ultimate Doom Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
\************************************************************************/
// This is required to prevent accidental use of a different configuration
type = "Doom Builder 2 Game Configuration";
// This is the title to show for this game
game = "Sonic Robo Blast 2 - 2.2 (Doom format)";
// This is the simplified game engine/sourceport name
engine = "zdoom";
// Settings common to all games and all map formats
include("Includes\\SRB222_common.cfg", "common");
// Settings common to Doom map format
include("Includes\\SRB222_common.cfg", "mapformat_doom");
include("Includes\\Game_SRB222.cfg");
// Script lumps detection
scriptlumpnames
{
include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
}
// THING TYPES
thingtypes
{
include("Includes\\SRB222_things.cfg");
}
//Default things filters
thingsfilters
{
include("Includes\\SRB222_misc.cfg", "thingsfilters");
}

View File

@ -0,0 +1,47 @@
/************************************************************************\
Ultimate Doom Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
\************************************************************************/
// This is required to prevent accidental use of a different configuration
type = "Doom Builder 2 Game Configuration";
// This is the title to show for this game
game = "Sonic Robo Blast 2 - 2.2 (UDMF)";
// This is the simplified game engine/sourceport name
engine = "zdoom";
// Settings common to all games and all map formats
include("Includes\\SRB222_common.cfg", "common");
// Settings common to text map format
include("Includes\\SRB222_common.cfg", "mapformat_udmf");
include("Includes\\Game_SRB222.cfg");
// Script lumps detection
scriptlumpnames
{
include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
}
// THING TYPES
thingtypes
{
include("Includes\\SRB222_things.cfg");
}
//Default things filters
thingsfilters
{
include("Includes\\SRB222_misc.cfg", "thingsfilters");
}
// ENUMERATIONS
// Each engine has its own additional thing types
// These are enumerated lists for linedef types and UDMF fields.
enums
{
// Basic game enums
include("Includes\\SRB222_misc.cfg", "enums");
}

View File

@ -228,6 +228,12 @@ set(SRB2_CONFIG_HAVE_OPENMPT ON CACHE BOOL
"Enable OpenMPT support.") "Enable OpenMPT support.")
set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL
"Enable curl support, used for downloading files via HTTP.") "Enable curl support, used for downloading files via HTTP.")
if(${CMAKE_SYSTEM} MATCHES Windows)
set(SRB2_CONFIG_HAVE_MIXERX ON CACHE BOOL
"Enable SDL Mixer X support.")
else()
set(SRB2_CONFIG_HAVE_MIXERX OFF)
endif()
set(SRB2_CONFIG_HWRENDER ON CACHE BOOL set(SRB2_CONFIG_HWRENDER ON CACHE BOOL
"Enable hardware rendering through OpenGL.") "Enable hardware rendering through OpenGL.")
set(SRB2_CONFIG_USEASM OFF CACHE BOOL set(SRB2_CONFIG_USEASM OFF CACHE BOOL
@ -368,6 +374,30 @@ if(${SRB2_CONFIG_HAVE_OPENMPT})
endif() endif()
endif() endif()
if(${SRB2_CONFIG_HAVE_MIXERX})
if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
set(MIXERX_FOUND ON)
set(MIXERX_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/i686-w64-mingw32/include/SDL2)
if(${SRB2_SYSTEM_BITS} EQUAL 64)
set(MIXERX_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/SDLMixerX/x86_64-w64-mingw32/lib -lSDL2_mixer_ext")
else() # 32-bit
set(MIXERX_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/SDLMixerX/i686-w64-mingw32/lib -lSDL2_mixer_ext")
endif()
else()
# No support for non-Windows (yet?)
#find_package(MIXERX)
message(WARNING "SDL Mixer X is not supported as an external library.")
set(MIXERX_FOUND OFF)
endif()
if(${MIXERX_FOUND})
set(SRB2_HAVE_MIXERX ON)
set(SRB2_SDL2_SOUNDIMPL mixer_sound.c)
add_definitions(-DHAVE_MIXERX)
else()
message(WARNING "You have specified that SDL Mixer X is available but it was not found.")
endif()
endif()
if(${SRB2_CONFIG_HAVE_ZLIB}) if(${SRB2_CONFIG_HAVE_ZLIB})
if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
set(ZLIB_FOUND ON) set(ZLIB_FOUND ON)
@ -515,6 +545,27 @@ endif()
# Targets # Targets
# If using CCACHE, then force it.
# https://github.com/Cockatrice/Cockatrice/pull/3052/files
if (${CMAKE_SYSTEM} MATCHES "Darwin")
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE)
MESSAGE(STATUS "Force enabling CCache usage under macOS")
# Set up wrapper scripts
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/launch-c.in ${CMAKE_BINARY_DIR}/launch-c)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/launch-cxx.in ${CMAKE_BINARY_DIR}/launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
endif()
# Compatibility flag with later versions of GCC # Compatibility flag with later versions of GCC
# We should really fix our code to not need this # We should really fix our code to not need this
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")

View File

@ -12,14 +12,15 @@
# to avoid a false positive with the version detection... # to avoid a false positive with the version detection...
SUPPORTED_GCC_VERSIONS:=\ SUPPORTED_GCC_VERSIONS:=\
91\ 101 102\
81 82 83\ 91 92 93\
71 72\ 81 82 83 84\
71 72 73 74 75\
61 62 63 64\ 61 62 63 64\
51 52 53 54\ 51 52 53 54 55\
40 41 42 43 44 45 46 47 48 49 40 41 42 43 44 45 46 47 48 49
LATEST_GCC_VERSION=9.1 LATEST_GCC_VERSION=10.2
# gcc or g++ # gcc or g++
ifdef PREFIX ifdef PREFIX
@ -68,7 +69,27 @@ ifeq (,$(filter GCC%,$(.VARIABLES)))
endif endif
endif endif
ifdef GCC102
GCC101=1
endif
ifdef GCC101
GCC93=1
endif
ifdef GCC93
GCC92=1
endif
ifdef GCC92
GCC91=1
endif
ifdef GCC91 ifdef GCC91
GCC84=1
endif
ifdef GCC84
GCC83=1 GCC83=1
endif endif
@ -81,6 +102,18 @@ GCC81=1
endif endif
ifdef GCC81 ifdef GCC81
GCC75=1
endif
ifdef GCC75
GCC74=1
endif
ifdef GCC74
GCC73=1
endif
ifdef GCC73
GCC72=1 GCC72=1
endif endif
@ -105,6 +138,10 @@ GCC61=1
endif endif
ifdef GCC61 ifdef GCC61
GCC55=1
endif
ifdef GCC55
GCC54=1 GCC54=1
endif endif

View File

@ -33,6 +33,7 @@
#include "p_setup.h" #include "p_setup.h"
#include "lua_script.h" #include "lua_script.h"
#include "d_netfil.h" // findfile #include "d_netfil.h" // findfile
#include "r_data.h" // Color_cons_t
//======== //========
// protos. // protos.
@ -818,6 +819,18 @@ static void COM_Help_f(void)
CONS_Printf(" Yes or No (On or Off, 1 or 0)\n"); CONS_Printf(" Yes or No (On or Off, 1 or 0)\n");
else if (cvar->PossibleValue == CV_OnOff) else if (cvar->PossibleValue == CV_OnOff)
CONS_Printf(" On or Off (Yes or No, 1 or 0)\n"); CONS_Printf(" On or Off (Yes or No, 1 or 0)\n");
else if (cvar->PossibleValue == Color_cons_t)
{
for (i = 1; i < numskincolors; ++i)
{
if (skincolors[i].accessible)
{
CONS_Printf(" %-2d : %s\n", i, skincolors[i].name);
if (i == cvar->value)
cvalue = skincolors[i].name;
}
}
}
else else
{ {
#define MINVAL 0 #define MINVAL 0

View File

@ -3664,6 +3664,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_RemovePlayer(pnum, kickreason); CL_RemovePlayer(pnum, kickreason);
} }
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = {"netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
@ -5428,6 +5431,10 @@ void TryRunTics(tic_t realtics)
ExtraDataTicker(); ExtraDataTicker();
gametic++; gametic++;
consistancy[gametic%BACKUPTICS] = Consistancy(); consistancy[gametic%BACKUPTICS] = Consistancy();
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
break;
} }
} }
} }

View File

@ -542,7 +542,7 @@ extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping; extern tic_t servermaxping;
extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout; extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout;
extern consvar_t cv_resynchattempts, cv_blamecfail; extern consvar_t cv_resynchattempts, cv_blamecfail;
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;

View File

@ -701,6 +701,7 @@ void D_RegisterClientCommands(void)
#endif #endif
CV_RegisterVar(&cv_rollingdemos); CV_RegisterVar(&cv_rollingdemos);
CV_RegisterVar(&cv_netstat); CV_RegisterVar(&cv_netstat);
CV_RegisterVar(&cv_netticbuffer);
#ifdef NETGAME_DEVMODE #ifdef NETGAME_DEVMODE
CV_RegisterVar(&cv_fishcake); CV_RegisterVar(&cv_fishcake);

View File

@ -806,8 +806,43 @@ static void readskincolor(MYFILE *f, INT32 num)
if (fastcmp(word, "NAME")) if (fastcmp(word, "NAME"))
{ {
deh_strlcpy(skincolors[num].name, word2, size_t namesize = sizeof(skincolors[num].name);
sizeof (skincolors[num].name), va("Skincolor %d: name", num)); char truncword[namesize];
UINT16 dupecheck;
deh_strlcpy(truncword, word2, namesize, va("Skincolor %d: name", num)); // truncate here to check for dupes
dupecheck = R_GetColorByName(truncword);
if (truncword[0] != '\0' && (!stricmp(truncword, skincolors[SKINCOLOR_NONE].name) || (dupecheck && dupecheck != num)))
{
size_t lastchar = strlen(truncword);
char oldword[lastchar+1];
char dupenum = '1';
strlcpy(oldword, truncword, lastchar+1);
lastchar--;
if (lastchar == namesize-2) // exactly max length, replace last character with 0
truncword[lastchar] = '0';
else // append 0
{
strcat(truncword, "0");
lastchar++;
}
while (R_GetColorByName(truncword))
{
truncword[lastchar] = dupenum;
if (dupenum == '9')
dupenum = 'A';
else if (dupenum == 'Z') // give up :?
break;
else
dupenum++;
}
deh_warning("Skincolor %d: name %s is a duplicate of another skincolor's name - renamed to %s", num, oldword, truncword);
}
strlcpy(skincolors[num].name, truncword, namesize); // already truncated
} }
else if (fastcmp(word, "RAMP")) else if (fastcmp(word, "RAMP"))
{ {
@ -818,10 +853,15 @@ static void readskincolor(MYFILE *f, INT32 num)
if ((tmp = strtok(NULL,",")) == NULL) if ((tmp = strtok(NULL,",")) == NULL)
break; break;
} }
skincolor_modified[num] = true;
} }
else if (fastcmp(word, "INVCOLOR")) else if (fastcmp(word, "INVCOLOR"))
{ {
skincolors[num].invcolor = (UINT16)get_number(word2); UINT16 v = (UINT16)get_number(word2);
if (v < numskincolors)
skincolors[num].invcolor = v;
else
skincolors[num].invcolor = SKINCOLOR_GREEN;
} }
else if (fastcmp(word, "INVSHADE")) else if (fastcmp(word, "INVSHADE"))
{ {
@ -4688,11 +4728,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
{ {
if (i == 0 && word2[0] != '0') // If word2 isn't a number if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_skincolor(word2); // find a skincolor by name i = get_skincolor(word2); // find a skincolor by name
if (i < numskincolors && i >= (INT32)SKINCOLOR_FIRSTFREESLOT) if (i && i < numskincolors)
readskincolor(f, i); readskincolor(f, i);
else else
{ {
deh_warning("Skincolor %d out of range (%d - %d)", i, SKINCOLOR_FIRSTFREESLOT, numskincolors-1); deh_warning("Skincolor %d out of range (1 - %d)", i, numskincolors-1);
ignorelines(f); ignorelines(f);
} }
} }
@ -8900,7 +8940,6 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_ANGLEMAN", "MT_ANGLEMAN",
"MT_POLYANCHOR", "MT_POLYANCHOR",
"MT_POLYSPAWN", "MT_POLYSPAWN",
"MT_POLYSPAWNCRUSH",
// Skybox objects // Skybox objects
"MT_SKYBOX", "MT_SKYBOX",
@ -10628,7 +10667,7 @@ static inline int lib_freeslot(lua_State *L)
CONS_Printf("State S_%s allocated.\n",word); CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word); strcpy(FREE_STATES[i],word);
lua_pushinteger(L, i); lua_pushinteger(L, S_FIRSTFREESLOT + i);
r++; r++;
break; break;
} }
@ -10643,7 +10682,7 @@ static inline int lib_freeslot(lua_State *L)
CONS_Printf("MobjType MT_%s allocated.\n",word); CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word); strcpy(FREE_MOBJS[i],word);
lua_pushinteger(L, i); lua_pushinteger(L, MT_FIRSTFREESLOT + i);
r++; r++;
break; break;
} }
@ -10659,7 +10698,7 @@ static inline int lib_freeslot(lua_State *L)
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word); strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++); M_AddMenuColor(numskincolors++);
lua_pushinteger(L, i); lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i);
r++; r++;
break; break;
} }
@ -10680,11 +10719,12 @@ static inline int lib_freeslot(lua_State *L)
CONS_Printf("Sprite SPR2_%s allocated.\n",word); CONS_Printf("Sprite SPR2_%s allocated.\n",word);
strncpy(spr2names[free_spr2],word,4); strncpy(spr2names[free_spr2],word,4);
spr2defaults[free_spr2] = 0; spr2defaults[free_spr2] = 0;
lua_pushinteger(L, free_spr2);
r++;
spr2names[free_spr2++][4] = 0; spr2names[free_spr2++][4] = 0;
} else } else
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
} }
r++;
} }
else if (fastcmp(type, "TOL")) else if (fastcmp(type, "TOL"))
{ {

View File

@ -23,6 +23,8 @@
// Some global defines, that configure the game. // Some global defines, that configure the game.
#include "doomdef.h" #include "doomdef.h"
#include "m_fixed.h" // See the mapthing_t scale.
// //
// Map level types. // Map level types.
// The following data structures define the persistent format // The following data structures define the persistent format
@ -193,16 +195,24 @@ typedef struct
#pragma pack() #pragma pack()
#endif #endif
#define NUMMAPTHINGARGS 6
#define NUMMAPTHINGSTRINGARGS 2
// Thing definition, position, orientation and type, // Thing definition, position, orientation and type,
// plus visibility flags and attributes. // plus visibility flags and attributes.
typedef struct typedef struct
{ {
INT16 x, y; INT16 x, y;
INT16 angle; INT16 angle, pitch, roll;
UINT16 type; UINT16 type;
UINT16 options; UINT16 options;
INT16 z; INT16 z;
UINT8 extrainfo; UINT8 extrainfo;
fixed_t scale;
INT16 tag;
INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS];
struct mobj_s *mobj; struct mobj_s *mobj;
} mapthing_t; } mapthing_t;

View File

@ -2382,9 +2382,12 @@ static void WriteDemoChecksum(void)
static void G_StopDemoRecording(void) static void G_StopDemoRecording(void)
{ {
boolean saved = false; boolean saved = false;
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker if (demo_p)
WriteDemoChecksum(); {
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
WriteDemoChecksum();
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
}
free(demobuffer); free(demobuffer);
demorecording = false; demorecording = false;

View File

@ -2013,7 +2013,9 @@ boolean G_Responder(event_t *ev)
if (F_CreditResponder(ev)) if (F_CreditResponder(ev))
{ {
// Skip credits for everyone // Skip credits for everyone
if (!netgame || server || IsPlayerAdmin(consoleplayer)) if (! serverrunning)/* hahahahahaha */
F_StartGameEvaluation();
else if (server || IsPlayerAdmin(consoleplayer))
SendNetXCmd(XD_EXITLEVEL, NULL, 0); SendNetXCmd(XD_EXITLEVEL, NULL, 0);
return true; return true;
} }

View File

@ -214,6 +214,9 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col
poly_color.s.blue = (UINT8)blue; poly_color.s.blue = (UINT8)blue;
} }
// Clamp the light level, since it can sometimes go out of the 0-255 range from animations
light_level = min(max(light_level, 0), 255);
Surface->PolyColor.rgba = poly_color.rgba; Surface->PolyColor.rgba = poly_color.rgba;
Surface->TintColor.rgba = tint_color.rgba; Surface->TintColor.rgba = tint_color.rgba;
Surface->FadeColor.rgba = fade_color.rgba; Surface->FadeColor.rgba = fade_color.rgba;
@ -491,7 +494,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
if (angle) // Only needs to be done if there's an altered angle if (angle) // Only needs to be done if there's an altered angle
{ {
angle = (InvAngle(angle)+ANGLE_180)>>ANGLETOFINESHIFT; angle = (InvAngle(angle))>>ANGLETOFINESHIFT;
// This needs to be done so that it scrolls in a different direction after rotation like software // This needs to be done so that it scrolls in a different direction after rotation like software
/*tempxsow = FLOAT_TO_FIXED(scrollx); /*tempxsow = FLOAT_TO_FIXED(scrollx);
@ -525,8 +528,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
{\ {\
tempxsow = FLOAT_TO_FIXED(vert->s);\ tempxsow = FLOAT_TO_FIXED(vert->s);\
tempytow = FLOAT_TO_FIXED(vert->t);\ tempytow = FLOAT_TO_FIXED(vert->t);\
if (texflat)\
tempytow = -tempytow;\
vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\
vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\
}\ }\
@ -770,6 +771,7 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
{ {
switch (transtablenum) switch (transtablenum)
{ {
case 0 : pSurf->PolyColor.s.alpha = 0x00;return PF_Masked;
case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent; case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent;
case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent; case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent;
case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent; case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent;
@ -1438,37 +1440,10 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
wallVerts[1].y = FIXED_TO_FLOAT(l); wallVerts[1].y = FIXED_TO_FLOAT(l);
} }
// set alpha for transparent walls (new boom and legacy linedef types) // set alpha for transparent walls
// ooops ! this do not work at all because render order we should render it in backtofront order // ooops ! this do not work at all because render order we should render it in backtofront order
switch (gl_linedef->special) switch (gl_linedef->special)
{ {
case 900:
blendmode = HWR_TranstableToAlpha(tr_trans10, &Surf);
break;
case 901:
blendmode = HWR_TranstableToAlpha(tr_trans20, &Surf);
break;
case 902:
blendmode = HWR_TranstableToAlpha(tr_trans30, &Surf);
break;
case 903:
blendmode = HWR_TranstableToAlpha(tr_trans40, &Surf);
break;
case 904:
blendmode = HWR_TranstableToAlpha(tr_trans50, &Surf);
break;
case 905:
blendmode = HWR_TranstableToAlpha(tr_trans60, &Surf);
break;
case 906:
blendmode = HWR_TranstableToAlpha(tr_trans70, &Surf);
break;
case 907:
blendmode = HWR_TranstableToAlpha(tr_trans80, &Surf);
break;
case 908:
blendmode = HWR_TranstableToAlpha(tr_trans90, &Surf);
break;
// Translucent // Translucent
case 102: case 102:
case 121: case 121:
@ -1489,7 +1464,10 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
blendmode = PF_Translucent; blendmode = PF_Translucent;
break; break;
default: default:
blendmode = PF_Masked; if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT)
blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), &Surf);
else
blendmode = PF_Masked;
break; break;
} }
@ -2280,8 +2258,8 @@ static void HWR_AddLine(seg_t * line)
v2y = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y); v2y = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y);
// OPTIMIZE: quickly reject orthogonal back sides. // OPTIMIZE: quickly reject orthogonal back sides.
angle1 = R_PointToAngle(v1x, v1y); angle1 = R_PointToAngle64(v1x, v1y);
angle2 = R_PointToAngle(v2x, v2y); angle2 = R_PointToAngle64(v2x, v2y);
#ifdef NEWCLIP #ifdef NEWCLIP
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle! // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
@ -2574,8 +2552,8 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
py2 = bspcoord[checkcoord[boxpos][3]]; py2 = bspcoord[checkcoord[boxpos][3]];
#ifdef NEWCLIP #ifdef NEWCLIP
angle1 = R_PointToAngle(px1, py1); angle1 = R_PointToAngle64(px1, py1);
angle2 = R_PointToAngle(px2, py2); angle2 = R_PointToAngle64(px2, py2);
return gld_clipper_SafeCheckRange(angle2, angle1); return gld_clipper_SafeCheckRange(angle2, angle1);
#else #else
// check clip list for an open space // check clip list for an open space
@ -2757,8 +2735,11 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
HWR_SetCurrentTexture(NULL); HWR_SetCurrentTexture(NULL);
// reference point for flat texture coord for each vertex around the polygon // reference point for flat texture coord for each vertex around the polygon
flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); flatxref = FIXED_TO_FLOAT(polysector->origVerts[0].x);
flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight); flatyref = FIXED_TO_FLOAT(polysector->origVerts[0].y);
flatxref = (float)(((fixed_t)flatxref & (~flatflag)) / fflatwidth);
flatyref = (float)(((fixed_t)flatyref & (~flatflag)) / fflatheight);
// transform // transform
v3d = planeVerts; v3d = planeVerts;
@ -2769,13 +2750,13 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{ {
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; angle = FOFsector->floorpic_angle;
} }
else // it's a ceiling else // it's a ceiling
{ {
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; angle = FOFsector->ceilingpic_angle;
} }
} }
else if (gl_frontsector) else if (gl_frontsector)
@ -2784,23 +2765,25 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{ {
scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth; scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight; scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight;
angle = gl_frontsector->floorpic_angle>>ANGLETOFINESHIFT; angle = gl_frontsector->floorpic_angle;
} }
else // it's a ceiling else // it's a ceiling
{ {
scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight;
angle = gl_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; angle = gl_frontsector->ceilingpic_angle;
} }
} }
if (angle) // Only needs to be done if there's an altered angle if (angle) // Only needs to be done if there's an altered angle
{ {
angle = (InvAngle(angle))>>ANGLETOFINESHIFT;
// This needs to be done so that it scrolls in a different direction after rotation like software // This needs to be done so that it scrolls in a different direction after rotation like software
tempxs = FLOAT_TO_FIXED(scrollx); /*tempxs = FLOAT_TO_FIXED(scrollx);
tempyt = FLOAT_TO_FIXED(scrolly); tempyt = FLOAT_TO_FIXED(scrolly);
scrollx = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); scrollx = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle))));
scrolly = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); scrolly = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle))));*/
// This needs to be done so everything aligns after rotation // This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
@ -2830,10 +2813,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{ {
tempxs = FLOAT_TO_FIXED(v3d->s); tempxs = FLOAT_TO_FIXED(v3d->s);
tempyt = FLOAT_TO_FIXED(v3d->t); tempyt = FLOAT_TO_FIXED(v3d->t);
if (texflat)
tempyt = -tempyt;
v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle))));
v3d->t = (FIXED_TO_FLOAT(-FixedMul(tempxs, FINESINE(angle)) - FixedMul(tempyt, FINECOSINE(angle)))); v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle))));
} }
v3d->x = FIXED_TO_FLOAT(polysector->vertices[i]->x); v3d->x = FIXED_TO_FLOAT(polysector->vertices[i]->x);

View File

@ -678,6 +678,29 @@ static INT32 shader_leveltime = 0;
"gl_FragColor = final_color;\n" \ "gl_FragColor = final_color;\n" \
"}\0" "}\0"
// same as above but multiplies results with the lighting value from the
// accompanying vertex shader (stored in gl_Color)
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color *= gl_Color;\n" \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\0"
// //
// Water surface shader // Water surface shader
// //
@ -775,6 +798,9 @@ static const char *fragment_shaders[] = {
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
"}\0", "}\0",
// Model fragment shader + diffuse lighting from above
GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER,
NULL, NULL,
}; };
@ -795,6 +821,20 @@ static const char *fragment_shaders[] = {
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0" "}\0"
// replicates the way fixed function lighting is used by the model lighting option,
// stores the lighting result to gl_Color
// (ambient lighting of 0.75 and diffuse lighting from above)
#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
"float light = 0.75 + max(nDotVP, 0.0);\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
static const char *vertex_shaders[] = { static const char *vertex_shaders[] = {
// Default vertex shader // Default vertex shader
GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_VERTEX_SHADER,
@ -820,6 +860,9 @@ static const char *vertex_shaders[] = {
// Sky vertex shader // Sky vertex shader
GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_VERTEX_SHADER,
// Model vertex shader + diffuse lighting from above
GLSL_MODEL_LIGHTING_VERTEX_SHADER,
NULL, NULL,
}; };
@ -1063,6 +1106,11 @@ EXPORT void HWRAPI(SetShader) (int shader)
#ifdef GL_SHADERS #ifdef GL_SHADERS
if (gl_allowshaders) if (gl_allowshaders)
{ {
// If using model lighting, set the appropriate shader.
// However don't override a custom shader.
// Should use an enum or something...
if (shader == 4 && model_lighting && !gl_shaderprograms[4].custom)
shader = 8;
if ((GLuint)shader != gl_currentshaderprogram) if ((GLuint)shader != gl_currentshaderprogram)
{ {
gl_currentshaderprogram = shader; gl_currentshaderprogram = shader;
@ -1535,7 +1583,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
// Sryder: Fog // Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them // multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
pglAlphaFunc(GL_NOTEQUAL, 0.0f); pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break; break;
default : // must be 0, otherwise it's an error default : // must be 0, otherwise it's an error
// No blending // No blending
@ -2660,31 +2708,34 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
poly.alpha = byte2float[Surface->PolyColor.s.alpha]; poly.alpha = byte2float[Surface->PolyColor.s.alpha];
#ifdef GL_LIGHT_MODEL_AMBIENT #ifdef GL_LIGHT_MODEL_AMBIENT
if (model_lighting && (!gl_shadersenabled)) // doesn't work with shaders anyway if (model_lighting)
{ {
ambient[0] = poly.red; if (!gl_shadersenabled)
ambient[1] = poly.green; {
ambient[2] = poly.blue; ambient[0] = poly.red;
ambient[3] = poly.alpha; ambient[1] = poly.green;
ambient[2] = poly.blue;
ambient[3] = poly.alpha;
diffuse[0] = poly.red; diffuse[0] = poly.red;
diffuse[1] = poly.green; diffuse[1] = poly.green;
diffuse[2] = poly.blue; diffuse[2] = poly.blue;
diffuse[3] = poly.alpha; diffuse[3] = poly.alpha;
if (ambient[0] > 0.75f) if (ambient[0] > 0.75f)
ambient[0] = 0.75f; ambient[0] = 0.75f;
if (ambient[1] > 0.75f) if (ambient[1] > 0.75f)
ambient[1] = 0.75f; ambient[1] = 0.75f;
if (ambient[2] > 0.75f) if (ambient[2] > 0.75f)
ambient[2] = 0.75f; ambient[2] = 0.75f;
pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); pglLightfv(GL_LIGHT0, GL_POSITION, LightPos);
pglEnable(GL_LIGHTING);
pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
}
pglShadeModel(GL_SMOOTH); pglShadeModel(GL_SMOOTH);
pglEnable(GL_LIGHTING);
pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
} }
#endif #endif
else else
@ -2874,9 +2925,10 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
pglDisable(GL_NORMALIZE); pglDisable(GL_NORMALIZE);
#ifdef GL_LIGHT_MODEL_AMBIENT #ifdef GL_LIGHT_MODEL_AMBIENT
if (model_lighting && (!gl_shadersenabled)) if (model_lighting)
{ {
pglDisable(GL_LIGHTING); if (!gl_shadersenabled)
pglDisable(GL_LIGHTING);
pglShadeModel(GL_FLAT); pglShadeModel(GL_FLAT);
} }
#endif #endif

View File

@ -20867,33 +20867,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_POLYSPAWNCRUSH
762, // doomednum
S_INVISIBLE, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
3, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
1*FRACUNIT, // radius
1*FRACUNIT, // height
0, // display offset
1000, // mass
8, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_NOCLIP, // flags
S_NULL // raisestate
},
{ // MT_SKYBOX { // MT_SKYBOX
780, // doomednum 780, // doomednum
S_INVISIBLE, // spawnstate S_INVISIBLE, // spawnstate

View File

@ -4774,7 +4774,6 @@ typedef enum mobj_type
MT_ANGLEMAN, MT_ANGLEMAN,
MT_POLYANCHOR, MT_POLYANCHOR,
MT_POLYSPAWN, MT_POLYSPAWN,
MT_POLYSPAWNCRUSH,
// Skybox objects // Skybox objects
MT_SKYBOX, MT_SKYBOX,

View File

@ -176,6 +176,11 @@ static const struct {
{META_SECTORLINES, "sector_t.lines"}, {META_SECTORLINES, "sector_t.lines"},
{META_SIDENUM, "line_t.sidenum"}, {META_SIDENUM, "line_t.sidenum"},
{META_LINEARGS, "line_t.args"},
{META_LINESTRINGARGS, "line_t.stringargs"},
{META_THINGARGS, "mapthing.args"},
{META_THINGSTRINGARGS, "mapthing.stringargs"},
#ifdef HAVE_LUA_SEGS #ifdef HAVE_LUA_SEGS
{META_NODEBBOX, "node_t.bbox"}, {META_NODEBBOX, "node_t.bbox"},
{META_NODECHILDREN, "node_t.children"}, {META_NODECHILDREN, "node_t.children"},
@ -1113,6 +1118,16 @@ static int lib_pPlayerCanDamage(lua_State *L)
return 1; return 1;
} }
static int lib_pPlayerFullbright(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_PlayerFullbright(player));
return 1;
}
static int lib_pIsObjectInGoop(lua_State *L) static int lib_pIsObjectInGoop(lua_State *L)
{ {
@ -2550,6 +2565,14 @@ static int lib_rGetColorByName(lua_State *L)
return 1; return 1;
} }
static int lib_rGetSuperColorByName(lua_State *L)
{
const char* colorname = luaL_checkstring(L, 1);
//HUDSAFE
lua_pushinteger(L, R_GetSuperColorByName(colorname));
return 1;
}
// Lua exclusive function, returns the name of a color from the SKINCOLOR_ constant. // Lua exclusive function, returns the name of a color from the SKINCOLOR_ constant.
// SKINCOLOR_GREEN > "Green" for example // SKINCOLOR_GREEN > "Green" for example
static int lib_rGetNameByColor(lua_State *L) static int lib_rGetNameByColor(lua_State *L)
@ -3108,6 +3131,117 @@ static int lib_gBuildMapTitle(lua_State *L)
return 1; return 1;
} }
static void
Lpushdim (lua_State *L, int c, struct searchdim *v)
{
int i;
lua_createtable(L, c, 0);/* I guess narr is numeric indices??? */
for (i = 0; i < c; ++i)
{
lua_createtable(L, 0, 2);/* and hashed indices (field)... */
lua_pushnumber(L, v[i].pos);
lua_setfield(L, -2, "pos");
lua_pushnumber(L, v[i].siz);
lua_setfield(L, -2, "siz");
lua_rawseti(L, -2, 1 + i);
}
}
/*
I decided to make this return a table because userdata
is scary and tables let the user set their own fields.
*/
/*
Returns:
[1] => map number
[2] => map title
[3] => search frequency table
The frequency table is unsorted. It has the following format:
{
['mapnum'],
['matchd'] => matches in map title string
['keywhd'] => matches in map keywords
The above two tables have the following format:
{
['pos'] => offset from start of string
['siz'] => length of match
}...
['total'] => the total matches
}...
*/
static int lib_gFindMap(lua_State *L)
{
const char *query = luaL_checkstring(L, 1);
INT32 map;
char *realname;
INT32 frc;
mapsearchfreq_t *frv;
INT32 i;
map = G_FindMap(query, &realname, &frv, &frc);
lua_settop(L, 0);
lua_pushnumber(L, map);
lua_pushstring(L, realname);
lua_createtable(L, frc, 0);
for (i = 0; i < frc; ++i)
{
lua_createtable(L, 0, 4);
lua_pushnumber(L, frv[i].mapnum);
lua_setfield(L, -2, "mapnum");
Lpushdim(L, frv[i].matchc, frv[i].matchd);
lua_setfield(L, -2, "matchd");
Lpushdim(L, frv[i].keywhc, frv[i].keywhd);
lua_setfield(L, -2, "keywhd");
lua_pushnumber(L, frv[i].total);
lua_setfield(L, -2, "total");
lua_rawseti(L, -2, 1 + i);
}
G_FreeMapSearch(frv, frc);
Z_Free(realname);
return 3;
}
/*
Returns:
[1] => map number
[2] => map title
*/
static int lib_gFindMapByNameOrCode(lua_State *L)
{
const char *query = luaL_checkstring(L, 1);
INT32 map;
char *realname;
map = G_FindMapByNameOrCode(query, &realname);
lua_pushnumber(L, map);
if (map)
{
lua_pushstring(L, realname);
Z_Free(realname);
return 2;
}
else
return 1;
}
static int lib_gDoReborn(lua_State *L) static int lib_gDoReborn(lua_State *L)
{ {
INT32 playernum = luaL_checkinteger(L, 1); INT32 playernum = luaL_checkinteger(L, 1);
@ -3378,6 +3512,7 @@ static luaL_Reg lib[] = {
{"P_DoPlayerPain",lib_pDoPlayerPain}, {"P_DoPlayerPain",lib_pDoPlayerPain},
{"P_ResetPlayer",lib_pResetPlayer}, {"P_ResetPlayer",lib_pResetPlayer},
{"P_PlayerCanDamage",lib_pPlayerCanDamage}, {"P_PlayerCanDamage",lib_pPlayerCanDamage},
{"P_PlayerFullbright",lib_pPlayerFullbright},
{"P_IsObjectInGoop",lib_pIsObjectInGoop}, {"P_IsObjectInGoop",lib_pIsObjectInGoop},
{"P_IsObjectOnGround",lib_pIsObjectOnGround}, {"P_IsObjectOnGround",lib_pIsObjectOnGround},
{"P_InSpaceSector",lib_pInSpaceSector}, {"P_InSpaceSector",lib_pInSpaceSector},
@ -3493,6 +3628,7 @@ static luaL_Reg lib[] = {
// r_draw // r_draw
{"R_GetColorByName", lib_rGetColorByName}, {"R_GetColorByName", lib_rGetColorByName},
{"R_GetSuperColorByName", lib_rGetSuperColorByName},
{"R_GetNameByColor", lib_rGetNameByColor}, {"R_GetNameByColor", lib_rGetNameByColor},
// s_sound // s_sound
@ -3519,6 +3655,8 @@ static luaL_Reg lib[] = {
{"G_AddGametype", lib_gAddGametype}, {"G_AddGametype", lib_gAddGametype},
{"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapName",lib_gBuildMapName},
{"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_BuildMapTitle",lib_gBuildMapTitle},
{"G_FindMap",lib_gFindMap},
{"G_FindMapByNameOrCode",lib_gFindMapByNameOrCode},
{"G_DoReborn",lib_gDoReborn}, {"G_DoReborn",lib_gDoReborn},
{"G_SetCustomExitVars",lib_gSetCustomExitVars}, {"G_SetCustomExitVars",lib_gSetCustomExitVars},
{"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished}, {"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished},

View File

@ -236,15 +236,14 @@ static int lib_comAddCommand(lua_State *L)
static int lib_comBufAddText(lua_State *L) static int lib_comBufAddText(lua_State *L)
{ {
int n = lua_gettop(L); /* number of arguments */ int n = lua_gettop(L); /* number of arguments */
player_t *plr; player_t *plr = NULL;
if (n < 2) if (n < 2)
return luaL_error(L, "COM_BufAddText requires two arguments: player and text."); return luaL_error(L, "COM_BufAddText requires two arguments: player and text.");
NOHUD NOHUD
lua_settop(L, 2); lua_settop(L, 2);
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!lua_isnoneornil(L, 1))
if (!plr) plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
return LUA_ErrInvalid(L, "player_t"); if (plr && plr != &players[consoleplayer])
if (plr != &players[consoleplayer])
return 0; return 0;
COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE);
return 0; return 0;
@ -253,15 +252,14 @@ static int lib_comBufAddText(lua_State *L)
static int lib_comBufInsertText(lua_State *L) static int lib_comBufInsertText(lua_State *L)
{ {
int n = lua_gettop(L); /* number of arguments */ int n = lua_gettop(L); /* number of arguments */
player_t *plr; player_t *plr = NULL;
if (n < 2) if (n < 2)
return luaL_error(L, "COM_BufInsertText requires two arguments: player and text."); return luaL_error(L, "COM_BufInsertText requires two arguments: player and text.");
NOHUD NOHUD
lua_settop(L, 2); lua_settop(L, 2);
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!lua_isnoneornil(L, 1))
if (!plr) plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
return LUA_ErrInvalid(L, "player_t"); if (plr && plr != &players[consoleplayer])
if (plr != &players[consoleplayer])
return 0; return 0;
COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE);
return 0; return 0;
@ -444,7 +442,7 @@ static int lib_consPrintf(lua_State *L)
if (n < 2) if (n < 2)
return luaL_error(L, "CONS_Printf requires at least two arguments: player and text."); return luaL_error(L, "CONS_Printf requires at least two arguments: player and text.");
//HUDSAFE //HUDSAFE
INLEVEL
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!plr) if (!plr)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");

View File

@ -1186,7 +1186,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next)
{ {
if (strcmp(hookp->s.str, line->text)) if (strcmp(hookp->s.str, line->stringargs[0]))
continue; continue;
if (lua_gettop(gL) == 1) if (lua_gettop(gL) == 1)

View File

@ -19,14 +19,15 @@
#include "z_zone.h" #include "z_zone.h"
#include "r_patch.h" #include "r_patch.h"
#include "r_things.h" #include "r_things.h"
#include "r_draw.h" // R_GetColorByName
#include "doomstat.h" // luabanks[] #include "doomstat.h" // luabanks[]
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
extern CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; extern CV_PossibleValue_t Color_cons_t[];
extern void R_FlushTranslationColormapCache(void); extern UINT8 skincolor_modified[];
boolean LUA_CallAction(const char *action, mobj_t *actor); boolean LUA_CallAction(const char *action, mobj_t *actor);
state_t *astate; state_t *astate;
@ -1490,7 +1491,7 @@ static void setRamp(lua_State *L, skincolor_t* c) {
UINT32 i; UINT32 i;
lua_pushnil(L); lua_pushnil(L);
for (i=0; i<COLORRAMPSIZE; i++) { for (i=0; i<COLORRAMPSIZE; i++) {
if (lua_objlen(L,-2)<COLORRAMPSIZE) { if (lua_objlen(L,-2)!=COLORRAMPSIZE) {
luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be %d entries long; got %d.", COLORRAMPSIZE, lua_objlen(L,-2)); luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be %d entries long; got %d.", COLORRAMPSIZE, lua_objlen(L,-2));
break; break;
} }
@ -1512,8 +1513,8 @@ static int lib_setSkinColor(lua_State *L)
lua_remove(L, 1); // don't care about skincolors[] userdata. lua_remove(L, 1); // don't care about skincolors[] userdata.
{ {
cnum = (UINT16)luaL_checkinteger(L, 1); cnum = (UINT16)luaL_checkinteger(L, 1);
if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors) if (!cnum || cnum >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1); return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1);
info = &skincolors[cnum]; // get the skincolor to assign to. info = &skincolors[cnum]; // get the skincolor to assign to.
} }
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
@ -1540,7 +1541,16 @@ static int lib_setSkinColor(lua_State *L)
const char* n = luaL_checkstring(L, 3); const char* n = luaL_checkstring(L, 3);
strlcpy(info->name, n, MAXCOLORNAME+1); strlcpy(info->name, n, MAXCOLORNAME+1);
if (strlen(n) > MAXCOLORNAME) if (strlen(n) > MAXCOLORNAME)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; shortened to %s.\n", n, MAXCOLORNAME, info->name); CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name);
if (strchr(info->name, ' ') != NULL)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", info->name);
if (info->name[0] != '\0') // don't check empty string for dupe
{
UINT16 dupecheck = R_GetColorByName(info->name);
if (!stricmp(info->name, skincolors[SKINCOLOR_NONE].name) || (dupecheck && (dupecheck != info-skincolors)))
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') is a duplicate of another skincolor's name.\n", info->name);
}
} else if (i == 2 || (str && fastcmp(str,"ramp"))) { } else if (i == 2 || (str && fastcmp(str,"ramp"))) {
if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL) if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array."); return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array.");
@ -1549,17 +1559,20 @@ static int lib_setSkinColor(lua_State *L)
else else
for (j=0; j<COLORRAMPSIZE; j++) for (j=0; j<COLORRAMPSIZE; j++)
info->ramp[j] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[j]; info->ramp[j] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[j];
R_FlushTranslationColormapCache(); skincolor_modified[cnum] = true;
} else if (i == 3 || (str && fastcmp(str,"invcolor"))) } else if (i == 3 || (str && fastcmp(str,"invcolor"))) {
info->invcolor = (UINT16)luaL_checkinteger(L, 3); UINT16 v = (UINT16)luaL_checkinteger(L, 3);
else if (i == 4 || (str && fastcmp(str,"invshade"))) if (v >= numskincolors)
return luaL_error(L, "skincolor_t field 'invcolor' out of range (1 - %d)", numskincolors-1);
info->invcolor = v;
} else if (i == 4 || (str && fastcmp(str,"invshade")))
info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE; info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE;
else if (i == 5 || (str && fastcmp(str,"chatcolor"))) else if (i == 5 || (str && fastcmp(str,"chatcolor")))
info->chatcolor = (UINT16)luaL_checkinteger(L, 3); info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
else if (i == 6 || (str && fastcmp(str,"accessible"))) { else if (i == 6 || (str && fastcmp(str,"accessible"))) {
boolean v = lua_isboolean(L,3) ? lua_toboolean(L, 3) : true; boolean v = lua_toboolean(L, 3);
if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible)
return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", i); return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum);
else else
info->accessible = v; info->accessible = v;
} }
@ -1607,20 +1620,28 @@ static int skincolor_set(lua_State *L)
UINT32 i; UINT32 i;
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR)); skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
const char *field = luaL_checkstring(L, 2); const char *field = luaL_checkstring(L, 2);
UINT16 cnum = (UINT16)(info-skincolors);
I_Assert(info != NULL); I_Assert(info != NULL);
I_Assert(info >= skincolors); I_Assert(info >= skincolors);
if (info-skincolors < SKINCOLOR_FIRSTFREESLOT || info-skincolors >= numskincolors) if (!cnum || cnum >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", info-skincolors, SKINCOLOR_FIRSTFREESLOT, numskincolors-1); return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1);
if (fastcmp(field,"name")) { if (fastcmp(field,"name")) {
const char* n = luaL_checkstring(L, 3); const char* n = luaL_checkstring(L, 3);
if (strchr(n, ' ') != NULL)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", n);
strlcpy(info->name, n, MAXCOLORNAME+1); strlcpy(info->name, n, MAXCOLORNAME+1);
if (strlen(n) > MAXCOLORNAME) if (strlen(n) > MAXCOLORNAME)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name); CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name);
if (strchr(info->name, ' ') != NULL)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", info->name);
if (info->name[0] != '\0') // don't check empty string for dupe
{
UINT16 dupecheck = R_GetColorByName(info->name);
if (!stricmp(info->name, skincolors[SKINCOLOR_NONE].name) || (dupecheck && (dupecheck != cnum)))
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') is a duplicate of another skincolor's name.\n", info->name);
}
} else if (fastcmp(field,"ramp")) { } else if (fastcmp(field,"ramp")) {
if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL) if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array."); return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array.");
@ -1629,16 +1650,23 @@ static int skincolor_set(lua_State *L)
else else
for (i=0; i<COLORRAMPSIZE; i++) for (i=0; i<COLORRAMPSIZE; i++)
info->ramp[i] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[i]; info->ramp[i] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[i];
R_FlushTranslationColormapCache(); skincolor_modified[cnum] = true;
} else if (fastcmp(field,"invcolor")) } else if (fastcmp(field,"invcolor")) {
info->invcolor = (UINT16)luaL_checkinteger(L, 3); UINT16 v = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"invshade")) if (v >= numskincolors)
return luaL_error(L, "skincolor_t field 'invcolor' out of range (1 - %d)", numskincolors-1);
info->invcolor = v;
} else if (fastcmp(field,"invshade"))
info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE; info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE;
else if (fastcmp(field,"chatcolor")) else if (fastcmp(field,"chatcolor"))
info->chatcolor = (UINT16)luaL_checkinteger(L, 3); info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"accessible")) else if (fastcmp(field,"accessible")) {
info->accessible = lua_isboolean(L,3); boolean v = lua_toboolean(L, 3);
else if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible)
return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum);
else
info->accessible = v;
} else
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field); CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
return 1; return 1;
} }
@ -1670,17 +1698,17 @@ static int colorramp_get(lua_State *L)
static int colorramp_set(lua_State *L) static int colorramp_set(lua_State *L)
{ {
UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP)); UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP));
UINT16 cnum = (UINT16)(((uint8_t*)colorramp - (uint8_t*)(skincolors[0].ramp))/sizeof(skincolor_t)); UINT16 cnum = (UINT16)(((UINT8*)colorramp - (UINT8*)(skincolors[0].ramp))/sizeof(skincolor_t));
UINT32 n = luaL_checkinteger(L, 2); UINT32 n = luaL_checkinteger(L, 2);
UINT8 i = (UINT8)luaL_checkinteger(L, 3); UINT8 i = (UINT8)luaL_checkinteger(L, 3);
if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors) if (!cnum || cnum >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1); return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1);
if (n >= COLORRAMPSIZE) if (n >= COLORRAMPSIZE)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1); return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!"); return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!");
colorramp[n] = i; colorramp[n] = i;
R_FlushTranslationColormapCache(); skincolor_modified[cnum] = true;
return 0; return 0;
} }

View File

@ -54,6 +54,10 @@ extern lua_State *gL;
#define META_SECTORLINES "SECTOR_T*LINES" #define META_SECTORLINES "SECTOR_T*LINES"
#define META_SIDENUM "LINE_T*SIDENUM" #define META_SIDENUM "LINE_T*SIDENUM"
#define META_LINEARGS "LINE_T*ARGS"
#define META_LINESTRINGARGS "LINE_T*STRINGARGS"
#define META_THINGARGS "MAPTHING_T*ARGS"
#define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS"
#ifdef HAVE_LUA_SEGS #ifdef HAVE_LUA_SEGS
#define META_NODEBBOX "NODE_T*BBOX" #define META_NODEBBOX "NODE_T*BBOX"
#define META_NODECHILDREN "NODE_T*CHILDREN" #define META_NODECHILDREN "NODE_T*CHILDREN"

View File

@ -85,9 +85,13 @@ enum line_e {
line_flags, line_flags,
line_special, line_special,
line_tag, line_tag,
line_args,
line_stringargs,
line_sidenum, line_sidenum,
line_frontside, line_frontside,
line_backside, line_backside,
line_alpha,
line_executordelay,
line_slopetype, line_slopetype,
line_frontsector, line_frontsector,
line_backsector, line_backsector,
@ -106,9 +110,13 @@ static const char *const line_opt[] = {
"flags", "flags",
"special", "special",
"tag", "tag",
"args",
"stringargs",
"sidenum", "sidenum",
"frontside", "frontside",
"backside", "backside",
"alpha",
"executordelay",
"slopetype", "slopetype",
"frontsector", "frontsector",
"backsector", "backsector",
@ -691,6 +699,42 @@ static int subsector_num(lua_State *L)
// line_t // // line_t //
//////////// ////////////
// args, i -> args[i]
static int lineargs_get(lua_State *L)
{
INT32 *args = *((INT32**)luaL_checkudata(L, 1, META_LINEARGS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMLINEARGS)
return luaL_error(L, LUA_QL("line_t.args") " index cannot be %d", i);
lua_pushinteger(L, args[i]);
return 1;
}
// #args -> NUMLINEARGS
static int lineargs_len(lua_State* L)
{
lua_pushinteger(L, NUMLINEARGS);
return 1;
}
// stringargs, i -> stringargs[i]
static int linestringargs_get(lua_State *L)
{
char **stringargs = *((char***)luaL_checkudata(L, 1, META_LINESTRINGARGS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMLINESTRINGARGS)
return luaL_error(L, LUA_QL("line_t.stringargs") " index cannot be %d", i);
lua_pushstring(L, stringargs[i]);
return 1;
}
// #stringargs -> NUMLINESTRINGARGS
static int linestringargs_len(lua_State *L)
{
lua_pushinteger(L, NUMLINESTRINGARGS);
return 1;
}
static int line_get(lua_State *L) static int line_get(lua_State *L)
{ {
line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
@ -731,6 +775,12 @@ static int line_get(lua_State *L)
case line_tag: case line_tag:
lua_pushinteger(L, line->tag); lua_pushinteger(L, line->tag);
return 1; return 1;
case line_args:
LUA_PushUserdata(L, line->args, META_LINEARGS);
return 1;
case line_stringargs:
LUA_PushUserdata(L, line->stringargs, META_LINESTRINGARGS);
return 1;
case line_sidenum: case line_sidenum:
LUA_PushUserdata(L, line->sidenum, META_SIDENUM); LUA_PushUserdata(L, line->sidenum, META_SIDENUM);
return 1; return 1;
@ -742,6 +792,12 @@ static int line_get(lua_State *L)
return 0; return 0;
LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE); LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE);
return 1; return 1;
case line_alpha:
lua_pushfixed(L, line->alpha);
return 1;
case line_executordelay:
lua_pushinteger(L, line->executordelay);
return 1;
case line_slopetype: case line_slopetype:
switch(line->slopetype) switch(line->slopetype)
{ {
@ -2143,6 +2199,22 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L, 1); lua_pop(L, 1);
luaL_newmetatable(L, META_LINEARGS);
lua_pushcfunction(L, lineargs_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lineargs_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_LINESTRINGARGS);
lua_pushcfunction(L, linestringargs_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, linestringargs_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_SIDENUM); luaL_newmetatable(L, META_SIDENUM);
lua_pushcfunction(L, sidenum_get); lua_pushcfunction(L, sidenum_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");

View File

@ -31,6 +31,8 @@ enum mobj_e {
mobj_snext, mobj_snext,
mobj_sprev, mobj_sprev,
mobj_angle, mobj_angle,
mobj_pitch,
mobj_roll,
mobj_rollangle, mobj_rollangle,
mobj_sprite, mobj_sprite,
mobj_frame, mobj_frame,
@ -98,6 +100,8 @@ static const char *const mobj_opt[] = {
"snext", "snext",
"sprev", "sprev",
"angle", "angle",
"pitch",
"roll",
"rollangle", "rollangle",
"sprite", "sprite",
"frame", "frame",
@ -165,14 +169,15 @@ static int mobj_get(lua_State *L)
enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt); enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt);
lua_settop(L, 2); lua_settop(L, 2);
INLEVEL if (!mo || !ISINLEVEL) {
if (!mo) {
if (field == mobj_valid) { if (field == mobj_valid) {
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
return 1; return 1;
} }
return LUA_ErrInvalid(L, "mobj_t"); if (!mo) {
return LUA_ErrInvalid(L, "mobj_t");
} else
return luaL_error(L, "Do not access an mobj_t field outside a level!");
} }
switch(field) switch(field)
@ -200,6 +205,12 @@ static int mobj_get(lua_State *L)
case mobj_angle: case mobj_angle:
lua_pushangle(L, mo->angle); lua_pushangle(L, mo->angle);
break; break;
case mobj_pitch:
lua_pushangle(L, mo->pitch);
break;
case mobj_roll:
lua_pushangle(L, mo->roll);
break;
case mobj_rollangle: case mobj_rollangle:
lua_pushangle(L, mo->rollangle); lua_pushangle(L, mo->rollangle);
break; break;
@ -457,6 +468,12 @@ static int mobj_set(lua_State *L)
if (mo->player) if (mo->player)
P_SetPlayerAngle(mo->player, mo->angle); P_SetPlayerAngle(mo->player, mo->angle);
break; break;
case mobj_pitch:
mo->pitch = luaL_checkangle(L, 3);
break;
case mobj_roll:
mo->roll = luaL_checkangle(L, 3);
break;
case mobj_rollangle: case mobj_rollangle:
mo->rollangle = luaL_checkangle(L, 3); mo->rollangle = luaL_checkangle(L, 3);
break; break;
@ -752,6 +769,42 @@ static int mobj_set(lua_State *L)
#undef NOSETPOS #undef NOSETPOS
#undef NOFIELD #undef NOFIELD
// args, i -> args[i]
static int thingargs_get(lua_State *L)
{
INT32 *args = *((INT32**)luaL_checkudata(L, 1, META_THINGARGS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMMAPTHINGARGS)
return luaL_error(L, LUA_QL("mapthing_t.args") " index cannot be %d", i);
lua_pushinteger(L, args[i]);
return 1;
}
// #args -> NUMMAPTHINGARGS
static int thingargs_len(lua_State* L)
{
lua_pushinteger(L, NUMMAPTHINGARGS);
return 1;
}
// stringargs, i -> stringargs[i]
static int thingstringargs_get(lua_State *L)
{
char **stringargs = *((char***)luaL_checkudata(L, 1, META_THINGSTRINGARGS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMMAPTHINGSTRINGARGS)
return luaL_error(L, LUA_QL("mapthing_t.stringargs") " index cannot be %d", i);
lua_pushstring(L, stringargs[i]);
return 1;
}
// #stringargs -> NUMMAPTHINGSTRINGARGS
static int thingstringargs_len(lua_State *L)
{
lua_pushinteger(L, NUMMAPTHINGSTRINGARGS);
return 1;
}
static int mapthing_get(lua_State *L) static int mapthing_get(lua_State *L)
{ {
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
@ -777,14 +830,32 @@ static int mapthing_get(lua_State *L)
number = mt->y; number = mt->y;
else if(fastcmp(field,"angle")) else if(fastcmp(field,"angle"))
number = mt->angle; number = mt->angle;
else if(fastcmp(field,"pitch"))
number = mt->pitch;
else if(fastcmp(field,"roll"))
number = mt->roll;
else if(fastcmp(field,"type")) else if(fastcmp(field,"type"))
number = mt->type; number = mt->type;
else if(fastcmp(field,"options")) else if(fastcmp(field,"options"))
number = mt->options; number = mt->options;
else if(fastcmp(field,"scale"))
number = mt->scale;
else if(fastcmp(field,"z")) else if(fastcmp(field,"z"))
number = mt->z; number = mt->z;
else if(fastcmp(field,"extrainfo")) else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo; number = mt->extrainfo;
else if(fastcmp(field,"tag"))
number = mt->tag;
else if(fastcmp(field,"args"))
{
LUA_PushUserdata(L, mt->args, META_THINGARGS);
return 1;
}
else if(fastcmp(field,"stringargs"))
{
LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS);
return 1;
}
else if(fastcmp(field,"mobj")) { else if(fastcmp(field,"mobj")) {
LUA_PushUserdata(L, mt->mobj, META_MOBJ); LUA_PushUserdata(L, mt->mobj, META_MOBJ);
return 1; return 1;
@ -814,10 +885,16 @@ static int mapthing_set(lua_State *L)
mt->y = (INT16)luaL_checkinteger(L, 3); mt->y = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"angle")) else if(fastcmp(field,"angle"))
mt->angle = (INT16)luaL_checkinteger(L, 3); mt->angle = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"pitch"))
mt->pitch = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"roll"))
mt->roll = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"type")) else if(fastcmp(field,"type"))
mt->type = (UINT16)luaL_checkinteger(L, 3); mt->type = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"options")) else if(fastcmp(field,"options"))
mt->options = (UINT16)luaL_checkinteger(L, 3); mt->options = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"scale"))
mt->scale = luaL_checkfixed(L, 3);
else if(fastcmp(field,"z")) else if(fastcmp(field,"z"))
mt->z = (INT16)luaL_checkinteger(L, 3); mt->z = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"extrainfo")) else if(fastcmp(field,"extrainfo"))
@ -827,6 +904,8 @@ static int mapthing_set(lua_State *L)
return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15);
mt->extrainfo = (UINT8)extrainfo; mt->extrainfo = (UINT8)extrainfo;
} }
else if (fastcmp(field,"tag"))
mt->tag = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"mobj")) else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else else
@ -902,6 +981,22 @@ int LUA_MobjLib(lua_State *L)
lua_setfield(L, -2, "__newindex"); lua_setfield(L, -2, "__newindex");
lua_pop(L,1); lua_pop(L,1);
luaL_newmetatable(L, META_THINGARGS);
lua_pushcfunction(L, thingargs_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, thingargs_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_THINGSTRINGARGS);
lua_pushcfunction(L, thingstringargs_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, thingstringargs_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_MAPTHING); luaL_newmetatable(L, META_MAPTHING);
lua_pushcfunction(L, mapthing_get); lua_pushcfunction(L, mapthing_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");

View File

@ -136,6 +136,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
if (fastcmp(word,"gamemap")) { if (fastcmp(word,"gamemap")) {
lua_pushinteger(L, gamemap); lua_pushinteger(L, gamemap);
return 1; return 1;
} else if (fastcmp(word,"udmf")) {
lua_pushboolean(L, udmf);
return 1;
} else if (fastcmp(word,"maptol")) { } else if (fastcmp(word,"maptol")) {
lua_pushinteger(L, maptol); lua_pushinteger(L, maptol);
return 1; return 1;

View File

@ -1489,21 +1489,23 @@ static menuitem_t OP_OpenGLLightingMenu[] =
static menuitem_t OP_SoundOptionsMenu[] = static menuitem_t OP_SoundOptionsMenu[] =
{ {
{IT_HEADER, NULL, "Game Audio", NULL, 0}, {IT_HEADER, NULL, "Game Audio", NULL, 0},
{IT_STRING | IT_CVAR, NULL, "Sound Effects", &cv_gamesounds, 12}, {IT_STRING | IT_CVAR, NULL, "Sound Effects", &cv_gamesounds, 6},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Sound Volume", &cv_soundvolume, 22}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Sound Volume", &cv_soundvolume, 11},
{IT_STRING | IT_CVAR, NULL, "Digital Music", &cv_gamedigimusic, 42}, {IT_STRING | IT_CVAR, NULL, "Digital Music", &cv_gamedigimusic, 21},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Digital Music Volume", &cv_digmusicvolume, 52}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Digital Music Volume", &cv_digmusicvolume, 26},
{IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 72}, {IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 36},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 82}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 41},
{IT_STRING | IT_CVAR, NULL, "Music Preference", &cv_musicpref, 51},
{IT_HEADER, NULL, "Miscellaneous", NULL, 102}, {IT_HEADER, NULL, "Miscellaneous", NULL, 61},
{IT_STRING | IT_CVAR, NULL, "Closed Captioning", &cv_closedcaptioning, 114}, {IT_STRING | IT_CVAR, NULL, "Closed Captioning", &cv_closedcaptioning, 67},
{IT_STRING | IT_CVAR, NULL, "Reset Music Upon Dying", &cv_resetmusic, 124}, {IT_STRING | IT_CVAR, NULL, "Reset Music Upon Dying", &cv_resetmusic, 72},
{IT_STRING | IT_CVAR, NULL, "Default 1-Up sound", &cv_1upsound, 134}, {IT_STRING | IT_CVAR, NULL, "Default 1-Up sound", &cv_1upsound, 77},
{IT_STRING | IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 154}, {IT_STRING | IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 87},
}; };
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
@ -2202,7 +2204,7 @@ menu_t OP_ColorOptionsDef =
0, 0,
NULL NULL
}; };
menu_t OP_SoundOptionsDef = DEFAULTMENUSTYLE( menu_t OP_SoundOptionsDef = DEFAULTSCROLLMENUSTYLE(
MTREE2(MN_OP_MAIN, MN_OP_SOUND), MTREE2(MN_OP_MAIN, MN_OP_SOUND),
"M_SOUND", OP_SoundOptionsMenu, &OP_MainDef, 30, 30); "M_SOUND", OP_SoundOptionsMenu, &OP_MainDef, 30, 30);
menu_t OP_SoundAdvancedDef = DEFAULTMENUSTYLE( menu_t OP_SoundAdvancedDef = DEFAULTMENUSTYLE(

View File

@ -142,6 +142,7 @@ void P_SetPlayerAngle(player_t *player, angle_t angle);
angle_t P_GetLocalAngle(player_t *player); angle_t P_GetLocalAngle(player_t *player);
void P_SetLocalAngle(player_t *player, angle_t angle); void P_SetLocalAngle(player_t *player, angle_t angle);
void P_ForceLocalAngle(player_t *player, angle_t angle); void P_ForceLocalAngle(player_t *player, angle_t angle);
boolean P_PlayerFullbright(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectInGoop(mobj_t *mo);
boolean P_IsObjectOnGround(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo);

View File

@ -442,7 +442,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
mobj->sprite2 = spr2; mobj->sprite2 = spr2;
mobj->frame = frame|(st->frame&~FF_FRAMEMASK); mobj->frame = frame|(st->frame&~FF_FRAMEMASK);
if (player->powers[pw_super] || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & (SF_SUPER|SF_NONIGHTSSUPER)) == SF_SUPER)) // Super colours? Super bright! if (P_PlayerFullbright(player))
mobj->frame |= FF_FULLBRIGHT; mobj->frame |= FF_FULLBRIGHT;
} }
// Regular sprites // Regular sprites
@ -2882,8 +2882,7 @@ static boolean P_PlayerPolyObjectZMovement(mobj_t *mo)
continue; continue;
// We're landing on a PO, so check for a linedef executor. // We're landing on a PO, so check for a linedef executor.
// Trigger tags are 32000 + the PO's ID number. P_LinedefExecute(po->triggertag, mo, NULL);
P_LinedefExecute((INT16)(32000 + po->id), mo, NULL);
} }
} }
} }
@ -11615,7 +11614,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
mapthing_t *huntemeralds[MAXHUNTEMERALDS]; mapthing_t *huntemeralds[MAXHUNTEMERALDS];
INT32 numhuntemeralds; INT32 numhuntemeralds;
fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t offset, const boolean flip) fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale)
{ {
const subsector_t *ss = R_PointInSubsector(x, y); const subsector_t *ss = R_PointInSubsector(x, y);
@ -11625,14 +11624,15 @@ fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const f
// Establish height. // Establish height.
if (flip) if (flip)
return P_GetSectorCeilingZAt(ss->sector, x, y) - offset - mobjinfo[mobjtype].height; return P_GetSectorCeilingZAt(ss->sector, x, y) - dz - FixedMul(scale, offset + mobjinfo[mobjtype].height);
else else
return P_GetSectorFloorZAt(ss->sector, x, y) + offset; return P_GetSectorFloorZAt(ss->sector, x, y) + dz + FixedMul(scale, offset);
} }
fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
{ {
fixed_t offset = mthing->z << FRACBITS; fixed_t dz = mthing->z << FRACBITS; // Base offset from the floor.
fixed_t offset = 0; // Specific scaling object offset.
boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP));
switch (mobjtype) switch (mobjtype)
@ -11648,17 +11648,17 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
case MT_JETTBOMBER: case MT_JETTBOMBER:
case MT_JETTGUNNER: case MT_JETTGUNNER:
case MT_EGGMOBILE2: case MT_EGGMOBILE2:
if (!offset) if (!dz)
offset = 33*FRACUNIT; dz = 33*FRACUNIT;
break; break;
case MT_EGGMOBILE: case MT_EGGMOBILE:
if (!offset) if (!dz)
offset = 128*FRACUNIT; dz = 128*FRACUNIT;
break; break;
case MT_GOLDBUZZ: case MT_GOLDBUZZ:
case MT_REDBUZZ: case MT_REDBUZZ:
if (!offset) if (!dz)
offset = 288*FRACUNIT; dz = 288*FRACUNIT;
break; break;
// Horizontal springs, may float additional units with MTF_AMBUSH. // Horizontal springs, may float additional units with MTF_AMBUSH.
@ -11691,7 +11691,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0;
} }
if (!offset) // Snap to the surfaces when there's no offset set. if (!(dz + offset)) // Snap to the surfaces when there's no offset set.
{ {
if (flip) if (flip)
return ONCEILINGZ; return ONCEILINGZ;
@ -11699,7 +11699,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
return ONFLOORZ; return ONFLOORZ;
} }
return P_GetMobjSpawnHeight(mobjtype, x, y, offset, flip); return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale);
} }
static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing)
@ -12583,10 +12583,16 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break; break;
} }
case MT_SKYBOX: case MT_SKYBOX:
if (mthing->tag < 0 || mthing->tag > 15)
{
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings)));
break;
}
if (mthing->options & MTF_OBJECTSPECIAL) if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->extrainfo] = mobj; skyboxcenterpnts[mthing->tag] = mobj;
else else
skyboxviewpnts[mthing->extrainfo] = mobj; skyboxviewpnts[mthing->tag] = mobj;
break; break;
case MT_EGGSTATUE: case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA) if (mthing->options & MTF_EXTRA)
@ -13074,12 +13080,18 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj = P_SpawnMobj(x, y, z, i); mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing; mobj->spawnpoint = mthing;
P_SetScale(mobj, mthing->scale);
mobj->destscale = mthing->scale;
if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle))
return mobj; return mobj;
if (doangle) if (doangle)
mobj->angle = FixedAngle(mthing->angle << FRACBITS); mobj->angle = FixedAngle(mthing->angle << FRACBITS);
mobj->pitch = FixedAngle(mthing->pitch << FRACBITS);
mobj->roll = FixedAngle(mthing->roll << FRACBITS);
mthing->mobj = mobj; mthing->mobj = mobj;
// ignore MTF_ flags and return early // ignore MTF_ flags and return early
@ -13176,7 +13188,7 @@ static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t size
TVector v, *res; TVector v, *res;
fixed_t x = mthing->x << FRACBITS; fixed_t x = mthing->x << FRACBITS;
fixed_t y = mthing->y << FRACBITS; fixed_t y = mthing->y << FRACBITS;
fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, false); fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale);
hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER);
hoopcenter->spawnpoint = mthing; hoopcenter->spawnpoint = mthing;
@ -13321,7 +13333,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t* itemtypes, UINT8 numi
itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]); itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]);
} }
} }
z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, mthing->options & MTF_OBJECTFLIP); z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale);
for (r = 0; r < numitems; r++) for (r = 0; r < numitems; r++)
{ {
@ -13379,7 +13391,7 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n
itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]); itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]);
} }
} }
z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, false); z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale);
for (i = 0; i < numitems; i++) for (i = 0; i < numitems; i++)
{ {

View File

@ -278,7 +278,7 @@ typedef struct mobj_s
struct mobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr struct mobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle; // orientation angle_t angle, pitch, roll; // orientation
angle_t rollangle; angle_t rollangle;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
@ -399,7 +399,7 @@ typedef struct precipmobj_s
struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle; // orientation angle_t angle, pitch, roll; // orientation
angle_t rollangle; angle_t rollangle;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
@ -452,7 +452,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing);
void P_MovePlayerToStarpost(INT32 playernum); void P_MovePlayerToStarpost(INT32 playernum);
void P_AfterPlayerSpawn(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum);
fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t offset, const boolean flip); fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale);
fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y); fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y);
mobj_t *P_SpawnMapThing(mapthing_t *mthing); mobj_t *P_SpawnMapThing(mapthing_t *mthing);

View File

@ -204,47 +204,44 @@ boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox)
return true; return true;
} }
// Finds the 'polyobject settings' linedef for a polyobject // Gets the polyobject's settings from its first line
// the polyobject's id should be set as its tag // args[0] of the first line should be the polyobject's id
static void Polyobj_GetInfo(polyobj_t *po) static void Polyobj_GetInfo(polyobj_t *po, line_t *line)
{ {
INT32 i = P_FindSpecialLineFromTag(POLYINFO_SPECIALNUM, po->id, -1); po->parent = line->args[1];
po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
if (i == -1)
return; // no extra settings to apply, let's leave it
po->parent = lines[i].frontsector->special;
if (po->parent == po->id) // do not allow a self-reference if (po->parent == po->id) // do not allow a self-reference
po->parent = -1; po->parent = -1;
po->translucency = (lines[i].flags & ML_DONTPEGTOP) po->translucency = max(min(line->args[2], NUMTRANSMAPS), 0);
? (sides[lines[i].sidenum[0]].textureoffset>>FRACBITS)
: ((lines[i].frontsector->floorheight>>FRACBITS) / 100);
po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0); po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES|POF_RENDERPLANES;
if (lines[i].flags & ML_EFFECT1) if (line->args[3] & TMPF_NOINSIDES)
po->flags |= POF_ONESIDE; po->flags |= POF_ONESIDE;
if (lines[i].flags & ML_EFFECT2) if (line->args[3] & TMPF_INTANGIBLE)
po->flags &= ~POF_SOLID; po->flags &= ~POF_SOLID;
if (lines[i].flags & ML_EFFECT3) if (line->args[3] & TMPF_PUSHABLESTOP)
po->flags |= POF_PUSHABLESTOP; po->flags |= POF_PUSHABLESTOP;
if (lines[i].flags & ML_EFFECT4) if (line->args[3] & TMPF_INVISIBLEPLANES)
po->flags |= POF_RENDERPLANES; po->flags &= ~POF_RENDERPLANES;
/*if (lines[i].flags & ML_EFFECT5) /*if (line->args[3] & TMPF_DONTCLIPPLANES)
po->flags &= ~POF_CLIPPLANES;*/ po->flags &= ~POF_CLIPPLANES;*/
if (lines[i].flags & ML_EFFECT6) if (line->args[3] & TMPF_SPLAT)
po->flags |= POF_SPLAT; po->flags |= POF_SPLAT;
if (lines[i].flags & ML_NOCLIMB) // Has a linedef executor if (line->args[3] & TMPF_EXECUTOR) // Has a linedef executor
po->flags |= POF_LDEXEC; po->flags |= POF_LDEXEC;
// TODO: support customized damage somehow?
if (line->args[3] & TMPF_CRUSH)
po->damage = 3;
po->triggertag = line->args[4];
} }
// Reallocating array maintenance // Reallocating array maintenance
@ -483,10 +480,6 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
po->id = id; po->id = id;
// TODO: support customized damage somehow?
if (spawnSpot->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
po->damage = 3;
// set to default thrust; may be modified by attached thinkers // set to default thrust; may be modified by attached thinkers
// TODO: support customized thrust? // TODO: support customized thrust?
po->thrust = FRACUNIT; po->thrust = FRACUNIT;
@ -508,10 +501,10 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
if (seg->linedef->special != POLYOBJ_START_LINE) if (seg->linedef->special != POLYOBJ_START_LINE)
continue; continue;
if (seg->linedef->tag != po->id) if (seg->linedef->args[0] != po->id)
continue; continue;
Polyobj_GetInfo(po); // apply extra settings if they exist! Polyobj_GetInfo(po, seg->linedef); // apply extra settings if they exist!
// save original flags and translucency to reference later for netgames! // save original flags and translucency to reference later for netgames!
po->spawnflags = po->flags; po->spawnflags = po->flags;
@ -564,9 +557,9 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
vertex_t dist, sspot; vertex_t dist, sspot;
size_t i; size_t i;
if (!(po = Polyobj_GetForNum(anchor->angle))) if (!(po = Polyobj_GetForNum(anchor->tag)))
{ {
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->angle); CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag);
return; return;
} }
@ -1314,8 +1307,7 @@ void Polyobj_InitLevel(void)
mo = (mobj_t *)th; mo = (mobj_t *)th;
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM)
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
{ {
++numPolyObjects; ++numPolyObjects;
@ -1350,7 +1342,7 @@ void Polyobj_InitLevel(void)
{ {
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue); qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->angle); Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag);
} }
// move polyobjects to spawn points // move polyobjects to spawn points

View File

@ -26,10 +26,8 @@
#define POLYOBJ_ANCHOR_DOOMEDNUM 760 #define POLYOBJ_ANCHOR_DOOMEDNUM 760
#define POLYOBJ_SPAWN_DOOMEDNUM 761 #define POLYOBJ_SPAWN_DOOMEDNUM 761
#define POLYOBJ_SPAWNCRUSH_DOOMEDNUM 762 // todo: REMOVE
#define POLYOBJ_START_LINE 20 #define POLYOBJ_START_LINE 20
#define POLYINFO_SPECIALNUM 22
typedef enum typedef enum
{ {
@ -52,6 +50,18 @@ typedef enum
POF_SPLAT = 0x2000, ///< Use splat flat renderer (treat cyan pixels as invisible). POF_SPLAT = 0x2000, ///< Use splat flat renderer (treat cyan pixels as invisible).
} polyobjflags_e; } polyobjflags_e;
typedef enum
{
TMPF_NOINSIDES = 1,
TMPF_INTANGIBLE = 1<<1,
TMPF_PUSHABLESTOP = 1<<2,
TMPF_INVISIBLEPLANES = 1<<3,
TMPF_EXECUTOR = 1<<4,
TMPF_CRUSH = 1<<5,
TMPF_SPLAT = 1<<6,
//TMPF_DONTCLIPPLANES = 1<<7,
} textmappolyobjectflags_t;
// //
// Polyobject Structure // Polyobject Structure
// //
@ -97,6 +107,7 @@ typedef struct polyobj_s
UINT8 isBad; // a bad polyobject: should not be rendered/manipulated UINT8 isBad; // a bad polyobject: should not be rendered/manipulated
INT32 translucency; // index to translucency tables INT32 translucency; // index to translucency tables
INT16 triggertag; // Tag of linedef executor to trigger on touch
struct visplane_s *visplane; // polyobject's visplane, for ease of putting into the list later struct visplane_s *visplane; // polyobject's visplane, for ease of putting into the list later

View File

@ -787,10 +787,38 @@ static void P_NetUnArchiveWaypoints(void)
#define LD_DIFF2 0x80 #define LD_DIFF2 0x80
// diff2 flags // diff2 flags
#define LD_S2TEXOFF 0x01 #define LD_S2TEXOFF 0x01
#define LD_S2TOPTEX 0x02 #define LD_S2TOPTEX 0x02
#define LD_S2BOTTEX 0x04 #define LD_S2BOTTEX 0x04
#define LD_S2MIDTEX 0x08 #define LD_S2MIDTEX 0x08
#define LD_ARGS 0x10
#define LD_STRINGARGS 0x20
#define LD_EXECUTORDELAY 0x40
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
{
UINT8 i;
for (i = 0; i < NUMLINEARGS; i++)
if (li->args[i] != spawnli->args[i])
return false;
return true;
}
static boolean P_AreStringArgsEqual(const line_t *li, const line_t *spawnli)
{
UINT8 i;
for (i = 0; i < NUMLINESTRINGARGS; i++)
{
if (!li->stringargs[i])
return !spawnli->stringargs[i];
if (strcmp(li->stringargs[i], spawnli->stringargs[i]))
return false;
}
return true;
}
#define FD_FLAGS 0x01 #define FD_FLAGS 0x01
#define FD_ALPHA 0x02 #define FD_ALPHA 0x02
@ -1085,6 +1113,15 @@ static void ArchiveLines(void)
if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
diff |= LD_CLLCOUNT; diff |= LD_CLLCOUNT;
if (!P_AreArgsEqual(li, spawnli))
diff2 |= LD_ARGS;
if (!P_AreStringArgsEqual(li, spawnli))
diff2 |= LD_STRINGARGS;
if (li->executordelay != spawnli->executordelay)
diff2 |= LD_EXECUTORDELAY;
if (li->sidenum[0] != 0xffff) if (li->sidenum[0] != 0xffff)
{ {
si = &sides[li->sidenum[0]]; si = &sides[li->sidenum[0]];
@ -1111,10 +1148,11 @@ static void ArchiveLines(void)
diff2 |= LD_S2BOTTEX; diff2 |= LD_S2BOTTEX;
if (si->midtexture != spawnsi->midtexture) if (si->midtexture != spawnsi->midtexture)
diff2 |= LD_S2MIDTEX; diff2 |= LD_S2MIDTEX;
if (diff2)
diff |= LD_DIFF2;
} }
if (diff2)
diff |= LD_DIFF2;
if (diff) if (diff)
{ {
WRITEINT16(save_p, i); WRITEINT16(save_p, i);
@ -1147,6 +1185,33 @@ static void ArchiveLines(void)
WRITEINT32(save_p, si->bottomtexture); WRITEINT32(save_p, si->bottomtexture);
if (diff2 & LD_S2MIDTEX) if (diff2 & LD_S2MIDTEX)
WRITEINT32(save_p, si->midtexture); WRITEINT32(save_p, si->midtexture);
if (diff2 & LD_ARGS)
{
UINT8 j;
for (j = 0; j < NUMLINEARGS; j++)
WRITEINT32(save_p, li->args[j]);
}
if (diff2 & LD_STRINGARGS)
{
UINT8 j;
for (j = 0; j < NUMLINESTRINGARGS; j++)
{
size_t len, k;
if (!li->stringargs[j])
{
WRITEINT32(save_p, 0);
continue;
}
len = strlen(li->stringargs[j]);
WRITEINT32(save_p, len);
for (k = 0; k < len; k++)
WRITECHAR(save_p, li->stringargs[j][k]);
}
}
if (diff2 & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay);
} }
} }
WRITEUINT16(save_p, 0xffff); WRITEUINT16(save_p, 0xffff);
@ -1202,6 +1267,36 @@ static void UnArchiveLines(void)
si->bottomtexture = READINT32(save_p); si->bottomtexture = READINT32(save_p);
if (diff2 & LD_S2MIDTEX) if (diff2 & LD_S2MIDTEX)
si->midtexture = READINT32(save_p); si->midtexture = READINT32(save_p);
if (diff2 & LD_ARGS)
{
UINT8 j;
for (j = 0; j < NUMLINEARGS; j++)
li->args[j] = READINT32(save_p);
}
if (diff2 & LD_STRINGARGS)
{
UINT8 j;
for (j = 0; j < NUMLINESTRINGARGS; j++)
{
size_t len = READINT32(save_p);
size_t k;
if (!len)
{
Z_Free(li->stringargs[j]);
li->stringargs[j] = NULL;
continue;
}
li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL);
for (k = 0; k < len; k++)
li->stringargs[j][k] = READCHAR(save_p);
li->stringargs[j][len] = '\0';
}
}
if (diff2 & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p);
} }
} }
@ -1400,7 +1495,9 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if ((mobj->x != mobj->spawnpoint->x << FRACBITS) || if ((mobj->x != mobj->spawnpoint->x << FRACBITS) ||
(mobj->y != mobj->spawnpoint->y << FRACBITS) || (mobj->y != mobj->spawnpoint->y << FRACBITS) ||
(mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT))) (mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)) ||
(mobj->pitch != FixedAngle(mobj->spawnpoint->pitch*FRACUNIT)) ||
(mobj->roll != FixedAngle(mobj->spawnpoint->roll*FRACUNIT)) )
diff |= MD_POS; diff |= MD_POS;
if (mobj->info->doomednum != mobj->spawnpoint->type) if (mobj->info->doomednum != mobj->spawnpoint->type)
@ -1556,6 +1653,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEFIXED(save_p, mobj->x); WRITEFIXED(save_p, mobj->x);
WRITEFIXED(save_p, mobj->y); WRITEFIXED(save_p, mobj->y);
WRITEANGLE(save_p, mobj->angle); WRITEANGLE(save_p, mobj->angle);
WRITEANGLE(save_p, mobj->pitch);
WRITEANGLE(save_p, mobj->roll);
} }
if (diff & MD_MOM) if (diff & MD_MOM)
{ {
@ -2513,12 +2612,16 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->x = READFIXED(save_p); mobj->x = READFIXED(save_p);
mobj->y = READFIXED(save_p); mobj->y = READFIXED(save_p);
mobj->angle = READANGLE(save_p); mobj->angle = READANGLE(save_p);
mobj->pitch = READANGLE(save_p);
mobj->roll = READANGLE(save_p);
} }
else else
{ {
mobj->x = mobj->spawnpoint->x << FRACBITS; mobj->x = mobj->spawnpoint->x << FRACBITS;
mobj->y = mobj->spawnpoint->y << FRACBITS; mobj->y = mobj->spawnpoint->y << FRACBITS;
mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
mobj->pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT);
mobj->roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT);
} }
if (diff & MD_MOM) if (diff & MD_MOM)
{ {

View File

@ -92,6 +92,7 @@ unsigned char mapmd5[16];
// Store VERTEXES, LINEDEFS, SIDEDEFS, etc. // Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
// //
boolean udmf;
size_t numvertexes, numsegs, numsectors, numsubsectors, numnodes, numlines, numsides, nummapthings; size_t numvertexes, numsegs, numsectors, numsubsectors, numnodes, numlines, numsides, nummapthings;
vertex_t *vertexes; vertex_t *vertexes;
seg_t *segs; seg_t *segs;
@ -355,8 +356,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->mustrack = 0; mapheaderinfo[num]->mustrack = 0;
mapheaderinfo[num]->muspos = 0; mapheaderinfo[num]->muspos = 0;
mapheaderinfo[num]->musinterfadeout = 0; mapheaderinfo[num]->musinterfadeout = 0;
mapheaderinfo[num]->musintername[0] = '\0'; mapheaderinfo[num]->musintername[0] = 0;
mapheaderinfo[num]->muspostbossname[6] = 0; mapheaderinfo[num]->muspostbossname[0] = 0;
mapheaderinfo[num]->muspostbosstrack = 0; mapheaderinfo[num]->muspostbosstrack = 0;
mapheaderinfo[num]->muspostbosspos = 0; mapheaderinfo[num]->muspostbosspos = 0;
mapheaderinfo[num]->muspostbossfadein = 0; mapheaderinfo[num]->muspostbossfadein = 0;
@ -1039,6 +1040,8 @@ static void P_LoadSectors(UINT8 *data)
ss->floorpic_angle = ss->ceilingpic_angle = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0;
ss->colormap_protected = false;
P_InitializeSector(ss); P_InitializeSector(ss);
} }
} }
@ -1145,6 +1148,10 @@ static void P_LoadLinedefs(UINT8 *data)
ld->flags = SHORT(mld->flags); ld->flags = SHORT(mld->flags);
ld->special = SHORT(mld->special); ld->special = SHORT(mld->special);
ld->tag = SHORT(mld->tag); ld->tag = SHORT(mld->tag);
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT;
ld->executordelay = 0;
P_SetLinedefV1(i, SHORT(mld->v1)); P_SetLinedefV1(i, SHORT(mld->v1));
P_SetLinedefV2(i, SHORT(mld->v2)); P_SetLinedefV2(i, SHORT(mld->v2));
@ -1218,9 +1225,11 @@ static void P_LoadSidedefs(UINT8 *data)
case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:) case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:)
// SoM: R_CreateColormap will only create a colormap in software mode... // SoM: R_CreateColormap will only create a colormap in software mode...
// Perhaps we should just call it instead of doing the calculations here. // Perhaps we should just call it instead of doing the calculations here.
sd->colormap_data = R_CreateColormap(msd->toptexture, msd->midtexture, if (!udmf)
msd->bottomtexture); {
sd->toptexture = sd->midtexture = sd->bottomtexture = 0; sd->colormap_data = R_CreateColormapFromLinedef(msd->toptexture, msd->midtexture, msd->bottomtexture);
sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
}
break; break;
case 413: // Change music case 413: // Change music
@ -1371,6 +1380,11 @@ static void P_LoadThings(UINT8 *data)
mt->type = READUINT16(data); mt->type = READUINT16(data);
mt->options = READUINT16(data); mt->options = READUINT16(data);
mt->extrainfo = (UINT8)(mt->type >> 12); mt->extrainfo = (UINT8)(mt->type >> 12);
mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0;
mt->type &= 4095; mt->type &= 4095;
@ -1475,6 +1489,19 @@ static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val)
} }
} }
typedef struct textmap_colormap_s {
boolean used;
INT32 lightcolor;
UINT8 lightalpha;
INT32 fadecolor;
UINT8 fadealpha;
UINT8 fadestart;
UINT8 fadeend;
UINT8 flags;
} textmap_colormap_t;
textmap_colormap_t textmap_colormap = { false, 0, 25, 0, 25, 0, 31, 0 };
static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "heightfloor")) if (fastcmp(param, "heightfloor"))
@ -1503,6 +1530,48 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "rotationceiling")) else if (fastcmp(param, "rotationceiling"))
sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "lightcolor"))
{
textmap_colormap.used = true;
textmap_colormap.lightcolor = atol(val);
}
else if (fastcmp(param, "lightalpha"))
{
textmap_colormap.used = true;
textmap_colormap.lightalpha = atol(val);
}
else if (fastcmp(param, "fadecolor"))
{
textmap_colormap.used = true;
textmap_colormap.fadecolor = atol(val);
}
else if (fastcmp(param, "fadealpha"))
{
textmap_colormap.used = true;
textmap_colormap.fadealpha = atol(val);
}
else if (fastcmp(param, "fadestart"))
{
textmap_colormap.used = true;
textmap_colormap.fadestart = atol(val);
}
else if (fastcmp(param, "fadeend"))
{
textmap_colormap.used = true;
textmap_colormap.fadeend = atol(val);
}
else if (fastcmp(param, "colormapfog") && fastcmp("true", val))
{
textmap_colormap.used = true;
textmap_colormap.flags |= CMF_FOG;
}
else if (fastcmp(param, "colormapfadesprites") && fastcmp("true", val))
{
textmap_colormap.used = true;
textmap_colormap.flags |= CMF_FADEFULLBRIGHTSPRITES;
}
else if (fastcmp(param, "colormapprotected") && fastcmp("true", val))
sectors[i].colormap_protected = true;
} }
static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
@ -1533,10 +1602,29 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
P_SetLinedefV1(i, atol(val)); P_SetLinedefV1(i, atol(val));
else if (fastcmp(param, "v2")) else if (fastcmp(param, "v2"))
P_SetLinedefV2(i, atol(val)); P_SetLinedefV2(i, atol(val));
else if (fastncmp(param, "arg", 3) && strlen(param) > 3)
{
size_t argnum = atol(param + 3);
if (argnum >= NUMLINEARGS)
return;
lines[i].args[argnum] = atol(val);
}
else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9)
{
size_t argnum = param[9] - '0';
if (argnum >= NUMLINESTRINGARGS)
return;
lines[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(lines[i].stringargs[argnum], val, strlen(val) + 1);
}
else if (fastcmp(param, "sidefront")) else if (fastcmp(param, "sidefront"))
lines[i].sidenum[0] = atol(val); lines[i].sidenum[0] = atol(val);
else if (fastcmp(param, "sideback")) else if (fastcmp(param, "sideback"))
lines[i].sidenum[1] = atol(val); lines[i].sidenum[1] = atol(val);
else if (fastcmp(param, "alpha"))
lines[i].alpha = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "executordelay"))
lines[i].executordelay = atol(val);
// Flags // Flags
else if (fastcmp(param, "blocking") && fastcmp("true", val)) else if (fastcmp(param, "blocking") && fastcmp("true", val))
@ -1575,6 +1663,8 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id"))
mapthings[i].tag = atol(val);
if (fastcmp(param, "x")) if (fastcmp(param, "x"))
mapthings[i].x = atol(val); mapthings[i].x = atol(val);
else if (fastcmp(param, "y")) else if (fastcmp(param, "y"))
@ -1583,18 +1673,39 @@ static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
mapthings[i].z = atol(val); mapthings[i].z = atol(val);
else if (fastcmp(param, "angle")) else if (fastcmp(param, "angle"))
mapthings[i].angle = atol(val); mapthings[i].angle = atol(val);
else if (fastcmp(param, "pitch"))
mapthings[i].pitch = atol(val);
else if (fastcmp(param, "roll"))
mapthings[i].roll = atol(val);
else if (fastcmp(param, "type")) else if (fastcmp(param, "type"))
mapthings[i].type = atol(val); mapthings[i].type = atol(val);
else if (fastcmp(param, "scale") || fastcmp(param, "scalex") || fastcmp(param, "scaley"))
mapthings[i].scale = FLOAT_TO_FIXED(atof(val));
// Flags // Flags
else if (fastcmp(param, "extra") && fastcmp("true", val)) else if (fastcmp(param, "extra") && fastcmp("true", val))
mapthings[i].options |= MTF_EXTRA; mapthings[i].options |= MTF_EXTRA;
else if (fastcmp(param, "flip") && fastcmp("true", val)) else if (fastcmp(param, "flip") && fastcmp("true", val))
mapthings[i].options |= MTF_OBJECTFLIP; mapthings[i].options |= MTF_OBJECTFLIP;
else if (fastcmp(param, "special") && fastcmp("true", val)) else if (fastcmp(param, "objectspecial") && fastcmp("true", val))
mapthings[i].options |= MTF_OBJECTSPECIAL; mapthings[i].options |= MTF_OBJECTSPECIAL;
else if (fastcmp(param, "ambush") && fastcmp("true", val)) else if (fastcmp(param, "ambush") && fastcmp("true", val))
mapthings[i].options |= MTF_AMBUSH; mapthings[i].options |= MTF_AMBUSH;
else if (fastncmp(param, "arg", 3) && strlen(param) > 3)
{
size_t argnum = atol(param + 3);
if (argnum >= NUMMAPTHINGARGS)
return;
mapthings[i].args[argnum] = atol(val);
}
else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9)
{
size_t argnum = param[9] - '0';
if (argnum >= NUMMAPTHINGSTRINGARGS)
return;
mapthings[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(mapthings[i].stringargs[argnum], val, strlen(val) + 1);
}
} }
/** From a given position table, run a specified parser function through a {}-encapsuled text. /** From a given position table, run a specified parser function through a {}-encapsuled text.
@ -1657,6 +1768,14 @@ static void TextmapFixFlatOffsets(sector_t *sec)
} }
} }
static INT32 P_ColorToRGBA(INT32 color, UINT8 alpha)
{
UINT8 r = (color >> 16) & 0xFF;
UINT8 g = (color >> 8) & 0xFF;
UINT8 b = color & 0xFF;
return R_PutRgbaRGBA(r, g, b, alpha);
}
/** Loads the textmap data, after obtaining the elements count and allocating their respective space. /** Loads the textmap data, after obtaining the elements count and allocating their respective space.
*/ */
static void P_LoadTextmap(void) static void P_LoadTextmap(void)
@ -1710,8 +1829,24 @@ static void P_LoadTextmap(void)
sc->floorpic_angle = sc->ceilingpic_angle = 0; sc->floorpic_angle = sc->ceilingpic_angle = 0;
sc->colormap_protected = false;
textmap_colormap.used = false;
textmap_colormap.lightcolor = 0;
textmap_colormap.lightalpha = 25;
textmap_colormap.fadecolor = 0;
textmap_colormap.fadealpha = 25;
textmap_colormap.fadestart = 0;
textmap_colormap.fadeend = 31;
textmap_colormap.flags = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc); P_InitializeSector(sc);
if (textmap_colormap.used)
{
INT32 rgba = P_ColorToRGBA(textmap_colormap.lightcolor, textmap_colormap.lightalpha);
INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, textmap_colormap.fadealpha);
sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags);
}
TextmapFixFlatOffsets(sc); TextmapFixFlatOffsets(sc);
} }
@ -1722,6 +1857,10 @@ static void P_LoadTextmap(void)
ld->flags = 0; ld->flags = 0;
ld->special = 0; ld->special = 0;
ld->tag = 0; ld->tag = 0;
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT;
ld->executordelay = 0;
ld->sidenum[0] = 0xffff; ld->sidenum[0] = 0xffff;
ld->sidenum[1] = 0xffff; ld->sidenum[1] = 0xffff;
@ -1760,11 +1899,15 @@ static void P_LoadTextmap(void)
{ {
// Defaults. // Defaults.
mt->x = mt->y = 0; mt->x = mt->y = 0;
mt->angle = 0; mt->angle = mt->pitch = mt->roll = 0;
mt->type = 0; mt->type = 0;
mt->options = 0; mt->options = 0;
mt->z = 0; mt->z = 0;
mt->extrainfo = 0; mt->extrainfo = 0;
mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL; mt->mobj = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
@ -1780,9 +1923,9 @@ static void P_ProcessLinedefsAfterSidedefs(void)
ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here
ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0;
// Compile linedef 'text' from both sidedefs 'text' for appropriate specials.
switch (ld->special) switch (ld->special)
{ {
// Compile linedef 'text' from both sidedefs 'text' for appropriate specials.
case 331: // Trigger linedef executor: Skin - Continuous case 331: // Trigger linedef executor: Skin - Continuous
case 332: // Trigger linedef executor: Skin - Each time case 332: // Trigger linedef executor: Skin - Each time
case 333: // Trigger linedef executor: Skin - Once case 333: // Trigger linedef executor: Skin - Once
@ -1798,6 +1941,41 @@ static void P_ProcessLinedefsAfterSidedefs(void)
M_Memcpy(ld->text + strlen(ld->text) + 1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text) + 1); M_Memcpy(ld->text + strlen(ld->text) + 1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text) + 1);
} }
break; break;
case 447: // Change colormap
case 455: // Fade colormap
if (udmf)
break;
if (ld->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets)
{
extracolormap_t *exc = R_CopyColormap(sides[ld->sidenum[0]].colormap_data, false);
INT16 alpha = max(min(sides[ld->sidenum[0]].textureoffset >> FRACBITS, 25), -25);
INT16 fadealpha = max(min(sides[ld->sidenum[0]].rowoffset >> FRACBITS, 25), -25);
// If alpha is negative, set "subtract alpha" flag and store absolute value
if (alpha < 0)
{
alpha *= -1;
ld->args[2] |= TMCF_SUBLIGHTA;
}
if (fadealpha < 0)
{
fadealpha *= -1;
ld->args[2] |= TMCF_SUBFADEA;
}
exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(alpha);
exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(fadealpha);
if (!(sides[ld->sidenum[0]].colormap_data = R_GetColormapFromList(exc)))
{
exc->colormap = R_CreateLightTable(exc);
R_AddColormapToList(exc);
sides[ld->sidenum[0]].colormap_data = exc;
}
else
Z_Free(exc);
}
break;
} }
} }
} }
@ -1805,11 +1983,11 @@ static void P_ProcessLinedefsAfterSidedefs(void)
static boolean P_LoadMapData(const virtres_t *virt) static boolean P_LoadMapData(const virtres_t *virt)
{ {
virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL; virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL;
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
// Count map data. // Count map data.
if (textmap) // Count how many entries for each type we got in textmap. if (udmf) // Count how many entries for each type we got in textmap.
{ {
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
if (!TextmapCount(textmap->data, textmap->size)) if (!TextmapCount(textmap->data, textmap->size))
return false; return false;
} }
@ -1864,7 +2042,7 @@ static boolean P_LoadMapData(const virtres_t *virt)
numlevelflats = 0; numlevelflats = 0;
// Load map data. // Load map data.
if (textmap) if (udmf)
P_LoadTextmap(); P_LoadTextmap();
else else
{ {
@ -1972,7 +2150,12 @@ static void P_InitializeSeg(seg_t *seg)
{ {
if (seg->linedef) if (seg->linedef)
{ {
seg->sidedef = &sides[seg->linedef->sidenum[seg->side]]; UINT16 side = seg->linedef->sidenum[seg->side];
if (side == 0xffff)
I_Error("P_InitializeSeg: Seg %s refers to side %d of linedef %s, which doesn't exist!\n", sizeu1((size_t)(seg - segs)), seg->side, sizeu1((size_t)(seg->linedef - lines)));
seg->sidedef = &sides[side];
seg->frontsector = seg->sidedef->sector; seg->frontsector = seg->sidedef->sector;
seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL; seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL;
@ -2041,7 +2224,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
nodetype_t nodetype = NT_UNSUPPORTED; nodetype_t nodetype = NT_UNSUPPORTED;
char signature[4 + 1]; char signature[4 + 1];
if (vres_Find(virt, "TEXTMAP")) if (udmf)
{ {
*nodedata = vres_Find(virt, "ZNODES")->data; *nodedata = vres_Find(virt, "ZNODES")->data;
supported[NT_XGLN] = supported[NT_XGL3] = true; supported[NT_XGLN] = supported[NT_XGL3] = true;
@ -2166,10 +2349,8 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
segs[k - 1 + ((m == 0) ? subsectors[i].numlines : 0)].v2 = segs[k].v1 = &vertexes[vertexnum]; segs[k - 1 + ((m == 0) ? subsectors[i].numlines : 0)].v2 = segs[k].v1 = &vertexes[vertexnum];
READUINT32((*data)); // partner, can be ignored by software renderer READUINT32((*data)); // partner, can be ignored by software renderer
if (nodetype == NT_XGL3)
READUINT16((*data)); // Line number is 32-bit in XGL3, but we're limited to 16 bits.
linenum = READUINT16((*data)); linenum = (nodetype == NT_XGL3) ? READUINT32((*data)) : READUINT16((*data));
if (linenum != 0xFFFF && linenum >= numlines) if (linenum != 0xFFFF && linenum >= numlines)
I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum); I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum);
segs[k].glseg = (linenum == 0xFFFF); segs[k].glseg = (linenum == 0xFFFF);
@ -2737,6 +2918,259 @@ static void P_LinkMapData(void)
} }
} }
/** Hashes the sector tags across the sectors and linedefs.
*
* \sa P_FindSectorFromTag, P_ChangeSectorTag
* \author Lee Killough
*/
static inline void P_InitTagLists(void)
{
register size_t i;
for (i = numsectors - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)sectors[i].tag % numsectors;
sectors[i].nexttag = sectors[j].firsttag;
sectors[j].firsttag = (INT32)i;
}
for (i = numlines - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)lines[i].tag % numlines;
lines[i].nexttag = lines[j].firsttag;
lines[j].firsttag = (INT32)i;
}
}
//For maps in binary format, converts setup of specials to UDMF format.
static void P_ConvertBinaryMap(void)
{
size_t i;
for (i = 0; i < numlines; i++)
{
switch (lines[i].special)
{
case 20: //PolyObject first line
{
INT32 paramline = P_FindSpecialLineFromTag(22, lines[i].tag, -1);
//PolyObject ID
lines[i].args[0] = lines[i].tag;
//Default: Invisible planes
lines[i].args[3] |= TMPF_INVISIBLEPLANES;
//Linedef executor tag
lines[i].args[4] = 32000 + lines[i].args[0];
if (paramline == -1)
break; // no extra settings to apply, let's leave it
//Parent ID
lines[i].args[1] = lines[paramline].frontsector->special;
//Translucency
lines[i].args[2] = (lines[paramline].flags & ML_DONTPEGTOP)
? (sides[lines[paramline].sidenum[0]].textureoffset >> FRACBITS)
: ((lines[paramline].frontsector->floorheight >> FRACBITS) / 100);
//Flags
if (lines[paramline].flags & ML_EFFECT1)
lines[i].args[3] |= TMPF_NOINSIDES;
if (lines[paramline].flags & ML_EFFECT2)
lines[i].args[3] |= TMPF_INTANGIBLE;
if (lines[paramline].flags & ML_EFFECT3)
lines[i].args[3] |= TMPF_PUSHABLESTOP;
if (lines[paramline].flags & ML_EFFECT4)
lines[i].args[3] &= ~TMPF_INVISIBLEPLANES;
/*if (lines[paramline].flags & ML_EFFECT5)
lines[i].args[3] |= TMPF_DONTCLIPPLANES;*/
if (lines[paramline].flags & ML_EFFECT6)
lines[i].args[3] |= TMPF_SPLAT;
if (lines[paramline].flags & ML_NOCLIMB)
lines[i].args[3] |= TMPF_EXECUTOR;
break;
}
case 443: //Call Lua function
if (lines[i].text)
{
lines[i].stringargs[0] = Z_Malloc(strlen(lines[i].text) + 1, PU_LEVEL, NULL);
M_Memcpy(lines[i].stringargs[0], lines[i].text, strlen(lines[i].text) + 1);
}
else
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i));
break;
case 447: //Change colormap
lines[i].args[0] = lines[i].tag;
if (lines[i].flags & ML_EFFECT3)
lines[i].args[2] |= TMCF_RELATIVE;
if (lines[i].flags & ML_EFFECT1)
lines[i].args[2] |= TMCF_SUBLIGHTR|TMCF_SUBFADER;
if (lines[i].flags & ML_NOCLIMB)
lines[i].args[2] |= TMCF_SUBLIGHTG|TMCF_SUBFADEG;
if (lines[i].flags & ML_EFFECT2)
lines[i].args[2] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB;
break;
case 455: //Fade colormap
{
INT32 speed = (INT32)((((lines[i].flags & ML_DONTPEGBOTTOM) || !sides[lines[i].sidenum[0]].rowoffset) && lines[i].sidenum[1] != 0xFFFF) ?
abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS)
: abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS));
lines[i].args[0] = lines[i].tag;
if (lines[i].flags & ML_EFFECT4)
lines[i].args[2] = speed;
else
lines[i].args[2] = (256 + speed - 1)/speed;
if (lines[i].flags & ML_EFFECT3)
lines[i].args[3] |= TMCF_RELATIVE;
if (lines[i].flags & ML_EFFECT1)
lines[i].args[3] |= TMCF_SUBLIGHTR|TMCF_SUBFADER;
if (lines[i].flags & ML_NOCLIMB)
lines[i].args[3] |= TMCF_SUBLIGHTG|TMCF_SUBFADEG;
if (lines[i].flags & ML_EFFECT2)
lines[i].args[3] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB;
if (lines[i].flags & ML_BOUNCY)
lines[i].args[3] |= TMCF_FROMBLACK;
if (lines[i].flags & ML_EFFECT5)
lines[i].args[3] |= TMCF_OVERRIDE;
break;
}
case 456: //Stop fading colormap
lines[i].args[0] = lines[i].tag;
break;
case 606: //Colormap
lines[i].args[0] = lines[i].tag;
break;
case 700: //Slope front sector floor
case 701: //Slope front sector ceiling
case 702: //Slope front sector floor and ceiling
case 703: //Slope front sector floor and back sector ceiling
case 710: //Slope back sector floor
case 711: //Slope back sector ceiling
case 712: //Slope back sector floor and ceiling
case 713: //Slope back sector floor and front sector ceiling
{
boolean frontfloor = (lines[i].special == 700 || lines[i].special == 702 || lines[i].special == 703);
boolean backfloor = (lines[i].special == 710 || lines[i].special == 712 || lines[i].special == 713);
boolean frontceil = (lines[i].special == 701 || lines[i].special == 702 || lines[i].special == 713);
boolean backceil = (lines[i].special == 711 || lines[i].special == 712 || lines[i].special == 703);
lines[i].args[0] = backfloor ? TMS_BACK : (frontfloor ? TMS_FRONT : TMS_NONE);
lines[i].args[1] = backceil ? TMS_BACK : (frontceil ? TMS_FRONT : TMS_NONE);
if (lines[i].flags & ML_NETONLY)
lines[i].args[2] |= TMSL_NOPHYSICS;
if (lines[i].flags & ML_NONET)
lines[i].args[2] |= TMSL_DYNAMIC;
lines[i].special = 700;
break;
}
case 704: //Slope front sector floor by 3 tagged vertices
case 705: //Slope front sector ceiling by 3 tagged vertices
case 714: //Slope back sector floor by 3 tagged vertices
case 715: //Slope back sector ceiling by 3 tagged vertices
{
if (lines[i].special == 704)
lines[i].args[0] = TMSP_FRONTFLOOR;
else if (lines[i].special == 705)
lines[i].args[0] = TMSP_FRONTCEILING;
else if (lines[i].special == 714)
lines[i].args[0] = TMSP_BACKFLOOR;
else if (lines[i].special == 715)
lines[i].args[0] = TMSP_BACKCEILING;
lines[i].args[1] = lines[i].tag;
if (lines[i].flags & ML_EFFECT6)
{
UINT8 side = lines[i].special >= 714;
if (side == 1 && lines[i].sidenum[1] == 0xffff)
CONS_Debug(DBG_GAMELOGIC, "P_ConvertBinaryMap: Line special %d (line #%s) missing 2nd side!\n", lines[i].special, sizeu1(i));
else
{
lines[i].args[2] = sides[lines[i].sidenum[side]].textureoffset >> FRACBITS;
lines[i].args[3] = sides[lines[i].sidenum[side]].rowoffset >> FRACBITS;
}
}
else
{
lines[i].args[2] = lines[i].args[1];
lines[i].args[3] = lines[i].args[1];
}
if (lines[i].flags & ML_NETONLY)
lines[i].args[4] |= TMSL_NOPHYSICS;
if (lines[i].flags & ML_NONET)
lines[i].args[4] |= TMSL_DYNAMIC;
lines[i].special = 704;
break;
}
case 720: //Copy front side floor slope
case 721: //Copy front side ceiling slope
case 722: //Copy front side floor and ceiling slope
if (lines[i].special != 721)
lines[i].args[0] = lines[i].tag;
if (lines[i].special != 720)
lines[i].args[1] = lines[i].tag;
lines[i].special = 720;
break;
case 900: //Translucent wall (10%)
case 901: //Translucent wall (20%)
case 902: //Translucent wall (30%)
case 903: //Translucent wall (40%)
case 904: //Translucent wall (50%)
case 905: //Translucent wall (60%)
case 906: //Translucent wall (70%)
case 907: //Translucent wall (80%)
case 908: //Translucent wall (90%)
lines[i].alpha = ((909 - lines[i].special) << FRACBITS)/10;
break;
default:
break;
}
//Linedef executor delay
if (lines[i].special >= 400 && lines[i].special < 500)
{
//Dummy value to indicate that this executor is delayed.
//The real value is taken from the back sector at runtime.
if (lines[i].flags & ML_DONTPEGTOP)
lines[i].executordelay = 1;
}
}
for (i = 0; i < nummapthings; i++)
{
switch (mapthings[i].type)
{
case 750:
case 760:
case 761:
mapthings[i].tag = mapthings[i].angle;
break;
case 762:
{
INT32 firstline = P_FindSpecialLineFromTag(20, mapthings[i].angle, -1);
if (firstline != -1)
lines[firstline].args[3] |= TMPF_CRUSH;
mapthings[i].tag = mapthings[i].angle;
mapthings[i].type = 761;
break;
}
case 780:
mapthings[i].tag = mapthings[i].extrainfo;
break;
default:
break;
}
}
}
/** Compute MD5 message digest for bytes read from memory source /** Compute MD5 message digest for bytes read from memory source
* *
* The resulting message digest number will be written into the 16 bytes * The resulting message digest number will be written into the 16 bytes
@ -2765,11 +3199,13 @@ static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock)
static void P_MakeMapMD5(virtres_t *virt, void *dest) static void P_MakeMapMD5(virtres_t *virt, void *dest)
{ {
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
unsigned char resmd5[16]; unsigned char resmd5[16];
if (textmap) if (udmf)
{
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5); P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5);
}
else else
{ {
unsigned char linemd5[16]; unsigned char linemd5[16];
@ -2800,6 +3236,8 @@ static void P_MakeMapMD5(virtres_t *virt, void *dest)
static boolean P_LoadMapFromFile(void) static boolean P_LoadMapFromFile(void)
{ {
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
udmf = textmap != NULL;
if (!P_LoadMapData(virt)) if (!P_LoadMapData(virt))
return false; return false;
@ -2808,6 +3246,11 @@ static boolean P_LoadMapFromFile(void)
P_LinkMapData(); P_LinkMapData();
P_InitTagLists(); // Create xref tables for tags
if (!udmf)
P_ConvertBinaryMap();
// Copy relevant map data for NetArchive purposes. // Copy relevant map data for NetArchive purposes.
spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL);
spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL);
@ -3682,8 +4125,7 @@ boolean P_LoadLevel(boolean fromnetsave)
if (!P_LoadMapFromFile()) if (!P_LoadMapFromFile())
return false; return false;
// init gravity, tag lists, // init anything that P_SpawnSlopes/P_LoadThings needs to know
// anything that P_SpawnSlopes/P_LoadThings needs to know
P_InitSpecials(); P_InitSpecials();
P_SpawnSlopes(fromnetsave); P_SpawnSlopes(fromnetsave);

View File

@ -245,32 +245,30 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
// because checking to see if a slope had changed will waste more memory than // because checking to see if a slope had changed will waste more memory than
// if the slope was just updated when called // if the slope was just updated when called
line_t *line = lines + linenum; line_t *line = lines + linenum;
INT16 special = line->special;
pslope_t *fslope = NULL, *cslope = NULL; pslope_t *fslope = NULL, *cslope = NULL;
vector3_t origin, point; vector3_t origin, point;
vector2_t direction; vector2_t direction;
fixed_t nx, ny, dz, extent; fixed_t nx, ny, dz, extent;
boolean frontfloor = (special == 700 || special == 702 || special == 703); boolean frontfloor = line->args[0] == TMS_FRONT;
boolean backfloor = (special == 710 || special == 712 || special == 713); boolean backfloor = line->args[0] == TMS_BACK;
boolean frontceil = (special == 701 || special == 702 || special == 713); boolean frontceil = line->args[1] == TMS_FRONT;
boolean backceil = (special == 711 || special == 712 || special == 703); boolean backceil = line->args[1] == TMS_BACK;
UINT8 flags = 0; // Slope flags UINT8 flags = 0; // Slope flags
if (line->flags & ML_NETONLY) if (line->args[2] & TMSL_NOPHYSICS)
flags |= SL_NOPHYSICS; flags |= SL_NOPHYSICS;
if (line->flags & ML_NONET) if (line->args[2] & TMSL_DYNAMIC)
flags |= SL_DYNAMIC; flags |= SL_DYNAMIC;
if(!frontfloor && !backfloor && !frontceil && !backceil) if(!frontfloor && !backfloor && !frontceil && !backceil)
{ {
CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n"); CONS_Printf("line_SpawnViaLine: Slope special with nothing to do.\n");
return; return;
} }
if(!line->frontsector || !line->backsector) if(!line->frontsector || !line->backsector)
{ {
CONS_Debug(DBG_SETUP, "P_SpawnSlope_Line used on a line without two sides. (line number %i)\n", linenum); CONS_Debug(DBG_SETUP, "line_SpawnViaLine: Slope special used on a line without two sides. (line number %i)\n", linenum);
return; return;
} }
@ -297,7 +295,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
if(extent < 0) if(extent < 0)
{ {
CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum); CONS_Printf("line_SpawnViaLine failed to get frontsector extent on line number %i\n", linenum);
return; return;
} }
@ -363,7 +361,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
if(extent < 0) if(extent < 0)
{ {
CONS_Printf("P_SpawnSlope_Line failed to get backsector extent on line number %i\n", linenum); CONS_Printf("line_SpawnViaLine failed to get backsector extent on line number %i\n", linenum);
return; return;
} }
@ -428,11 +426,11 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something! if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue; continue;
if (!vertices[0] && mt->angle == tag1) if (!vertices[0] && mt->tag == tag1)
vertices[0] = mt; vertices[0] = mt;
else if (!vertices[1] && mt->angle == tag2) else if (!vertices[1] && mt->tag == tag2)
vertices[1] = mt; vertices[1] = mt;
else if (!vertices[2] && mt->angle == tag3) else if (!vertices[2] && mt->tag == tag3)
vertices[2] = mt; vertices[2] = mt;
} }
@ -462,44 +460,36 @@ static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawn
line_t *line = lines + linenum; line_t *line = lines + linenum;
side_t *side; side_t *side;
pslope_t **slopetoset; pslope_t **slopetoset;
UINT16 tag1, tag2, tag3; UINT16 tag1 = line->args[1];
UINT16 tag2 = line->args[2];
UINT8 flags = 0; UINT16 tag3 = line->args[3];
if (line->flags & ML_NETONLY) UINT8 flags = 0; // Slope flags
if (line->args[4] & TMSL_NOPHYSICS)
flags |= SL_NOPHYSICS; flags |= SL_NOPHYSICS;
if (line->flags & ML_NONET) if (line->args[4] & TMSL_DYNAMIC)
flags |= SL_DYNAMIC; flags |= SL_DYNAMIC;
switch(line->special) switch(line->args[0])
{ {
case 704: case TMSP_FRONTFLOOR:
slopetoset = &line->frontsector->f_slope; slopetoset = &line->frontsector->f_slope;
side = &sides[line->sidenum[0]]; side = &sides[line->sidenum[0]];
break; break;
case 705: case TMSP_FRONTCEILING:
slopetoset = &line->frontsector->c_slope; slopetoset = &line->frontsector->c_slope;
side = &sides[line->sidenum[0]]; side = &sides[line->sidenum[0]];
break; break;
case 714: case TMSP_BACKFLOOR:
slopetoset = &line->backsector->f_slope; slopetoset = &line->backsector->f_slope;
side = &sides[line->sidenum[1]]; side = &sides[line->sidenum[1]];
break; break;
case 715: case TMSP_BACKCEILING:
slopetoset = &line->backsector->c_slope; slopetoset = &line->backsector->c_slope;
side = &sides[line->sidenum[1]]; side = &sides[line->sidenum[1]];
default: default:
return; return;
} }
if (line->flags & ML_EFFECT6)
{
tag1 = line->tag;
tag2 = side->textureoffset >> FRACBITS;
tag3 = side->rowoffset >> FRACBITS;
}
else
tag1 = tag2 = tag3 = line->tag;
*slopetoset = MakeViaMapthings(tag1, tag2, tag3, flags, spawnthinker); *slopetoset = MakeViaMapthings(tag1, tag2, tag3, flags, spawnthinker);
side->sector->hasslope = true; side->sector->hasslope = true;
@ -555,6 +545,47 @@ static void SpawnVertexSlopes(void)
} }
} }
static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
{
INT32 i;
pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope;
if (!tag || *secslope)
return false;
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;)
{
pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope;
if (srcslope)
{
*secslope = srcslope;
return true;
}
}
return false;
}
static boolean P_CopySlope(pslope_t **toslope, pslope_t *fromslope)
{
if (*toslope || !fromslope)
return true;
*toslope = fromslope;
return true;
}
static void P_UpdateHasSlope(sector_t *sec)
{
size_t i;
sec->hasslope = true;
// if this is an FOF control sector, make sure any target sectors also are marked as having slopes
if (sec->numattached)
for (i = 0; i < sec->numattached; i++)
sectors[sec->attached[i]].hasslope = true;
}
// //
// P_CopySectorSlope // P_CopySectorSlope
// //
@ -563,25 +594,31 @@ static void SpawnVertexSlopes(void)
void P_CopySectorSlope(line_t *line) void P_CopySectorSlope(line_t *line)
{ {
sector_t *fsec = line->frontsector; sector_t *fsec = line->frontsector;
int i, special = line->special; sector_t *bsec = line->backsector;
boolean setfront = false;
boolean setback = false;
// Check for copy linedefs setfront |= P_SetSlopeFromTag(fsec, line->args[0], false);
for (i = -1; (i = P_FindSectorFromTag(line->tag, i)) >= 0;) setfront |= P_SetSlopeFromTag(fsec, line->args[1], true);
if (bsec)
{ {
sector_t *srcsec = sectors + i; setback |= P_SetSlopeFromTag(bsec, line->args[2], false);
setback |= P_SetSlopeFromTag(bsec, line->args[3], true);
if ((special - 719) & 1 && !fsec->f_slope && srcsec->f_slope) if (line->args[4] & TMSC_FRONTTOBACKFLOOR)
fsec->f_slope = srcsec->f_slope; //P_CopySlope(srcsec->f_slope); setback |= P_CopySlope(&bsec->f_slope, fsec->f_slope);
if ((special - 719) & 2 && !fsec->c_slope && srcsec->c_slope) if (line->args[4] & TMSC_BACKTOFRONTFLOOR)
fsec->c_slope = srcsec->c_slope; //P_CopySlope(srcsec->c_slope); setfront |= P_CopySlope(&fsec->f_slope, bsec->f_slope);
if (line->args[4] & TMSC_FRONTTOBACKCEILING)
setback |= P_CopySlope(&bsec->c_slope, fsec->c_slope);
if (line->args[4] & TMSC_BACKTOFRONTCEILING)
setfront |= P_CopySlope(&fsec->c_slope, bsec->c_slope);
} }
fsec->hasslope = true; if (setfront)
P_UpdateHasSlope(fsec);
// if this is an FOF control sector, make sure any target sectors also are marked as having slopes if (setback)
if (fsec->numattached) P_UpdateHasSlope(bsec);
for (i = 0; i < (int)fsec->numattached; i++)
sectors[fsec->attached[i]].hasslope = true;
line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef
} }
@ -614,20 +651,10 @@ void P_SpawnSlopes(const boolean fromsave) {
switch (lines[i].special) switch (lines[i].special)
{ {
case 700: case 700:
case 701:
case 702:
case 703:
case 710:
case 711:
case 712:
case 713:
line_SpawnViaLine(i, !fromsave); line_SpawnViaLine(i, !fromsave);
break; break;
case 704: case 704:
case 705:
case 714:
case 715:
line_SpawnViaMapthingVertexes(i, !fromsave); line_SpawnViaMapthingVertexes(i, !fromsave);
break; break;
@ -642,8 +669,6 @@ void P_SpawnSlopes(const boolean fromsave) {
switch (lines[i].special) switch (lines[i].special)
{ {
case 720: case 720:
case 721:
case 722:
P_CopySectorSlope(&lines[i]); P_CopySectorSlope(&lines[i]);
default: default:
break; break;

View File

@ -18,6 +18,35 @@
extern pslope_t *slopelist; extern pslope_t *slopelist;
extern UINT16 slopecount; extern UINT16 slopecount;
typedef enum
{
TMSP_FRONTFLOOR,
TMSP_FRONTCEILING,
TMSP_BACKFLOOR,
TMSP_BACKCEILING,
} textmapslopeplane_t;
typedef enum
{
TMSC_FRONTTOBACKFLOOR = 1,
TMSC_BACKTOFRONTFLOOR = 1<<1,
TMSC_FRONTTOBACKCEILING = 1<<2,
TMSC_BACKTOFRONTCEILING = 1<<3,
} textmapslopecopy_t;
typedef enum
{
TMS_NONE,
TMS_FRONT,
TMS_BACK,
} textmapside_t;
typedef enum
{
TMSL_NOPHYSICS = 1,
TMSL_DYNAMIC = 2,
} textmapslopeflags_t;
void P_LinkSlopeThinkers (void); void P_LinkSlopeThinkers (void);
void P_CalculateSlopeNormal(pslope_t *slope); void P_CalculateSlopeNormal(pslope_t *slope);

View File

@ -1496,30 +1496,6 @@ void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean e
} }
} }
/** Hashes the sector tags across the sectors and linedefs.
*
* \sa P_FindSectorFromTag, P_ChangeSectorTag
* \author Lee Killough
*/
static inline void P_InitTagLists(void)
{
register size_t i;
for (i = numsectors - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)sectors[i].tag % numsectors;
sectors[i].nexttag = sectors[j].firsttag;
sectors[j].firsttag = (INT32)i;
}
for (i = numlines - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)lines[i].tag % numlines;
lines[i].nexttag = lines[j].firsttag;
lines[j].firsttag = (INT32)i;
}
}
/** Finds minimum light from an adjacent sector. /** Finds minimum light from an adjacent sector.
* *
* \param sector Sector to start in. * \param sector Sector to start in.
@ -1563,16 +1539,24 @@ void T_ExecutorDelay(executor_t *e)
static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector) static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
{ {
executor_t *e; executor_t *e;
INT32 delay;
if (!line->backsector) if (udmf)
I_Error("P_AddExecutorDelay: Line has no backsector!\n"); delay = line->executordelay;
else
{
if (!line->backsector)
I_Error("P_AddExecutorDelay: Line has no backsector!\n");
delay = (line->backsector->ceilingheight >> FRACBITS) + (line->backsector->floorheight >> FRACBITS);
}
e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL); e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL);
e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay; e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay;
e->line = line; e->line = line;
e->sector = sector; e->sector = sector;
e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS); e->timer = delay;
P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying. P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying.
P_AddThinker(THINK_MAIN, &e->thinker); P_AddThinker(THINK_MAIN, &e->thinker);
} }
@ -1973,7 +1957,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
if (ctlsector->lines[i]->special >= 400 if (ctlsector->lines[i]->special >= 400
&& ctlsector->lines[i]->special < 500) && ctlsector->lines[i]->special < 500)
{ {
if (ctlsector->lines[i]->flags & ML_DONTPEGTOP) if (ctlsector->lines[i]->executordelay)
P_AddExecutorDelay(ctlsector->lines[i], actor, caller); P_AddExecutorDelay(ctlsector->lines[i], actor, caller);
else else
P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); P_ProcessLineSpecial(ctlsector->lines[i], actor, caller);
@ -2061,7 +2045,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
if (ctlsector->lines[i]->special >= 400 if (ctlsector->lines[i]->special >= 400
&& ctlsector->lines[i]->special < 500) && ctlsector->lines[i]->special < 500)
{ {
if (ctlsector->lines[i]->flags & ML_DONTPEGTOP) if (ctlsector->lines[i]->executordelay)
P_AddExecutorDelay(ctlsector->lines[i], actor, caller); P_AddExecutorDelay(ctlsector->lines[i], actor, caller);
else else
P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); P_ProcessLineSpecial(ctlsector->lines[i], actor, caller);
@ -3294,10 +3278,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
} }
case 443: // Calls a named Lua function case 443: // Calls a named Lua function
if (line->text) if (line->stringargs[0])
LUAh_LinedefExecute(line, mo, callsec); LUAh_LinedefExecute(line, mo, callsec);
else else
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(line-lines)); CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines));
break; break;
case 444: // Earthquake camera case 444: // Earthquake camera
@ -3420,46 +3404,53 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// Except it is activated by linedef executor, not level load // Except it is activated by linedef executor, not level load
// This could even override existing colormaps I believe // This could even override existing colormaps I believe
// -- Monster Iestyn 14/06/18 // -- Monster Iestyn 14/06/18
for (secnum = -1; (secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0 ;) {
extracolormap_t *source;
if (!udmf)
source = sides[line->sidenum[0]].colormap_data;
else
{ {
if (!line->args[1])
source = line->frontsector->extra_colormap;
else
{
INT32 sourcesec = P_FindSectorFromTag(line->args[1], -1);
if (sourcesec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 447 Executor: Can't find sector with source colormap (tag %d)!\n", line->args[1]);
return;
}
source = sectors[sourcesec].extra_colormap;
}
}
for (secnum = -1; (secnum = P_FindSectorFromTag(line->args[0], secnum)) >= 0;)
{
if (sectors[secnum].colormap_protected)
continue;
P_ResetColormapFader(&sectors[secnum]); P_ResetColormapFader(&sectors[secnum]);
if (line->flags & ML_EFFECT3) // relative calc if (line->args[2] & TMCF_RELATIVE)
{ {
extracolormap_t *exc = R_AddColormaps( extracolormap_t *target = (!udmf && (line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF) ?
(line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF ? sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap; // use back colormap instead of target sector
sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap, // use back colormap instead of target sector
sides[line->sidenum[0]].colormap_data,
line->flags & ML_EFFECT1, // subtract R
line->flags & ML_NOCLIMB, // subtract G
line->flags & ML_EFFECT2, // subtract B
false, // subtract A (no flag for this, just pass negative alpha)
line->flags & ML_EFFECT1, // subtract FadeR
line->flags & ML_NOCLIMB, // subtract FadeG
line->flags & ML_EFFECT2, // subtract FadeB
false, // subtract FadeA (no flag for this, just pass negative alpha)
false, // subtract FadeStart (we ran out of flags)
false, // subtract FadeEnd (we ran out of flags)
false, // ignore Flags (we ran out of flags)
line->flags & ML_DONTPEGBOTTOM,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0,
false);
if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) extracolormap_t *exc = R_AddColormaps(
{ target,
exc->colormap = R_CreateLightTable(exc); source,
R_AddColormapToList(exc); line->args[2] & TMCF_SUBLIGHTR,
sectors[secnum].extra_colormap = exc; line->args[2] & TMCF_SUBLIGHTG,
} line->args[2] & TMCF_SUBLIGHTB,
else line->args[2] & TMCF_SUBLIGHTA,
Z_Free(exc); line->args[2] & TMCF_SUBFADER,
} line->args[2] & TMCF_SUBFADEG,
else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) line->args[2] & TMCF_SUBFADEB,
{ line->args[2] & TMCF_SUBFADEA,
extracolormap_t *exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false); line->args[2] & TMCF_SUBFADESTART,
exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0)); line->args[2] & TMCF_SUBFADEEND,
exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0)); line->args[2] & TMCF_IGNOREFLAGS,
false);
if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc)))
{ {
@ -3471,10 +3462,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
Z_Free(exc); Z_Free(exc);
} }
else else
sectors[secnum].extra_colormap = sides[line->sidenum[0]].colormap_data; sectors[secnum].extra_colormap = source;
} }
break; break;
}
case 448: // Change skybox viewpoint/centerpoint case 448: // Change skybox viewpoint/centerpoint
if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB))
{ {
@ -3748,15 +3739,35 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
} }
case 455: // Fade colormap case 455: // Fade colormap
for (secnum = -1; (secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0 ;) {
extracolormap_t *dest;
if (!udmf)
dest = sides[line->sidenum[0]].colormap_data;
else
{
if (!line->args[1])
dest = line->frontsector->extra_colormap;
else
{
INT32 destsec = P_FindSectorFromTag(line->args[1], -1);
if (destsec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", line->args[1]);
return;
}
dest = sectors[destsec].extra_colormap;
}
}
for (secnum = -1; (secnum = P_FindSectorFromTag(line->args[0], secnum)) >= 0;)
{ {
extracolormap_t *source_exc, *dest_exc, *exc; extracolormap_t *source_exc, *dest_exc, *exc;
INT32 speed = (INT32)((line->flags & ML_DONTPEGBOTTOM) || !sides[line->sidenum[0]].rowoffset) && line->sidenum[1] != 0xFFFF ?
abs(sides[line->sidenum[1]].rowoffset >> FRACBITS)
: abs(sides[line->sidenum[0]].rowoffset >> FRACBITS);
// Prevent continuous execs from interfering on an existing fade if (sectors[secnum].colormap_protected)
if (!(line->flags & ML_EFFECT5) continue;
// Don't interrupt ongoing fade
if (!(line->args[3] & TMCF_OVERRIDE)
&& sectors[secnum].fadecolormapdata) && sectors[secnum].fadecolormapdata)
//&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2))
{ {
@ -3764,19 +3775,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
continue; continue;
} }
if (line->flags & ML_TFERLINE) // use back colormap instead of target sector if (!udmf && (line->flags & ML_TFERLINE)) // use back colormap instead of target sector
sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ?
sides[line->sidenum[1]].colormap_data : NULL; sides[line->sidenum[1]].colormap_data : NULL;
exc = sectors[secnum].extra_colormap; exc = sectors[secnum].extra_colormap;
if (!(line->flags & ML_BOUNCY) // BOUNCY: Do not override fade from default rgba if (!(line->args[3] & TMCF_FROMBLACK) // Override fade from default rgba
&& !R_CheckDefaultColormap(sides[line->sidenum[0]].colormap_data, true, false, false) && !R_CheckDefaultColormap(dest, true, false, false)
&& R_CheckDefaultColormap(exc, true, false, false)) && R_CheckDefaultColormap(exc, true, false, false))
{ {
exc = R_CopyColormap(exc, false); exc = R_CopyColormap(exc, false);
exc->rgba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); exc->rgba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba));
//exc->fadergba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); //exc->fadergba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba));
if (!(source_exc = R_GetColormapFromList(exc))) if (!(source_exc = R_GetColormapFromList(exc)))
{ {
@ -3792,35 +3803,26 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
else else
source_exc = exc ? exc : R_GetDefaultColormap(); source_exc = exc ? exc : R_GetDefaultColormap();
if (line->flags & ML_EFFECT3) // relative calc if (line->args[3] & TMCF_RELATIVE)
{ {
exc = R_AddColormaps( exc = R_AddColormaps(
source_exc, source_exc,
sides[line->sidenum[0]].colormap_data, dest,
line->flags & ML_EFFECT1, // subtract R line->args[3] & TMCF_SUBLIGHTR,
line->flags & ML_NOCLIMB, // subtract G line->args[3] & TMCF_SUBLIGHTG,
line->flags & ML_EFFECT2, // subtract B line->args[3] & TMCF_SUBLIGHTB,
false, // subtract A (no flag for this, just pass negative alpha) line->args[3] & TMCF_SUBLIGHTA,
line->flags & ML_EFFECT1, // subtract FadeR line->args[3] & TMCF_SUBFADER,
line->flags & ML_NOCLIMB, // subtract FadeG line->args[3] & TMCF_SUBFADEG,
line->flags & ML_EFFECT2, // subtract FadeB line->args[3] & TMCF_SUBFADEB,
false, // subtract FadeA (no flag for this, just pass negative alpha) line->args[3] & TMCF_SUBFADEA,
false, // subtract FadeStart (we ran out of flags) line->args[3] & TMCF_SUBFADESTART,
false, // subtract FadeEnd (we ran out of flags) line->args[3] & TMCF_SUBFADEEND,
false, // ignore Flags (we ran out of flags) line->args[3] & TMCF_IGNOREFLAGS,
line->flags & ML_DONTPEGBOTTOM,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0,
false); false);
} }
else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets)
{
exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false);
exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0));
exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0));
}
else else
exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false); exc = R_CopyColormap(dest, false);
if (!(dest_exc = R_GetColormapFromList(exc))) if (!(dest_exc = R_GetColormapFromList(exc)))
{ {
@ -3831,13 +3833,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
else else
Z_Free(exc); Z_Free(exc);
Add_ColormapFader(&sectors[secnum], source_exc, dest_exc, (line->flags & ML_EFFECT4), // tic-based timing Add_ColormapFader(&sectors[secnum], source_exc, dest_exc, true, // tic-based timing
speed); line->args[2]);
} }
break; break;
}
case 456: // Stop fade colormap case 456: // Stop fade colormap
for (secnum = -1; (secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0 ;) for (secnum = -1; (secnum = P_FindSectorFromTag(line->args[0], secnum)) >= 0 ;)
P_ResetColormapFader(&sectors[secnum]); P_ResetColormapFader(&sectors[secnum]);
break; break;
@ -4027,6 +4029,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
} }
break; break;
case 465: // Set linedef executor delay
{
INT32 linenum;
if (!udmf)
break;
for (linenum = -1; (linenum = P_FindLineFromTag(line->args[0], linenum)) >= 0 ;)
{
if (line->args[2])
lines[linenum].executordelay += line->args[1];
else
lines[linenum].executordelay = line->args[1];
}
}
break;
case 480: // Polyobj_DoorSlide case 480: // Polyobj_DoorSlide
case 481: // Polyobj_DoorSwing case 481: // Polyobj_DoorSwing
PolyDoor(line); PolyDoor(line);
@ -5890,7 +5909,7 @@ static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t c
raise->ceilingtop = ceilingtop; raise->ceilingtop = ceilingtop;
raise->ceilingbottom = ceilingbottom; raise->ceilingbottom = ceilingbottom;
raise->basespeed = speed; raise->basespeed = speed;
if (lower) if (lower)
raise->flags |= RF_REVERSE; raise->flags |= RF_REVERSE;
@ -6133,7 +6152,7 @@ static void P_RunLevelLoadExecutors(void)
* by P_SpawnSlopes or P_LoadThings. This was split off from * by P_SpawnSlopes or P_LoadThings. This was split off from
* P_SpawnSpecials, in case you couldn't tell. * P_SpawnSpecials, in case you couldn't tell.
* *
* \sa P_SpawnSpecials, P_InitTagLists * \sa P_SpawnSpecials
* \author Monster Iestyn * \author Monster Iestyn
*/ */
void P_InitSpecials(void) void P_InitSpecials(void)
@ -6164,8 +6183,6 @@ void P_InitSpecials(void)
// Set globalweather // Set globalweather
globalweather = mapheaderinfo[gamemap-1]->weather; globalweather = mapheaderinfo[gamemap-1]->weather;
P_InitTagLists(); // Create xref tables for tags
} }
static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs) static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs)
@ -7145,8 +7162,32 @@ void P_SpawnSpecials(boolean fromnetsave)
break; break;
case 606: // HACK! Copy colormaps. Just plain colormaps. case 606: // HACK! Copy colormaps. Just plain colormaps.
for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0;)
sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data; {
extracolormap_t *exc;
if (sectors[s].colormap_protected)
continue;
if (!udmf)
exc = sides[lines[i].sidenum[0]].colormap_data;
else
{
if (!lines[i].args[1])
exc = lines[i].frontsector->extra_colormap;
else
{
INT32 sourcesec = P_FindSectorFromTag(lines[i].args[1], -1);
if (sourcesec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 606: Can't find sector with source colormap (tag %d)!\n", lines[i].args[1]);
return;
}
exc = sectors[sourcesec].extra_colormap;
}
}
sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = exc;
}
break; break;
default: default:
@ -8109,7 +8150,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor
d->destlightlevel = -1; d->destlightlevel = -1;
// Set a separate thinker for colormap fading // Set a separate thinker for colormap fading
if (docolormap && !(rover->flags & FF_NOSHADE) && sectors[rover->secnum].spawn_extra_colormap) if (docolormap && !(rover->flags & FF_NOSHADE) && sectors[rover->secnum].spawn_extra_colormap && !sectors[rover->secnum].colormap_protected)
{ {
extracolormap_t *dest_exc, extracolormap_t *dest_exc,
*source_exc = sectors[rover->secnum].extra_colormap ? sectors[rover->secnum].extra_colormap : R_GetDefaultColormap(); *source_exc = sectors[rover->secnum].extra_colormap ? sectors[rover->secnum].extra_colormap : R_GetDefaultColormap();

View File

@ -5536,7 +5536,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
if ((!(gametyperules & GTR_TEAMFLAGS) || !player->gotflag) && !player->exiting) if ((!(gametyperules & GTR_TEAMFLAGS) || !player->gotflag) && !player->exiting)
{ {
if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP && player->charability != CA_THOK)
{ {
fixed_t potentialmomz; fixed_t potentialmomz;
if (player->charability == CA_SLOWFALL) if (player->charability == CA_SLOWFALL)
@ -7975,20 +7975,13 @@ void P_MovePlayer(player_t *player)
// Locate the capsule for this mare. // Locate the capsule for this mare.
else if (maptol & TOL_NIGHTS) else if (maptol & TOL_NIGHTS)
{ {
if ((player->powers[pw_carry] == CR_NIGHTSMODE) if (P_PlayerFullbright(player))
&& (player->exiting
|| !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6]))) // Note the < instead of <=
{ {
skin_t *skin = ((skin_t *)(player->mo->skin)); player->mo->color = ((skin_t *)player->mo->skin)->supercolor
if (( skin->flags & (SF_SUPER|SF_NONIGHTSSUPER) ) == SF_SUPER) + ((player->nightstime == player->startedtime)
{ ? 4
player->mo->color = skin->supercolor : abs((((signed)leveltime >> 1) % 9) - 4)); // This is where super flashing is handled.
+ ((player->nightstime == player->startedtime) G_GhostAddColor(GHC_SUPER);
? 4
: abs((((signed)leveltime >> 1) % 9) - 4)); // This is where super flashing is handled.
G_GhostAddColor(GHC_SUPER);
}
} }
if (!player->capsule && !player->bonustime) if (!player->capsule && !player->bonustime)
@ -12895,3 +12888,12 @@ void P_ForceLocalAngle(player_t *player, angle_t angle)
else if (player == &players[secondarydisplayplayer]) else if (player == &players[secondarydisplayplayer])
localangle2 = angle; localangle2 = angle;
} }
boolean P_PlayerFullbright(player_t *player)
{
return (player->powers[pw_super]
|| ((player->powers[pw_carry] == CR_NIGHTSMODE && (((skin_t *)player->mo->skin)->flags & (SF_SUPER|SF_NONIGHTSSUPER)) == SF_SUPER) // Super colours? Super bright!
&& (player->exiting
|| !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))); // Note the < instead of <=
}

View File

@ -2080,7 +2080,7 @@ extracolormap_t *R_ColormapForName(char *name)
#endif #endif
// //
// R_CreateColormap // R_CreateColormapFromLinedef
// //
// This is a more GL friendly way of doing colormaps: Specify colormap // This is a more GL friendly way of doing colormaps: Specify colormap
// data in a special linedef's texture areas and use that to generate // data in a special linedef's texture areas and use that to generate
@ -2219,10 +2219,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
return lighttable; return lighttable;
} }
extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3)
{ {
extracolormap_t *extra_colormap, *exc;
// default values // default values
UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25; UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25;
UINT32 fadestart = 0, fadeend = 31; UINT32 fadestart = 0, fadeend = 31;
@ -2345,6 +2343,13 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
rgba = R_PutRgbaRGBA(cr, cg, cb, ca); rgba = R_PutRgbaRGBA(cr, cg, cb, ca);
fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa); fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa);
return R_CreateColormap(rgba, fadergba, fadestart, fadeend, flags);
}
extracolormap_t *R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags)
{
extracolormap_t *extra_colormap;
// Did we just make a default colormap? // Did we just make a default colormap?
#ifdef EXTRACOLORMAPLUMPS #ifdef EXTRACOLORMAPLUMPS
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, flags, LUMPERROR)) if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, flags, LUMPERROR))
@ -2356,17 +2361,16 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
// Look for existing colormaps // Look for existing colormaps
#ifdef EXTRACOLORMAPLUMPS #ifdef EXTRACOLORMAPLUMPS
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags, LUMPERROR); extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags, LUMPERROR);
#else #else
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags); extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags);
#endif #endif
if (exc) if (extra_colormap)
return exc; return extra_colormap;
CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%x) fadergba(%x)\n", rgba, fadergba);
cr, cg, cb, ca, cfr, cfg, cfb, cfa);
extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL); extra_colormap = Z_Calloc(sizeof(*extra_colormap), PU_LEVEL, NULL);
extra_colormap->fadestart = (UINT16)fadestart; extra_colormap->fadestart = (UINT16)fadestart;
extra_colormap->fadeend = (UINT16)fadeend; extra_colormap->fadeend = (UINT16)fadeend;
@ -2398,7 +2402,6 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
boolean subR, boolean subG, boolean subB, boolean subA, boolean subR, boolean subG, boolean subB, boolean subA,
boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags, boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags,
boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
boolean lighttable) boolean lighttable)
{ {
INT16 red, green, blue, alpha; INT16 red, green, blue, alpha;
@ -2434,7 +2437,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
* R_GetRgbaB(exc_addend->rgba) * R_GetRgbaB(exc_addend->rgba)
, 255), 0); , 255), 0);
alpha = useAltAlpha ? altAlpha : R_GetRgbaA(exc_addend->rgba); alpha = R_GetRgbaA(exc_addend->rgba);
alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0); alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0);
exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha); exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha);
@ -2461,8 +2464,8 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
* R_GetRgbaB(exc_addend->fadergba) * R_GetRgbaB(exc_addend->fadergba)
, 255), 0); , 255), 0);
alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba); alpha = R_GetRgbaA(exc_addend->fadergba);
if (alpha == 25 && !useAltAlpha && !R_GetRgbaRGB(exc_addend->fadergba)) if (alpha == 25 && !R_GetRgbaRGB(exc_addend->fadergba))
alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case
alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0); alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0);

View File

@ -149,13 +149,31 @@ boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgb
boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams); boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams);
extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap);
typedef enum
{
TMCF_RELATIVE = 1,
TMCF_SUBLIGHTR = 1<<1,
TMCF_SUBLIGHTG = 1<<2,
TMCF_SUBLIGHTB = 1<<3,
TMCF_SUBLIGHTA = 1<<4,
TMCF_SUBFADER = 1<<5,
TMCF_SUBFADEG = 1<<6,
TMCF_SUBFADEB = 1<<7,
TMCF_SUBFADEA = 1<<8,
TMCF_SUBFADESTART = 1<<9,
TMCF_SUBFADEEND = 1<<10,
TMCF_IGNOREFLAGS = 1<<11,
TMCF_FROMBLACK = 1<<12,
TMCF_OVERRIDE = 1<<13,
} textmapcolormapflags_t;
lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3);
extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags);
extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
boolean subR, boolean subG, boolean subB, boolean subA, boolean subR, boolean subG, boolean subB, boolean subA,
boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags, boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags,
boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
boolean lighttable); boolean lighttable);
#ifdef EXTRACOLORMAPLUMPS #ifdef EXTRACOLORMAPLUMPS
extracolormap_t *R_ColormapForName(char *name); extracolormap_t *R_ColormapForName(char *name);

View File

@ -333,6 +333,7 @@ typedef struct sector_s
// per-sector colormaps! // per-sector colormaps!
extracolormap_t *extra_colormap; extracolormap_t *extra_colormap;
boolean colormap_protected;
// This points to the master's floorheight, so it can be changed in realtime! // This points to the master's floorheight, so it can be changed in realtime!
fixed_t *gravity; // per-sector gravity fixed_t *gravity; // per-sector gravity
@ -374,6 +375,9 @@ typedef enum
#define HORIZONSPECIAL 41 #define HORIZONSPECIAL 41
#define NUMLINEARGS 6
#define NUMLINESTRINGARGS 2
typedef struct line_s typedef struct line_s
{ {
// Vertices, from v1 to v2. // Vertices, from v1 to v2.
@ -386,9 +390,13 @@ typedef struct line_s
INT16 flags; INT16 flags;
INT16 special; INT16 special;
INT16 tag; INT16 tag;
INT32 args[NUMLINEARGS];
char *stringargs[NUMLINESTRINGARGS];
// Visual appearance: sidedefs. // Visual appearance: sidedefs.
UINT16 sidenum[2]; // sidenum[1] will be 0xffff if one-sided UINT16 sidenum[2]; // sidenum[1] will be 0xffff if one-sided
fixed_t alpha; // translucency
INT32 executordelay;
fixed_t bbox[4]; // bounding box for the extent of the linedef fixed_t bbox[4]; // bounding box for the extent of the linedef

View File

@ -134,6 +134,7 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
#define NUM_PALETTE_ENTRIES 256 #define NUM_PALETTE_ENTRIES 256
static UINT8** translationtablecache[MAXSKINS + 7] = {NULL}; static UINT8** translationtablecache[MAXSKINS + 7] = {NULL};
UINT8 skincolor_modified[MAXSKINCOLORS];
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
@ -362,6 +363,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
{ {
UINT8* ret; UINT8* ret;
INT32 skintableindex; INT32 skintableindex;
INT32 i;
// Adjust if we want the default colormap // Adjust if we want the default colormap
switch (skinnum) switch (skinnum)
@ -385,6 +387,15 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
// Get colormap // Get colormap
ret = translationtablecache[skintableindex][color]; ret = translationtablecache[skintableindex][color];
// Rebuild the cache if necessary
if (skincolor_modified[color])
{
for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++)
if (translationtablecache[i] && translationtablecache[i][color])
R_GenerateTranslationColormap(translationtablecache[i][color], i>=MAXSKINS ? MAXSKINS-i-1 : i, color);
skincolor_modified[color] = false;
}
} }
else ret = NULL; else ret = NULL;
@ -427,12 +438,12 @@ UINT16 R_GetColorByName(const char *name)
for (color = 1; color < numskincolors; color++) for (color = 1; color < numskincolors; color++)
if (!stricmp(skincolors[color].name, name)) if (!stricmp(skincolors[color].name, name))
return color; return color;
return SKINCOLOR_GREEN; return SKINCOLOR_NONE;
} }
UINT16 R_GetSuperColorByName(const char *name) UINT16 R_GetSuperColorByName(const char *name)
{ {
UINT16 i, color = SKINCOLOR_SUPERGOLD1; UINT16 i, color = SKINCOLOR_NONE;
char *realname = Z_Malloc(MAXCOLORNAME+1, PU_STATIC, NULL); char *realname = Z_Malloc(MAXCOLORNAME+1, PU_STATIC, NULL);
snprintf(realname, MAXCOLORNAME+1, "Super %s 1", name); snprintf(realname, MAXCOLORNAME+1, "Super %s 1", name);
for (i = 1; i < numskincolors; i++) for (i = 1; i < numskincolors; i++)

View File

@ -117,6 +117,9 @@ void R_FlushTranslationColormapCache(void);
UINT16 R_GetColorByName(const char *name); UINT16 R_GetColorByName(const char *name);
UINT16 R_GetSuperColorByName(const char *name); UINT16 R_GetSuperColorByName(const char *name);
// Color ramp modification should force a recache
extern UINT8 skincolor_modified[];
// Custom player skin translation // Custom player skin translation
void R_InitViewBuffer(INT32 width, INT32 height); void R_InitViewBuffer(INT32 width, INT32 height);
void R_InitViewBorder(void); void R_InitViewBorder(void);

View File

@ -318,6 +318,24 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y)
0; 0;
} }
// This version uses 64-bit variables to avoid overflows with large values.
// Currently used only by OpenGL rendering.
angle_t R_PointToAngle64(INT64 x, INT64 y)
{
return (y -= viewy, (x -= viewx) || y) ?
x >= 0 ?
y >= 0 ?
(x > y) ? tantoangle[SlopeDivEx(y,x)] : // octant 0
ANGLE_90-tantoangle[SlopeDivEx(x,y)] : // octant 1
x > (y = -y) ? 0-tantoangle[SlopeDivEx(y,x)] : // octant 8
ANGLE_270+tantoangle[SlopeDivEx(x,y)] : // octant 7
y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDivEx(y,x)] : // octant 3
ANGLE_90 + tantoangle[SlopeDivEx(x,y)] : // octant 2
(x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDivEx(y,x)] : // octant 4
ANGLE_270-tantoangle[SlopeDivEx(x,y)] : // octant 5
0;
}
angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y) angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
{ {
return (y -= pviewy, (x -= pviewx) || y) ? return (y -= pviewy, (x -= pviewx) || y) ?

View File

@ -63,6 +63,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node); INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line); INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
angle_t R_PointToAngle(fixed_t x, fixed_t y); angle_t R_PointToAngle(fixed_t x, fixed_t y);
angle_t R_PointToAngle64(INT64 x, INT64 y);
angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1); angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1);
fixed_t R_PointToDist(fixed_t x, fixed_t y); fixed_t R_PointToDist(fixed_t x, fixed_t y);

View File

@ -274,6 +274,11 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
} }
} }
transnum_t R_GetLinedefTransTable(fixed_t alpha)
{
return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1);
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
size_t pindex; size_t pindex;
@ -300,31 +305,24 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
texnum = R_GetTextureNum(curline->sidedef->midtexture); texnum = R_GetTextureNum(curline->sidedef->midtexture);
windowbottom = windowtop = sprbotscreen = INT32_MAX; windowbottom = windowtop = sprbotscreen = INT32_MAX;
// hack translucent linedef types (900-909 for transtables 1-9)
ldef = curline->linedef; ldef = curline->linedef;
switch (ldef->special) if (!ldef->alpha)
return;
if (ldef->alpha > 0 && ldef->alpha < FRACUNIT)
{ {
case 900: dc_transmap = transtables + ((R_GetLinedefTransTable(ldef->alpha) - 1) << FF_TRANSSHIFT);
case 901: colfunc = colfuncs[COLDRAWFUNC_FUZZY];
case 902:
case 903:
case 904:
case 905:
case 906:
case 907:
case 908:
dc_transmap = transtables + ((ldef->special-900)<<FF_TRANSSHIFT);
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
break;
case 909:
colfunc = colfuncs[COLDRAWFUNC_FOG];
windowtop = frontsector->ceilingheight;
windowbottom = frontsector->floorheight;
break;
default:
colfunc = colfuncs[BASEDRAWFUNC];
break;
} }
else if (ldef->special == 909)
{
colfunc = colfuncs[COLDRAWFUNC_FOG];
windowtop = frontsector->ceilingheight;
windowbottom = frontsector->floorheight;
}
else
colfunc = colfuncs[BASEDRAWFUNC];
if (curline->polyseg && curline->polyseg->translucency > 0) if (curline->polyseg && curline->polyseg->translucency > 0)
{ {

View File

@ -18,6 +18,7 @@
#pragma interface #pragma interface
#endif #endif
transnum_t R_GetLinedefTransTable(fixed_t alpha);
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2);
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor);
void R_StoreWallRange(INT32 start, INT32 stop); void R_StoreWallRange(INT32 start, INT32 stop);

View File

@ -464,12 +464,19 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
GETINT(contangle) GETINT(contangle)
#undef GETINT #undef GETINT
#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value); #define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) \
{ \
UINT16 color = R_GetColorByName(value); \
skin->field = (color ? color : SKINCOLOR_GREEN); \
}
GETSKINCOLOR(prefcolor) GETSKINCOLOR(prefcolor)
GETSKINCOLOR(prefoppositecolor) GETSKINCOLOR(prefoppositecolor)
#undef GETSKINCOLOR #undef GETSKINCOLOR
else if (!stricmp(stoken, "supercolor")) else if (!stricmp(stoken, "supercolor"))
skin->supercolor = R_GetSuperColorByName(value); {
UINT16 color = R_GetSuperColorByName(value);
skin->supercolor = (color ? color : SKINCOLOR_SUPERGOLD1);
}
#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); #define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value));
GETFLOAT(jumpfactor) GETFLOAT(jumpfactor)

View File

@ -52,6 +52,8 @@ extern size_t numspritelumps, max_spritelumps;
// //
// Lookup tables for map data. // Lookup tables for map data.
// //
extern boolean udmf;
extern size_t numsprites; extern size_t numsprites;
extern spritedef_t *sprites; extern spritedef_t *sprites;

View File

@ -2773,7 +2773,7 @@ boolean R_ThingVisible (mobj_t *thing)
return (!( return (!(
thing->sprite == SPR_NULL || thing->sprite == SPR_NULL ||
( thing->flags2 & (MF2_DONTDRAW) ) || ( thing->flags2 & (MF2_DONTDRAW) ) ||
thing == r_viewmobj (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing)))
)); ));
} }

View File

@ -60,6 +60,7 @@ static void Command_RestartAudio_f(void);
static void GameMIDIMusic_OnChange(void); static void GameMIDIMusic_OnChange(void);
static void GameSounds_OnChange(void); static void GameSounds_OnChange(void);
static void GameDigiMusic_OnChange(void); static void GameDigiMusic_OnChange(void);
static void MusicPref_OnChange(void);
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
static void ModFilter_OnChange(void); static void ModFilter_OnChange(void);
@ -129,6 +130,14 @@ consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_O
consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gamesounds = {"sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameSounds_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gamesounds = {"sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameSounds_OnChange, 0, NULL, NULL, 0, 0, NULL};
// Music preference
static CV_PossibleValue_t cons_musicpref_t[] = {
{0, "Digital"},
{1, "MIDI"},
{0, NULL}
};
consvar_t cv_musicpref = {"musicpref", "Digital", CV_SAVE|CV_CALL|CV_NOINIT, cons_musicpref_t, MusicPref_OnChange, 0, NULL, NULL, 0, 0, NULL};
// Window focus sound sytem toggles // Window focus sound sytem toggles
consvar_t cv_playmusicifunfocused = {"playmusicifunfocused", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_playmusicifunfocused = {"playmusicifunfocused", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playsoundsifunfocused = {"playsoundsifunfocused", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_playsoundsifunfocused = {"playsoundsifunfocused", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -301,6 +310,7 @@ void S_RegisterSoundStuff(void)
CV_RegisterVar(&cv_gamesounds); CV_RegisterVar(&cv_gamesounds);
CV_RegisterVar(&cv_gamedigimusic); CV_RegisterVar(&cv_gamedigimusic);
CV_RegisterVar(&cv_gamemidimusic); CV_RegisterVar(&cv_gamemidimusic);
CV_RegisterVar(&cv_musicpref);
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
CV_RegisterVar(&cv_modfilter); CV_RegisterVar(&cv_modfilter);
#endif #endif
@ -1847,19 +1857,6 @@ const char *S_MusicName(void)
return music_name; return music_name;
} }
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping)
{
if (!I_SongPlaying())
return false;
strncpy(mname, music_name, 7);
mname[6] = 0;
*mflags = music_flags;
*looping = music_looping;
return (boolean)mname[0];
}
boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi) boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi)
{ {
return ( return (
@ -2100,6 +2097,8 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
boolean mapmuschanged = false; boolean mapmuschanged = false;
musicstack_t *result; musicstack_t *result;
musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL); musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
boolean currentmidi = (I_SongType() == MU_MID || I_SongType() == MU_MID_EX);
boolean midipref = cv_musicpref.value;
if (status) if (status)
result = S_GetMusicStackEntry(status, fromfirst, -1); result = S_GetMusicStackEntry(status, fromfirst, -1);
@ -2154,7 +2153,8 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
return false; return false;
} }
if (strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it if (strncmp(entry->musname, S_MusicName(), 7) || // don't restart music if we're already playing it
(midipref != currentmidi && S_PrefAvailable(midipref, entry->musname))) // but do if the user's preference has changed
{ {
if (music_stack_fadeout) if (music_stack_fadeout)
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0); S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0);
@ -2201,10 +2201,12 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
static lumpnum_t S_GetMusicLumpNum(const char *mname) static lumpnum_t S_GetMusicLumpNum(const char *mname)
{ {
if (!S_DigMusicDisabled() && S_DigExists(mname)) boolean midipref = cv_musicpref.value;
return W_GetNumForName(va("o_%s", mname));
else if (!S_MIDIMusicDisabled() && S_MIDIExists(mname)) if (S_PrefAvailable(midipref, mname))
return W_GetNumForName(va("d_%s", mname)); return W_GetNumForName(va(midipref ? "d_%s":"o_%s", mname));
else if (S_PrefAvailable(!midipref, mname))
return W_GetNumForName(va(midipref ? "o_%s":"d_%s", mname));
else else
return LUMPERROR; return LUMPERROR;
} }
@ -2330,6 +2332,8 @@ static void S_ChangeMusicToQueue(void)
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms) void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
{ {
char newmusic[7]; char newmusic[7];
boolean currentmidi = (I_SongType() == MU_MID || I_SongType() == MU_MID_EX);
boolean midipref = cv_musicpref.value;
if (S_MusicDisabled()) if (S_MusicDisabled())
return; return;
@ -2359,7 +2363,8 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
I_FadeSong(0, prefadems, S_ChangeMusicToQueue); I_FadeSong(0, prefadems, S_ChangeMusicToQueue);
return; return;
} }
else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET)) else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET) ||
(midipref != currentmidi && S_PrefAvailable(midipref, newmusic)))
{ {
CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic); CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic);
@ -2665,32 +2670,24 @@ void GameDigiMusic_OnChange(void)
digital_disabled = false; digital_disabled = false;
I_StartupSound(); // will return early if initialised I_StartupSound(); // will return early if initialised
I_InitMusic(); I_InitMusic();
S_StopMusic();
if (Playing()) if (Playing())
P_RestoreMusic(&players[consoleplayer]); P_RestoreMusic(&players[consoleplayer]);
else else if ((!cv_musicpref.value || midi_disabled) && S_DigExists("_clear"))
S_ChangeMusicInternal("_clear", false); S_ChangeMusicInternal("_clear", false);
} }
else else
{ {
digital_disabled = true; digital_disabled = true;
if (S_MusicType() != MU_MID) if (S_MusicType() != MU_MID && S_MusicType() != MU_MID_EX)
{ {
if (midi_disabled) S_StopMusic();
S_StopMusic(); if (!midi_disabled)
else
{ {
char mmusic[7]; if (Playing())
UINT16 mflags; P_RestoreMusic(&players[consoleplayer]);
boolean looping;
if (S_MusicInfo(mmusic, &mflags, &looping) && S_MIDIExists(mmusic))
{
S_StopMusic();
S_ChangeMusic(mmusic, mflags, looping);
}
else else
S_StopMusic(); S_ChangeMusicInternal("_clear", false);
} }
} }
} }
@ -2708,9 +2705,10 @@ void GameMIDIMusic_OnChange(void)
midi_disabled = false; midi_disabled = false;
I_StartupSound(); // will return early if initialised I_StartupSound(); // will return early if initialised
I_InitMusic(); I_InitMusic();
if (Playing()) if (Playing())
P_RestoreMusic(&players[consoleplayer]); P_RestoreMusic(&players[consoleplayer]);
else else if ((cv_musicpref.value || digital_disabled) && S_MIDIExists("_clear"))
S_ChangeMusicInternal("_clear", false); S_ChangeMusicInternal("_clear", false);
} }
else else
@ -2718,26 +2716,30 @@ void GameMIDIMusic_OnChange(void)
midi_disabled = true; midi_disabled = true;
if (S_MusicType() == MU_MID || S_MusicType() == MU_MID_EX) if (S_MusicType() == MU_MID || S_MusicType() == MU_MID_EX)
{ {
if (digital_disabled) S_StopMusic();
S_StopMusic(); if (!digital_disabled)
else
{ {
char mmusic[7]; if (Playing())
UINT16 mflags; P_RestoreMusic(&players[consoleplayer]);
boolean looping;
if (S_MusicInfo(mmusic, &mflags, &looping) && S_DigExists(mmusic))
{
S_StopMusic();
S_ChangeMusic(mmusic, mflags, looping);
}
else else
S_StopMusic(); S_ChangeMusicInternal("_clear", false);
} }
} }
} }
} }
void MusicPref_OnChange(void)
{
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio") ||
M_CheckParm("-nomidimusic") || M_CheckParm("-nodigmusic"))
return;
if (Playing())
P_RestoreMusic(&players[consoleplayer]);
else if (S_PrefAvailable(cv_musicpref.value, "_clear"))
S_ChangeMusicInternal("_clear", false);
}
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
void ModFilter_OnChange(void) void ModFilter_OnChange(void)
{ {

View File

@ -46,6 +46,7 @@ extern consvar_t cv_1upsound;
extern consvar_t cv_gamedigimusic; extern consvar_t cv_gamedigimusic;
extern consvar_t cv_gamemidimusic; extern consvar_t cv_gamemidimusic;
extern consvar_t cv_gamesounds; extern consvar_t cv_gamesounds;
extern consvar_t cv_musicpref;
extern consvar_t cv_playmusicifunfocused; extern consvar_t cv_playmusicifunfocused;
extern consvar_t cv_playsoundsifunfocused; extern consvar_t cv_playsoundsifunfocused;
@ -178,11 +179,16 @@ boolean S_MusicPaused(void);
boolean S_MusicNotInFocus(void); boolean S_MusicNotInFocus(void);
musictype_t S_MusicType(void); musictype_t S_MusicType(void);
const char *S_MusicName(void); const char *S_MusicName(void);
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping);
boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
#define S_DigExists(a) S_MusicExists(a, false, true) #define S_DigExists(a) S_MusicExists(a, false, true)
#define S_MIDIExists(a) S_MusicExists(a, true, false) #define S_MIDIExists(a) S_MusicExists(a, true, false)
// Returns whether the preferred format a (true = MIDI, false = Digital)
// exists and is enabled for musicname b
#define S_PrefAvailable(a, b) (a ? \
(!S_MIDIMusicDisabled() && S_MIDIExists(b)) : \
(!S_DigMusicDisabled() && S_DigExists(b)))
// //
// Music Effects // Music Effects
// //

View File

@ -1,6 +1,10 @@
# Declare SDL2 interface sources # Declare SDL2 interface sources
set(SRB2_CONFIG_SDL2_USEMIXER ON CACHE BOOL "Use SDL2_mixer or regular sdl sound") if(NOT ${SRB2_CONFIG_HAVE_MIXERX})
set(SRB2_CONFIG_SDL2_USEMIXER ON CACHE BOOL "Use SDL2_mixer or regular sdl sound")
else()
set(SRB2_CONFIG_SDL2_USEMIXER OFF)
endif()
if(${SRB2_CONFIG_SDL2_USEMIXER}) if(${SRB2_CONFIG_SDL2_USEMIXER})
if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
@ -22,6 +26,8 @@ if(${SRB2_CONFIG_SDL2_USEMIXER})
message(WARNING "You specified that SDL2_mixer is available, but it was not found. Falling back to sdl sound.") message(WARNING "You specified that SDL2_mixer is available, but it was not found. Falling back to sdl sound.")
set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) set(SRB2_SDL2_SOUNDIMPL sdl_sound.c)
endif() endif()
elseif(${MIXERX_FOUND})
set(SRB2_SDL2_SOUNDIMPL mixer_sound.c)
else() else()
set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) set(SRB2_SDL2_SOUNDIMPL sdl_sound.c)
endif() endif()
@ -156,6 +162,7 @@ if(${SDL2_FOUND})
SDL2_mixer SDL2_mixer
${GME_LIBRARIES} ${GME_LIBRARIES}
${OPENMPT_LIBRARIES} ${OPENMPT_LIBRARIES}
${MIXERX_LIBRARIES}
${PNG_LIBRARIES} ${PNG_LIBRARIES}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
${OPENGL_LIBRARIES} ${OPENGL_LIBRARIES}
@ -168,6 +175,7 @@ if(${SDL2_FOUND})
${SDL2_MIXER_LIBRARIES} ${SDL2_MIXER_LIBRARIES}
${GME_LIBRARIES} ${GME_LIBRARIES}
${OPENMPT_LIBRARIES} ${OPENMPT_LIBRARIES}
${MIXERX_LIBRARIES}
${PNG_LIBRARIES} ${PNG_LIBRARIES}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
${OPENGL_LIBRARIES} ${OPENGL_LIBRARIES}
@ -249,28 +257,33 @@ if(${SDL2_FOUND})
${SDL2_MIXER_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS}
${GME_INCLUDE_DIRS} ${GME_INCLUDE_DIRS}
${OPENMPT_INCLUDE_DIRS} ${OPENMPT_INCLUDE_DIRS}
${MIXERX_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}
${OPENGL_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS}
${CURL_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS}
) )
if(${SRB2_HAVE_MIXER}) if((${SRB2_HAVE_MIXER}) OR (${SRB2_HAVE_MIXERX}))
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER)
endif() endif()
target_compile_definitions(SRB2SDL2 PRIVATE target_compile_definitions(SRB2SDL2 PRIVATE
-DHAVE_SDL -DDDIRECTFULLSCREEN -DHAVE_SDL
) )
## strip debug symbols into separate file when using gcc ## strip debug symbols into separate file when using gcc.
if(CMAKE_COMPILER_IS_GNUCC) ## to be consistent with Makefile, don't generate for OS X.
if(${CMAKE_BUILD_TYPE} MATCHES Debug) if((CMAKE_COMPILER_IS_GNUCC) AND NOT (${CMAKE_SYSTEM} MATCHES Darwin))
if((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo))
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(OBJCOPY_ONLY_KEEP_DEBUG "--only-keep-debug")
endif()
message(STATUS "Will make separate debug symbols in *.debug") message(STATUS "Will make separate debug symbols in *.debug")
add_custom_command(TARGET SRB2SDL2 POST_BUILD add_custom_command(TARGET SRB2SDL2 POST_BUILD
COMMAND ${OBJCOPY} --only-keep-debug $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2> COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2>
COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE_NAME:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2> COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
) )
endif() endif()
endif() endif()
@ -284,6 +297,15 @@ if(${SDL2_FOUND})
install(TARGETS SRB2SDL2 SRB2SDL2 install(TARGETS SRB2SDL2 SRB2SDL2
RUNTIME DESTINATION . RUNTIME DESTINATION .
) )
if ((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo))
set(SRB2_DEBUG_INSTALL OFF CACHE BOOL "Insert *.debug file into the install directory or package.")
if (${SRB2_DEBUG_INSTALL})
install(FILES $<TARGET_FILE:SRB2SDL2>.debug
DESTINATION .
OPTIONAL
)
endif()
endif()
endif() endif()
if(${CMAKE_SYSTEM} MATCHES Windows) if(${CMAKE_SYSTEM} MATCHES Windows)
@ -297,6 +319,7 @@ if(${SDL2_FOUND})
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/bin HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/bin
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/x86_64-w64-mingw32/bin HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/x86_64-w64-mingw32/bin
HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86_64/mingw HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86_64/mingw
HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/x86_64-w64-mingw32/bin
) )
else() else()
find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}" find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}"
@ -304,6 +327,7 @@ if(${SDL2_FOUND})
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/bin HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/bin
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/i686-w64-mingw32/bin HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/i686-w64-mingw32/bin
HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86/mingw HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86/mingw
HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/i686-w64-mingw32/bin
) )
endif() endif()
else() else()
@ -313,6 +337,7 @@ if(${SDL2_FOUND})
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x64 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x64
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x64 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x64
HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86_64/mingw HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86_64/mingw
HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/x86_64-w64-mingw32/bin
) )
else() else()
find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}" find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}"
@ -320,6 +345,7 @@ if(${SDL2_FOUND})
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x86 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x86
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x86 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x86
HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86/mingw HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86/mingw
HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/i686-w64-mingw32/bin
) )
endif() endif()
endif() endif()
@ -343,6 +369,12 @@ if(${SDL2_FOUND})
if(${SRB2_CONFIG_HAVE_OPENMPT}) if(${SRB2_CONFIG_HAVE_OPENMPT})
getwinlib(libopenmpt "libopenmpt.dll") getwinlib(libopenmpt "libopenmpt.dll")
endif() endif()
if(${SRB2_CONFIG_HAVE_MIXERX})
getwinlib(SDL2_mixer_ext "SDL2_mixer_ext.dll")
getwinlib(libfluidsynth-2 "libfluidsynth-2.dll")
getwinlib(libgcc_s_sjlj-1 "libgcc_s_sjlj-1.dll")
getwinlib(libstdc++-6 "libstdc++-6.dll")
endif()
install(PROGRAMS install(PROGRAMS
${win_extra_dll_list} ${win_extra_dll_list}

View File

@ -1862,7 +1862,7 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
#else #else
I_Error I_Error
#endif #endif
(M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); (M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);
} }
#endif #endif
} }

View File

@ -141,7 +141,6 @@ static y_data data;
// graphics // graphics
static patch_t *bgpatch = NULL; // INTERSCR static patch_t *bgpatch = NULL; // INTERSCR
static patch_t *widebgpatch = NULL; // INTERSCW
static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK
static patch_t *interpic = NULL; // custom picture defined in map header static patch_t *interpic = NULL; // custom picture defined in map header
static boolean usetile; static boolean usetile;
@ -330,7 +329,7 @@ void Y_IntermissionDrawer(void)
safetorender = false; safetorender = false;
} }
if (!usebuffer || !safetorender) if (!safetorender)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
if (!safetorender) if (!safetorender)
@ -359,12 +358,11 @@ void Y_IntermissionDrawer(void)
else if (rendermode != render_soft && usebuffer) else if (rendermode != render_soft && usebuffer)
HWR_DrawIntermissionBG(); HWR_DrawIntermissionBG();
#endif #endif
else else if (bgpatch)
{ {
if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) fixed_t hs = vid.width * FRACUNIT / BASEVIDWIDTH;
V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, widebgpatch); fixed_t vs = vid.height * FRACUNIT / BASEVIDHEIGHT;
else if (bgpatch) V_DrawStretchyFixedPatch(0, 0, hs, vs, V_NOSCALEPATCH, bgpatch, NULL);
V_DrawScaledPatch(0, 0, 0, bgpatch);
} }
} }
else if (bgtile) else if (bgtile)
@ -1266,7 +1264,6 @@ void Y_StartIntermission(void)
data.coop.actnum = mapheaderinfo[gamemap-1]->actnum; data.coop.actnum = mapheaderinfo[gamemap-1]->actnum;
// get background patches // get background patches
widebgpatch = W_CachePatchName("INTERSCW", PU_PATCH);
bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); bgpatch = W_CachePatchName("INTERSCR", PU_PATCH);
// grab an interscreen if appropriate // grab an interscreen if appropriate
@ -2084,7 +2081,6 @@ static void Y_UnloadData(void)
// unload the background patches // unload the background patches
UNLOAD(bgpatch); UNLOAD(bgpatch);
UNLOAD(widebgpatch);
UNLOAD(bgtile); UNLOAD(bgtile);
UNLOAD(interpic); UNLOAD(interpic);
@ -2127,7 +2123,6 @@ static void Y_CleanupData(void)
{ {
// unload the background patches // unload the background patches
CLEANUP(bgpatch); CLEANUP(bgpatch);
CLEANUP(widebgpatch);
CLEANUP(bgtile); CLEANUP(bgtile);
CLEANUP(interpic); CLEANUP(interpic);

View File

@ -1,4 +1,4 @@
/client /client
/server /server
/server.log /*.log
/*.o /*.o

View File

@ -140,8 +140,8 @@ typedef struct
char port[8]; char port[8];
char name[32]; char name[32];
INT32 room; INT32 room;
char key[32]; // Secret key for linking dedicated servers to accounts
char version[8]; // format is: x.yy.z (like 1.30.2 or 1.31) char version[8]; // format is: x.yy.z (like 1.30.2 or 1.31)
char key[32]; // Secret key for linking dedicated servers to accounts
} ATTRPACK msg_server_t; } ATTRPACK msg_server_t;
typedef struct typedef struct

View File

@ -5,9 +5,10 @@
# Get LSB functions # Get LSB functions
. /lib/lsb/init-functions . /lib/lsb/init-functions
. /etc/default/rcS #. /etc/default/rcS
SRB2MS=/usr/local/bin/masterserver #SRB2MS=/usr/local/bin/masterserver
SRB2MS=./server
SRB2MS_PORT=28900 SRB2MS_PORT=28900
# Check that the package is still installed # Check that the package is still installed
@ -15,11 +16,9 @@ SRB2MS_PORT=28900
case "$1" in case "$1" in
start) start)
log_begin_msg "Starting SRB2MS..." log_begin_msg "Starting SRB2MS...\n"
umask 002 umask 002
if start-stop-daemon --start \ if exec $SRB2MS $SRB2MS_PORT & then
--exec $SRB2MS \
-- $SRB2MS_PORT; then
log_end_msg 0 log_end_msg 0
else else
log_end_msg $? log_end_msg $?
@ -27,11 +26,11 @@ case "$1" in
;; ;;
stop) stop)
log_begin_msg "Stopping SRB2MS..." log_begin_msg "Stopping SRB2MS...\n"
if start-stop-daemon --stop --exec $SRB2MS; then if killall $SRB2MS -q & then
log_end_msg 0 log_end_msg 0
else else
log_end_msg $? log_end_msg $?
fi fi
;; ;;
@ -40,7 +39,7 @@ case "$1" in
;; ;;
*) *)
e cho "Usage: /etc/init.d/masterserver {start|stop|restart|force-reload}" echo "Usage: $0 {start|stop|restart|force-reload}"
exit 1 exit 1
;; ;;
esac esac

View File

@ -86,7 +86,7 @@ typedef struct
//============================================================================= //=============================================================================
#define HOSTNAME "loopback" #define HOSTNAME "localhost"
#define USER "srb2_ms" #define USER "srb2_ms"
#define PASSWORD "gLRDRb7WgLRDRb7W" #define PASSWORD "gLRDRb7WgLRDRb7W"
#define DATABASE "srb2_ms" #define DATABASE "srb2_ms"
@ -291,17 +291,17 @@ void MySQL_AddServer(const char *ip, const char *port, const char *name, const c
char checkquery[500]; char checkquery[500];
char updatequery[5000]; char updatequery[5000];
char queryp1[5000] = "INSERT INTO `ms_servers` (`name`,`ip`,`port`,`version`,`timestamp`,`room`,`key`) VALUES ('%s','%s','%s','%s','%ld','%d','%s')"; char queryp1[5000] = "INSERT INTO `ms_servers` (`name`,`ip`,`port`,`version`,`timestamp`,`room`,`key`) VALUES ('%s','%s','%s','%s','%ld','%d','%s')";
char checkqueryp1[500] = "SELECT room_override FROM `ms_servers` WHERE `ip` = '%s'"; char checkqueryp1[500] = "SELECT room_override FROM `ms_servers` WHERE `ip` = '%s' AND `port` = '%s'";
char updatequeryp1[5000]; char updatequeryp1[5000];
if(firstadd) if(firstadd)
{ {
logPrintf(logfile, "First add.\n"); logPrintf(logfile, "First add.\n");
strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `delisted` = '0', `key` = '%s' WHERE `ip` = '%s'"); strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `delisted` = '0', `key` = '%s' WHERE `ip` = '%s' AND `port` = '%s'");
} }
else else
{ {
logPrintf(logfile, "Update ping.\n"); logPrintf(logfile, "Update ping.\n");
strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `key` = '%s' WHERE `ip` = '%s' AND `delisted` = '0'"); strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `key` = '%s' WHERE `ip` = '%s' AND `port` = '%s' AND `delisted` = '0'");
} }
MySQL_Conn(false); MySQL_Conn(false);
mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name)); mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name));
@ -314,10 +314,10 @@ void MySQL_AddServer(const char *ip, const char *port, const char *name, const c
logPrintf(errorfile, "IP %s tried to use the private room %d! THIS SHOULD NOT HAPPEN\n", ip, room); logPrintf(errorfile, "IP %s tried to use the private room %d! THIS SHOULD NOT HAPPEN\n", ip, room);
return; return;
} }
sprintf(checkquery, checkqueryp1, ip); sprintf(checkquery, checkqueryp1, ip, port);
time_t timestamp; time_t timestamp;
timestamp = time (NULL); timestamp = time (NULL);
logPrintf(logfile, "Checking for existing servers in table with the same IP...\n"); logPrintf(logfile, "Checking for existing servers in table with the same IP and port...\n");
logPrintf(mysqlfile, "Executing MySQL Query: %s\n", checkquery); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", checkquery);
if(mysql_query(conn, checkquery)) { if(mysql_query(conn, checkquery)) {
logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn));
@ -341,9 +341,9 @@ void MySQL_AddServer(const char *ip, const char *port, const char *name, const c
if(atoi(row[0]) != 0) if(atoi(row[0]) != 0)
room = atoi(row[0]); room = atoi(row[0]);
mysql_free_result(res); mysql_free_result(res);
logPrintf(logfile, "Server's IP already exists, so let's just update it instead...\n"); logPrintf(logfile, "Server's IP and port already exists, so let's just update it instead...\n");
logPrintf(logfile, "Updating Server Data for %s\n", ip); logPrintf(logfile, "Updating Server Data for %s\n", ip);
sprintf(updatequery, updatequeryp1, escapedName, escapedPort, escapedVersion, timestamp, room, escapedKey, ip); sprintf(updatequery, updatequeryp1, escapedName, escapedPort, escapedVersion, timestamp, room, escapedKey, ip, port);
logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery);
if(mysql_query(conn, updatequery)) { if(mysql_query(conn, updatequery)) {
logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn));
@ -619,10 +619,10 @@ void MySQL_ListServServers(UINT32 id, UINT32 type, const char *ip) {
void MySQL_RemoveServer(char *ip, char *port, char *name, char *version) { void MySQL_RemoveServer(char *ip, char *port, char *name, char *version) {
char escapedName[255]; char escapedName[255];
char updatequery[5000]; char updatequery[5000];
char updatequeryp1[5000] = "UPDATE `ms_servers` SET upnow = '0' WHERE `ip` = '%s' AND `permanent` = '0'"; char updatequeryp1[5000] = "UPDATE `ms_servers` SET upnow = '0' WHERE `ip` = '%s' AND `port` = '%s' AND `permanent` = '0'";
MySQL_Conn(false); MySQL_Conn(false);
mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name)); mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name));
sprintf(updatequery, updatequeryp1, ip); sprintf(updatequery, updatequeryp1, ip, port);
logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery);
if(mysql_query(conn, updatequery)) { if(mysql_query(conn, updatequery)) {
logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn));
@ -841,6 +841,10 @@ static void addServer(int id, char *buffer, bool firstadd)
info->port[sizeof (info->port)-1] = '\0'; info->port[sizeof (info->port)-1] = '\0';
info->name[sizeof (info->name)-1] = '\0'; info->name[sizeof (info->name)-1] = '\0';
info->version[sizeof (info->version)-1] = '\0'; info->version[sizeof (info->version)-1] = '\0';
logPrintf(logfile, "addServer(): Version = \"%s\"\n", info->version);
logPrintf(logfile, "addServer(): Key = \"%s\"\n", info->key);
// retrieve the true ip of the server // retrieve the true ip of the server
strcpy(info->ip, server_socket.getClientIP(id)); strcpy(info->ip, server_socket.getClientIP(id));
//strcpy(info->port, server_socket.getClientPort(id)); //strcpy(info->port, server_socket.getClientPort(id));
@ -995,7 +999,7 @@ int main(int argc, char *argv[])
if (server_socket.listen(argv[1]) < 0) if (server_socket.listen(argv[1]) < 0)
{ {
fprintf(stderr, "Error while initializing the server\n"); fprintf(stderr, "Error while initializing the server; port being used! Try killing the other Master Server.\n");
exit(2); exit(2);
} }

View File

@ -13,8 +13,8 @@ SET time_zone = "+00:00";
-- Database: `srb2ms` -- Database: `srb2ms`
-- --
CREATE DATABASE IF NOT EXISTS `srb2ms` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE DATABASE IF NOT EXISTS `srb2_ms` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `srb2ms`; USE `srb2_ms`;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -25,8 +25,8 @@ USE `srb2ms`;
CREATE TABLE `ms_bans` ( CREATE TABLE `ms_bans` (
`bid` int(11) DEFAULT NULL, `bid` int(11) DEFAULT NULL,
`ipstart` int(11) DEFAULT NULL, `ipstart` int(10) unsigned DEFAULT NULL,
`ipend` int(11) DEFAULT NULL, `ipend` int(10) unsigned DEFAULT NULL,
`full_endtime` int(11) DEFAULT NULL, `full_endtime` int(11) DEFAULT NULL,
`permanent` tinyint(1) DEFAULT NULL, `permanent` tinyint(1) DEFAULT NULL,
`hostonly` tinyint(1) DEFAULT NULL, `hostonly` tinyint(1) DEFAULT NULL,
@ -63,19 +63,19 @@ INSERT INTO `ms_rooms` (`room_id`, `title`, `motd`, `visible`, `order`, `private
-- --
CREATE TABLE `ms_servers` ( CREATE TABLE `ms_servers` (
`sid` int(11) NOT NULL, `sid` int(11) primary key AUTO_INCREMENT,
`name` text COLLATE utf8mb4_unicode_ci NOT NULL, `name` text COLLATE utf8mb4_unicode_ci NOT NULL,
`ip` text COLLATE utf8mb4_unicode_ci NOT NULL, `ip` text COLLATE utf8mb4_unicode_ci NOT NULL,
`port` int(11) NOT NULL, `port` int(11) NOT NULL DEFAULT 5029,
`version` text COLLATE utf8mb4_unicode_ci NOT NULL, `version` text COLLATE utf8mb4_unicode_ci NOT NULL,
`timestamp` int(11) NOT NULL, `timestamp` int(11) NOT NULL DEFAULT 0,
`room` int(11) NOT NULL, `room` int(11) NOT NULL DEFAULT 0,
`key` text COLLATE utf8mb4_unicode_ci NOT NULL, `key` text COLLATE utf8mb4_unicode_ci NOT NULL,
`room_override` int(11) NOT NULL, `room_override` int(11) NOT NULL DEFAULT 0,
`upnow` tinyint(1) NOT NULL, `upnow` tinyint(1) NOT NULL DEFAULT 1,
`permanent` tinyint(1) NOT NULL, `permanent` tinyint(1) NOT NULL DEFAULT 0,
`delisted` tinyint(1) NOT NULL, `delisted` tinyint(1) NOT NULL DEFAULT 0,
`sticky` int(11) NOT NULL `sticky` int(11) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -85,16 +85,20 @@ CREATE TABLE `ms_servers` (
-- --
CREATE TABLE `ms_versions` ( CREATE TABLE `ms_versions` (
`mod_id` int(11) NOT NULL, `mod_id` int(10) unsigned primary key AUTO_INCREMENT,
`mod_version` int(11) NOT NULL `mod_version` int(10) unsigned NOT NULL DEFAULT 1,
`mod_vstring` varchar(45) NOT NULL DEFAULT 'v1.0',
`mod_codebase` int(10) unsigned NOT NULL DEFAULT 205,
`mod_name` varchar(255) NOT NULL DEFAULT 'Default MOD Name',
`mod_url` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --
-- Dumping data for table `ms_versions` -- Dumping data for table `ms_versions`
-- --
INSERT INTO `ms_versions` (`mod_id`, `mod_version`) VALUES INSERT INTO `ms_versions` (`mod_id`, `mod_version`, `mod_vstring`, `mod_codebase`, `mod_name`, `mod_url`) VALUES
(12, 25); (18, 42, 'v2.2.2', 205, 'SRB2 2.2', 'SRB2.org');
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -114,4 +118,4 @@ COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;