mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-24 21:31:46 +00:00
Merge branch 'udmf-scrollers' into udmf-polyobjects
This commit is contained in:
commit
de82afe338
83 changed files with 3730 additions and 1800 deletions
27
appveyor.yml
27
appveyor.yml
|
@ -2,15 +2,11 @@ version: 2.2.9.{branch}-{build}
|
|||
os: MinGW
|
||||
|
||||
environment:
|
||||
CC: ccache
|
||||
CCACHE_CC: i686-w64-mingw32-gcc
|
||||
CCACHE_CC_64: x86_64-w64-mingw32-gcc
|
||||
CC: i686-w64-mingw32-gcc
|
||||
WINDRES: windres
|
||||
# c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead
|
||||
MINGW_SDK: c:\msys64\mingw32
|
||||
# c:\msys64 x86_64 has gcc 8.2.0, so use c:\mingw-w64 7.3.0 instead
|
||||
MINGW_SDK_64: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64
|
||||
CFLAGS: -Wall -W -Werror -Wno-error=implicit-fallthrough -Wimplicit-fallthrough=3 -Wno-tautological-compare -Wno-error=suggest-attribute=noreturn
|
||||
CFLAGS: -Wno-implicit-fallthrough
|
||||
NASM_ZIP: nasm-2.12.01
|
||||
NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip
|
||||
UPX_ZIP: upx391w
|
||||
|
@ -19,8 +15,6 @@ environment:
|
|||
CCACHE_URL: http://alam.srb2.org/ccache.exe
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_DIR: C:\Users\appveyor\.ccache
|
||||
# Disable UPX by default. The user can override this in their Appveyor project settings
|
||||
NOUPX: 1
|
||||
##############################
|
||||
# DEPLOYER VARIABLES
|
||||
# DPL_ENABLED=1 builds installers for branch names starting with `deployer`.
|
||||
|
@ -53,11 +47,6 @@ cache:
|
|||
- C:\Users\appveyor\srb2_cache
|
||||
|
||||
install:
|
||||
- if [%CONFIGURATION%] == [SDL64] ( set "X86_64=1" )
|
||||
- if [%CONFIGURATION%] == [SDL64] ( set "CONFIGURATION=SDL" )
|
||||
- if [%X86_64%] == [1] ( set "MINGW_SDK=%MINGW_SDK_64%" )
|
||||
- if [%X86_64%] == [1] ( set "CCACHE_CC=%CCACHE_CC_64%" )
|
||||
|
||||
- if not exist "%NASM_ZIP%.zip" appveyor DownloadFile "%NASM_URL%" -FileName "%NASM_ZIP%.zip"
|
||||
- 7z x -y "%NASM_ZIP%.zip" -o%TMP% >null
|
||||
- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%NASM_ZIP%" "%MINGW_SDK%\bin" nasm.exe || exit 0
|
||||
|
@ -72,34 +61,27 @@ install:
|
|||
|
||||
configuration:
|
||||
- SDL
|
||||
- SDL64
|
||||
|
||||
before_build:
|
||||
- set "Path=%MINGW_SDK%\bin;%Path%"
|
||||
- if [%X86_64%] == [1] ( x86_64-w64-mingw32-gcc --version ) else ( i686-w64-mingw32-gcc --version )
|
||||
- mingw32-make --version
|
||||
- if not [%X86_64%] == [1] ( nasm -v )
|
||||
- nasm -v
|
||||
- if not [%NOUPX%] == [1] ( upx -V )
|
||||
- ccache -V
|
||||
- ccache -s
|
||||
- if [%NOUPX%] == [1] ( set "NOUPX=NOUPX=1" ) else ( set "NOUPX=" )
|
||||
- if defined [%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%] ( set "COMMIT=%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%" ) else ( set "COMMIT=%APPVEYOR_REPO_COMMIT%" )
|
||||
- cmd: git rev-parse --short %COMMIT%>%TMP%/gitshort.txt
|
||||
- cmd: set /P GITSHORT=<%TMP%/gitshort.txt
|
||||
# for pull requests, take the owner's name only, if this isn't the same repo of course
|
||||
- set "REPO=%APPVEYOR_REPO_BRANCH%"
|
||||
- if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [] ( if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [%APPVEYOR_REPO_NAME%] ( for /f "delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set "REPO=%%a-%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%" ) )
|
||||
- set "EXENAME=EXENAME=srb2win-%REPO%-%GITSHORT%.exe"
|
||||
- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX% %EXENAME%"
|
||||
- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1 GCC81=1" ) else ( set "MINGW_FLAGS=MINGW=1 GCC91=1" )
|
||||
- set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1"
|
||||
- set "SRB2_MFLAGS=-C src NOECHOFILENAMES=1 CCACHE=1 EXENAME=srb2win-%REPO%-%GITSHORT%.exe"
|
||||
|
||||
build_script:
|
||||
- cmd: mingw32-make.exe %SRB2_MFLAGS% clean
|
||||
- cmd: mingw32-make.exe %SRB2_MFLAGS% ERRORMODE=1 -k
|
||||
|
||||
after_build:
|
||||
- if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" )
|
||||
- ccache -s
|
||||
- set BUILD_ARCHIVE=%REPO%-%GITSHORT%-%CONFIGURATION%.7z
|
||||
- set BUILDSARCHIVE=%REPO%-%CONFIGURATION%.7z
|
||||
|
@ -134,3 +116,4 @@ test: off
|
|||
on_finish:
|
||||
#- cmd: echo xfreerdp /u:appveyor /cert-ignore +clipboard /v:<ip>:<port>
|
||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# vim: et ts=1
|
||||
|
|
|
@ -2958,8 +2958,10 @@ linedeftypes
|
|||
prefix = "(700)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 1;
|
||||
copyslopeargs = 1;
|
||||
}
|
||||
|
||||
701
|
||||
|
@ -2968,8 +2970,10 @@ linedeftypes
|
|||
prefix = "(701)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 2;
|
||||
copyslopeargs = 4;
|
||||
}
|
||||
|
||||
702
|
||||
|
@ -2978,8 +2982,10 @@ linedeftypes
|
|||
prefix = "(702)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 3;
|
||||
copyslopeargs = 5;
|
||||
}
|
||||
|
||||
703
|
||||
|
@ -2988,8 +2994,10 @@ linedeftypes
|
|||
prefix = "(703)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 9;
|
||||
copyslopeargs = 8;
|
||||
}
|
||||
|
||||
704
|
||||
|
@ -3020,8 +3028,10 @@ linedeftypes
|
|||
prefix = "(710)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 4;
|
||||
copyslopeargs = 2;
|
||||
}
|
||||
|
||||
711
|
||||
|
@ -3030,8 +3040,10 @@ linedeftypes
|
|||
prefix = "(711)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 8;
|
||||
copyslopeargs = 8;
|
||||
}
|
||||
|
||||
712
|
||||
|
@ -3040,8 +3052,10 @@ linedeftypes
|
|||
prefix = "(712)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 12;
|
||||
copyslopeargs = 10;
|
||||
}
|
||||
|
||||
713
|
||||
|
@ -3050,8 +3064,10 @@ linedeftypes
|
|||
prefix = "(713)";
|
||||
flags2048text = "[11] No physics";
|
||||
flags4096text = "[12] Dynamic";
|
||||
flags32768text = "[15] Copy to other side";
|
||||
slope = "regular";
|
||||
slopeargs = 6;
|
||||
copyslopeargs = 6;
|
||||
}
|
||||
|
||||
714
|
||||
|
|
|
@ -4,7 +4,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32)
|
|||
|
||||
# Core sources
|
||||
target_sourcefile(c)
|
||||
target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h)
|
||||
target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h.in)
|
||||
|
||||
set(SRB2_ASM_SOURCES vid_copy.s)
|
||||
|
||||
|
@ -60,7 +60,7 @@ if(${SRB2_CONFIG_HAVE_GME})
|
|||
endif()
|
||||
if(${GME_FOUND})
|
||||
set(SRB2_HAVE_GME ON)
|
||||
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_LIBGME)
|
||||
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_GME)
|
||||
else()
|
||||
message(WARNING "You have specified that GME is available but it was not found.")
|
||||
endif()
|
||||
|
|
70
src/Makefile
70
src/Makefile
|
@ -132,6 +132,10 @@ goals:=$(or $(MAKECMDGOALS),all)
|
|||
cleanonly:=$(filter $(clean_targets),$(goals))
|
||||
destructive:=$(filter-out info,$(cleanonly))
|
||||
|
||||
ifndef cleanonly
|
||||
include Makefile.d/old.mk
|
||||
endif
|
||||
|
||||
include Makefile.d/util.mk
|
||||
|
||||
ifdef PREFIX
|
||||
|
@ -141,7 +145,7 @@ endif
|
|||
OBJDUMP_OPTS?=--wide --source --line-numbers
|
||||
|
||||
OBJCOPY:=$(call Prefix,objcopy)
|
||||
OBJDUMP:=$(call Prefix,objdump) $(OBJDUMP_OPTS)
|
||||
OBJDUMP:=$(call Prefix,objdump)
|
||||
WINDRES:=$(call Prefix,windres)
|
||||
|
||||
ifdef YASM
|
||||
|
@ -176,11 +180,7 @@ include Makefile.d/detect.mk
|
|||
# make would try to remove the implicitly made directories
|
||||
.PRECIOUS : %/ comptime.c
|
||||
|
||||
# very sophisticated dependency
|
||||
sources:=\
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,blua/Sourcefile)\
|
||||
|
||||
sources:=
|
||||
makedir:=../make
|
||||
|
||||
# -DCOMPVERSION: flag to use comptime.h
|
||||
|
@ -204,6 +204,11 @@ endif
|
|||
depdir:=$(makedir)/deps
|
||||
objdir:=$(makedir)/objs
|
||||
|
||||
# very sophisticated dependency
|
||||
sources+=\
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,blua/Sourcefile)\
|
||||
|
||||
depends:=$(basename $(filter %.c %.s,$(sources)))
|
||||
objects:=$(basename $(filter %.c %.s %.nas,$(sources)))
|
||||
|
||||
|
@ -268,16 +273,18 @@ opts+=$(debug_opts)
|
|||
|
||||
opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v)))
|
||||
|
||||
CFLAGS:=$(opts) $(WFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||
LDFLAGS:=$(libs) $(LDFLAGS)
|
||||
ASFLAGS+=-x assembler-with-cpp
|
||||
opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||
libs+=$(LDFLAGS)
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
|
||||
cc=$(CC)
|
||||
|
||||
ifdef DISTCC
|
||||
CC:=distcc $(CC)
|
||||
cc=distcc $(CC)
|
||||
endif
|
||||
|
||||
ifdef CCACHE
|
||||
CC:=ccache $(CC)
|
||||
cc=ccache $(CC)
|
||||
endif
|
||||
|
||||
ifndef SILENT
|
||||
|
@ -288,11 +295,13 @@ ifndef destructive
|
|||
$(shell $(CC) -v)
|
||||
define flags =
|
||||
|
||||
CC ........ $(CC)
|
||||
SHELL ..... $(SHELL)
|
||||
|
||||
CFLAGS .... $(CFLAGS)
|
||||
CC ........ $(cc)
|
||||
|
||||
LDFLAGS ... $(LDFLAGS)
|
||||
CFLAGS .... $(opts)
|
||||
|
||||
LDFLAGS ... $(libs)
|
||||
|
||||
endef
|
||||
$(info $(flags))
|
||||
|
@ -306,13 +315,12 @@ endif
|
|||
endif
|
||||
|
||||
LD:=$(CC)
|
||||
CC:=$(CC) $(CFLAGS)
|
||||
NASM:=$(NASM) $(NASMOPTS) -f $(nasm_format)
|
||||
GZIP:=$(GZIP) $(GZIP_OPTS)
|
||||
cc:=$(cc) $(opts)
|
||||
nasm=$(NASM) $(NASMOPTS) -f $(nasm_format)
|
||||
ifdef UPX
|
||||
UPX:=$(UPX) $(UPX_OPTS)
|
||||
upx=$(UPX) $(UPX_OPTS)
|
||||
endif
|
||||
WINDRES:=$(WINDRES) $(WINDRESFLAGS)\
|
||||
windres=$(WINDRES) $(WINDRESFLAGS)\
|
||||
$(debug_opts) --include-dir=win32 -O coff
|
||||
|
||||
%/ :
|
||||
|
@ -322,7 +330,7 @@ WINDRES:=$(WINDRES) $(WINDRESFLAGS)\
|
|||
# prerequisites
|
||||
.SECONDEXPANSION :
|
||||
|
||||
# 'UPX' is also recognized in the enviornment by upx
|
||||
# 'UPX' is also recognized in the environment by upx
|
||||
unexport UPX
|
||||
|
||||
# executable stripped of debugging symbols
|
||||
|
@ -331,19 +339,19 @@ $(exe) : $(dbg) | $$(@D)/
|
|||
$(.)-$(OBJCOPY) --add-gnu-debuglink=$< $@
|
||||
ifdef UPX
|
||||
$(call Echo,Compressing final executable...)
|
||||
$(.)-$(UPX) $@
|
||||
$(.)-$(upx) $@
|
||||
endif
|
||||
|
||||
# original executable with debugging symbols
|
||||
$(dbg) : $(objects) | $$(@D)/
|
||||
$(call Echo,Linking $(@F)...)
|
||||
$(.)$(LD) -o $@ $^ $(LDFLAGS)
|
||||
$(.)$(LD) -o $@ $^ $(libs)
|
||||
|
||||
# disassembly of executable
|
||||
$(dbg).txt : $(dbg)
|
||||
$(call Echo,Dumping debugging info...)
|
||||
$(.)$(OBJDUMP) $< > $@
|
||||
$(.)$(GZIP) $@
|
||||
$(.)$(OBJDUMP) $(OBJDUMP_OPTS) $< > $@
|
||||
$(.)$(GZIP) $(GZIP_OPTS) $@
|
||||
|
||||
# '::' means run unconditionally
|
||||
# this really updates comptime.h
|
||||
|
@ -368,11 +376,11 @@ ifdef Echo_name
|
|||
@printf '%-20.20s\r' $$<
|
||||
endif
|
||||
endif
|
||||
$(.)$(CC) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$<
|
||||
$(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
$(eval $(call _recipe,c))
|
||||
$(eval $(call _recipe,s,$(ASFLAGS)))
|
||||
$(eval $(call _recipe,s,$(asflags)))
|
||||
|
||||
# compiling recipe template
|
||||
# 1: target file suffix
|
||||
|
@ -384,10 +392,10 @@ $(objdir)/%.$(1) : %.$(2) | $$$$(@D)/
|
|||
$(.)$(3)
|
||||
endef
|
||||
|
||||
$(eval $(call _recipe,o,c,$(CC) -c -o $$@ $$<))
|
||||
$(eval $(call _recipe,o,nas,$(NASM) -o $$@ $$<))
|
||||
$(eval $(call _recipe,o,s,$(CC) $(ASFLAGS) -c -o $$@ $$<))
|
||||
$(eval $(call _recipe,res,rc,$(WINDRES) -i $$< -o $$@))
|
||||
$(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<))
|
||||
$(eval $(call _recipe,o,nas,$(nasm) -o $$@ $$<))
|
||||
$(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<))
|
||||
$(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@))
|
||||
|
||||
_rm=$(.)$(rmrf) $(call Windows_path,$(1))
|
||||
|
||||
|
@ -398,7 +406,7 @@ clean :
|
|||
$(call _rm,$(exe) $(dbg) $(dbg).txt $(objects))
|
||||
|
||||
distclean :
|
||||
$(call _rm,../bin ../objs ../deps comptime.h)
|
||||
$(call _rm,../bin ../objs ../dep ../make comptime.h)
|
||||
|
||||
info:
|
||||
ifdef WINDOWSHELL
|
||||
|
|
|
@ -29,7 +29,6 @@ $(call Print,$(_m))
|
|||
|
||||
# go for a 32-bit sdl mingw exe by default
|
||||
MINGW:=1
|
||||
WINDOWSHELL:=1
|
||||
|
||||
else # if you on the *nix
|
||||
|
||||
|
@ -72,13 +71,17 @@ latest_gcc_version:=10.2
|
|||
# manually set. And don't bother if this is a clean only
|
||||
# run.
|
||||
ifeq (,$(call Wildvar,GCC% destructive))
|
||||
version:=$(shell $(CC) --version)
|
||||
|
||||
# can't use $(CC) --version here since that uses argv[0] to display the name
|
||||
# also gcc outputs the information to stderr, so I had to do 2>&1
|
||||
# this program really doesn't like identifying itself
|
||||
version:=$(shell $(CC) -v 2>&1)
|
||||
|
||||
# check if this is in fact GCC
|
||||
ifneq (,$(or $(findstring gcc,$(version)),\
|
||||
$(findstring GCC,$(version))))
|
||||
ifneq (,$(findstring gcc version,$(version)))
|
||||
|
||||
version:=$(shell $(CC) -dumpversion)
|
||||
# in stark contrast to the name, gcc will give me a nicely formatted version number for free
|
||||
version:=$(shell $(CC) -dumpfullversion)
|
||||
|
||||
# Turn version into words of major, minor
|
||||
v:=$(subst ., ,$(version))
|
||||
|
@ -91,7 +94,7 @@ ifeq (,$(filter $(v),$(gcc_versions)))
|
|||
define line =
|
||||
Your compiler version, GCC $(version), \
|
||||
is not supported by the Makefile.
|
||||
The Makefile will assume GCC $(latest_gcc_version).))
|
||||
The Makefile will assume GCC $(latest_gcc_version).
|
||||
endef
|
||||
$(call Print,$(line))
|
||||
GCC$(subst .,,$(latest_gcc_version)):=1
|
||||
|
|
16
src/Makefile.d/old.mk
Normal file
16
src/Makefile.d/old.mk
Normal file
|
@ -0,0 +1,16 @@
|
|||
#
|
||||
# Warn about old build directories and offer to purge.
|
||||
#
|
||||
|
||||
_old:=$(wildcard $(addprefix ../bin/,FreeBSD Linux \
|
||||
Linux64 Mingw Mingw64 SDL dummy) ../objs ../dep)
|
||||
|
||||
ifdef _old
|
||||
$(foreach v,$(_old),$(info $(abspath $(v))))
|
||||
$(info )
|
||||
$(info These directories are no longer\
|
||||
required and should be removed.)
|
||||
$(info You may remove them manually or\
|
||||
by using 'make distclean')
|
||||
$(error )
|
||||
endif
|
|
@ -7,9 +7,11 @@ PKG_CONFIG?=pkg-config
|
|||
ifdef WINDOWSHELL
|
||||
rmrf=-2>NUL DEL /S /Q
|
||||
mkdir=-2>NUL MD
|
||||
cat=TYPE
|
||||
else
|
||||
rmrf=rm -rf
|
||||
mkdir=mkdir -p
|
||||
cat=cat
|
||||
endif
|
||||
|
||||
ifdef LINUX64
|
||||
|
|
|
@ -10,7 +10,8 @@ Wildvar=$(foreach v,$(filter $(1),$(.VARIABLES)),$($(v)))
|
|||
|
||||
# Read a list of words from file and prepend each with the
|
||||
# directory of the file.
|
||||
List=$(addprefix $(dir $(1)),$(file < $(1)))
|
||||
_cat=$(shell $(cat) $(call Windows_path,$(1)))
|
||||
List=$(addprefix $(dir $(1)),$(call _cat,$(1)))
|
||||
|
||||
# Convert path separators to backslash on Windows.
|
||||
Windows_path=$(if $(WINDOWSHELL),$(subst /,\,$(1)),$(1))
|
||||
|
|
|
@ -458,7 +458,7 @@ boolean AM_Responder(event_t *ev)
|
|||
{
|
||||
if (!automapactive)
|
||||
{
|
||||
if (ev->type == ev_keydown && ev->data1 == AM_TOGGLEKEY)
|
||||
if (ev->type == ev_keydown && ev->key == AM_TOGGLEKEY)
|
||||
{
|
||||
//faB: prevent alt-tab in win32 version to activate automap just before
|
||||
// minimizing the app; doesn't do any harm to the DOS version
|
||||
|
@ -473,7 +473,7 @@ boolean AM_Responder(event_t *ev)
|
|||
else if (ev->type == ev_keydown)
|
||||
{
|
||||
rc = true;
|
||||
switch (ev->data1)
|
||||
switch (ev->key)
|
||||
{
|
||||
case AM_PANRIGHTKEY: // pan right
|
||||
if (!followplayer)
|
||||
|
@ -550,7 +550,7 @@ boolean AM_Responder(event_t *ev)
|
|||
else if (ev->type == ev_keyup)
|
||||
{
|
||||
rc = false;
|
||||
switch (ev->data1)
|
||||
switch (ev->key)
|
||||
{
|
||||
case AM_PANRIGHTKEY:
|
||||
if (!followplayer)
|
||||
|
|
234
src/b_bot.c
234
src/b_bot.c
|
@ -18,29 +18,38 @@
|
|||
#include "b_bot.h"
|
||||
#include "lua_hook.h"
|
||||
|
||||
// If you want multiple bots, variables like this will
|
||||
// have to be stuffed in something accessible through player_t.
|
||||
static boolean lastForward = false;
|
||||
static boolean lastBlocked = false;
|
||||
static boolean blocked = false;
|
||||
|
||||
static boolean jump_last = false;
|
||||
static boolean spin_last = false;
|
||||
static UINT8 anxiety = 0;
|
||||
static boolean panic = false;
|
||||
static UINT8 flymode = 0;
|
||||
static boolean spinmode = false;
|
||||
static boolean thinkfly = false;
|
||||
|
||||
static inline void B_ResetAI(void)
|
||||
void B_UpdateBotleader(player_t *player)
|
||||
{
|
||||
jump_last = false;
|
||||
spin_last = false;
|
||||
anxiety = 0;
|
||||
panic = false;
|
||||
flymode = 0;
|
||||
spinmode = false;
|
||||
thinkfly = false;
|
||||
UINT32 i;
|
||||
fixed_t dist;
|
||||
fixed_t neardist = INT32_MAX;
|
||||
player_t *nearplayer = NULL;
|
||||
//Find new botleader
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (players[i].bot || players[i].playerstate != PST_LIVE || players[i].spectator || !players[i].mo)
|
||||
continue;
|
||||
if (!player->mo) //Can't do distance calculations if there's no player object, so we'll just take the first we find
|
||||
{
|
||||
player->botleader = &players[i];
|
||||
return;
|
||||
}
|
||||
//Update best candidate based on nearest distance
|
||||
dist = R_PointToDist2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y);
|
||||
if (neardist > dist)
|
||||
{
|
||||
neardist = dist;
|
||||
nearplayer = &players[i];
|
||||
}
|
||||
}
|
||||
//Set botleader to best candidate (or null if none available)
|
||||
player->botleader = nearplayer;
|
||||
}
|
||||
|
||||
static inline void B_ResetAI(botmem_t *mem)
|
||||
{
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
mem->catchup_tics = 0;
|
||||
}
|
||||
|
||||
static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||
|
@ -49,39 +58,47 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
|
||||
player_t *player = sonic->player, *bot = tails->player;
|
||||
ticcmd_t *pcmd = &player->cmd;
|
||||
boolean water = tails->eflags & MFE_UNDERWATER;
|
||||
botmem_t *mem = &bot->botmem;
|
||||
boolean water = (tails->eflags & MFE_UNDERWATER);
|
||||
SINT8 flip = P_MobjFlip(tails);
|
||||
boolean _2d = (tails->flags2 & MF2_TWOD) || twodlevel;
|
||||
fixed_t scale = tails->scale;
|
||||
boolean jump_last = (bot->lastbuttons & BT_JUMP);
|
||||
boolean spin_last = (bot->lastbuttons & BT_SPIN);
|
||||
|
||||
fixed_t dist = P_AproxDistance(sonic->x - tails->x, sonic->y - tails->y);
|
||||
fixed_t zdist = flip * (sonic->z - tails->z);
|
||||
angle_t ang = sonic->angle;
|
||||
fixed_t pmom = P_AproxDistance(sonic->momx, sonic->momy);
|
||||
fixed_t bmom = P_AproxDistance(tails->momx, tails->momy);
|
||||
fixed_t followmax = 128 * 8 * scale; // Max follow distance before AI begins to enter "panic" state
|
||||
fixed_t followmax = 128 * 8 * scale; // Max follow distance before AI begins to enter catchup state
|
||||
fixed_t followthres = 92 * scale; // Distance that AI will try to reach
|
||||
fixed_t followmin = 32 * scale;
|
||||
fixed_t comfortheight = 96 * scale;
|
||||
fixed_t touchdist = 24 * scale;
|
||||
boolean stalled = (bmom < scale >> 1) && dist > followthres; // Helps to see if the AI is having trouble catching up
|
||||
boolean samepos = (sonic->x == tails->x && sonic->y == tails->y);
|
||||
boolean blocked = bot->blocked;
|
||||
|
||||
if (!samepos)
|
||||
ang = R_PointToAngle2(tails->x, tails->y, sonic->x, sonic->y);
|
||||
|
||||
// We can't follow Sonic if he's not around!
|
||||
if (!sonic || sonic->health <= 0)
|
||||
return;
|
||||
|
||||
// Lua can handle it!
|
||||
if (LUA_HookBotAI(sonic, tails, cmd))
|
||||
return;
|
||||
|
||||
// We can't follow Sonic if he's not around!
|
||||
if (!sonic || sonic->health <= 0)
|
||||
{
|
||||
mem->thinkstate = AI_STANDBY;
|
||||
return;
|
||||
}
|
||||
else if (mem->thinkstate == AI_STANDBY)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
|
||||
if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC)
|
||||
{
|
||||
boolean isrelevant = (sonic->player->powers[pw_carry] == CR_MACESPIN || sonic->player->powers[pw_carry] == CR_GENERIC);
|
||||
dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y);
|
||||
if (sonic->player->cmd.buttons & BT_JUMP && (sonic->player->pflags & PF_JUMPED) && isrelevant)
|
||||
cmd->buttons |= BT_JUMP;
|
||||
if (isrelevant)
|
||||
|
@ -103,56 +120,57 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
followmin = 0;
|
||||
followthres = 16*scale;
|
||||
followmax >>= 1;
|
||||
thinkfly = false;
|
||||
if (mem->thinkstate == AI_THINKFLY)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
|
||||
// Check anxiety
|
||||
if (spinmode)
|
||||
// Update catchup_tics
|
||||
if (mem->thinkstate == AI_SPINFOLLOW)
|
||||
{
|
||||
anxiety = 0;
|
||||
panic = false;
|
||||
mem-> catchup_tics = 0;
|
||||
}
|
||||
else if (dist > followmax || zdist > comfortheight || stalled)
|
||||
{
|
||||
anxiety = min(anxiety + 2, 70);
|
||||
if (anxiety >= 70)
|
||||
panic = true;
|
||||
mem-> catchup_tics = min(mem-> catchup_tics + 2, 70);
|
||||
if (mem-> catchup_tics >= 70)
|
||||
mem->thinkstate = AI_CATCHUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
anxiety = max(anxiety - 1, 0);
|
||||
panic = false;
|
||||
mem-> catchup_tics = max(mem-> catchup_tics - 1, 0);
|
||||
if (mem->thinkstate == AI_CATCHUP)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
|
||||
// Orientation
|
||||
// cmd->angleturn won't be relative to player angle, since we're not going through G_BuildTiccmd.
|
||||
if (bot->pflags & (PF_SPINNING|PF_STARTDASH))
|
||||
{
|
||||
cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
}
|
||||
else if (flymode == 2)
|
||||
else if (mem->thinkstate == AI_FLYCARRY)
|
||||
{
|
||||
cmd->angleturn = sonic->player->cmd.angleturn - (tails->angle >> 16);
|
||||
cmd->angleturn = sonic->player->cmd.angleturn;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->angleturn = (ang - tails->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->angleturn = (ang) >> 16; // NOT FRACBITS DAMNIT
|
||||
}
|
||||
|
||||
// ********
|
||||
// FLY MODE
|
||||
// spinmode check
|
||||
if (spinmode || player->exiting)
|
||||
thinkfly = false;
|
||||
// exiting check
|
||||
if (player->exiting && mem->thinkstate == AI_THINKFLY)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
else
|
||||
{
|
||||
// Activate co-op flight
|
||||
if (thinkfly && player->pflags & PF_JUMPED)
|
||||
if (mem->thinkstate == AI_THINKFLY && player->pflags & PF_JUMPED)
|
||||
{
|
||||
if (!jump_last)
|
||||
{
|
||||
jump = true;
|
||||
flymode = 1;
|
||||
thinkfly = false;
|
||||
mem->thinkstate = AI_FLYSTANDBY;
|
||||
bot->pflags |= PF_CANCARRY;
|
||||
}
|
||||
}
|
||||
|
@ -165,20 +183,19 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
&& P_IsObjectOnGround(sonic) && P_IsObjectOnGround(tails)
|
||||
&& !(player->pflags & PF_STASIS)
|
||||
&& bot->charability == CA_FLY)
|
||||
thinkfly = true;
|
||||
else
|
||||
thinkfly = false;
|
||||
mem->thinkstate = AI_THINKFLY;
|
||||
else if (mem->thinkstate == AI_THINKFLY)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
|
||||
// Set carried state
|
||||
if (player->powers[pw_carry] == CR_PLAYER && sonic->tracer == tails)
|
||||
{
|
||||
flymode = 2;
|
||||
mem->thinkstate = AI_FLYCARRY;
|
||||
}
|
||||
|
||||
// Ready for takeoff
|
||||
if (flymode == 1)
|
||||
if (mem->thinkstate == AI_FLYSTANDBY)
|
||||
{
|
||||
thinkfly = false;
|
||||
if (zdist < -64*scale || (flip * tails->momz) > scale) // Make sure we're not too high up
|
||||
spin = true;
|
||||
else if (!jump_last)
|
||||
|
@ -186,10 +203,10 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
|
||||
// Abort if the player moves away or spins
|
||||
if (dist > followthres || player->dashspeed)
|
||||
flymode = 0;
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
// Read player inputs while carrying
|
||||
else if (flymode == 2)
|
||||
else if (mem->thinkstate == AI_FLYCARRY)
|
||||
{
|
||||
cmd->forwardmove = pcmd->forwardmove;
|
||||
cmd->sidemove = pcmd->sidemove;
|
||||
|
@ -203,19 +220,19 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
// End flymode
|
||||
if (player->powers[pw_carry] != CR_PLAYER)
|
||||
{
|
||||
flymode = 0;
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flymode && P_IsObjectOnGround(tails) && !(pcmd->buttons & BT_JUMP))
|
||||
flymode = 0;
|
||||
if (P_IsObjectOnGround(tails) && !(pcmd->buttons & BT_JUMP) && (mem->thinkstate == AI_FLYSTANDBY || mem->thinkstate == AI_FLYCARRY))
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
|
||||
// ********
|
||||
// SPINNING
|
||||
if (panic || flymode || !(player->pflags & PF_SPINNING) || (player->pflags & PF_JUMPED))
|
||||
spinmode = false;
|
||||
else
|
||||
if (!(player->pflags & (PF_SPINNING|PF_STARTDASH)) && mem->thinkstate == AI_SPINFOLLOW)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
else if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_SPINFOLLOW)
|
||||
{
|
||||
if (!_2d)
|
||||
{
|
||||
|
@ -224,21 +241,21 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
{
|
||||
if (dist < followthres && dist > touchdist) // Do positioning
|
||||
{
|
||||
cmd->angleturn = (ang - tails->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->angleturn = (ang) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->forwardmove = 50;
|
||||
spinmode = true;
|
||||
mem->thinkstate = AI_SPINFOLLOW;
|
||||
}
|
||||
else if (dist < touchdist)
|
||||
{
|
||||
if (!bmom && (!(bot->pflags & PF_SPINNING) || (bot->dashspeed && bot->pflags & PF_SPINNING)))
|
||||
{
|
||||
cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
spin = true;
|
||||
}
|
||||
spinmode = true;
|
||||
mem->thinkstate = AI_SPINFOLLOW;
|
||||
}
|
||||
else
|
||||
spinmode = false;
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
// Spin
|
||||
else if (player->dashspeed == bot->dashspeed && player->pflags & PF_SPINNING)
|
||||
|
@ -246,12 +263,12 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
if (bot->pflags & PF_SPINNING || !spin_last)
|
||||
{
|
||||
spin = true;
|
||||
cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
spinmode = true;
|
||||
mem->thinkstate = AI_SPINFOLLOW;
|
||||
}
|
||||
else
|
||||
spinmode = false;
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
}
|
||||
// 2D mode
|
||||
|
@ -261,17 +278,19 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
&& ((bot->pflags & PF_SPINNING) || !spin_last))
|
||||
{
|
||||
spin = true;
|
||||
spinmode = true;
|
||||
mem->thinkstate = AI_SPINFOLLOW;
|
||||
}
|
||||
else
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
}
|
||||
|
||||
// ********
|
||||
// FOLLOW
|
||||
if (!(flymode || spinmode))
|
||||
if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_CATCHUP)
|
||||
{
|
||||
// Too far
|
||||
if (panic || dist > followthres)
|
||||
if (mem->thinkstate == AI_CATCHUP || dist > followthres)
|
||||
{
|
||||
if (!_2d)
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
|
@ -281,7 +300,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
cmd->sidemove = -MAXPLMOVE;
|
||||
}
|
||||
// Within threshold
|
||||
else if (!panic && dist > followmin && abs(zdist) < 192*scale)
|
||||
else if (dist > followmin && abs(zdist) < 192*scale)
|
||||
{
|
||||
if (!_2d)
|
||||
cmd->forwardmove = FixedHypot(pcmd->forwardmove, pcmd->sidemove);
|
||||
|
@ -292,7 +311,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
else if (dist < followmin)
|
||||
{
|
||||
// Copy inputs
|
||||
cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
bot->drawangle = ang;
|
||||
cmd->forwardmove = 8 * pcmd->forwardmove / 10;
|
||||
cmd->sidemove = 8 * pcmd->sidemove / 10;
|
||||
|
@ -301,7 +320,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
|
||||
// ********
|
||||
// JUMP
|
||||
if (!(flymode || spinmode))
|
||||
if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_CATCHUP || (mem->thinkstate == AI_SPINFOLLOW && player->pflags & PF_JUMPED))
|
||||
{
|
||||
// Flying catch-up
|
||||
if (bot->pflags & PF_THOKKED)
|
||||
|
@ -319,31 +338,30 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
// Start jump
|
||||
else if (!jump_last && !(bot->pflags & PF_JUMPED) //&& !(player->pflags & PF_SPINNING)
|
||||
&& ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following
|
||||
|| (zdist > 64*scale && panic) // Vertical catch-up
|
||||
|| (stalled && anxiety > 20 && bot->powers[pw_carry] == CR_NONE)
|
||||
|| (zdist > 64*scale && mem->thinkstate == AI_CATCHUP) // Vertical catch-up
|
||||
|| (stalled && mem-> catchup_tics > 20 && bot->powers[pw_carry] == CR_NONE)
|
||||
//|| (bmom < scale>>3 && dist > followthres && !(bot->powers[pw_carry])) // Stopped & not in carry state
|
||||
|| (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning
|
||||
jump = true;
|
||||
// Hold jump
|
||||
else if (bot->pflags & PF_JUMPED && jump_last && tails->momz*flip > 0 && (zdist > 0 || panic))
|
||||
else if (bot->pflags & PF_JUMPED && jump_last && tails->momz*flip > 0 && (zdist > 0 || mem->thinkstate == AI_CATCHUP))
|
||||
jump = true;
|
||||
// Start flying
|
||||
else if (bot->pflags & PF_JUMPED && panic && !jump_last && bot->charability == CA_FLY)
|
||||
else if (bot->pflags & PF_JUMPED && mem->thinkstate == AI_CATCHUP && !jump_last && bot->charability == CA_FLY)
|
||||
jump = true;
|
||||
}
|
||||
|
||||
// ********
|
||||
// HISTORY
|
||||
jump_last = jump;
|
||||
spin_last = spin;
|
||||
//jump_last = jump;
|
||||
//spin_last = spin;
|
||||
|
||||
// Turn the virtual keypresses into ticcmd_t.
|
||||
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin);
|
||||
|
||||
// Update our status
|
||||
lastForward = forward;
|
||||
lastBlocked = blocked;
|
||||
blocked = false;
|
||||
mem->lastForward = forward;
|
||||
mem->lastBlocked = blocked;
|
||||
}
|
||||
|
||||
void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
|
@ -366,22 +384,25 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd)))
|
||||
return;
|
||||
|
||||
// We don't have any main character AI, sorry. D:
|
||||
if (player-players == consoleplayer)
|
||||
// Make sure we have a valid main character to follow
|
||||
B_UpdateBotleader(player);
|
||||
if (!player->botleader)
|
||||
return;
|
||||
|
||||
// Basic Tails AI
|
||||
B_BuildTailsTiccmd(players[consoleplayer].mo, player->mo, cmd);
|
||||
// Single Player Tails AI
|
||||
//B_BuildTailsTiccmd(players[consoleplayer].mo, player->mo, cmd);
|
||||
B_BuildTailsTiccmd(player->botleader->mo, player->mo, cmd);
|
||||
}
|
||||
|
||||
void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin)
|
||||
{
|
||||
player_t *player = mo->player;
|
||||
// don't try to do stuff if your sonic is in a minecart or something
|
||||
if (players[consoleplayer].powers[pw_carry] && players[consoleplayer].powers[pw_carry] != CR_PLAYER)
|
||||
if (&player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER)
|
||||
return;
|
||||
// Turn the virtual keypresses into ticcmd_t.
|
||||
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
||||
if (players[consoleplayer].climbing
|
||||
if (player->botleader->climbing
|
||||
|| mo->player->pflags & PF_GLIDING) {
|
||||
// Don't mess with bot inputs during these unhandled movement conditions.
|
||||
// The normal AI doesn't use abilities, so custom AI should be sending us exactly what it wants anyway.
|
||||
|
@ -420,7 +441,7 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
|||
cmd->forwardmove += MAXPLMOVE<<FRACBITS>>16;
|
||||
if (backward)
|
||||
cmd->forwardmove -= MAXPLMOVE<<FRACBITS>>16;
|
||||
if (left)
|
||||
if (left)
|
||||
cmd->angleturn += 1280;
|
||||
if (right)
|
||||
cmd->angleturn -= 1280;
|
||||
|
@ -447,14 +468,19 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
|||
void B_MoveBlocked(player_t *player)
|
||||
{
|
||||
(void)player;
|
||||
blocked = true;
|
||||
player->blocked = true;
|
||||
}
|
||||
|
||||
boolean B_CheckRespawn(player_t *player)
|
||||
{
|
||||
mobj_t *sonic = players[consoleplayer].mo;
|
||||
mobj_t *sonic;
|
||||
mobj_t *tails = player->mo;
|
||||
|
||||
//We don't have a main player to spawn to!
|
||||
if (!player->botleader)
|
||||
return false;
|
||||
|
||||
sonic = player->botleader->mo;
|
||||
// We can't follow Sonic if he's not around!
|
||||
if (!sonic || sonic->health <= 0)
|
||||
return false;
|
||||
|
@ -505,15 +531,19 @@ void B_RespawnBot(INT32 playernum)
|
|||
{
|
||||
player_t *player = &players[playernum];
|
||||
fixed_t x,y,z;
|
||||
mobj_t *sonic = players[consoleplayer].mo;
|
||||
mobj_t *sonic;
|
||||
mobj_t *tails;
|
||||
|
||||
if (!player->botleader)
|
||||
return;
|
||||
|
||||
sonic = player->botleader->mo;
|
||||
if (!sonic || sonic->health <= 0)
|
||||
return;
|
||||
|
||||
B_ResetAI();
|
||||
B_ResetAI(&player->botmem);
|
||||
|
||||
player->bot = 1;
|
||||
player->bot = BOT_2PAI;
|
||||
P_SpawnPlayer(playernum);
|
||||
tails = player->mo;
|
||||
|
||||
|
@ -540,10 +570,6 @@ void B_RespawnBot(INT32 playernum)
|
|||
player->powers[pw_spacetime] = sonic->player->powers[pw_spacetime];
|
||||
player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots];
|
||||
player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol];
|
||||
player->acceleration = sonic->player->acceleration;
|
||||
player->accelstart = sonic->player->accelstart;
|
||||
player->thrustfactor = sonic->player->thrustfactor;
|
||||
player->normalspeed = sonic->player->normalspeed;
|
||||
player->pflags |= PF_AUTOBRAKE|(sonic->player->pflags & PF_DIRECTIONCHAR);
|
||||
|
||||
P_TeleportMove(tails, x, y, z);
|
||||
|
@ -561,11 +587,11 @@ void B_RespawnBot(INT32 playernum)
|
|||
void B_HandleFlightIndicator(player_t *player)
|
||||
{
|
||||
mobj_t *tails = player->mo;
|
||||
|
||||
botmem_t *mem = &player->botmem;
|
||||
if (!tails)
|
||||
return;
|
||||
|
||||
if (thinkfly && player->bot == 1 && tails->health)
|
||||
if (mem->thinkstate == AI_THINKFLY && player->bot == BOT_2PAI && tails->health)
|
||||
{
|
||||
if (!tails->hnext)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
/// \file b_bot.h
|
||||
/// \brief Basic bot handling
|
||||
|
||||
void B_UpdateBotleader(player_t *player);
|
||||
void B_BuildTiccmd(player_t *player, ticcmd_t *cmd);
|
||||
void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin);
|
||||
boolean B_CheckRespawn(player_t *player);
|
||||
|
|
|
@ -274,7 +274,7 @@ static int luaB_dofile (lua_State *L) {
|
|||
UINT16 lumpnum;
|
||||
int n = lua_gettop(L);
|
||||
|
||||
if (wadfiles[numwadfiles - 1]->type != RET_PK3)
|
||||
if (!W_FileHasFolders(wadfiles[numwadfiles - 1]))
|
||||
luaL_error(L, "dofile() only works with PK3 files");
|
||||
|
||||
snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename);
|
||||
|
|
|
@ -650,7 +650,7 @@ static void COM_ExecuteString(char *ptext)
|
|||
else
|
||||
{ // Monster Iestyn: keep track of how many levels of recursion we're in
|
||||
recursion++;
|
||||
COM_BufInsertText(a->value);
|
||||
COM_BufInsertTextEx(a->value, com_flags);
|
||||
recursion--;
|
||||
}
|
||||
return;
|
||||
|
@ -1738,6 +1738,8 @@ void CV_SaveVars(UINT8 **p, boolean in_demo)
|
|||
static void CV_LoadVars(UINT8 **p,
|
||||
consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth))
|
||||
{
|
||||
const boolean store = (client || demoplayback);
|
||||
|
||||
consvar_t *cvar;
|
||||
UINT16 count;
|
||||
|
||||
|
@ -1751,7 +1753,7 @@ static void CV_LoadVars(UINT8 **p,
|
|||
{
|
||||
if (cvar->flags & CV_NETVAR)
|
||||
{
|
||||
if (client && cvar->revert.v.string == NULL)
|
||||
if (store && cvar->revert.v.string == NULL)
|
||||
{
|
||||
cvar->revert.v.const_munge = cvar->string;
|
||||
cvar->revert.allocated = ( cvar->zstring != NULL );
|
||||
|
@ -2364,7 +2366,10 @@ static boolean CV_Command(void)
|
|||
return false;
|
||||
|
||||
if (( com_flags & COM_SAFE ) && ( v->flags & CV_NOLUA ))
|
||||
return false;
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "Variable '%s' cannot be changed from Lua.\n", v->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
// perform a variable print or set
|
||||
if (COM_Argc() == 1)
|
||||
|
|
|
@ -221,7 +221,7 @@ static void CONS_Bind_f(void)
|
|||
for (key = 0; key < NUMINPUTS; key++)
|
||||
if (bindtable[key])
|
||||
{
|
||||
CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]);
|
||||
CONS_Printf("%s : \"%s\"\n", G_KeyNumToName(key), bindtable[key]);
|
||||
na = 1;
|
||||
}
|
||||
if (!na)
|
||||
|
@ -229,7 +229,7 @@ static void CONS_Bind_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
key = G_KeyStringToNum(COM_Argv(1));
|
||||
key = G_KeyNameToNum(COM_Argv(1));
|
||||
if (key <= 0 || key >= NUMINPUTS)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n"));
|
||||
|
@ -913,12 +913,12 @@ boolean CON_Responder(event_t *ev)
|
|||
// let go keyup events, don't eat them
|
||||
if (ev->type != ev_keydown && ev->type != ev_console)
|
||||
{
|
||||
if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1])
|
||||
if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1])
|
||||
consdown = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
key = ev->data1;
|
||||
key = ev->key;
|
||||
|
||||
// check for console toggle key
|
||||
if (ev->type != ev_console)
|
||||
|
@ -926,7 +926,7 @@ boolean CON_Responder(event_t *ev)
|
|||
if (modeattacking || metalrecording || marathonmode)
|
||||
return false;
|
||||
|
||||
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
|
||||
if (key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1])
|
||||
{
|
||||
if (consdown) // ignore repeat
|
||||
return true;
|
||||
|
@ -1759,8 +1759,8 @@ static void CON_DrawBackpic(void)
|
|||
}
|
||||
|
||||
// Draw the patch.
|
||||
V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
|
||||
0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
|
||||
V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, FRACUNIT, V_NOSCALESTART, con_backpic, NULL,
|
||||
0, (BASEVIDHEIGHT - h) << FRACBITS, BASEVIDWIDTH << FRACBITS, h << FRACBITS);
|
||||
|
||||
// Unlock the cached patch.
|
||||
W_UnlockCachedPatch(con_backpic);
|
||||
|
|
272
src/d_clisrv.c
272
src/d_clisrv.c
|
@ -43,6 +43,7 @@
|
|||
#include "lzf.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "lua_libs.h"
|
||||
#include "md5.h"
|
||||
#include "m_perfstats.h"
|
||||
|
||||
|
@ -663,14 +664,14 @@ static void Snake_Handle(void)
|
|||
UINT16 i;
|
||||
|
||||
// Handle retry
|
||||
if (snake->gameover && (PLAYER1INPUTDOWN(gc_jump) || gamekeydown[KEY_ENTER]))
|
||||
if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER]))
|
||||
{
|
||||
Snake_Initialise();
|
||||
snake->pausepressed = true; // Avoid accidental pause on respawn
|
||||
}
|
||||
|
||||
// Handle pause
|
||||
if (PLAYER1INPUTDOWN(gc_pause) || gamekeydown[KEY_ENTER])
|
||||
if (PLAYER1INPUTDOWN(GC_PAUSE) || gamekeydown[KEY_ENTER])
|
||||
{
|
||||
if (!snake->pausepressed)
|
||||
snake->paused = !snake->paused;
|
||||
|
@ -1150,15 +1151,14 @@ static boolean CL_SendJoin(void)
|
|||
CONS_Printf(M_GetText("Sending join request...\n"));
|
||||
netbuffer->packettype = PT_CLIENTJOIN;
|
||||
|
||||
netbuffer->u.clientcfg.modversion = MODVERSION;
|
||||
strncpy(netbuffer->u.clientcfg.application,
|
||||
SRB2APPLICATION,
|
||||
sizeof netbuffer->u.clientcfg.application);
|
||||
|
||||
if (splitscreen || botingame)
|
||||
localplayers++;
|
||||
netbuffer->u.clientcfg.localplayers = localplayers;
|
||||
netbuffer->u.clientcfg._255 = 255;
|
||||
netbuffer->u.clientcfg.packetversion = PACKETVERSION;
|
||||
netbuffer->u.clientcfg.version = VERSION;
|
||||
netbuffer->u.clientcfg.subversion = SUBVERSION;
|
||||
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
|
||||
sizeof netbuffer->u.clientcfg.application);
|
||||
|
||||
CleanupPlayerName(consoleplayer, cv_playername.zstring);
|
||||
if (splitscreen)
|
||||
|
@ -1201,6 +1201,21 @@ static INT32 FindRejoinerNum(SINT8 node)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static UINT8
|
||||
GetRefuseReason (INT32 node)
|
||||
{
|
||||
if (!node || FindRejoinerNum(node) != -1)
|
||||
return 0;
|
||||
else if (bannednode && bannednode[node])
|
||||
return REFUSE_BANNED;
|
||||
else if (!cv_allownewplayer.value)
|
||||
return REFUSE_JOINS_DISABLED;
|
||||
else if (D_NumPlayers() >= cv_maxplayers.value)
|
||||
return REFUSE_SLOTS_FULL;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
||||
{
|
||||
UINT8 *p;
|
||||
|
@ -1219,14 +1234,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
|
||||
netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value;
|
||||
|
||||
if (!node || FindRejoinerNum(node) != -1)
|
||||
netbuffer->u.serverinfo.refusereason = 0;
|
||||
else if (!cv_allownewplayer.value)
|
||||
netbuffer->u.serverinfo.refusereason = 1;
|
||||
else if (D_NumPlayers() >= cv_maxplayers.value)
|
||||
netbuffer->u.serverinfo.refusereason = 2;
|
||||
else
|
||||
netbuffer->u.serverinfo.refusereason = 0;
|
||||
netbuffer->u.serverinfo.refusereason = GetRefuseReason(node);
|
||||
|
||||
strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
|
||||
sizeof netbuffer->u.serverinfo.gametypename);
|
||||
|
@ -1344,9 +1352,6 @@ static boolean SV_SendServerConfig(INT32 node)
|
|||
|
||||
netbuffer->packettype = PT_SERVERCFG;
|
||||
|
||||
netbuffer->u.servercfg.version = VERSION;
|
||||
netbuffer->u.servercfg.subversion = SUBVERSION;
|
||||
|
||||
netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer;
|
||||
netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots);
|
||||
netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic);
|
||||
|
@ -1667,20 +1672,24 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
|
|||
if (serverlistcount >= MAXSERVERLIST)
|
||||
return; // list full
|
||||
|
||||
if (info->_255 != 255)
|
||||
return;/* old packet format */
|
||||
/* check it later if connecting to this one */
|
||||
if (node != servernode)
|
||||
{
|
||||
if (info->_255 != 255)
|
||||
return;/* old packet format */
|
||||
|
||||
if (info->packetversion != PACKETVERSION)
|
||||
return;/* old new packet format */
|
||||
if (info->packetversion != PACKETVERSION)
|
||||
return;/* old new packet format */
|
||||
|
||||
if (info->version != VERSION)
|
||||
return; // Not same version.
|
||||
if (info->version != VERSION)
|
||||
return; // Not same version.
|
||||
|
||||
if (info->subversion != SUBVERSION)
|
||||
return; // Close, but no cigar.
|
||||
if (info->subversion != SUBVERSION)
|
||||
return; // Close, but no cigar.
|
||||
|
||||
if (strcmp(info->application, SRB2APPLICATION))
|
||||
return;/* that's a different mod */
|
||||
if (strcmp(info->application, SRB2APPLICATION))
|
||||
return;/* that's a different mod */
|
||||
}
|
||||
|
||||
i = serverlistcount++;
|
||||
}
|
||||
|
@ -1829,6 +1838,72 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
|
|||
|
||||
#endif // ifndef NONET
|
||||
|
||||
static const char * InvalidServerReason (INT32 i)
|
||||
{
|
||||
#define EOT "\nPress ESC\n"
|
||||
|
||||
serverinfo_pak *info = &serverlist[i].info;
|
||||
|
||||
/* magic number for new packet format */
|
||||
if (info->_255 != 255)
|
||||
{
|
||||
return
|
||||
"Outdated server (version unknown).\n" EOT;
|
||||
}
|
||||
|
||||
if (strncmp(info->application, SRB2APPLICATION, sizeof
|
||||
info->application))
|
||||
{
|
||||
return va(
|
||||
"%s cannot connect\n"
|
||||
"to %s servers.\n" EOT,
|
||||
SRB2APPLICATION,
|
||||
info->application);
|
||||
}
|
||||
|
||||
if (
|
||||
info->packetversion != PACKETVERSION ||
|
||||
info->version != VERSION ||
|
||||
info->subversion != SUBVERSION
|
||||
){
|
||||
return va(
|
||||
"Incompatible %s versions.\n"
|
||||
"(server version %d.%d.%d)\n" EOT,
|
||||
SRB2APPLICATION,
|
||||
info->version / 100,
|
||||
info->version % 100,
|
||||
info->subversion);
|
||||
}
|
||||
|
||||
switch (info->refusereason)
|
||||
{
|
||||
case REFUSE_BANNED:
|
||||
return
|
||||
"You have been banned\n"
|
||||
"from the server.\n" EOT;
|
||||
case REFUSE_JOINS_DISABLED:
|
||||
return
|
||||
"The server is not accepting\n"
|
||||
"joins for the moment.\n" EOT;
|
||||
case REFUSE_SLOTS_FULL:
|
||||
return va(
|
||||
"Maximum players reached: %d\n" EOT,
|
||||
info->maxplayer);
|
||||
default:
|
||||
if (info->refusereason)
|
||||
{
|
||||
return
|
||||
"You can't join.\n"
|
||||
"I don't know why,\n"
|
||||
"but you can't join.\n" EOT;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
#undef EOT
|
||||
}
|
||||
|
||||
/** Called by CL_ServerConnectionTicker
|
||||
*
|
||||
* \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit.
|
||||
|
@ -1859,23 +1934,23 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Quit here rather than downloading files and being refused later.
|
||||
if (serverlist[i].info.refusereason)
|
||||
{
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
if (serverlist[i].info.refusereason == 1)
|
||||
M_StartMessage(M_GetText("The server is not accepting\njoins for the moment.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
else if (serverlist[i].info.refusereason == 2)
|
||||
M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
|
||||
else
|
||||
M_StartMessage(M_GetText("You can't join.\nI don't know why,\nbut you can't join.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (client)
|
||||
{
|
||||
const char *reason = InvalidServerReason(i);
|
||||
|
||||
// Quit here rather than downloading files
|
||||
// and being refused later.
|
||||
if (reason)
|
||||
{
|
||||
char *message = Z_StrDup(reason);
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
M_StartMessage(message, NULL, MM_NOTHING);
|
||||
Z_Free(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
D_ParseFileneeded(serverlist[i].info.fileneedednum,
|
||||
serverlist[i].info.fileneeded);
|
||||
CONS_Printf(M_GetText("Checking files...\n"));
|
||||
|
@ -2463,7 +2538,7 @@ void CL_ClearPlayer(INT32 playernum)
|
|||
//
|
||||
// Removes a player from the current game
|
||||
//
|
||||
static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
|
||||
void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
|
||||
{
|
||||
// Sanity check: exceptional cases (i.e. c-fails) can cause multiple
|
||||
// kick commands to be issued for the same player.
|
||||
|
@ -2599,7 +2674,6 @@ void CL_Reset(void)
|
|||
doomcom->numslots = 1;
|
||||
SV_StopServer();
|
||||
SV_ResetServer();
|
||||
CV_RevertNetVars();
|
||||
|
||||
// make sure we don't leave any fileneeded gunk over from a failed join
|
||||
fileneedednum = 0;
|
||||
|
@ -3231,6 +3305,8 @@ void SV_ResetServer(void)
|
|||
// clear server_context
|
||||
memset(server_context, '-', 8);
|
||||
|
||||
CV_RevertNetVars();
|
||||
|
||||
DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n");
|
||||
}
|
||||
|
||||
|
@ -3256,6 +3332,9 @@ static inline void SV_GenContext(void)
|
|||
//
|
||||
void D_QuitNetGame(void)
|
||||
{
|
||||
mousegrabbedbylua = true;
|
||||
I_UpdateMouseGrab();
|
||||
|
||||
if (!netgame || !netbuffer)
|
||||
return;
|
||||
|
||||
|
@ -3620,6 +3699,78 @@ static size_t TotalTextCmdPerTic(tic_t tic)
|
|||
return total;
|
||||
}
|
||||
|
||||
static const char *
|
||||
ConnectionRefused (SINT8 node, INT32 rejoinernum)
|
||||
{
|
||||
clientconfig_pak *cc = &netbuffer->u.clientcfg;
|
||||
|
||||
boolean rejoining = (rejoinernum != -1);
|
||||
|
||||
if (!node)/* server connecting to itself */
|
||||
return NULL;
|
||||
|
||||
if (
|
||||
cc->modversion != MODVERSION ||
|
||||
strncmp(cc->application, SRB2APPLICATION,
|
||||
sizeof cc->application)
|
||||
){
|
||||
return/* this is probably client's fault */
|
||||
"Incompatible.";
|
||||
}
|
||||
else if (bannednode && bannednode[node])
|
||||
{
|
||||
return
|
||||
"You have been banned\n"
|
||||
"from the server.";
|
||||
}
|
||||
else if (cc->localplayers != 1)
|
||||
{
|
||||
return
|
||||
"Wrong player count.";
|
||||
}
|
||||
|
||||
if (!rejoining)
|
||||
{
|
||||
if (!cv_allownewplayer.value)
|
||||
{
|
||||
return
|
||||
"The server is not accepting\n"
|
||||
"joins for the moment.";
|
||||
}
|
||||
else if (D_NumPlayers() >= cv_maxplayers.value)
|
||||
{
|
||||
return va(
|
||||
"Maximum players reached: %d",
|
||||
cv_maxplayers.value);
|
||||
}
|
||||
}
|
||||
|
||||
if (luafiletransfers)
|
||||
{
|
||||
return
|
||||
"The serveris broadcasting a file\n"
|
||||
"requested by a Lua script.\n"
|
||||
"Please wait a bit and then\n"
|
||||
"try rejoining.";
|
||||
}
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
const tic_t th = 2 * cv_joindelay.value * TICRATE;
|
||||
|
||||
if (joindelay > th)
|
||||
{
|
||||
return va(
|
||||
"Too many people are connecting.\n"
|
||||
"Please wait %d seconds and then\n"
|
||||
"try rejoining.",
|
||||
(joindelay - th) / TICRATE);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Called when a PT_CLIENTJOIN packet is received
|
||||
*
|
||||
* \param node The packet sender
|
||||
|
@ -3630,33 +3781,14 @@ static void HandleConnect(SINT8 node)
|
|||
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
|
||||
INT32 rejoinernum;
|
||||
INT32 i;
|
||||
const char *refuse;
|
||||
|
||||
rejoinernum = FindRejoinerNum(node);
|
||||
|
||||
if (bannednode && bannednode[node])
|
||||
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server."));
|
||||
else if (netbuffer->u.clientcfg._255 != 255 ||
|
||||
netbuffer->u.clientcfg.packetversion != PACKETVERSION)
|
||||
SV_SendRefuse(node, "Incompatible packet formats.");
|
||||
else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION,
|
||||
sizeof netbuffer->u.clientcfg.application))
|
||||
SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible.");
|
||||
else if (netbuffer->u.clientcfg.version != VERSION
|
||||
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
|
||||
SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
|
||||
else if (!cv_allownewplayer.value && node && rejoinernum == -1)
|
||||
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment."));
|
||||
else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1)
|
||||
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
|
||||
else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
|
||||
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
|
||||
else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
|
||||
SV_SendRefuse(node, M_GetText("No players from\nthis node."));
|
||||
else if (luafiletransfers)
|
||||
SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining."));
|
||||
else if (netgame && joindelay > 2 * (tic_t)cv_joindelay.value * TICRATE)
|
||||
SV_SendRefuse(node, va(M_GetText("Too many people are connecting.\nPlease wait %d seconds and then\ntry rejoining."),
|
||||
(joindelay - 2 * cv_joindelay.value * TICRATE) / TICRATE));
|
||||
refuse = ConnectionRefused(node, rejoinernum);
|
||||
|
||||
if (refuse)
|
||||
SV_SendRefuse(node, refuse);
|
||||
else
|
||||
{
|
||||
#ifndef NONET
|
||||
|
|
|
@ -22,11 +22,15 @@
|
|||
#include "mserv.h"
|
||||
|
||||
/*
|
||||
The 'packet version' is used to distinguish packet formats.
|
||||
This version is independent of VERSION and SUBVERSION. Different
|
||||
applications may follow different packet versions.
|
||||
The 'packet version' is used to distinguish packet
|
||||
formats. This version is independent of VERSION and
|
||||
SUBVERSION. Different applications may follow different
|
||||
packet versions.
|
||||
|
||||
If you change the struct or the meaning of a field
|
||||
therein, increment this number.
|
||||
*/
|
||||
#define PACKETVERSION 3
|
||||
#define PACKETVERSION 4
|
||||
|
||||
// Network play related stuff.
|
||||
// There is a data struct that stores network
|
||||
|
@ -141,9 +145,6 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 version; // Different versions don't work
|
||||
UINT8 subversion; // Contains build version
|
||||
|
||||
// Server launch stuffs
|
||||
UINT8 serverplayer;
|
||||
UINT8 totalslotnum; // "Slots": highest player number in use plus one.
|
||||
|
@ -190,16 +191,19 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 _255;/* see serverinfo_pak */
|
||||
UINT8 packetversion;
|
||||
UINT8 modversion;
|
||||
char application[MAXAPPLICATION];
|
||||
UINT8 version; // Different versions don't work
|
||||
UINT8 subversion; // Contains build version
|
||||
UINT8 localplayers;
|
||||
UINT8 mode;
|
||||
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
|
||||
} ATTRPACK clientconfig_pak;
|
||||
|
||||
enum {
|
||||
REFUSE_JOINS_DISABLED = 1,
|
||||
REFUSE_SLOTS_FULL,
|
||||
REFUSE_BANNED,
|
||||
};
|
||||
|
||||
#define MAXSERVERNAME 32
|
||||
#define MAXFILENEEDED 915
|
||||
// This packet is too large
|
||||
|
@ -217,7 +221,7 @@ typedef struct
|
|||
UINT8 subversion;
|
||||
UINT8 numberofplayer;
|
||||
UINT8 maxplayer;
|
||||
UINT8 refusereason; // 0: joinable, 1: joins disabled, 2: full
|
||||
UINT8 refusereason; // 0: joinable, REFUSE enum
|
||||
char gametypename[24];
|
||||
UINT8 modifiedgame;
|
||||
UINT8 cheatsenabled;
|
||||
|
@ -401,6 +405,7 @@ void CL_Reset(void);
|
|||
void CL_ClearPlayer(INT32 playernum);
|
||||
void CL_QueryServerList(msg_server_t *list);
|
||||
void CL_UpdateServerList(boolean internetsearch, INT32 room);
|
||||
void CL_RemovePlayer(INT32 playernum, kickreason_t reason);
|
||||
// Is there a game running
|
||||
boolean Playing(void);
|
||||
|
||||
|
|
|
@ -33,9 +33,10 @@ typedef enum
|
|||
typedef struct
|
||||
{
|
||||
evtype_t type;
|
||||
INT32 data1; // keys / mouse/joystick buttons
|
||||
INT32 data2; // mouse/joystick x move
|
||||
INT32 data3; // mouse/joystick y move
|
||||
INT32 key; // keys/mouse/joystick buttons
|
||||
INT32 x; // mouse/joystick x move
|
||||
INT32 y; // mouse/joystick y move
|
||||
boolean repeated; // key repeat
|
||||
} event_t;
|
||||
|
||||
//
|
||||
|
|
62
src/d_main.c
62
src/d_main.c
|
@ -191,22 +191,22 @@ void D_ProcessEvents(void)
|
|||
if (ev->type == ev_keydown || ev->type == ev_keyup)
|
||||
{
|
||||
// Mouse buttons
|
||||
if ((UINT32)(ev->data1 - KEY_MOUSE1) < MOUSEBUTTONS)
|
||||
if ((UINT32)(ev->key - KEY_MOUSE1) < MOUSEBUTTONS)
|
||||
{
|
||||
if (ev->type == ev_keydown)
|
||||
mouse.buttons |= 1 << (ev->data1 - KEY_MOUSE1);
|
||||
mouse.buttons |= 1 << (ev->key - KEY_MOUSE1);
|
||||
else
|
||||
mouse.buttons &= ~(1 << (ev->data1 - KEY_MOUSE1));
|
||||
mouse.buttons &= ~(1 << (ev->key - KEY_MOUSE1));
|
||||
}
|
||||
else if ((UINT32)(ev->data1 - KEY_2MOUSE1) < MOUSEBUTTONS)
|
||||
else if ((UINT32)(ev->key - KEY_2MOUSE1) < MOUSEBUTTONS)
|
||||
{
|
||||
if (ev->type == ev_keydown)
|
||||
mouse2.buttons |= 1 << (ev->data1 - KEY_2MOUSE1);
|
||||
mouse2.buttons |= 1 << (ev->key - KEY_2MOUSE1);
|
||||
else
|
||||
mouse2.buttons &= ~(1 << (ev->data1 - KEY_2MOUSE1));
|
||||
mouse2.buttons &= ~(1 << (ev->key - KEY_2MOUSE1));
|
||||
}
|
||||
// Scroll (has no keyup event)
|
||||
else switch (ev->data1) {
|
||||
else switch (ev->key) {
|
||||
case KEY_MOUSEWHEELUP:
|
||||
mouse.buttons |= MB_SCROLLUP;
|
||||
break;
|
||||
|
@ -936,10 +936,26 @@ static void D_AddFile(char **list, const char *file)
|
|||
|
||||
newfile = malloc(strlen(file) + 1);
|
||||
if (!newfile)
|
||||
{
|
||||
I_Error("No more free memory to AddFile %s",file);
|
||||
}
|
||||
|
||||
strcpy(newfile, file);
|
||||
list[pnumwadfiles] = newfile;
|
||||
}
|
||||
|
||||
static void D_AddFolder(char **list, const char *file)
|
||||
{
|
||||
size_t pnumwadfiles;
|
||||
char *newfile;
|
||||
|
||||
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
|
||||
;
|
||||
|
||||
newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator
|
||||
if (!newfile)
|
||||
I_Error("No more free memory to AddFolder %s",file);
|
||||
|
||||
strcpy(newfile, file);
|
||||
strcat(newfile, PATHSEP);
|
||||
|
||||
list[pnumwadfiles] = newfile;
|
||||
}
|
||||
|
@ -1237,21 +1253,25 @@ void D_SRB2Main(void)
|
|||
// Do this up here so that WADs loaded through the command line can use ExecCfg
|
||||
COM_Init();
|
||||
|
||||
// add any files specified on the command line with -file wadfile
|
||||
// to the wad list
|
||||
// Add any files specified on the command line with
|
||||
// "-file <file>" or "-folder <folder>" to the add-on list
|
||||
if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server")))
|
||||
{
|
||||
if (M_CheckParm("-file"))
|
||||
{
|
||||
// the parms after p are wadfile/lump names,
|
||||
// until end of parms or another - preceded parm
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
const char *s = M_GetNextParm();
|
||||
INT32 addontype = 0;
|
||||
INT32 i;
|
||||
|
||||
if (s) // Check for NULL?
|
||||
D_AddFile(startuppwads, s);
|
||||
}
|
||||
for (i = 1; i < myargc; i++)
|
||||
{
|
||||
if (!strcasecmp(myargv[i], "-file"))
|
||||
addontype = 1;
|
||||
else if (!strcasecmp(myargv[i], "-folder"))
|
||||
addontype = 2;
|
||||
else if (myargv[i][0] == '-' || myargv[i][0] == '+')
|
||||
addontype = 0;
|
||||
else if (addontype == 1)
|
||||
D_AddFile(startuppwads, myargv[i]);
|
||||
else if (addontype == 2)
|
||||
D_AddFolder(startuppwads, myargv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
256
src/d_netcmd.c
256
src/d_netcmd.c
|
@ -63,7 +63,9 @@ static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
|
|||
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Pause(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Suicide(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RandomSeed(UINT8 **cp, INT32 playernum);
|
||||
|
@ -115,6 +117,7 @@ static void Command_Map_f(void);
|
|||
static void Command_ResetCamera_f(void);
|
||||
|
||||
static void Command_Addfile(void);
|
||||
static void Command_Addfolder(void);
|
||||
static void Command_ListWADS_f(void);
|
||||
static void Command_RunSOC(void);
|
||||
static void Command_Pause(void);
|
||||
|
@ -284,7 +287,7 @@ consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL
|
|||
|
||||
consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange);
|
||||
|
||||
static CV_PossibleValue_t minitimelimit_cons_t[] = {{15, "MIN"}, {9999, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t minitimelimit_cons_t[] = {{1, "MIN"}, {9999, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL);
|
||||
|
||||
consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
|
||||
|
@ -398,16 +401,16 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
"MAP",
|
||||
"EXITLEVEL",
|
||||
"ADDFILE",
|
||||
"ADDFOLDER",
|
||||
"PAUSE",
|
||||
"ADDPLAYER",
|
||||
"TEAMCHANGE",
|
||||
"CLEARSCORES",
|
||||
"LOGIN",
|
||||
"VERIFIED",
|
||||
"RANDOMSEED",
|
||||
"RUNSOC",
|
||||
"REQADDFILE",
|
||||
"DELFILE", // replace next time we add an XD
|
||||
"REQADDFOLDER",
|
||||
"SETMOTD",
|
||||
"SUICIDE",
|
||||
"LUACMD",
|
||||
|
@ -441,7 +444,9 @@ void D_RegisterServerCommands(void)
|
|||
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
|
||||
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
|
||||
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
|
||||
RegisterNetXCmd(XD_ADDFOLDER, Got_Addfoldercmd);
|
||||
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
|
||||
RegisterNetXCmd(XD_REQADDFOLDER, Got_RequestAddfoldercmd);
|
||||
RegisterNetXCmd(XD_PAUSE, Got_Pause);
|
||||
RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
|
||||
RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
|
||||
|
@ -472,6 +477,7 @@ void D_RegisterServerCommands(void)
|
|||
COM_AddCommand("showmap", Command_Showmap_f);
|
||||
COM_AddCommand("mapmd5", Command_Mapmd5_f);
|
||||
|
||||
COM_AddCommand("addfolder", Command_Addfolder);
|
||||
COM_AddCommand("addfile", Command_Addfile);
|
||||
COM_AddCommand("listwad", Command_ListWADS_f);
|
||||
|
||||
|
@ -3342,9 +3348,9 @@ static void Command_Addfile(void)
|
|||
++p;
|
||||
|
||||
// check total packet size and no of files currently loaded
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
|| ((packetsizetally + nameonlylength(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
|
||||
return;
|
||||
|
@ -3392,6 +3398,139 @@ static void Command_Addfile(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void Command_Addfolder(void)
|
||||
{
|
||||
size_t argc = COM_Argc(); // amount of arguments total
|
||||
size_t curarg; // current argument index
|
||||
|
||||
const char *addedfolders[argc]; // list of filenames already processed
|
||||
size_t numfoldersadded = 0; // the amount of filenames processed
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("addfolder <path> [path2...] [...]: Load add-ons\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// start at one to skip command name
|
||||
for (curarg = 1; curarg < argc; curarg++)
|
||||
{
|
||||
const char *fn, *p;
|
||||
char *fullpath;
|
||||
char buf[256];
|
||||
char *buf_p = buf;
|
||||
INT32 i, stat;
|
||||
size_t ii;
|
||||
boolean folderadded = false;
|
||||
|
||||
fn = COM_Argv(curarg);
|
||||
|
||||
// For the amount of filenames previously processed...
|
||||
for (ii = 0; ii < numfoldersadded; ii++)
|
||||
{
|
||||
// If this is one of them, don't try to add it.
|
||||
if (!strcmp(fn, addedfolders[ii]))
|
||||
{
|
||||
folderadded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we've added this one, skip to the next one.
|
||||
if (folderadded)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disallow non-printing characters and semicolons.
|
||||
for (i = 0; fn[i] != '\0'; i++)
|
||||
if (!isprint(fn[i]) || fn[i] == ';')
|
||||
return;
|
||||
|
||||
// Add file on your client directly if you aren't in a netgame.
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
P_AddFolder(fn);
|
||||
addedfolders[numfoldersadded++] = fn;
|
||||
continue;
|
||||
}
|
||||
|
||||
p = fn+strlen(fn);
|
||||
while(--p >= fn)
|
||||
if (*p == '\\' || *p == '/' || *p == ':')
|
||||
break;
|
||||
++p;
|
||||
|
||||
// Don't add an empty path.
|
||||
if (M_IsStringEmpty(fn))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Folder name is empty, skipping\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
// check total packet size and no of files currently loaded
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + strlen(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the path is valid.
|
||||
stat = W_IsPathToFolderValid(fn);
|
||||
|
||||
if (stat == 0)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Path %s is invalid, skipping\n"), fn);
|
||||
continue;
|
||||
}
|
||||
else if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Error accessing %s (%s), skipping\n"), fn, strerror(direrror));
|
||||
#else
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Error accessing %s, skipping\n"), fn);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the full path for this folder.
|
||||
fullpath = W_GetFullFolderPath(fn);
|
||||
|
||||
if (fullpath == NULL)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Path %s is invalid, skipping\n"), fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the folder is already added.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (samepaths(wadfiles[i]->path, fullpath) > 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(fullpath);
|
||||
|
||||
addedfolders[numfoldersadded++] = fn;
|
||||
|
||||
WRITESTRINGN(buf_p,p,240);
|
||||
|
||||
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
|
||||
SendNetXCmd(XD_REQADDFOLDER, buf, buf_p - buf);
|
||||
else
|
||||
SendNetXCmd(XD_ADDFOLDER, buf, buf_p - buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3420,9 +3559,9 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
|| ((packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfile(filename,md5sum,true);
|
||||
|
@ -3452,6 +3591,64 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
COM_BufAddText(va("addfile %s\n", filename));
|
||||
}
|
||||
|
||||
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char path[241];
|
||||
filestatus_t ncs = FS_NOTFOUND;
|
||||
boolean kick = false;
|
||||
boolean toomany = false;
|
||||
INT32 i,j;
|
||||
|
||||
READSTRINGN(*cp, path, 240);
|
||||
|
||||
/// \todo Integrity checks.
|
||||
|
||||
// Only the server processes this message.
|
||||
if (client)
|
||||
return;
|
||||
|
||||
// Disallow non-printing characters and semicolons.
|
||||
for (i = 0; path[i] != '\0'; i++)
|
||||
if (!isprint(path[i]) || path[i] == ';')
|
||||
kick = true;
|
||||
|
||||
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfolder command received from %s\n"), player_names[playernum]);
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||
return;
|
||||
}
|
||||
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + strlen(path) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfolder(path);
|
||||
|
||||
if (ncs != FS_FOUND || toomany)
|
||||
{
|
||||
char message[256];
|
||||
|
||||
if (toomany)
|
||||
sprintf(message, M_GetText("Too many files loaded to add %s\n"), path);
|
||||
else if (ncs == FS_NOTFOUND)
|
||||
sprintf(message, M_GetText("The server doesn't have %s\n"), path);
|
||||
else
|
||||
sprintf(message, M_GetText("Unknown error finding folder (%s)\n"), path);
|
||||
|
||||
CONS_Printf("%s",message);
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
if (adminplayers[j])
|
||||
COM_BufAddText(va("sayto %d %s", adminplayers[j], message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
COM_BufAddText(va("addfolder \"%s\"\n", path));
|
||||
}
|
||||
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3500,6 +3697,49 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
|||
G_SetGameModified(true);
|
||||
}
|
||||
|
||||
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char path[241];
|
||||
filestatus_t ncs = FS_NOTFOUND;
|
||||
|
||||
READSTRINGN(*cp, path, 240);
|
||||
|
||||
/// \todo Integrity checks.
|
||||
|
||||
if (playernum != serverplayer)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfolder command received from %s\n"), player_names[playernum]);
|
||||
if (server)
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||
return;
|
||||
}
|
||||
|
||||
ncs = findfolder(path);
|
||||
|
||||
if (ncs != FS_FOUND || !P_AddFolder(path))
|
||||
{
|
||||
Command_ExitGame_f();
|
||||
if (ncs == FS_FOUND)
|
||||
{
|
||||
CONS_Printf(M_GetText("The server tried to add %s,\nbut you have too many files added.\nRestart the game to clear loaded files\nand play on this server."), path);
|
||||
M_StartMessage(va("The server added a folder \n(%s)\nbut you have too many files added.\nRestart the game to clear loaded files.\n\nPress ESC\n",path), NULL, MM_NOTHING);
|
||||
}
|
||||
else if (ncs == FS_NOTFOUND)
|
||||
{
|
||||
CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), path);
|
||||
M_StartMessage(va("The server added a folder \n(%s)\nthat you do not have.\n\nPress ESC\n",path), NULL, MM_NOTHING);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Unknown error finding folder (%s) the server added.\n"), path);
|
||||
M_StartMessage(va("Unknown error trying to load a folder\nthat the server added \n(%s).\n\nPress ESC\n",path), NULL, MM_NOTHING);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
G_SetGameModified(true);
|
||||
}
|
||||
|
||||
static void Command_ListWADS_f(void)
|
||||
{
|
||||
INT32 i = numwadfiles;
|
||||
|
@ -3514,6 +3754,8 @@ static void Command_ListWADS_f(void)
|
|||
CONS_Printf("\x82 * %.2d\x80: %s\n", i, tempname);
|
||||
else if (!wadfiles[i]->important)
|
||||
CONS_Printf("\x86 %.2d: %s\n", i, tempname);
|
||||
else if (wadfiles[i]->type == RET_FOLDER)
|
||||
CONS_Printf("\x82 * %.2d\x84: %s\n", i, tempname);
|
||||
else
|
||||
CONS_Printf(" %.2d: %s\n", i, tempname);
|
||||
}
|
||||
|
|
|
@ -128,16 +128,16 @@ typedef enum
|
|||
XD_MAP, // 6
|
||||
XD_EXITLEVEL, // 7
|
||||
XD_ADDFILE, // 8
|
||||
XD_PAUSE, // 9
|
||||
XD_ADDPLAYER, // 10
|
||||
XD_TEAMCHANGE, // 11
|
||||
XD_CLEARSCORES, // 12
|
||||
// UNUSED 13 (Because I don't want to change these comments)
|
||||
XD_VERIFIED = 14,//14
|
||||
XD_ADDFOLDER, // 9
|
||||
XD_PAUSE, // 10
|
||||
XD_ADDPLAYER, // 11
|
||||
XD_TEAMCHANGE, // 12
|
||||
XD_CLEARSCORES, // 13
|
||||
XD_VERIFIED, // 14
|
||||
XD_RANDOMSEED, // 15
|
||||
XD_RUNSOC, // 16
|
||||
XD_REQADDFILE, // 17
|
||||
XD_DELFILE, // 18 - replace next time we add an XD
|
||||
XD_REQADDFOLDER,// 18
|
||||
XD_SETMOTD, // 19
|
||||
XD_SUICIDE, // 20
|
||||
XD_DEMOTED, // 21
|
||||
|
|
|
@ -116,7 +116,7 @@ char luafiledir[256 + 16] = "luafiles";
|
|||
/** Fills a serverinfo packet with information about wad files loaded.
|
||||
*
|
||||
* \todo Give this function a better name since it is in global scope.
|
||||
* Used to have size limiting built in - now handled via W_LoadWadFile in w_wad.c
|
||||
* Used to have size limiting built in - now handled via W_InitFile in w_wad.c
|
||||
*
|
||||
*/
|
||||
UINT8 *PutFileNeeded(void)
|
||||
|
@ -124,7 +124,7 @@ UINT8 *PutFileNeeded(void)
|
|||
size_t i, count = 0;
|
||||
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
|
||||
char wadfilename[MAX_WADPATH] = "";
|
||||
UINT8 filestatus;
|
||||
UINT8 filestatus, folder;
|
||||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
|
@ -133,9 +133,10 @@ UINT8 *PutFileNeeded(void)
|
|||
continue;
|
||||
|
||||
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
|
||||
folder = (wadfiles[i]->type == RET_FOLDER);
|
||||
|
||||
// Store in the upper four bits
|
||||
if (!cv_downloading.value)
|
||||
if (!cv_downloading.value || folder) /// \todo Implement folder downloading.
|
||||
filestatus += (2 << 4); // Won't send
|
||||
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
|
||||
filestatus += (1 << 4); // Will send if requested
|
||||
|
@ -143,6 +144,7 @@ UINT8 *PutFileNeeded(void)
|
|||
// filestatus += (0 << 4); -- Won't send, too big
|
||||
|
||||
WRITEUINT8(p, filestatus);
|
||||
WRITEUINT8(p, folder);
|
||||
|
||||
count++;
|
||||
WRITEUINT32(p, wadfiles[i]->filesize);
|
||||
|
@ -174,6 +176,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
|
|||
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
|
||||
fileneeded[i].justdownloaded = false;
|
||||
filestatus = READUINT8(p); // The first byte is the file status
|
||||
fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag
|
||||
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
||||
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
||||
fileneeded[i].file = NULL; // The file isn't open yet
|
||||
|
@ -416,7 +419,7 @@ INT32 CL_CheckFiles(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
// See W_InitFile in w_wad.c
|
||||
packetsize = packetsizetally;
|
||||
|
||||
for (i = 1; i < fileneedednum; i++)
|
||||
|
@ -438,7 +441,10 @@ INT32 CL_CheckFiles(void)
|
|||
if (fileneeded[i].status != FS_NOTFOUND)
|
||||
continue;
|
||||
|
||||
packetsize += nameonlylength(fileneeded[i].filename) + 22;
|
||||
if (fileneeded[i].folder)
|
||||
packetsize += strlen(fileneeded[i].filename) + FILENEEDEDSIZE;
|
||||
else
|
||||
packetsize += nameonlylength(fileneeded[i].filename) + FILENEEDEDSIZE;
|
||||
|
||||
if ((numwadfiles+filestoget >= MAX_WADFILES)
|
||||
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
|
||||
|
@ -446,7 +452,10 @@ INT32 CL_CheckFiles(void)
|
|||
|
||||
filestoget++;
|
||||
|
||||
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
|
||||
if (fileneeded[i].folder)
|
||||
fileneeded[i].status = findfolder(fileneeded[i].filename);
|
||||
else
|
||||
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
|
||||
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
|
||||
if (fileneeded[i].status != FS_FOUND)
|
||||
ret = 0;
|
||||
|
@ -468,7 +477,10 @@ void CL_LoadServerFiles(void)
|
|||
continue; // Already loaded
|
||||
else if (fileneeded[i].status == FS_FOUND)
|
||||
{
|
||||
P_AddWadFile(fileneeded[i].filename);
|
||||
if (fileneeded[i].folder)
|
||||
P_AddFolder(fileneeded[i].filename);
|
||||
else
|
||||
P_AddWadFile(fileneeded[i].filename);
|
||||
G_SetGameModified(true);
|
||||
fileneeded[i].status = FS_OPEN;
|
||||
}
|
||||
|
@ -756,7 +768,7 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
|
|||
// This formerly checked if (!findfile(p->id.filename, NULL, true))
|
||||
|
||||
// Not found
|
||||
// Don't inform client (probably someone who thought they could leak 2.2 ACZ)
|
||||
// Don't inform client
|
||||
DEBFILE(va("Client %d request %s: not found\n", node, filename));
|
||||
free(p->id.filename);
|
||||
free(p);
|
||||
|
@ -1571,3 +1583,26 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
|
|||
|
||||
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
|
||||
}
|
||||
|
||||
// Searches for a folder.
|
||||
// This can be used with a full path, or an incomplete path.
|
||||
// In the latter case, the function will try to find folders in
|
||||
// srb2home, srb2path, and the current directory.
|
||||
filestatus_t findfolder(const char *path)
|
||||
{
|
||||
// Check the path by itself first.
|
||||
if (concatpaths(path, NULL) == 1)
|
||||
return FS_FOUND;
|
||||
|
||||
#define checkpath(startpath) \
|
||||
if (concatpaths(path, startpath) == 1) \
|
||||
return FS_FOUND
|
||||
|
||||
checkpath(srb2home); // Then, look in srb2home.
|
||||
checkpath(srb2path); // Now, look in srb2path.
|
||||
checkpath("."); // Finally, look in the current directory.
|
||||
|
||||
#undef checkpath
|
||||
|
||||
return FS_NOTFOUND;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef enum
|
|||
typedef struct
|
||||
{
|
||||
UINT8 willsend; // Is the server willing to send it?
|
||||
UINT8 folder; // File is a folder
|
||||
char filename[MAX_WADPATH];
|
||||
UINT8 md5sum[16];
|
||||
filestatus_t status; // The value returned by recsearch
|
||||
|
@ -54,6 +55,8 @@ typedef struct
|
|||
UINT32 ackresendposition; // Used when resuming downloads
|
||||
} fileneeded_t;
|
||||
|
||||
#define FILENEEDEDSIZE 23
|
||||
|
||||
extern INT32 fileneedednum;
|
||||
extern fileneeded_t fileneeded[MAX_WADFILES];
|
||||
extern char downloaddir[512];
|
||||
|
@ -135,6 +138,9 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
|
|||
boolean completepath);
|
||||
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);
|
||||
|
||||
// Searches for a folder
|
||||
filestatus_t findfolder(const char *path);
|
||||
|
||||
void nameonly(char *s);
|
||||
size_t nameonlylength(const char *s);
|
||||
|
||||
|
|
|
@ -313,9 +313,43 @@ typedef enum
|
|||
RW_RAIL = 32
|
||||
} ringweapons_t;
|
||||
|
||||
//Bot types
|
||||
typedef enum
|
||||
{
|
||||
BOT_NONE = 0,
|
||||
BOT_2PAI,
|
||||
BOT_2PHUMAN,
|
||||
BOT_MPAI
|
||||
} bottype_t;
|
||||
|
||||
//AI states
|
||||
typedef enum
|
||||
{
|
||||
AI_STANDBY = 0,
|
||||
AI_FOLLOW,
|
||||
AI_CATCHUP,
|
||||
AI_THINKFLY,
|
||||
AI_FLYSTANDBY,
|
||||
AI_FLYCARRY,
|
||||
AI_SPINFOLLOW
|
||||
} aistatetype_t;
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// PLAYER STRUCTURE
|
||||
// ========================================================================
|
||||
|
||||
//Bot memory struct
|
||||
typedef struct botmem_s
|
||||
{
|
||||
boolean lastForward;
|
||||
boolean lastBlocked;
|
||||
boolean blocked;
|
||||
UINT8 catchup_tics;
|
||||
UINT8 thinkstate;
|
||||
} botmem_t;
|
||||
|
||||
//Main struct
|
||||
typedef struct player_s
|
||||
{
|
||||
mobj_t *mo;
|
||||
|
@ -525,7 +559,12 @@ typedef struct player_s
|
|||
|
||||
boolean spectator;
|
||||
boolean outofcoop;
|
||||
boolean removing;
|
||||
UINT8 bot;
|
||||
struct player_s *botleader;
|
||||
UINT16 lastbuttons;
|
||||
botmem_t botmem;
|
||||
boolean blocked;
|
||||
|
||||
tic_t jointime; // Timer when player joins game to change skin/color
|
||||
tic_t quittime; // Time elapsed since user disconnected, zero if connected
|
||||
|
|
|
@ -5170,6 +5170,12 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"GF_REDFLAG",GF_REDFLAG},
|
||||
{"GF_BLUEFLAG",GF_BLUEFLAG},
|
||||
|
||||
// Bot types
|
||||
{"BOT_NONE",BOT_NONE},
|
||||
{"BOT_2PAI",BOT_2PAI},
|
||||
{"BOT_2PHUMAN",BOT_2PHUMAN},
|
||||
{"BOT_MPAI",BOT_MPAI},
|
||||
|
||||
// Customisable sounds for Skins, from sounds.h
|
||||
{"SKSSPIN",SKSSPIN},
|
||||
{"SKSPUTPUT",SKSPUTPUT},
|
||||
|
@ -5482,49 +5488,49 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"JOYAXISRANGE",JOYAXISRANGE},
|
||||
|
||||
// Game controls
|
||||
{"gc_null",gc_null},
|
||||
{"gc_forward",gc_forward},
|
||||
{"gc_backward",gc_backward},
|
||||
{"gc_strafeleft",gc_strafeleft},
|
||||
{"gc_straferight",gc_straferight},
|
||||
{"gc_turnleft",gc_turnleft},
|
||||
{"gc_turnright",gc_turnright},
|
||||
{"gc_weaponnext",gc_weaponnext},
|
||||
{"gc_weaponprev",gc_weaponprev},
|
||||
{"gc_wepslot1",gc_wepslot1},
|
||||
{"gc_wepslot2",gc_wepslot2},
|
||||
{"gc_wepslot3",gc_wepslot3},
|
||||
{"gc_wepslot4",gc_wepslot4},
|
||||
{"gc_wepslot5",gc_wepslot5},
|
||||
{"gc_wepslot6",gc_wepslot6},
|
||||
{"gc_wepslot7",gc_wepslot7},
|
||||
{"gc_wepslot8",gc_wepslot8},
|
||||
{"gc_wepslot9",gc_wepslot9},
|
||||
{"gc_wepslot10",gc_wepslot10},
|
||||
{"gc_fire",gc_fire},
|
||||
{"gc_firenormal",gc_firenormal},
|
||||
{"gc_tossflag",gc_tossflag},
|
||||
{"gc_spin",gc_spin},
|
||||
{"gc_camtoggle",gc_camtoggle},
|
||||
{"gc_camreset",gc_camreset},
|
||||
{"gc_lookup",gc_lookup},
|
||||
{"gc_lookdown",gc_lookdown},
|
||||
{"gc_centerview",gc_centerview},
|
||||
{"gc_mouseaiming",gc_mouseaiming},
|
||||
{"gc_talkkey",gc_talkkey},
|
||||
{"gc_teamkey",gc_teamkey},
|
||||
{"gc_scores",gc_scores},
|
||||
{"gc_jump",gc_jump},
|
||||
{"gc_console",gc_console},
|
||||
{"gc_pause",gc_pause},
|
||||
{"gc_systemmenu",gc_systemmenu},
|
||||
{"gc_screenshot",gc_screenshot},
|
||||
{"gc_recordgif",gc_recordgif},
|
||||
{"gc_viewpoint",gc_viewpoint},
|
||||
{"gc_custom1",gc_custom1},
|
||||
{"gc_custom2",gc_custom2},
|
||||
{"gc_custom3",gc_custom3},
|
||||
{"num_gamecontrols",num_gamecontrols},
|
||||
{"GC_NULL",GC_NULL},
|
||||
{"GC_FORWARD",GC_FORWARD},
|
||||
{"GC_BACKWARD",GC_BACKWARD},
|
||||
{"GC_STRAFELEFT",GC_STRAFELEFT},
|
||||
{"GC_STRAFERIGHT",GC_STRAFERIGHT},
|
||||
{"GC_TURNLEFT",GC_TURNLEFT},
|
||||
{"GC_TURNRIGHT",GC_TURNRIGHT},
|
||||
{"GC_WEAPONNEXT",GC_WEAPONNEXT},
|
||||
{"GC_WEAPONPREV",GC_WEAPONPREV},
|
||||
{"GC_WEPSLOT1",GC_WEPSLOT1},
|
||||
{"GC_WEPSLOT2",GC_WEPSLOT2},
|
||||
{"GC_WEPSLOT3",GC_WEPSLOT3},
|
||||
{"GC_WEPSLOT4",GC_WEPSLOT4},
|
||||
{"GC_WEPSLOT5",GC_WEPSLOT5},
|
||||
{"GC_WEPSLOT6",GC_WEPSLOT6},
|
||||
{"GC_WEPSLOT7",GC_WEPSLOT7},
|
||||
{"GC_WEPSLOT8",GC_WEPSLOT8},
|
||||
{"GC_WEPSLOT9",GC_WEPSLOT9},
|
||||
{"GC_WEPSLOT10",GC_WEPSLOT10},
|
||||
{"GC_FIRE",GC_FIRE},
|
||||
{"GC_FIRENORMAL",GC_FIRENORMAL},
|
||||
{"GC_TOSSFLAG",GC_TOSSFLAG},
|
||||
{"GC_SPIN",GC_SPIN},
|
||||
{"GC_CAMTOGGLE",GC_CAMTOGGLE},
|
||||
{"GC_CAMRESET",GC_CAMRESET},
|
||||
{"GC_LOOKUP",GC_LOOKUP},
|
||||
{"GC_LOOKDOWN",GC_LOOKDOWN},
|
||||
{"GC_CENTERVIEW",GC_CENTERVIEW},
|
||||
{"GC_MOUSEAIMING",GC_MOUSEAIMING},
|
||||
{"GC_TALKKEY",GC_TALKKEY},
|
||||
{"GC_TEAMKEY",GC_TEAMKEY},
|
||||
{"GC_SCORES",GC_SCORES},
|
||||
{"GC_JUMP",GC_JUMP},
|
||||
{"GC_CONSOLE",GC_CONSOLE},
|
||||
{"GC_PAUSE",GC_PAUSE},
|
||||
{"GC_SYSTEMMENU",GC_SYSTEMMENU},
|
||||
{"GC_SCREENSHOT",GC_SCREENSHOT},
|
||||
{"GC_RECORDGIF",GC_RECORDGIF},
|
||||
{"GC_VIEWPOINT",GC_VIEWPOINT},
|
||||
{"GC_CUSTOM1",GC_CUSTOM1},
|
||||
{"GC_CUSTOM2",GC_CUSTOM2},
|
||||
{"GC_CUSTOM3",GC_CUSTOM3},
|
||||
{"NUM_GAMECONTROLS",NUM_GAMECONTROLS},
|
||||
|
||||
// Mouse buttons
|
||||
{"MB_BUTTON1",MB_BUTTON1},
|
||||
|
|
|
@ -127,6 +127,7 @@ extern char logfilename[1024];
|
|||
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
|
||||
#ifdef DEVELOP
|
||||
#define VERSIONSTRING "Development EXE"
|
||||
#define VERSIONSTRING_RC "Development EXE" "\0"
|
||||
// most interface strings are ignored in development mode.
|
||||
// we use comprevision and compbranch instead.
|
||||
// VERSIONSTRING_RC is for the resource-definition script used by windows builds
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "console.h"
|
||||
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hook.h"
|
||||
|
||||
// Stage of animation:
|
||||
// 0 = text, 1 = art screen
|
||||
|
@ -1011,7 +1012,7 @@ void F_IntroTicker(void)
|
|||
//
|
||||
boolean F_IntroResponder(event_t *event)
|
||||
{
|
||||
INT32 key = event->data1;
|
||||
INT32 key = event->key;
|
||||
|
||||
// remap virtual keys (mouse & joystick buttons)
|
||||
switch (key)
|
||||
|
@ -1089,7 +1090,6 @@ static const char *credits[] = {
|
|||
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
|
||||
"Kepa \"Nev3r\" Iceta",
|
||||
"Thomas \"Shadow Hog\" Igoe",
|
||||
"\"james\"",
|
||||
"Iestyn \"Monster Iestyn\" Jealous",
|
||||
"\"Jimita\"",
|
||||
"\"Kaito Sinclaire\"",
|
||||
|
@ -1102,6 +1102,7 @@ static const char *credits[] = {
|
|||
"Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol
|
||||
"John \"JTE\" Muniz",
|
||||
"Colin \"Sonict\" Pfaff",
|
||||
"James \"james\" Robert Roman",
|
||||
"Sean \"Sryder13\" Ryder",
|
||||
"Ehab \"Wolfy\" Saeed",
|
||||
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
|
||||
|
@ -1166,7 +1167,6 @@ static const char *credits[] = {
|
|||
"Alexander \"DrTapeworm\" Moench-Ford",
|
||||
"Stefan \"Stuf\" Rimalia",
|
||||
"Shane Mychal Sexton",
|
||||
"\"Spazzo\"",
|
||||
"David \"Big Wave Dave\" Spencer Sr.",
|
||||
"David \"Instant Sonic\" Spencer Jr.",
|
||||
"\"SSNTails\"",
|
||||
|
@ -1191,7 +1191,6 @@ static const char *credits[] = {
|
|||
"\"Revan\"",
|
||||
"Anna \"QueenDelta\" Sandlin",
|
||||
"Wessel \"sphere\" Smit",
|
||||
"\"Spazzo\"",
|
||||
"\"SSNTails\"",
|
||||
"Rob Tisdell",
|
||||
"\"Torgo\"",
|
||||
|
@ -1399,7 +1398,7 @@ void F_CreditTicker(void)
|
|||
|
||||
boolean F_CreditResponder(event_t *event)
|
||||
{
|
||||
INT32 key = event->data1;
|
||||
INT32 key = event->key;
|
||||
|
||||
// remap virtual keys (mouse & joystick buttons)
|
||||
switch (key)
|
||||
|
@ -3423,7 +3422,7 @@ void F_TitleScreenDrawer(void)
|
|||
}
|
||||
|
||||
luahook:
|
||||
LUAh_TitleHUD();
|
||||
LUA_HUDHOOK(title);
|
||||
}
|
||||
|
||||
// separate animation timer for backgrounds, since we also count
|
||||
|
@ -3823,7 +3822,7 @@ void F_ContinueTicker(void)
|
|||
|
||||
boolean F_ContinueResponder(event_t *event)
|
||||
{
|
||||
INT32 key = event->data1;
|
||||
INT32 key = event->key;
|
||||
|
||||
if (keypressed)
|
||||
return true;
|
||||
|
|
398
src/filesrch.c
398
src/filesrch.c
|
@ -13,6 +13,7 @@
|
|||
/// FS_FOUND
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifdef __GNUC__
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
@ -29,10 +30,10 @@
|
|||
#include "m_misc.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_menu.h" // Addons_option_Onchange
|
||||
#include "w_wad.h"
|
||||
|
||||
#if defined (_WIN32) && defined (_MSC_VER)
|
||||
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <tchar.h>
|
||||
|
||||
|
@ -340,6 +341,11 @@ char *refreshdirname = NULL;
|
|||
size_t packetsizetally = 0;
|
||||
size_t mainwadstally = 0;
|
||||
|
||||
#define dirpathlen 1024
|
||||
#define maxdirdepth 48
|
||||
|
||||
#define isuptree(dirent) ((dirent)[0]=='.' && ((dirent)[1]=='\0' || ((dirent)[1]=='.' && (dirent)[2]=='\0')))
|
||||
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
|
||||
{
|
||||
filestatus_t retval = FS_NOTFOUND;
|
||||
|
@ -387,10 +393,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
continue;
|
||||
}
|
||||
|
||||
if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
if (isuptree(dent->d_name))
|
||||
{
|
||||
// we don't want to scan uptree
|
||||
continue;
|
||||
|
@ -445,6 +448,380 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifndef AVOID_ERRNO
|
||||
int direrror = 0;
|
||||
#endif
|
||||
|
||||
// Checks if the specified path is a directory.
|
||||
// Returns 1 if so, 0 if not, and -1 if an error occurred.
|
||||
// direrror is set if there was an error.
|
||||
INT32 pathisdirectory(const char *path)
|
||||
{
|
||||
struct stat fsstat;
|
||||
|
||||
if (stat(path, &fsstat) < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = errno;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else if (S_ISDIR(fsstat.st_mode))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Concatenates two paths, and checks if it is a directory that can be opened.
|
||||
// Returns 1 if so, 0 if not, and -1 if an error occurred.
|
||||
INT32 concatpaths(const char *path, const char *startpath)
|
||||
{
|
||||
char dirpath[dirpathlen];
|
||||
DIR *dirhandle;
|
||||
INT32 stat;
|
||||
|
||||
if (startpath)
|
||||
{
|
||||
char basepath[dirpathlen];
|
||||
|
||||
snprintf(basepath, sizeof basepath, "%s" PATHSEP, startpath);
|
||||
snprintf(dirpath, sizeof dirpath, "%s%s", basepath, path);
|
||||
|
||||
// Base path and directory path are the same? Not valid.
|
||||
stat = samepaths(basepath, dirpath);
|
||||
|
||||
if (stat == 1)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
snprintf(dirpath, sizeof dirpath, "%s", path);
|
||||
|
||||
// Check if the path is a directory.
|
||||
// Will return -1 if there was an error.
|
||||
stat = pathisdirectory(dirpath);
|
||||
if (stat == 0)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
{
|
||||
// The path doesn't exist, so it can't be a directory.
|
||||
if (direrror == ENOENT)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open the directory.
|
||||
// Will return 0 if it couldn't be opened.
|
||||
dirhandle = opendir(dirpath);
|
||||
if (dirhandle == NULL)
|
||||
return 0;
|
||||
else
|
||||
closedir(dirhandle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if two paths are the same. Returns 1 if so, and 0 if not.
|
||||
// Returns -1 if an error occurred with the first path,
|
||||
// and returns -2 if an error occurred with the second path.
|
||||
// direrror is set if there was an error.
|
||||
INT32 samepaths(const char *path1, const char *path2)
|
||||
{
|
||||
struct stat stat1;
|
||||
struct stat stat2;
|
||||
|
||||
if (stat(path1, &stat1) < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = errno;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if (stat(path2, &stat2) < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = errno;
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (stat1.st_dev == stat2.st_dev)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
return (stat1.st_ino == stat2.st_ino);
|
||||
#else
|
||||
// The above doesn't work on NTFS or FAT.
|
||||
HANDLE file1 = CreateFileA(path1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
HANDLE file2 = CreateFileA(path2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
BY_HANDLE_FILE_INFORMATION file1info, file2info;
|
||||
|
||||
if (file1 == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = ENOENT;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else if (file2 == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(file1);
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = ENOENT;
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
// I have no idea why GetFileInformationByHandle would fail.
|
||||
// Microsoft's documentation doesn't tell me.
|
||||
// I'll just use EIO...
|
||||
if (!GetFileInformationByHandle(file1, &file1info))
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = EIO;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else if (!GetFileInformationByHandle(file2, &file2info))
|
||||
{
|
||||
CloseHandle(file1);
|
||||
CloseHandle(file2);
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = EIO;
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (file1info.dwVolumeSerialNumber == file2info.dwVolumeSerialNumber
|
||||
&& file1info.nFileIndexLow == file2info.nFileIndexLow
|
||||
&& file1info.nFileIndexHigh == file2info.nFileIndexHigh)
|
||||
{
|
||||
CloseHandle(file1);
|
||||
CloseHandle(file2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Directory loading
|
||||
//
|
||||
|
||||
static void initdirpath(char *dirpath, size_t *dirpathindex, int depthleft)
|
||||
{
|
||||
dirpathindex[depthleft] = strlen(dirpath) + 1;
|
||||
|
||||
if (dirpath[dirpathindex[depthleft]-2] != PATHSEP[0])
|
||||
{
|
||||
dirpath[dirpathindex[depthleft]-1] = PATHSEP[0];
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
dirpathindex[depthleft]--;
|
||||
}
|
||||
|
||||
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
|
||||
{
|
||||
DIR **dirhandle;
|
||||
struct dirent *dent;
|
||||
struct stat fsstat;
|
||||
|
||||
int rootdir = (maxdirdepth - 1);
|
||||
int depthleft = rootdir;
|
||||
|
||||
char dirpath[dirpathlen];
|
||||
size_t *dirpathindex;
|
||||
|
||||
lumpinfo_t *lumpinfo, *lump_p;
|
||||
UINT16 i = 0, numlumps = 0;
|
||||
|
||||
boolean failure = false;
|
||||
|
||||
dirhandle = (DIR **)malloc(maxdirdepth * sizeof (DIR*));
|
||||
dirpathindex = (size_t *)malloc(maxdirdepth * sizeof(size_t));
|
||||
|
||||
// Open the root directory
|
||||
strlcpy(dirpath, path, dirpathlen);
|
||||
dirhandle[depthleft] = opendir(dirpath);
|
||||
|
||||
if (dirhandle[depthleft] == NULL)
|
||||
{
|
||||
free(dirhandle);
|
||||
free(dirpathindex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
initdirpath(dirpath, dirpathindex, depthleft);
|
||||
(*nfolders) = 0;
|
||||
|
||||
// Count files and directories
|
||||
while (depthleft < maxdirdepth)
|
||||
{
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
|
||||
if (!dent)
|
||||
{
|
||||
if (depthleft != rootdir) // Don't close the root directory
|
||||
closedir(dirhandle[depthleft]);
|
||||
depthleft++;
|
||||
continue;
|
||||
}
|
||||
else if (isuptree(dent->d_name))
|
||||
continue;
|
||||
|
||||
strcpy(&dirpath[dirpathindex[depthleft]], dent->d_name);
|
||||
|
||||
if (stat(dirpath, &fsstat) < 0)
|
||||
;
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
dirpathindex[--depthleft] = strlen(dirpath) + 1;
|
||||
dirhandle[depthleft] = opendir(dirpath);
|
||||
|
||||
if (dirhandle[depthleft])
|
||||
(*nfolders)++;
|
||||
else
|
||||
depthleft++;
|
||||
|
||||
dirpath[dirpathindex[depthleft]-1] = '/';
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
numlumps++;
|
||||
|
||||
// Failure: Too many files.
|
||||
if (numlumps == UINT16_MAX)
|
||||
{
|
||||
(*nlmp) = UINT16_MAX;
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Failure: No files have been found.
|
||||
if (!numlumps)
|
||||
{
|
||||
(*nlmp) = 0;
|
||||
failure = true;
|
||||
}
|
||||
|
||||
// Close any open directories and return if something went wrong.
|
||||
if (failure)
|
||||
{
|
||||
free(dirpathindex);
|
||||
free(dirhandle);
|
||||
for (; depthleft < maxdirdepth; closedir(dirhandle[depthleft++]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the files and directories as lump entries
|
||||
// It's possible to create lumps and count files at the same time,
|
||||
// but I didn't want to have to reallocate memory for every lump.
|
||||
rewinddir(dirhandle[rootdir]);
|
||||
depthleft = rootdir;
|
||||
|
||||
strlcpy(dirpath, path, dirpathlen);
|
||||
initdirpath(dirpath, dirpathindex, depthleft);
|
||||
|
||||
lump_p = lumpinfo = Z_Calloc(numlumps * sizeof(lumpinfo_t), PU_STATIC, NULL);
|
||||
|
||||
while (depthleft < maxdirdepth)
|
||||
{
|
||||
char *fullname, *trimname;
|
||||
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
|
||||
if (!dent)
|
||||
{
|
||||
closedir(dirhandle[depthleft++]);
|
||||
continue;
|
||||
}
|
||||
else if (isuptree(dent->d_name))
|
||||
continue;
|
||||
|
||||
strcpy(&dirpath[dirpathindex[depthleft]], dent->d_name);
|
||||
|
||||
if (stat(dirpath, &fsstat) < 0)
|
||||
continue;
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
dirpathindex[--depthleft] = strlen(dirpath) + 1;
|
||||
dirhandle[depthleft] = opendir(dirpath);
|
||||
|
||||
if (dirhandle[depthleft])
|
||||
{
|
||||
dirpath[dirpathindex[depthleft]-1] = '/';
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
depthleft++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
lump_p->diskpath = Z_StrDup(dirpath); // Path in the filesystem to the file
|
||||
lump_p->compression = CM_NOCOMPRESSION; // Lump is uncompressed
|
||||
|
||||
// Remove the directory's path.
|
||||
fullname = lump_p->diskpath;
|
||||
if (strstr(fullname, path))
|
||||
fullname += strlen(path) + 1;
|
||||
|
||||
// Get the 8-character long lump name.
|
||||
trimname = strrchr(fullname, '/');
|
||||
if (trimname)
|
||||
trimname++;
|
||||
else
|
||||
trimname = fullname;
|
||||
|
||||
if (trimname[0])
|
||||
{
|
||||
char *dotpos = strrchr(trimname, '.');
|
||||
if (dotpos == NULL)
|
||||
dotpos = fullname + strlen(fullname);
|
||||
|
||||
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
|
||||
|
||||
// The name of the file, without the extension.
|
||||
lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
|
||||
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
|
||||
}
|
||||
else
|
||||
lump_p->longname = Z_Calloc(1, PU_STATIC, NULL);
|
||||
|
||||
// The complete name of the file, with its extension,
|
||||
// excluding the path of the directory where it resides.
|
||||
lump_p->fullname = Z_StrDup(fullname);
|
||||
|
||||
lump_p++;
|
||||
i++;
|
||||
|
||||
if (i > numlumps || i == (UINT16_MAX-1))
|
||||
{
|
||||
for (; depthleft < maxdirdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(dirpathindex);
|
||||
free(dirhandle);
|
||||
|
||||
(*nlmp) = numlumps;
|
||||
return lumpinfo;
|
||||
}
|
||||
|
||||
//
|
||||
// Addons menu
|
||||
//
|
||||
|
||||
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)
|
||||
"\5.txt", "\5.cfg", // exec
|
||||
"\5.wad",
|
||||
|
@ -455,7 +832,6 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl
|
|||
|
||||
char filenamebuf[MAX_WADFILES][MAX_WADPATH];
|
||||
|
||||
|
||||
static boolean filemenucmp(char *haystack, char *needle)
|
||||
{
|
||||
static char localhaystack[128];
|
||||
|
@ -640,10 +1016,7 @@ boolean preparefilemenu(boolean samedepth)
|
|||
|
||||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
else if (isuptree(dent->d_name))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
@ -704,10 +1077,7 @@ boolean preparefilemenu(boolean samedepth)
|
|||
|
||||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
else if (isuptree(dent->d_name))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
#include "w_wad.h"
|
||||
|
||||
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
|
||||
|
||||
|
@ -28,6 +29,16 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
|
|||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth);
|
||||
|
||||
INT32 pathisdirectory(const char *path);
|
||||
INT32 samepaths(const char *path1, const char *path2);
|
||||
INT32 concatpaths(const char *path, const char *startpath);
|
||||
|
||||
#ifndef AVOID_ERRNO
|
||||
extern int direrror;
|
||||
#endif
|
||||
|
||||
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders);
|
||||
|
||||
#define menudepth 20
|
||||
|
||||
extern char menupath[1024];
|
||||
|
@ -94,5 +105,4 @@ typedef enum
|
|||
void closefilemenu(boolean validsize);
|
||||
void searchfilemenu(char *tempname);
|
||||
boolean preparefilemenu(boolean samedepth);
|
||||
|
||||
#endif // __FILESRCH_H__
|
||||
|
|
21
src/g_demo.c
21
src/g_demo.c
|
@ -1680,6 +1680,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
switch(oldversion) // demoversion
|
||||
{
|
||||
case DEMOVERSION: // latest always supported
|
||||
case 0x000d: // The previous demoversion also supported
|
||||
case 0x000c: // all that changed between then and now was longer color name
|
||||
break;
|
||||
// too old, cannot support.
|
||||
|
@ -2023,7 +2024,7 @@ void G_AddGhost(char *defdemoname)
|
|||
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
|
||||
UINT8 cnamelen;
|
||||
demoghost *gh;
|
||||
UINT8 flags;
|
||||
UINT8 flags, subversion;
|
||||
UINT8 *buffer,*p;
|
||||
mapthing_t *mthing;
|
||||
UINT16 count, ghostversion;
|
||||
|
@ -2071,7 +2072,7 @@ void G_AddGhost(char *defdemoname)
|
|||
return;
|
||||
} p += 12; // DEMOHEADER
|
||||
p++; // VERSION
|
||||
p++; // SUBVERSION
|
||||
subversion = READUINT8(p); // SUBVERSION
|
||||
ghostversion = READUINT16(p);
|
||||
switch(ghostversion)
|
||||
{
|
||||
|
@ -2170,9 +2171,19 @@ void G_AddGhost(char *defdemoname)
|
|||
count = READUINT16(p);
|
||||
while (count--)
|
||||
{
|
||||
SKIPSTRING(p);
|
||||
SKIPSTRING(p);
|
||||
p++;
|
||||
// In 2.2.7 netvar saving was updated
|
||||
if (subversion < 7)
|
||||
{
|
||||
p += 2;
|
||||
SKIPSTRING(p);
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
SKIPSTRING(p);
|
||||
SKIPSTRING(p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == DEMOMARKER)
|
||||
|
|
221
src/g_game.c
221
src/g_game.c
|
@ -45,6 +45,7 @@
|
|||
#include "lua_hook.h"
|
||||
#include "b_bot.h"
|
||||
#include "m_cond.h" // condition sets
|
||||
#include "lua_script.h"
|
||||
|
||||
#include "lua_hud.h"
|
||||
|
||||
|
@ -1071,7 +1072,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
boolean turnleft, turnright, strafelkey, straferkey, movefkey, movebkey, mouseaiming, analogjoystickmove, gamepadjoystickmove, thisjoyaiming;
|
||||
boolean strafeisturn; // Simple controls only
|
||||
player_t *player = &players[ssplayer == 2 ? secondarydisplayplayer : consoleplayer];
|
||||
camera_t *thiscam = ((ssplayer == 1 || player->bot == 2) ? &camera : &camera2);
|
||||
camera_t *thiscam = ((ssplayer == 1 || player->bot == BOT_2PHUMAN) ? &camera : &camera2);
|
||||
angle_t *myangle = (ssplayer == 1 ? &localangle : &localangle2);
|
||||
INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2);
|
||||
|
||||
|
@ -1139,13 +1140,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
return;
|
||||
}
|
||||
|
||||
turnright = PLAYERINPUTDOWN(ssplayer, gc_turnright);
|
||||
turnleft = PLAYERINPUTDOWN(ssplayer, gc_turnleft);
|
||||
turnright = PLAYERINPUTDOWN(ssplayer, GC_TURNRIGHT);
|
||||
turnleft = PLAYERINPUTDOWN(ssplayer, GC_TURNLEFT);
|
||||
|
||||
straferkey = PLAYERINPUTDOWN(ssplayer, gc_straferight);
|
||||
strafelkey = PLAYERINPUTDOWN(ssplayer, gc_strafeleft);
|
||||
movefkey = PLAYERINPUTDOWN(ssplayer, gc_forward);
|
||||
movebkey = PLAYERINPUTDOWN(ssplayer, gc_backward);
|
||||
straferkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFERIGHT);
|
||||
strafelkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFELEFT);
|
||||
movefkey = PLAYERINPUTDOWN(ssplayer, GC_FORWARD);
|
||||
movebkey = PLAYERINPUTDOWN(ssplayer, GC_BACKWARD);
|
||||
|
||||
if (strafeisturn)
|
||||
{
|
||||
|
@ -1154,7 +1155,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
straferkey = strafelkey = false;
|
||||
}
|
||||
|
||||
mouseaiming = (PLAYERINPUTDOWN(ssplayer, gc_mouseaiming)) ^
|
||||
mouseaiming = (PLAYERINPUTDOWN(ssplayer, GC_MOUSEAIMING)) ^
|
||||
((chasecam && !player->spectator) ? chasefreelook : alwaysfreelook);
|
||||
analogjoystickmove = usejoystick && !Joystick.bGamepadStyle;
|
||||
gamepadjoystickmove = usejoystick && Joystick.bGamepadStyle;
|
||||
|
@ -1270,11 +1271,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
// forward with key or button
|
||||
if (movefkey || (gamepadjoystickmove && movejoystickvector.yaxis < 0)
|
||||
|| ((player->powers[pw_carry] == CR_NIGHTSMODE)
|
||||
&& (PLAYERINPUTDOWN(ssplayer, gc_lookup) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))))
|
||||
&& (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))))
|
||||
forward = forwardmove[speed];
|
||||
if (movebkey || (gamepadjoystickmove && movejoystickvector.yaxis > 0)
|
||||
|| ((player->powers[pw_carry] == CR_NIGHTSMODE)
|
||||
&& (PLAYERINPUTDOWN(ssplayer, gc_lookdown) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))))
|
||||
&& (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))))
|
||||
forward -= forwardmove[speed];
|
||||
|
||||
if (analogjoystickmove && movejoystickvector.yaxis != 0)
|
||||
|
@ -1287,9 +1288,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
if (strafelkey)
|
||||
side -= sidemove[speed];
|
||||
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_weaponnext))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONNEXT))
|
||||
cmd->buttons |= BT_WEAPONNEXT; // Next Weapon
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_weaponprev))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONPREV))
|
||||
cmd->buttons |= BT_WEAPONPREV; // Previous Weapon
|
||||
|
||||
#if NUM_WEAPONS > 10
|
||||
|
@ -1298,7 +1299,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
//use the four avaliable bits to determine the weapon.
|
||||
cmd->buttons &= ~BT_WEAPONMASK;
|
||||
for (i = 0; i < NUM_WEAPONS; ++i)
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_wepslot1 + i))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i))
|
||||
{
|
||||
cmd->buttons |= (UINT16)(i + 1);
|
||||
break;
|
||||
|
@ -1306,34 +1307,34 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
|
||||
// fire with any button/key
|
||||
axis = PlayerJoyAxis(ssplayer, JA_FIRE);
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_fire) || (usejoystick && axis > 0))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_FIRE) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_ATTACK;
|
||||
|
||||
// fire normal with any button/key
|
||||
axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL);
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_firenormal) || (usejoystick && axis > 0))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_FIRENORMAL;
|
||||
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_tossflag))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG))
|
||||
cmd->buttons |= BT_TOSSFLAG;
|
||||
|
||||
// Lua scriptable buttons
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_custom1))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1))
|
||||
cmd->buttons |= BT_CUSTOM1;
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_custom2))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM2))
|
||||
cmd->buttons |= BT_CUSTOM2;
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_custom3))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM3))
|
||||
cmd->buttons |= BT_CUSTOM3;
|
||||
|
||||
// use with any button/key
|
||||
axis = PlayerJoyAxis(ssplayer, JA_SPIN);
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_spin) || (usejoystick && axis > 0))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_SPIN;
|
||||
|
||||
// Centerview can be a toggle in simple mode!
|
||||
{
|
||||
static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior
|
||||
boolean down = PLAYERINPUTDOWN(ssplayer, gc_centerview);
|
||||
boolean down = PLAYERINPUTDOWN(ssplayer, GC_CENTERVIEW);
|
||||
|
||||
if (!(controlstyle == CS_SIMPLE && cv_cam_centertoggle[forplayer].value))
|
||||
centerviewdown = down;
|
||||
|
@ -1432,7 +1433,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
if (ticcmd_centerviewdown[forplayer] && controlstyle == CS_SIMPLE)
|
||||
controlstyle = CS_LEGACY;
|
||||
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_camreset))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_CAMRESET))
|
||||
{
|
||||
if (thiscam->chase && !resetdown[forplayer])
|
||||
P_ResetCamera(&players[ssplayer == 1 ? displayplayer : secondarydisplayplayer], thiscam);
|
||||
|
@ -1445,7 +1446,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
|
||||
// jump button
|
||||
axis = PlayerJoyAxis(ssplayer, JA_JUMP);
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_jump) || (usejoystick && axis > 0))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_JUMP) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_JUMP;
|
||||
|
||||
// player aiming shit, ahhhh...
|
||||
|
@ -1475,12 +1476,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
|
||||
if (!(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
{
|
||||
if (PLAYERINPUTDOWN(ssplayer, gc_lookup) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))
|
||||
{
|
||||
*myaiming += KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look[forplayer] = true;
|
||||
}
|
||||
else if (PLAYERINPUTDOWN(ssplayer, gc_lookdown) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))
|
||||
else if (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))
|
||||
{
|
||||
*myaiming -= KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look[forplayer] = true;
|
||||
|
@ -1545,22 +1546,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
|
||||
cmd->sidemove = (SINT8)(cmd->sidemove + side);
|
||||
|
||||
if (player->bot == 1) { // Tailsbot for P2
|
||||
if (!player->powers[pw_tailsfly] && (cmd->forwardmove || cmd->sidemove || cmd->buttons))
|
||||
{
|
||||
player->bot = 2; // A player-controlled bot. Returns to AI when it respawns.
|
||||
CV_SetValue(&cv_analog[1], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver
|
||||
B_BuildTiccmd(player, cmd);
|
||||
}
|
||||
B_HandleFlightIndicator(player);
|
||||
}
|
||||
else if (player->bot == 2)
|
||||
// Note: Majority of botstuffs are handled in G_Ticker now.
|
||||
if (player->bot == BOT_2PHUMAN) //Player-controlled bot
|
||||
{
|
||||
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver
|
||||
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
|
||||
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
||||
}
|
||||
|
||||
*myangle += (cmd->angleturn<<16);
|
||||
|
||||
|
@ -1968,7 +1960,7 @@ boolean G_Responder(event_t *ev)
|
|||
if (gameaction == ga_nothing && !singledemo &&
|
||||
((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN))
|
||||
{
|
||||
if (ev->type == ev_keydown && ev->data1 != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE))
|
||||
if (ev->type == ev_keydown && ev->key != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE))
|
||||
{
|
||||
M_StartControlPanel();
|
||||
return true;
|
||||
|
@ -2044,7 +2036,7 @@ boolean G_Responder(event_t *ev)
|
|||
|
||||
// allow spy mode changes even during the demo
|
||||
if (gamestate == GS_LEVEL && ev->type == ev_keydown
|
||||
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
|
||||
&& (ev->key == KEY_F12 || ev->key == gamecontrol[GC_VIEWPOINT][0] || ev->key == gamecontrol[GC_VIEWPOINT][1]))
|
||||
{
|
||||
// ViewpointSwitch Lua hook.
|
||||
UINT8 canSwitchView = 0;
|
||||
|
@ -2117,13 +2109,13 @@ boolean G_Responder(event_t *ev)
|
|||
switch (ev->type)
|
||||
{
|
||||
case ev_keydown:
|
||||
if (ev->data1 == gamecontrol[gc_pause][0]
|
||||
|| ev->data1 == gamecontrol[gc_pause][1]
|
||||
|| ev->data1 == KEY_PAUSE)
|
||||
if (ev->key == gamecontrol[GC_PAUSE][0]
|
||||
|| ev->key == gamecontrol[GC_PAUSE][1]
|
||||
|| ev->key == KEY_PAUSE)
|
||||
{
|
||||
if (modeattacking && !demoplayback && (gamestate == GS_LEVEL))
|
||||
{
|
||||
pausebreakkey = (ev->data1 == KEY_PAUSE);
|
||||
pausebreakkey = (ev->key == KEY_PAUSE);
|
||||
if (menuactive || pausedelay < 0 || leveltime < 2)
|
||||
return true;
|
||||
|
||||
|
@ -2148,8 +2140,8 @@ boolean G_Responder(event_t *ev)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ev->data1 == gamecontrol[gc_camtoggle][0]
|
||||
|| ev->data1 == gamecontrol[gc_camtoggle][1])
|
||||
if (ev->key == gamecontrol[GC_CAMTOGGLE][0]
|
||||
|| ev->key == gamecontrol[GC_CAMTOGGLE][1])
|
||||
{
|
||||
if (!camtoggledelay)
|
||||
{
|
||||
|
@ -2157,8 +2149,8 @@ boolean G_Responder(event_t *ev)
|
|||
CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1);
|
||||
}
|
||||
}
|
||||
if (ev->data1 == gamecontrolbis[gc_camtoggle][0]
|
||||
|| ev->data1 == gamecontrolbis[gc_camtoggle][1])
|
||||
if (ev->key == gamecontrolbis[GC_CAMTOGGLE][0]
|
||||
|| ev->key == gamecontrolbis[GC_CAMTOGGLE][1])
|
||||
{
|
||||
if (!camtoggledelay2)
|
||||
{
|
||||
|
@ -2194,8 +2186,20 @@ boolean G_Responder(event_t *ev)
|
|||
//
|
||||
boolean G_LuaResponder(event_t *ev)
|
||||
{
|
||||
return (ev->type == ev_keydown && LUA_HookKey(ev->data1, HOOK(KeyDown))) ||
|
||||
(ev->type == ev_keyup && LUA_HookKey(ev->data1, HOOK(KeyUp)));
|
||||
boolean cancelled = false;
|
||||
|
||||
if (ev->type == ev_keydown)
|
||||
{
|
||||
cancelled = LUA_HookKey(ev, HOOK(KeyDown));
|
||||
LUA_InvalidateUserdata(ev);
|
||||
}
|
||||
else if (ev->type == ev_keyup)
|
||||
{
|
||||
cancelled = LUA_HookKey(ev, HOOK(KeyUp));
|
||||
LUA_InvalidateUserdata(ev);
|
||||
}
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2207,6 +2211,23 @@ void G_Ticker(boolean run)
|
|||
UINT32 i;
|
||||
INT32 buf;
|
||||
|
||||
// Bot players queued for removal
|
||||
for (i = MAXPLAYERS-1; i != UINT32_MAX; i--)
|
||||
{
|
||||
if (playeringame[i] && players[i].removing)
|
||||
{
|
||||
CL_RemovePlayer(i, i);
|
||||
if (netgame)
|
||||
{
|
||||
char kickmsg[256];
|
||||
|
||||
strcpy(kickmsg, M_GetText("\x82*Bot %s has been removed"));
|
||||
strcpy(kickmsg, va(kickmsg, player_names[i], i));
|
||||
HU_AddChatText(kickmsg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see also SCR_DisplayMarathonInfo
|
||||
if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL)
|
||||
marathontime++;
|
||||
|
@ -2292,23 +2313,58 @@ void G_Ticker(boolean run)
|
|||
if (playeringame[i])
|
||||
{
|
||||
INT16 received;
|
||||
// Save last frame's button readings
|
||||
players[i].lastbuttons = players[i].cmd.buttons;
|
||||
|
||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||
// Bot ticcmd handling
|
||||
// Yes, ordinarily this would be handled in G_BuildTiccmd...
|
||||
// ...however, bot players won't have a corresponding consoleplayer or splitscreen player 2 to send that information.
|
||||
// Therefore, this has to be done after ticcmd sends are received.
|
||||
if (players[i].bot == BOT_2PAI) { // Tailsbot for P2
|
||||
if (!players[i].powers[pw_tailsfly] && (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons))
|
||||
{
|
||||
players[i].bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns.
|
||||
CV_SetValue(&cv_analog[1], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
||||
}
|
||||
B_HandleFlightIndicator(&players[i]);
|
||||
}
|
||||
else if (players[i].bot == BOT_MPAI) {
|
||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
||||
}
|
||||
|
||||
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||
// Do angle adjustments.
|
||||
if (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN)
|
||||
{
|
||||
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = players[i].angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = players[i].angleturn;
|
||||
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = players[i].angleturn;
|
||||
|
||||
players[i].cmd.angleturn &= ~TICCMD_RECEIVED;
|
||||
players[i].cmd.angleturn &= ~TICCMD_RECEIVED;
|
||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||
players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1);
|
||||
}
|
||||
else // Less work is required if we're building a bot ticcmd.
|
||||
{
|
||||
// Since bot TicCmd is pre-determined for both the client and server, the latency and packet checks are simplified.
|
||||
received = 1;
|
||||
players[i].cmd.latency = 0;
|
||||
players[i].angleturn = players[i].cmd.angleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
}
|
||||
players[i].cmd.angleturn |= received;
|
||||
|
||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||
players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2494,6 +2550,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
tic_t quittime;
|
||||
boolean spectator;
|
||||
boolean outofcoop;
|
||||
boolean removing;
|
||||
INT16 bot;
|
||||
SINT8 pity;
|
||||
INT16 rings;
|
||||
|
@ -2510,6 +2567,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
quittime = players[player].quittime;
|
||||
spectator = players[player].spectator;
|
||||
outofcoop = players[player].outofcoop;
|
||||
removing = players[player].removing;
|
||||
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
|
||||
playerangleturn = players[player].angleturn;
|
||||
oldrelangleturn = players[player].oldrelangleturn;
|
||||
|
@ -2586,6 +2644,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->quittime = quittime;
|
||||
p->spectator = spectator;
|
||||
p->outofcoop = outofcoop;
|
||||
p->removing = removing;
|
||||
p->angleturn = playerangleturn;
|
||||
p->oldrelangleturn = oldrelangleturn;
|
||||
|
||||
|
@ -2630,8 +2689,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->totalring = totalring;
|
||||
|
||||
p->mare = mare;
|
||||
if (bot)
|
||||
p->bot = 1; // reset to AI-controlled
|
||||
if (bot == BOT_2PHUMAN)
|
||||
p->bot = BOT_2PAI; // reset to AI-controlled
|
||||
else
|
||||
p->bot = bot;
|
||||
p->pity = pity;
|
||||
p->rings = rings;
|
||||
p->spheres = spheres;
|
||||
|
@ -2977,7 +3038,8 @@ void G_DoReborn(INT32 playernum)
|
|||
// Make sure objectplace is OFF when you first start the level!
|
||||
OP_ResetObjectplace();
|
||||
|
||||
if (player->bot && playernum != consoleplayer)
|
||||
// Tailsbot
|
||||
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN)
|
||||
{ // Bots respawn next to their master.
|
||||
mobj_t *oldmo = NULL;
|
||||
|
||||
|
@ -2996,6 +3058,28 @@ void G_DoReborn(INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
// Additional players (e.g. independent bots) in Single Player
|
||||
if (playernum != consoleplayer && !(netgame || multiplayer))
|
||||
{
|
||||
mobj_t *oldmo = NULL;
|
||||
// Do nothing if out of lives
|
||||
if (player->lives <= 0)
|
||||
return;
|
||||
|
||||
// Otherwise do respawn, starting by removing the player object
|
||||
if (player->mo)
|
||||
{
|
||||
oldmo = player->mo;
|
||||
P_RemoveMobj(player->mo);
|
||||
}
|
||||
// Do spawning
|
||||
G_SpawnPlayer(playernum);
|
||||
if (oldmo)
|
||||
G_ChangePlayerReferences(oldmo, players[playernum].mo);
|
||||
|
||||
return; //Exit function to avoid proccing other SP related mechanics
|
||||
}
|
||||
|
||||
if (countdowntimeup || (!(netgame || multiplayer) && (gametyperules & GTR_CAMPAIGN)))
|
||||
resetlevel = true;
|
||||
else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
|
||||
|
@ -3176,7 +3260,7 @@ void G_AddPlayer(INT32 playernum)
|
|||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].bot) // ignore dumb, stupid tails
|
||||
if (players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) // ignore dumb, stupid tails
|
||||
continue;
|
||||
|
||||
countplayers++;
|
||||
|
@ -3217,7 +3301,7 @@ boolean G_EnoughPlayersFinished(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN)
|
||||
continue;
|
||||
if (players[i].quittime > 30 * TICRATE)
|
||||
continue;
|
||||
|
@ -5240,4 +5324,3 @@ INT32 G_TicsToMilliseconds(tic_t tics)
|
|||
{
|
||||
return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
|
||||
}
|
||||
|
||||
|
|
276
src/g_input.c
276
src/g_input.c
|
@ -41,49 +41,49 @@ INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymo
|
|||
UINT8 gamekeydown[NUMINPUTS];
|
||||
|
||||
// two key codes (or virtual key) per game control
|
||||
INT32 gamecontrol[num_gamecontrols][2];
|
||||
INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
|
||||
INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
|
||||
INT32 gamecontrolbisdefault[num_gamecontrolschemes][num_gamecontrols][2];
|
||||
INT32 gamecontrol[NUM_GAMECONTROLS][2];
|
||||
INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
|
||||
INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
|
||||
INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
|
||||
|
||||
// lists of GC codes for selective operation
|
||||
const INT32 gcl_tutorial_check[num_gcl_tutorial_check] = {
|
||||
gc_forward, gc_backward, gc_strafeleft, gc_straferight,
|
||||
gc_turnleft, gc_turnright
|
||||
GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
|
||||
GC_TURNLEFT, GC_TURNRIGHT
|
||||
};
|
||||
|
||||
const INT32 gcl_tutorial_used[num_gcl_tutorial_used] = {
|
||||
gc_forward, gc_backward, gc_strafeleft, gc_straferight,
|
||||
gc_turnleft, gc_turnright,
|
||||
gc_jump, gc_spin
|
||||
GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
|
||||
GC_TURNLEFT, GC_TURNRIGHT,
|
||||
GC_JUMP, GC_SPIN
|
||||
};
|
||||
|
||||
const INT32 gcl_tutorial_full[num_gcl_tutorial_full] = {
|
||||
gc_forward, gc_backward, gc_strafeleft, gc_straferight,
|
||||
gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview,
|
||||
gc_jump, gc_spin,
|
||||
gc_fire, gc_firenormal
|
||||
GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
|
||||
GC_LOOKUP, GC_LOOKDOWN, GC_TURNLEFT, GC_TURNRIGHT, GC_CENTERVIEW,
|
||||
GC_JUMP, GC_SPIN,
|
||||
GC_FIRE, GC_FIRENORMAL
|
||||
};
|
||||
|
||||
const INT32 gcl_movement[num_gcl_movement] = {
|
||||
gc_forward, gc_backward, gc_strafeleft, gc_straferight
|
||||
GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT
|
||||
};
|
||||
|
||||
const INT32 gcl_camera[num_gcl_camera] = {
|
||||
gc_turnleft, gc_turnright
|
||||
GC_TURNLEFT, GC_TURNRIGHT
|
||||
};
|
||||
|
||||
const INT32 gcl_movement_camera[num_gcl_movement_camera] = {
|
||||
gc_forward, gc_backward, gc_strafeleft, gc_straferight,
|
||||
gc_turnleft, gc_turnright
|
||||
GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
|
||||
GC_TURNLEFT, GC_TURNRIGHT
|
||||
};
|
||||
|
||||
const INT32 gcl_jump[num_gcl_jump] = { gc_jump };
|
||||
const INT32 gcl_jump[num_gcl_jump] = { GC_JUMP };
|
||||
|
||||
const INT32 gcl_spin[num_gcl_spin] = { gc_spin };
|
||||
const INT32 gcl_spin[num_gcl_spin] = { GC_SPIN };
|
||||
|
||||
const INT32 gcl_jump_spin[num_gcl_jump_spin] = {
|
||||
gc_jump, gc_spin
|
||||
GC_JUMP, GC_SPIN
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -115,54 +115,54 @@ void G_MapEventsToControls(event_t *ev)
|
|||
switch (ev->type)
|
||||
{
|
||||
case ev_keydown:
|
||||
if (ev->data1 < NUMINPUTS)
|
||||
gamekeydown[ev->data1] = 1;
|
||||
if (ev->key < NUMINPUTS)
|
||||
gamekeydown[ev->key] = 1;
|
||||
#ifdef PARANOIA
|
||||
else
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->data1);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->key);
|
||||
}
|
||||
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ev_keyup:
|
||||
if (ev->data1 < NUMINPUTS)
|
||||
gamekeydown[ev->data1] = 0;
|
||||
if (ev->key < NUMINPUTS)
|
||||
gamekeydown[ev->key] = 0;
|
||||
#ifdef PARANOIA
|
||||
else
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->data1);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->key);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ev_mouse: // buttons are virtual keys
|
||||
mouse.rdx = ev->data2;
|
||||
mouse.rdy = ev->data3;
|
||||
mouse.rdx = ev->x;
|
||||
mouse.rdy = ev->y;
|
||||
break;
|
||||
|
||||
case ev_joystick: // buttons are virtual keys
|
||||
i = ev->data1;
|
||||
i = ev->key;
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
if (ev->data2 != INT32_MAX) joyxmove[i] = ev->data2;
|
||||
if (ev->data3 != INT32_MAX) joyymove[i] = ev->data3;
|
||||
if (ev->x != INT32_MAX) joyxmove[i] = ev->x;
|
||||
if (ev->y != INT32_MAX) joyymove[i] = ev->y;
|
||||
break;
|
||||
|
||||
case ev_joystick2: // buttons are virtual keys
|
||||
i = ev->data1;
|
||||
i = ev->key;
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2;
|
||||
if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3;
|
||||
if (ev->x != INT32_MAX) joy2xmove[i] = ev->x;
|
||||
if (ev->y != INT32_MAX) joy2ymove[i] = ev->y;
|
||||
break;
|
||||
|
||||
case ev_mouse2: // buttons are virtual keys
|
||||
if (menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
mouse2.rdx = ev->data2;
|
||||
mouse2.rdy = ev->data3;
|
||||
mouse2.rdx = ev->x;
|
||||
mouse2.rdy = ev->y;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -553,9 +553,9 @@ static keyname_t keynames[] =
|
|||
|
||||
};
|
||||
|
||||
static const char *gamecontrolname[num_gamecontrols] =
|
||||
static const char *gamecontrolname[NUM_GAMECONTROLS] =
|
||||
{
|
||||
"nothing", // a key/button mapped to gc_null has no effect
|
||||
"nothing", // a key/button mapped to GC_NULL has no effect
|
||||
"forward",
|
||||
"backward",
|
||||
"strafeleft",
|
||||
|
@ -613,7 +613,7 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control)
|
|||
void G_ClearAllControlKeys(void)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
for (i = 0; i < NUM_GAMECONTROLS; i++)
|
||||
{
|
||||
G_ClearControlKeys(gamecontrol, i);
|
||||
G_ClearControlKeys(gamecontrolbis, i);
|
||||
|
@ -624,7 +624,7 @@ void G_ClearAllControlKeys(void)
|
|||
// Returns the name of a key (or virtual key for mouse and joy)
|
||||
// the input value being an keynum
|
||||
//
|
||||
const char *G_KeyNumToString(INT32 keynum)
|
||||
const char *G_KeyNumToName(INT32 keynum)
|
||||
{
|
||||
static char keynamestr[8];
|
||||
|
||||
|
@ -648,7 +648,7 @@ const char *G_KeyNumToString(INT32 keynum)
|
|||
return keynamestr;
|
||||
}
|
||||
|
||||
INT32 G_KeyStringToNum(const char *keystr)
|
||||
INT32 G_KeyNameToNum(const char *keystr)
|
||||
{
|
||||
UINT32 j;
|
||||
|
||||
|
@ -676,92 +676,92 @@ void G_DefineDefaultControls(void)
|
|||
INT32 i;
|
||||
|
||||
// FPS game controls (WASD)
|
||||
gamecontroldefault[gcs_fps][gc_forward ][0] = 'w';
|
||||
gamecontroldefault[gcs_fps][gc_backward ][0] = 's';
|
||||
gamecontroldefault[gcs_fps][gc_strafeleft ][0] = 'a';
|
||||
gamecontroldefault[gcs_fps][gc_straferight][0] = 'd';
|
||||
gamecontroldefault[gcs_fps][gc_lookup ][0] = KEY_UPARROW;
|
||||
gamecontroldefault[gcs_fps][gc_lookdown ][0] = KEY_DOWNARROW;
|
||||
gamecontroldefault[gcs_fps][gc_turnleft ][0] = KEY_LEFTARROW;
|
||||
gamecontroldefault[gcs_fps][gc_turnright ][0] = KEY_RIGHTARROW;
|
||||
gamecontroldefault[gcs_fps][gc_centerview ][0] = KEY_END;
|
||||
gamecontroldefault[gcs_fps][gc_jump ][0] = KEY_SPACE;
|
||||
gamecontroldefault[gcs_fps][gc_spin ][0] = KEY_LSHIFT;
|
||||
gamecontroldefault[gcs_fps][gc_fire ][0] = KEY_RCTRL;
|
||||
gamecontroldefault[gcs_fps][gc_fire ][1] = KEY_MOUSE1+0;
|
||||
gamecontroldefault[gcs_fps][gc_firenormal ][0] = 'c';
|
||||
gamecontroldefault[gcs_fps][GC_FORWARD ][0] = 'w';
|
||||
gamecontroldefault[gcs_fps][GC_BACKWARD ][0] = 's';
|
||||
gamecontroldefault[gcs_fps][GC_STRAFELEFT ][0] = 'a';
|
||||
gamecontroldefault[gcs_fps][GC_STRAFERIGHT][0] = 'd';
|
||||
gamecontroldefault[gcs_fps][GC_LOOKUP ][0] = KEY_UPARROW;
|
||||
gamecontroldefault[gcs_fps][GC_LOOKDOWN ][0] = KEY_DOWNARROW;
|
||||
gamecontroldefault[gcs_fps][GC_TURNLEFT ][0] = KEY_LEFTARROW;
|
||||
gamecontroldefault[gcs_fps][GC_TURNRIGHT ][0] = KEY_RIGHTARROW;
|
||||
gamecontroldefault[gcs_fps][GC_CENTERVIEW ][0] = KEY_END;
|
||||
gamecontroldefault[gcs_fps][GC_JUMP ][0] = KEY_SPACE;
|
||||
gamecontroldefault[gcs_fps][GC_SPIN ][0] = KEY_LSHIFT;
|
||||
gamecontroldefault[gcs_fps][GC_FIRE ][0] = KEY_RCTRL;
|
||||
gamecontroldefault[gcs_fps][GC_FIRE ][1] = KEY_MOUSE1+0;
|
||||
gamecontroldefault[gcs_fps][GC_FIRENORMAL ][0] = 'c';
|
||||
|
||||
// Platform game controls (arrow keys)
|
||||
gamecontroldefault[gcs_platform][gc_forward ][0] = KEY_UPARROW;
|
||||
gamecontroldefault[gcs_platform][gc_backward ][0] = KEY_DOWNARROW;
|
||||
gamecontroldefault[gcs_platform][gc_strafeleft ][0] = 'a';
|
||||
gamecontroldefault[gcs_platform][gc_straferight][0] = 'd';
|
||||
gamecontroldefault[gcs_platform][gc_lookup ][0] = KEY_PGUP;
|
||||
gamecontroldefault[gcs_platform][gc_lookdown ][0] = KEY_PGDN;
|
||||
gamecontroldefault[gcs_platform][gc_turnleft ][0] = KEY_LEFTARROW;
|
||||
gamecontroldefault[gcs_platform][gc_turnright ][0] = KEY_RIGHTARROW;
|
||||
gamecontroldefault[gcs_platform][gc_centerview ][0] = KEY_END;
|
||||
gamecontroldefault[gcs_platform][gc_jump ][0] = KEY_SPACE;
|
||||
gamecontroldefault[gcs_platform][gc_spin ][0] = KEY_LSHIFT;
|
||||
gamecontroldefault[gcs_platform][gc_fire ][0] = 's';
|
||||
gamecontroldefault[gcs_platform][gc_fire ][1] = KEY_MOUSE1+0;
|
||||
gamecontroldefault[gcs_platform][gc_firenormal ][0] = 'w';
|
||||
gamecontroldefault[gcs_platform][GC_FORWARD ][0] = KEY_UPARROW;
|
||||
gamecontroldefault[gcs_platform][GC_BACKWARD ][0] = KEY_DOWNARROW;
|
||||
gamecontroldefault[gcs_platform][GC_STRAFELEFT ][0] = 'a';
|
||||
gamecontroldefault[gcs_platform][GC_STRAFERIGHT][0] = 'd';
|
||||
gamecontroldefault[gcs_platform][GC_LOOKUP ][0] = KEY_PGUP;
|
||||
gamecontroldefault[gcs_platform][GC_LOOKDOWN ][0] = KEY_PGDN;
|
||||
gamecontroldefault[gcs_platform][GC_TURNLEFT ][0] = KEY_LEFTARROW;
|
||||
gamecontroldefault[gcs_platform][GC_TURNRIGHT ][0] = KEY_RIGHTARROW;
|
||||
gamecontroldefault[gcs_platform][GC_CENTERVIEW ][0] = KEY_END;
|
||||
gamecontroldefault[gcs_platform][GC_JUMP ][0] = KEY_SPACE;
|
||||
gamecontroldefault[gcs_platform][GC_SPIN ][0] = KEY_LSHIFT;
|
||||
gamecontroldefault[gcs_platform][GC_FIRE ][0] = 's';
|
||||
gamecontroldefault[gcs_platform][GC_FIRE ][1] = KEY_MOUSE1+0;
|
||||
gamecontroldefault[gcs_platform][GC_FIRENORMAL ][0] = 'w';
|
||||
|
||||
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
|
||||
{
|
||||
gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0;
|
||||
gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0;
|
||||
gamecontroldefault[i][gc_wepslot1 ][0] = '1';
|
||||
gamecontroldefault[i][gc_wepslot2 ][0] = '2';
|
||||
gamecontroldefault[i][gc_wepslot3 ][0] = '3';
|
||||
gamecontroldefault[i][gc_wepslot4 ][0] = '4';
|
||||
gamecontroldefault[i][gc_wepslot5 ][0] = '5';
|
||||
gamecontroldefault[i][gc_wepslot6 ][0] = '6';
|
||||
gamecontroldefault[i][gc_wepslot7 ][0] = '7';
|
||||
gamecontroldefault[i][gc_wepslot8 ][0] = '8';
|
||||
gamecontroldefault[i][gc_wepslot9 ][0] = '9';
|
||||
gamecontroldefault[i][gc_wepslot10 ][0] = '0';
|
||||
gamecontroldefault[i][gc_tossflag ][0] = '\'';
|
||||
gamecontroldefault[i][gc_camtoggle ][0] = 'v';
|
||||
gamecontroldefault[i][gc_camreset ][0] = 'r';
|
||||
gamecontroldefault[i][gc_talkkey ][0] = 't';
|
||||
gamecontroldefault[i][gc_teamkey ][0] = 'y';
|
||||
gamecontroldefault[i][gc_scores ][0] = KEY_TAB;
|
||||
gamecontroldefault[i][gc_console ][0] = KEY_CONSOLE;
|
||||
gamecontroldefault[i][gc_pause ][0] = 'p';
|
||||
gamecontroldefault[i][gc_screenshot ][0] = KEY_F8;
|
||||
gamecontroldefault[i][gc_recordgif ][0] = KEY_F9;
|
||||
gamecontroldefault[i][gc_viewpoint ][0] = KEY_F12;
|
||||
gamecontroldefault[i][GC_WEAPONNEXT ][0] = KEY_MOUSEWHEELUP+0;
|
||||
gamecontroldefault[i][GC_WEAPONPREV ][0] = KEY_MOUSEWHEELDOWN+0;
|
||||
gamecontroldefault[i][GC_WEPSLOT1 ][0] = '1';
|
||||
gamecontroldefault[i][GC_WEPSLOT2 ][0] = '2';
|
||||
gamecontroldefault[i][GC_WEPSLOT3 ][0] = '3';
|
||||
gamecontroldefault[i][GC_WEPSLOT4 ][0] = '4';
|
||||
gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5';
|
||||
gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6';
|
||||
gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7';
|
||||
gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8';
|
||||
gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9';
|
||||
gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0';
|
||||
gamecontroldefault[i][GC_TOSSFLAG ][0] = '\'';
|
||||
gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v';
|
||||
gamecontroldefault[i][GC_CAMRESET ][0] = 'r';
|
||||
gamecontroldefault[i][GC_TALKKEY ][0] = 't';
|
||||
gamecontroldefault[i][GC_TEAMKEY ][0] = 'y';
|
||||
gamecontroldefault[i][GC_SCORES ][0] = KEY_TAB;
|
||||
gamecontroldefault[i][GC_CONSOLE ][0] = KEY_CONSOLE;
|
||||
gamecontroldefault[i][GC_PAUSE ][0] = 'p';
|
||||
gamecontroldefault[i][GC_SCREENSHOT ][0] = KEY_F8;
|
||||
gamecontroldefault[i][GC_RECORDGIF ][0] = KEY_F9;
|
||||
gamecontroldefault[i][GC_VIEWPOINT ][0] = KEY_F12;
|
||||
|
||||
// Gamepad controls -- same for both schemes
|
||||
gamecontroldefault[i][gc_weaponnext ][1] = KEY_JOY1+1; // B
|
||||
gamecontroldefault[i][gc_weaponprev ][1] = KEY_JOY1+2; // X
|
||||
gamecontroldefault[i][gc_tossflag ][1] = KEY_JOY1+0; // A
|
||||
gamecontroldefault[i][gc_spin ][1] = KEY_JOY1+4; // LB
|
||||
gamecontroldefault[i][gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up
|
||||
gamecontroldefault[i][gc_camreset ][1] = KEY_JOY1+3; // Y
|
||||
gamecontroldefault[i][gc_centerview ][1] = KEY_JOY1+9; // Right Stick
|
||||
gamecontroldefault[i][gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left
|
||||
gamecontroldefault[i][gc_scores ][1] = KEY_HAT1+3; // D-Pad Right
|
||||
gamecontroldefault[i][gc_jump ][1] = KEY_JOY1+5; // RB
|
||||
gamecontroldefault[i][gc_pause ][1] = KEY_JOY1+6; // Back
|
||||
gamecontroldefault[i][gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down
|
||||
gamecontroldefault[i][gc_systemmenu ][0] = KEY_JOY1+7; // Start
|
||||
gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_JOY1+1; // B
|
||||
gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_JOY1+2; // X
|
||||
gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_JOY1+0; // A
|
||||
gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+4; // LB
|
||||
gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+0; // D-Pad Up
|
||||
gamecontroldefault[i][GC_CAMRESET ][1] = KEY_JOY1+3; // Y
|
||||
gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+9; // Right Stick
|
||||
gamecontroldefault[i][GC_TALKKEY ][1] = KEY_HAT1+2; // D-Pad Left
|
||||
gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+3; // D-Pad Right
|
||||
gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+5; // RB
|
||||
gamecontroldefault[i][GC_PAUSE ][1] = KEY_JOY1+6; // Back
|
||||
gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_HAT1+1; // D-Pad Down
|
||||
gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start
|
||||
|
||||
// Second player controls only have joypad defaults
|
||||
gamecontrolbisdefault[i][gc_weaponnext][0] = KEY_2JOY1+1; // B
|
||||
gamecontrolbisdefault[i][gc_weaponprev][0] = KEY_2JOY1+2; // X
|
||||
gamecontrolbisdefault[i][gc_tossflag ][0] = KEY_2JOY1+0; // A
|
||||
gamecontrolbisdefault[i][gc_spin ][0] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbisdefault[i][gc_camreset ][0] = KEY_2JOY1+3; // Y
|
||||
gamecontrolbisdefault[i][gc_centerview][0] = KEY_2JOY1+9; // Right Stick
|
||||
gamecontrolbisdefault[i][gc_jump ][0] = KEY_2JOY1+5; // RB
|
||||
//gamecontrolbisdefault[i][gc_pause ][0] = KEY_2JOY1+6; // Back
|
||||
//gamecontrolbisdefault[i][gc_systemmenu][0] = KEY_2JOY1+7; // Start
|
||||
gamecontrolbisdefault[i][gc_camtoggle ][0] = KEY_2HAT1+0; // D-Pad Up
|
||||
gamecontrolbisdefault[i][gc_screenshot][0] = KEY_2HAT1+1; // D-Pad Down
|
||||
//gamecontrolbisdefault[i][gc_talkkey ][0] = KEY_2HAT1+2; // D-Pad Left
|
||||
//gamecontrolbisdefault[i][gc_scores ][0] = KEY_2HAT1+3; // D-Pad Right
|
||||
gamecontrolbisdefault[i][GC_WEAPONNEXT][0] = KEY_2JOY1+1; // B
|
||||
gamecontrolbisdefault[i][GC_WEAPONPREV][0] = KEY_2JOY1+2; // X
|
||||
gamecontrolbisdefault[i][GC_TOSSFLAG ][0] = KEY_2JOY1+0; // A
|
||||
gamecontrolbisdefault[i][GC_SPIN ][0] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbisdefault[i][GC_CAMRESET ][0] = KEY_2JOY1+3; // Y
|
||||
gamecontrolbisdefault[i][GC_CENTERVIEW][0] = KEY_2JOY1+9; // Right Stick
|
||||
gamecontrolbisdefault[i][GC_JUMP ][0] = KEY_2JOY1+5; // RB
|
||||
//gamecontrolbisdefault[i][GC_PAUSE ][0] = KEY_2JOY1+6; // Back
|
||||
//gamecontrolbisdefault[i][GC_SYSTEMMENU][0] = KEY_2JOY1+7; // Start
|
||||
gamecontrolbisdefault[i][GC_CAMTOGGLE ][0] = KEY_2HAT1+0; // D-Pad Up
|
||||
gamecontrolbisdefault[i][GC_SCREENSHOT][0] = KEY_2HAT1+1; // D-Pad Down
|
||||
//gamecontrolbisdefault[i][GC_TALKKEY ][0] = KEY_2HAT1+2; // D-Pad Left
|
||||
//gamecontrolbisdefault[i][GC_SCORES ][0] = KEY_2HAT1+3; // D-Pad Right
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -773,7 +773,7 @@ INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gc
|
|||
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
|
||||
{
|
||||
skipscheme = false;
|
||||
for (j = 0; j < (gclist && gclen ? gclen : num_gamecontrols); j++)
|
||||
for (j = 0; j < (gclist && gclen ? gclen : NUM_GAMECONTROLS); j++)
|
||||
{
|
||||
gc = (gclist && gclen) ? gclist[j] : j;
|
||||
if (((fromcontrols[gc][0] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][0] : true) &&
|
||||
|
@ -796,7 +796,7 @@ void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const I
|
|||
{
|
||||
INT32 i, gc;
|
||||
|
||||
for (i = 0; i < (gclist && gclen ? gclen : num_gamecontrols); i++)
|
||||
for (i = 0; i < (gclist && gclen ? gclen : NUM_GAMECONTROLS); i++)
|
||||
{
|
||||
gc = (gclist && gclen) ? gclist[i] : i;
|
||||
setupcontrols[gc][0] = fromcontrols[gc][0];
|
||||
|
@ -808,24 +808,24 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 1; i < num_gamecontrols; i++)
|
||||
for (i = 1; i < NUM_GAMECONTROLS; i++)
|
||||
{
|
||||
fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i],
|
||||
G_KeyNumToString(fromcontrols[i][0]));
|
||||
G_KeyNumToName(fromcontrols[i][0]));
|
||||
|
||||
if (fromcontrols[i][1])
|
||||
fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1]));
|
||||
fprintf(f, " \"%s\"\n", G_KeyNumToName(fromcontrols[i][1]));
|
||||
else
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
for (i = 1; i < num_gamecontrols; i++)
|
||||
for (i = 1; i < NUM_GAMECONTROLS; i++)
|
||||
{
|
||||
fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i],
|
||||
G_KeyNumToString(fromcontrolsbis[i][0]));
|
||||
G_KeyNumToName(fromcontrolsbis[i][0]));
|
||||
|
||||
if (fromcontrolsbis[i][1])
|
||||
fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1]));
|
||||
fprintf(f, " \"%s\"\n", G_KeyNumToName(fromcontrolsbis[i][1]));
|
||||
else
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
@ -833,11 +833,11 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis
|
|||
|
||||
INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify)
|
||||
{
|
||||
INT32 result = gc_null;
|
||||
INT32 result = GC_NULL;
|
||||
if (cv_controlperkey.value == 1)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
for (i = 0; i < NUM_GAMECONTROLS; i++)
|
||||
{
|
||||
if (gamecontrol[i][0] == keynum)
|
||||
{
|
||||
|
@ -883,11 +883,11 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT
|
|||
return -1; // skip setting control
|
||||
|
||||
if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22
|
||||
numctrl == gc_weaponnext || numctrl == gc_weaponprev || numctrl == gc_tossflag ||
|
||||
numctrl == gc_spin || numctrl == gc_camreset || numctrl == gc_jump ||
|
||||
numctrl == gc_pause || numctrl == gc_systemmenu || numctrl == gc_camtoggle ||
|
||||
numctrl == gc_screenshot || numctrl == gc_talkkey || numctrl == gc_scores ||
|
||||
numctrl == gc_centerview
|
||||
numctrl == GC_WEAPONNEXT || numctrl == GC_WEAPONPREV || numctrl == GC_TOSSFLAG ||
|
||||
numctrl == GC_SPIN || numctrl == GC_CAMRESET || numctrl == GC_JUMP ||
|
||||
numctrl == GC_PAUSE || numctrl == GC_SYSTEMMENU || numctrl == GC_CAMTOGGLE ||
|
||||
numctrl == GC_SCREENSHOT || numctrl == GC_TALKKEY || numctrl == GC_SCORES ||
|
||||
numctrl == GC_CENTERVIEW
|
||||
))
|
||||
{
|
||||
INT32 keynum = 0, existingctrl = 0;
|
||||
|
@ -895,7 +895,7 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT
|
|||
boolean defaultoverride = false;
|
||||
|
||||
// get the default gamecontrol
|
||||
if (player == 0 && numctrl == gc_systemmenu)
|
||||
if (player == 0 && numctrl == GC_SYSTEMMENU)
|
||||
defaultkey = gamecontrol[numctrl][0];
|
||||
else
|
||||
defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]);
|
||||
|
@ -993,16 +993,16 @@ static void setcontrol(INT32 (*gc)[2])
|
|||
// Update me for 2.3
|
||||
namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin";
|
||||
|
||||
for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]);
|
||||
for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]);
|
||||
numctrl++)
|
||||
;
|
||||
if (numctrl == num_gamecontrols)
|
||||
if (numctrl == NUM_GAMECONTROLS)
|
||||
{
|
||||
CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl);
|
||||
return;
|
||||
}
|
||||
keynum1 = G_KeyStringToNum(COM_Argv(2));
|
||||
keynum2 = G_KeyStringToNum(COM_Argv(3));
|
||||
keynum1 = G_KeyNameToNum(COM_Argv(2));
|
||||
keynum2 = G_KeyNameToNum(COM_Argv(3));
|
||||
keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride);
|
||||
|
||||
if (keynum >= 0)
|
||||
|
|
|
@ -58,49 +58,49 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
gc_null = 0, // a key/button mapped to gc_null has no effect
|
||||
gc_forward,
|
||||
gc_backward,
|
||||
gc_strafeleft,
|
||||
gc_straferight,
|
||||
gc_turnleft,
|
||||
gc_turnright,
|
||||
gc_weaponnext,
|
||||
gc_weaponprev,
|
||||
gc_wepslot1,
|
||||
gc_wepslot2,
|
||||
gc_wepslot3,
|
||||
gc_wepslot4,
|
||||
gc_wepslot5,
|
||||
gc_wepslot6,
|
||||
gc_wepslot7,
|
||||
gc_wepslot8,
|
||||
gc_wepslot9,
|
||||
gc_wepslot10,
|
||||
gc_fire,
|
||||
gc_firenormal,
|
||||
gc_tossflag,
|
||||
gc_spin,
|
||||
gc_camtoggle,
|
||||
gc_camreset,
|
||||
gc_lookup,
|
||||
gc_lookdown,
|
||||
gc_centerview,
|
||||
gc_mouseaiming, // mouse aiming is momentary (toggleable in the menu)
|
||||
gc_talkkey,
|
||||
gc_teamkey,
|
||||
gc_scores,
|
||||
gc_jump,
|
||||
gc_console,
|
||||
gc_pause,
|
||||
gc_systemmenu,
|
||||
gc_screenshot,
|
||||
gc_recordgif,
|
||||
gc_viewpoint,
|
||||
gc_custom1, // Lua scriptable
|
||||
gc_custom2, // Lua scriptable
|
||||
gc_custom3, // Lua scriptable
|
||||
num_gamecontrols
|
||||
GC_NULL = 0, // a key/button mapped to GC_NULL has no effect
|
||||
GC_FORWARD,
|
||||
GC_BACKWARD,
|
||||
GC_STRAFELEFT,
|
||||
GC_STRAFERIGHT,
|
||||
GC_TURNLEFT,
|
||||
GC_TURNRIGHT,
|
||||
GC_WEAPONNEXT,
|
||||
GC_WEAPONPREV,
|
||||
GC_WEPSLOT1,
|
||||
GC_WEPSLOT2,
|
||||
GC_WEPSLOT3,
|
||||
GC_WEPSLOT4,
|
||||
GC_WEPSLOT5,
|
||||
GC_WEPSLOT6,
|
||||
GC_WEPSLOT7,
|
||||
GC_WEPSLOT8,
|
||||
GC_WEPSLOT9,
|
||||
GC_WEPSLOT10,
|
||||
GC_FIRE,
|
||||
GC_FIRENORMAL,
|
||||
GC_TOSSFLAG,
|
||||
GC_SPIN,
|
||||
GC_CAMTOGGLE,
|
||||
GC_CAMRESET,
|
||||
GC_LOOKUP,
|
||||
GC_LOOKDOWN,
|
||||
GC_CENTERVIEW,
|
||||
GC_MOUSEAIMING, // mouse aiming is momentary (toggleable in the menu)
|
||||
GC_TALKKEY,
|
||||
GC_TEAMKEY,
|
||||
GC_SCORES,
|
||||
GC_JUMP,
|
||||
GC_CONSOLE,
|
||||
GC_PAUSE,
|
||||
GC_SYSTEMMENU,
|
||||
GC_SCREENSHOT,
|
||||
GC_RECORDGIF,
|
||||
GC_VIEWPOINT,
|
||||
GC_CUSTOM1, // Lua scriptable
|
||||
GC_CUSTOM2, // Lua scriptable
|
||||
GC_CUSTOM3, // Lua scriptable
|
||||
NUM_GAMECONTROLS
|
||||
} gamecontrols_e;
|
||||
|
||||
typedef enum
|
||||
|
@ -146,10 +146,10 @@ extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET],
|
|||
extern UINT8 gamekeydown[NUMINPUTS];
|
||||
|
||||
// two key codes (or virtual key) per game control
|
||||
extern INT32 gamecontrol[num_gamecontrols][2];
|
||||
extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
|
||||
extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
|
||||
extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][num_gamecontrols][2];
|
||||
extern INT32 gamecontrol[NUM_GAMECONTROLS][2];
|
||||
extern INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
|
||||
extern INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
|
||||
extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
|
||||
#define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
|
||||
#define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
|
||||
#define PLAYERINPUTDOWN(p, gc) ((p) == 2 ? PLAYER2INPUTDOWN(gc) : PLAYER1INPUTDOWN(gc))
|
||||
|
@ -181,8 +181,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin];
|
|||
void G_MapEventsToControls(event_t *ev);
|
||||
|
||||
// returns the name of a key
|
||||
const char *G_KeyNumToString(INT32 keynum);
|
||||
INT32 G_KeyStringToNum(const char *keystr);
|
||||
const char *G_KeyNumToName(INT32 keynum);
|
||||
INT32 G_KeyNameToNum(const char *keystr);
|
||||
|
||||
// detach any keys associated to the given game control
|
||||
void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);
|
||||
|
|
|
@ -317,7 +317,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
}
|
||||
}
|
||||
|
||||
if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
|
||||
if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
|
||||
{
|
||||
fwidth = (float)(gpatch->width) * fscalew * dupx;
|
||||
fheight = (float)(gpatch->height) * fscaleh * dupy;
|
||||
|
@ -382,7 +382,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
HWD.pfnDrawPolygon(NULL, v, 4, flags);
|
||||
}
|
||||
|
||||
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
|
||||
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
|
||||
{
|
||||
FOutVector v[4];
|
||||
FBITFIELD flags;
|
||||
|
@ -395,13 +395,19 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
float dupx, dupy, fscale, fwidth, fheight;
|
||||
float dupx, dupy, fscalew, fscaleh, fwidth, fheight;
|
||||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
if (alphalevel >= 10 && alphalevel < 13)
|
||||
return;
|
||||
|
||||
// make patch ready in hardware cache
|
||||
HWR_GetPatch(gpatch);
|
||||
if (!colormap)
|
||||
HWR_GetPatch(gpatch);
|
||||
else
|
||||
HWR_GetMappedPatch(gpatch, colormap);
|
||||
|
||||
hwrPatch = ((GLPatch_t *)gpatch->hardware);
|
||||
|
||||
dupx = (float)vid.dupx;
|
||||
|
@ -423,12 +429,80 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
}
|
||||
|
||||
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
||||
fscale = FIXED_TO_FLOAT(pscale);
|
||||
fscalew = fscaleh = FIXED_TO_FLOAT(pscale);
|
||||
if (vscale != pscale)
|
||||
fscaleh = FIXED_TO_FLOAT(vscale);
|
||||
|
||||
// fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus...
|
||||
cx -= (float)(gpatch->leftoffset) * fscalew;
|
||||
cy -= (float)(gpatch->topoffset) * fscaleh;
|
||||
|
||||
cy -= (float)(gpatch->topoffset) * fscale;
|
||||
cx -= (float)(gpatch->leftoffset) * fscale;
|
||||
if (splitscreen && (option & V_PERPLAYER))
|
||||
{
|
||||
float adjusty = ((option & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
|
||||
fscaleh /= 2;
|
||||
cy /= 2;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
|
||||
fscalew /= 2;
|
||||
cx /= 2;
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
option &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
cx += adjustx;
|
||||
option &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[thirddisplayplayer])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
cy += adjusty;
|
||||
option &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[fourthdisplayplayer])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
cx += adjustx;
|
||||
cy += adjusty;
|
||||
option &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle = 1;
|
||||
option &= ~V_SNAPTOBOTTOM;
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle = 2;
|
||||
cy += adjusty;
|
||||
option &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(option & V_NOSCALESTART))
|
||||
{
|
||||
|
@ -447,6 +521,10 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
|
||||
if (perplayershuffle & 4)
|
||||
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
else if (perplayershuffle & 8)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
|
@ -454,23 +532,27 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
|
||||
if (perplayershuffle & 1)
|
||||
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
else if (perplayershuffle & 2)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fwidth = w;
|
||||
fheight = h;
|
||||
fwidth = FIXED_TO_FLOAT(w);
|
||||
fheight = FIXED_TO_FLOAT(h);
|
||||
|
||||
if (sx + w > gpatch->width)
|
||||
fwidth = gpatch->width - sx;
|
||||
if (sx + w > gpatch->width<<FRACBITS)
|
||||
fwidth = FIXED_TO_FLOAT((gpatch->width<<FRACBITS) - sx);
|
||||
|
||||
if (sy + h > gpatch->height)
|
||||
fheight = gpatch->height - sy;
|
||||
if (sy + h > gpatch->height<<FRACBITS)
|
||||
fheight = FIXED_TO_FLOAT((gpatch->height<<FRACBITS) - sy);
|
||||
|
||||
if (pscale != FRACUNIT)
|
||||
if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
|
||||
{
|
||||
fwidth *= fscale * dupx;
|
||||
fheight *= fscale * dupy;
|
||||
fwidth *= fscalew * dupx;
|
||||
fheight *= fscaleh * dupy;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -495,17 +577,17 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s;
|
||||
if (sx + w > gpatch->width)
|
||||
v[0].s = v[3].s = (FIXED_TO_FLOAT(sx)/(float)(gpatch->width))*hwrPatch->max_s;
|
||||
if (sx + w > gpatch->width<<FRACBITS)
|
||||
v[2].s = v[1].s = hwrPatch->max_s;
|
||||
else
|
||||
v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
|
||||
v[2].s = v[1].s = (FIXED_TO_FLOAT(sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
|
||||
|
||||
v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t;
|
||||
if (sy + h > gpatch->height)
|
||||
v[0].t = v[1].t = (FIXED_TO_FLOAT(sy)/(float)(gpatch->height))*hwrPatch->max_t;
|
||||
if (sy + h > gpatch->height<<FRACBITS)
|
||||
v[2].t = v[3].t = hwrPatch->max_t;
|
||||
else
|
||||
v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
|
||||
v[2].t = v[3].t = (FIXED_TO_FLOAT(sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
|
||||
|
||||
flags = PF_Translucent|PF_NoDepthTest;
|
||||
|
||||
|
@ -514,6 +596,76 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
if (option & V_WRAPY)
|
||||
flags |= PF_ForceWrapY;
|
||||
|
||||
// Auto-crop at splitscreen borders!
|
||||
if (splitscreen && (option & V_PERPLAYER))
|
||||
{
|
||||
#define flerp(a,b,amount) (((a) * (1.0f - (amount))) + ((b) * (amount))) // Float lerp
|
||||
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
#error Auto-cropping doesnt take quadscreen into account! Fix it!
|
||||
// Hint: For player 1/2, copy player 1's code below. For player 3/4, copy player 2's code below
|
||||
// For player 1/3 and 2/4, mangle the below code to apply horizontally instead of vertically
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
|
||||
{
|
||||
if ((cy - fheight) < 0) // If the bottom is below the border
|
||||
{
|
||||
if (cy <= 0) // If the whole patch is beyond the border...
|
||||
return; // ...crop away the entire patch, don't draw anything
|
||||
|
||||
if (fheight <= 0) // Don't divide by zero
|
||||
return;
|
||||
|
||||
v[2].y = v[3].y = 0; // Clamp the polygon edge vertex position
|
||||
// Now for the UV-map... Uh-oh, math time!
|
||||
|
||||
// On second thought, a basic linear interpolation suffices
|
||||
//float full_height = fheight;
|
||||
//float cropped_height = fheight - cy;
|
||||
//float remaining_height = cy;
|
||||
//float cropped_percentage = (fheight - cy) / fheight;
|
||||
//float remaining_percentage = cy / fheight;
|
||||
//v[2].t = v[3].t = lerp(v[2].t, v[0].t, cropped_percentage);
|
||||
// By swapping v[2] and v[0], we can use remaining_percentage for less operations
|
||||
//v[2].t = v[3].t = lerp(v[0].t, v[2].t, remaining_percentage);
|
||||
|
||||
v[2].t = v[3].t = flerp(v[0].t, v[2].t, cy/fheight);
|
||||
}
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
|
||||
{
|
||||
if (cy > 0) // If the top is above the border
|
||||
{
|
||||
if ((cy - fheight) >= 0) // If the whole patch is beyond the border...
|
||||
return; // ...crop away the entire patch, don't draw anything
|
||||
|
||||
if (fheight <= 0) // Don't divide by zero
|
||||
return;
|
||||
|
||||
v[0].y = v[1].y = 0; // Clamp the polygon edge vertex position
|
||||
// Now for the UV-map... Uh-oh, math time!
|
||||
|
||||
// On second thought, a basic linear interpolation suffices
|
||||
//float full_height = fheight;
|
||||
//float cropped_height = cy;
|
||||
//float remaining_height = fheight - cy;
|
||||
//float cropped_percentage = cy / fheight;
|
||||
//float remaining_percentage = (fheight - cy) / fheight;
|
||||
//v[0].t = v[1].t = lerp(v[0].t, v[2].t, cropped_percentage);
|
||||
|
||||
v[0].t = v[1].t = flerp(v[0].t, v[2].t, cy/fheight);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef flerp
|
||||
}
|
||||
|
||||
// clip it since it is used for bunny scroll in doom I
|
||||
if (alphalevel)
|
||||
{
|
||||
|
|
|
@ -6767,7 +6767,7 @@ void HWR_LoadAllCustomShaders(void)
|
|||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3));
|
||||
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
|
||||
}
|
||||
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
|
||||
|
|
|
@ -39,7 +39,7 @@ void HWR_InitTextureMapping(void);
|
|||
void HWR_SetViewSize(void);
|
||||
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
|
||||
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
|
||||
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
|
||||
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
|
||||
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
|
||||
void HWR_CreatePlanePolygons(INT32 bspnum);
|
||||
void HWR_CreateStaticLightmaps(INT32 bspnum);
|
||||
|
|
|
@ -62,6 +62,9 @@ static FBITFIELD CurrentPolyFlags;
|
|||
static FTextureInfo *TexCacheTail = NULL;
|
||||
static FTextureInfo *TexCacheHead = NULL;
|
||||
|
||||
static RGBA_t *textureBuffer = NULL;
|
||||
static size_t textureBufferSize = 0;
|
||||
|
||||
RGBA_t myPaletteData[256];
|
||||
GLint screen_width = 0; // used by Draw2DLine()
|
||||
GLint screen_height = 0;
|
||||
|
@ -131,7 +134,6 @@ static const GLfloat byte2float[256] = {
|
|||
// -----------------+
|
||||
// GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined,
|
||||
// : else do nothing
|
||||
// Returns :
|
||||
// -----------------+
|
||||
|
||||
#ifdef DEBUG_TO_FILE
|
||||
|
@ -159,8 +161,6 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
|
|||
|
||||
// -----------------+
|
||||
// GL_MSG_Warning : Raises a warning.
|
||||
// :
|
||||
// Returns :
|
||||
// -----------------+
|
||||
|
||||
static void GL_MSG_Warning(const char *format, ...)
|
||||
|
@ -184,8 +184,6 @@ static void GL_MSG_Warning(const char *format, ...)
|
|||
|
||||
// -----------------+
|
||||
// GL_MSG_Error : Raises an error.
|
||||
// :
|
||||
// Returns :
|
||||
// -----------------+
|
||||
|
||||
static void GL_MSG_Error(const char *format, ...)
|
||||
|
@ -1345,6 +1343,10 @@ void Flush(void)
|
|||
|
||||
TexCacheTail = TexCacheHead = NULL; //Hurdler: well, TexCacheHead is already NULL
|
||||
tex_downloaded = 0;
|
||||
|
||||
free(textureBuffer);
|
||||
textureBuffer = NULL;
|
||||
textureBufferSize = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1378,7 +1380,6 @@ INT32 isExtAvailable(const char *extension, const GLubyte *start)
|
|||
|
||||
// -----------------+
|
||||
// Init : Initialise the OpenGL interface API
|
||||
// Returns :
|
||||
// -----------------+
|
||||
EXPORT boolean HWRAPI(Init) (void)
|
||||
{
|
||||
|
@ -1738,37 +1739,48 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
|
|||
CurrentPolyFlags = PolyFlags;
|
||||
}
|
||||
|
||||
static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
|
||||
{
|
||||
size_t size = pTexInfo->width * pTexInfo->height;
|
||||
if (size > textureBufferSize)
|
||||
{
|
||||
textureBuffer = realloc(textureBuffer, size * sizeof(RGBA_t));
|
||||
if (textureBuffer == NULL)
|
||||
I_Error("AllocTextureBuffer: out of memory allocating %s bytes", sizeu1(size * sizeof(RGBA_t)));
|
||||
textureBufferSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// UpdateTexture : Updates the texture data.
|
||||
// UpdateTexture : Updates texture data.
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
||||
{
|
||||
// Download a mipmap
|
||||
boolean updatemipmap = true;
|
||||
static RGBA_t tex[2048*2048];
|
||||
const GLvoid *ptex = tex;
|
||||
INT32 w, h;
|
||||
GLuint texnum = 0;
|
||||
// Upload a texture
|
||||
GLuint num = pTexInfo->downloaded;
|
||||
boolean update = true;
|
||||
|
||||
if (!pTexInfo->downloaded)
|
||||
INT32 w = pTexInfo->width, h = pTexInfo->height;
|
||||
INT32 i, j;
|
||||
|
||||
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
|
||||
const GLvoid *ptex = NULL;
|
||||
RGBA_t *tex = NULL;
|
||||
|
||||
// Generate a new texture name.
|
||||
if (!num)
|
||||
{
|
||||
pglGenTextures(1, &texnum);
|
||||
pTexInfo->downloaded = texnum;
|
||||
updatemipmap = false;
|
||||
pglGenTextures(1, &num);
|
||||
pTexInfo->downloaded = num;
|
||||
update = false;
|
||||
}
|
||||
else
|
||||
texnum = pTexInfo->downloaded;
|
||||
|
||||
//GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->data);
|
||||
//GL_DBG_Printf("UpdateTexture %d %x\n", (INT32)num, pImgData);
|
||||
|
||||
w = pTexInfo->width;
|
||||
h = pTexInfo->height;
|
||||
|
||||
if ((pTexInfo->format == GL_TEXFMT_P_8) ||
|
||||
(pTexInfo->format == GL_TEXFMT_AP_88))
|
||||
if ((pTexInfo->format == GL_TEXFMT_P_8) || (pTexInfo->format == GL_TEXFMT_AP_88))
|
||||
{
|
||||
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
|
||||
INT32 i, j;
|
||||
AllocTextureBuffer(pTexInfo);
|
||||
ptex = tex = textureBuffer;
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
|
@ -1799,20 +1811,18 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
tex[w*j+i].s.alpha = *pImgData;
|
||||
pImgData++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_RGBA)
|
||||
{
|
||||
// corona test : passed as ARGB 8888, which is not in glide formats
|
||||
// Hurdler: not used for coronas anymore, just for dynamic lighting
|
||||
ptex = pTexInfo->data;
|
||||
// Directly upload the texture data without any kind of conversion.
|
||||
ptex = pImgData;
|
||||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
|
||||
{
|
||||
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
|
||||
INT32 i, j;
|
||||
AllocTextureBuffer(pTexInfo);
|
||||
ptex = tex = textureBuffer;
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
|
@ -1829,8 +1839,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks
|
||||
{
|
||||
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
|
||||
INT32 i, j;
|
||||
AllocTextureBuffer(pTexInfo);
|
||||
ptex = tex = textureBuffer;
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
|
@ -1845,11 +1855,10 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
}
|
||||
}
|
||||
else
|
||||
GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->format);
|
||||
GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format);
|
||||
|
||||
// the texture number was already generated by pglGenTextures
|
||||
pglBindTexture(GL_TEXTURE_2D, texnum);
|
||||
tex_downloaded = texnum;
|
||||
pglBindTexture(GL_TEXTURE_2D, num);
|
||||
tex_downloaded = num;
|
||||
|
||||
// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
|
||||
if (pTexInfo->flags & TF_TRANSPARENT)
|
||||
|
@ -1878,7 +1887,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (updatemipmap)
|
||||
if (update)
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
else
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
|
@ -1899,7 +1908,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (updatemipmap)
|
||||
if (update)
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
else
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
|
@ -1919,7 +1928,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (updatemipmap)
|
||||
if (update)
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
else
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
|
|
|
@ -936,7 +936,7 @@ void HU_Ticker(void)
|
|||
hu_tick++;
|
||||
hu_tick &= 7; // currently only to blink chat input cursor
|
||||
|
||||
if (PLAYER1INPUTDOWN(gc_scores))
|
||||
if (PLAYER1INPUTDOWN(GC_SCORES))
|
||||
hu_showscores = !chat_on;
|
||||
else
|
||||
hu_showscores = false;
|
||||
|
@ -1111,26 +1111,26 @@ boolean HU_Responder(event_t *ev)
|
|||
// (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...)
|
||||
// (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...)
|
||||
|
||||
if (ev->data1 >= KEY_MOUSE1)
|
||||
if (ev->key >= KEY_MOUSE1)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
for (i = 0; i < NUM_GAMECONTROLS; i++)
|
||||
{
|
||||
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
|
||||
if (gamecontrol[i][0] == ev->key || gamecontrol[i][1] == ev->key)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == num_gamecontrols)
|
||||
if (i == NUM_GAMECONTROLS)
|
||||
return false;
|
||||
}*/ //We don't actually care about that unless we get splitscreen netgames. :V
|
||||
|
||||
#ifndef NONET
|
||||
c = (INT32)ev->data1;
|
||||
c = (INT32)ev->key;
|
||||
|
||||
if (!chat_on)
|
||||
{
|
||||
// enter chat mode
|
||||
if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1])
|
||||
if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1])
|
||||
&& netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise.
|
||||
{
|
||||
chat_on = true;
|
||||
|
@ -1140,7 +1140,7 @@ boolean HU_Responder(event_t *ev)
|
|||
typelines = 1;
|
||||
return true;
|
||||
}
|
||||
if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1])
|
||||
if ((ev->key == gamecontrol[GC_TEAMKEY][0] || ev->key == gamecontrol[GC_TEAMKEY][1])
|
||||
&& netgame && !OLD_MUTE)
|
||||
{
|
||||
chat_on = true;
|
||||
|
@ -1157,12 +1157,12 @@ boolean HU_Responder(event_t *ev)
|
|||
// Ignore modifier keys
|
||||
// Note that we do this here so users can still set
|
||||
// their chat keys to one of these, if they so desire.
|
||||
if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT
|
||||
|| ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL
|
||||
|| ev->data1 == KEY_LALT || ev->data1 == KEY_RALT)
|
||||
if (ev->key == KEY_LSHIFT || ev->key == KEY_RSHIFT
|
||||
|| ev->key == KEY_LCTRL || ev->key == KEY_RCTRL
|
||||
|| ev->key == KEY_LALT || ev->key == KEY_RALT)
|
||||
return true;
|
||||
|
||||
c = (INT32)ev->data1;
|
||||
c = (INT32)ev->key;
|
||||
|
||||
// I know this looks very messy but this works. If it ain't broke, don't fix it!
|
||||
// shift LETTERS to uppercase if we have capslock or are holding shift
|
||||
|
@ -1234,8 +1234,8 @@ boolean HU_Responder(event_t *ev)
|
|||
I_UpdateMouseGrab();
|
||||
}
|
||||
else if (c == KEY_ESCAPE
|
||||
|| ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1]
|
||||
|| c == gamecontrol[gc_teamkey][0] || c == gamecontrol[gc_teamkey][1])
|
||||
|| ((c == gamecontrol[GC_TALKKEY][0] || c == gamecontrol[GC_TALKKEY][1]
|
||||
|| c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1])
|
||||
&& c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle.
|
||||
{
|
||||
chat_on = false;
|
||||
|
@ -2104,7 +2104,7 @@ void HU_Drawer(void)
|
|||
}
|
||||
else
|
||||
HU_DrawCoopOverlay();
|
||||
LUAh_ScoresHUD();
|
||||
LUA_HUDHOOK(scores);
|
||||
}
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
#include "m_menu.h" // Player Setup menu color stuff
|
||||
#include "m_misc.h" // M_MapNumber
|
||||
#include "b_bot.h" // B_UpdateBotleader
|
||||
#include "d_clisrv.h" // CL_RemovePlayer
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
@ -1883,6 +1885,37 @@ static int lib_pDoSpring(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pTryCameraMove(lua_State *L)
|
||||
{
|
||||
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
|
||||
if (!cam)
|
||||
return LUA_ErrInvalid(L, "camera_t");
|
||||
lua_pushboolean(L, P_TryCameraMove(x, y, cam));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pTeleportCameraMove(lua_State *L)
|
||||
{
|
||||
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
|
||||
if (!cam)
|
||||
return LUA_ErrInvalid(L, "camera_t");
|
||||
cam->x = x;
|
||||
cam->y = y;
|
||||
cam->z = z;
|
||||
P_CheckCameraPosition(x, y, cam);
|
||||
cam->subsector = R_PointInSubsector(x, y);
|
||||
cam->floorz = tmfloorz;
|
||||
cam->ceilingz = tmceilingz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// P_INTER
|
||||
////////////
|
||||
|
||||
|
@ -3397,6 +3430,111 @@ static int lib_gAddGametype(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Bot adding function!
|
||||
// Partly lifted from Got_AddPlayer
|
||||
static int lib_gAddPlayer(lua_State *L)
|
||||
{
|
||||
INT16 i, newplayernum, botcount = 1;
|
||||
player_t *newplayer;
|
||||
SINT8 skinnum = 0, bot;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
break;
|
||||
|
||||
if (players[i].bot)
|
||||
botcount++; // How many of us are there already?
|
||||
}
|
||||
if (i >= MAXPLAYERS)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
newplayernum = i;
|
||||
|
||||
CL_ClearPlayer(newplayernum);
|
||||
|
||||
playeringame[newplayernum] = true;
|
||||
G_AddPlayer(newplayernum);
|
||||
newplayer = &players[newplayernum];
|
||||
|
||||
newplayer->jointime = 0;
|
||||
newplayer->quittime = 0;
|
||||
|
||||
// Set the bot name (defaults to Bot #)
|
||||
strcpy(player_names[newplayernum], va("Bot %d", botcount));
|
||||
|
||||
// Read the skin argument (defaults to Sonic)
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
{
|
||||
skinnum = R_SkinAvailable(luaL_checkstring(L, 1));
|
||||
skinnum = skinnum < 0 ? 0 : skinnum;
|
||||
}
|
||||
|
||||
// Read the color (defaults to skin prefcolor)
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2));
|
||||
else
|
||||
newplayer->skincolor = skins[newplayer->skin].prefcolor;
|
||||
|
||||
// Read the bot name, if given
|
||||
if (!lua_isnoneornil(L, 3))
|
||||
strcpy(player_names[newplayernum], luaL_checkstring(L, 3));
|
||||
|
||||
bot = luaL_optinteger(L, 4, 3);
|
||||
newplayer->bot = (bot >= BOT_NONE && bot <= BOT_MPAI) ? bot : BOT_MPAI;
|
||||
|
||||
// If our bot is a 2P type, we'll need to set its leader so it can spawn
|
||||
if (newplayer->bot == BOT_2PAI || newplayer->bot == BOT_2PHUMAN)
|
||||
B_UpdateBotleader(newplayer);
|
||||
|
||||
// Set the skin (can't do this until AFTER bot type is set!)
|
||||
SetPlayerSkinByNum(newplayernum, skinnum);
|
||||
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
char joinmsg[256];
|
||||
|
||||
strcpy(joinmsg, M_GetText("\x82*Bot %s has joined the game (player %d)"));
|
||||
strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum));
|
||||
HU_AddChatText(joinmsg, false);
|
||||
}
|
||||
|
||||
LUA_PushUserdata(L, newplayer, META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Bot removing function
|
||||
static int lib_gRemovePlayer(lua_State *L)
|
||||
{
|
||||
UINT8 pnum = -1;
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
pnum = luaL_checkinteger(L, 1);
|
||||
else // No argument
|
||||
return luaL_error(L, "argument #1 not given (expected number)");
|
||||
if (pnum >= MAXPLAYERS) // Out of range
|
||||
return luaL_error(L, "playernum %d out of range (0 - %d)", pnum, MAXPLAYERS-1);
|
||||
if (playeringame[pnum]) // Found player
|
||||
{
|
||||
if (players[pnum].bot == BOT_NONE) // Can't remove clients.
|
||||
return luaL_error(L, "G_RemovePlayer can only be used on players with a bot value other than BOT_NONE.");
|
||||
else
|
||||
{
|
||||
players[pnum].removing = true;
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Fell through. Invalid player
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
|
||||
static int Lcheckmapnumber (lua_State *L, int idx, const char *fun)
|
||||
{
|
||||
if (ISINLEVEL)
|
||||
|
@ -3881,6 +4019,8 @@ static luaL_Reg lib[] = {
|
|||
{"P_FloorzAtPos",lib_pFloorzAtPos},
|
||||
{"P_CeilingzAtPos",lib_pCeilingzAtPos},
|
||||
{"P_DoSpring",lib_pDoSpring},
|
||||
{"P_TryCameraMove", lib_pTryCameraMove},
|
||||
{"P_TeleportCameraMove", lib_pTeleportCameraMove},
|
||||
|
||||
// p_inter
|
||||
{"P_RemoveShield",lib_pRemoveShield},
|
||||
|
@ -3983,6 +4123,8 @@ static luaL_Reg lib[] = {
|
|||
|
||||
// g_game
|
||||
{"G_AddGametype", lib_gAddGametype},
|
||||
{"G_AddPlayer", lib_gAddPlayer},
|
||||
{"G_RemovePlayer", lib_gRemovePlayer},
|
||||
{"G_BuildMapName",lib_gBuildMapName},
|
||||
{"G_BuildMapTitle",lib_gBuildMapTitle},
|
||||
{"G_FindMap",lib_gFindMap},
|
||||
|
|
|
@ -433,7 +433,7 @@ static int CVarSetFunction
|
|||
consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR);
|
||||
|
||||
if (cvar->flags & CV_NOLUA)
|
||||
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
|
||||
return luaL_error(L, "Variable '%s' cannot be set from Lua.", cvar->name);
|
||||
|
||||
switch (lua_type(L, 2))
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "r_defs.h"
|
||||
#include "d_player.h"
|
||||
#include "s_sound.h"
|
||||
#include "d_event.h"
|
||||
|
||||
/*
|
||||
Do you know what an 'X Macro' is? Such a macro is called over each element of
|
||||
|
@ -78,6 +79,13 @@ automatically.
|
|||
X (LinedefExecute),\
|
||||
X (ShouldJingleContinue),/* should jingle of the given music continue playing */\
|
||||
|
||||
#define HUD_HOOK_LIST(X) \
|
||||
X (game),\
|
||||
X (scores),/* emblems/multiplayer list */\
|
||||
X (title),/* titlescreen */\
|
||||
X (titlecard),\
|
||||
X (intermission),\
|
||||
|
||||
/*
|
||||
I chose to access the hook enums through a macro as well. This could provide
|
||||
a hint to lookup the macro's definition instead of the enum's definition.
|
||||
|
@ -88,18 +96,26 @@ grepped and found in the lists above.
|
|||
|
||||
#define MOBJ_HOOK(name) mobjhook_ ## name
|
||||
#define HOOK(name) hook_ ## name
|
||||
#define HUD_HOOK(name) hudhook_ ## name
|
||||
#define STRING_HOOK(name) stringhook_ ## name
|
||||
|
||||
enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) };
|
||||
enum { HOOK_LIST (HOOK) HOOK(MAX) };
|
||||
enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) };
|
||||
#define ENUM(X) enum { X ## _LIST (X) X(MAX) }
|
||||
|
||||
ENUM (MOBJ_HOOK);
|
||||
ENUM (HOOK);
|
||||
ENUM (HUD_HOOK);
|
||||
ENUM (STRING_HOOK);
|
||||
|
||||
#undef ENUM
|
||||
|
||||
/* dead simple, LUA_HOOK(GameQuit) */
|
||||
#define LUA_HOOK(type) LUA_HookVoid(HOOK(type))
|
||||
#define LUA_HUDHOOK(type) LUA_HookHUD(HUD_HOOK(type))
|
||||
|
||||
extern boolean hook_cmd_running;
|
||||
|
||||
void LUA_HookVoid(int hook);
|
||||
void LUA_HookHUD(int hook);
|
||||
|
||||
int LUA_HookMobj(mobj_t *, int hook);
|
||||
int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook);
|
||||
|
@ -107,6 +123,7 @@ void LUA_HookInt(INT32 integer, int hook);
|
|||
void LUA_HookBool(boolean value, int hook);
|
||||
int LUA_HookPlayer(player_t *, int hook);
|
||||
int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook);
|
||||
int LUA_HookKey(event_t *event, int hook); // Hooks for key events
|
||||
|
||||
void LUA_HookThinkFrame(void);
|
||||
int LUA_HookMobjLineCollide(mobj_t *, line_t *);
|
||||
|
@ -114,6 +131,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher);
|
|||
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
|
||||
int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
|
||||
int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype);
|
||||
int LUA_HookMobjMoveBlocked(mobj_t *, mobj_t *, line_t *);
|
||||
int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd);
|
||||
void LUA_HookLinedefExecute(line_t *, mobj_t *, sector_t *);
|
||||
int LUA_HookPlayerMsg(int source, int target, int flags, char *msg);
|
||||
|
@ -130,4 +148,3 @@ int LUA_HookPlayerCmd(player_t *, ticcmd_t *);
|
|||
int LUA_HookMusicChange(const char *oldname, struct MusicChange *);
|
||||
fixed_t LUA_HookPlayerHeight(player_t *player);
|
||||
int LUA_HookPlayerCanEnterSpinGaps(player_t *player);
|
||||
int LUA_HookKey(INT32 keycode, int hooktype); // Hooks for key events
|
||||
|
|
|
@ -31,12 +31,15 @@
|
|||
ABSTRACTION
|
||||
========================================================================= */
|
||||
|
||||
static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL };
|
||||
static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL };
|
||||
#define LIST(id, M) \
|
||||
static const char * const id [] = { M (TOSTR) NULL }
|
||||
|
||||
static const char * const stringHookNames[] = {
|
||||
STRING_HOOK_LIST (TOSTR) NULL
|
||||
};
|
||||
LIST (mobjHookNames, MOBJ_HOOK_LIST);
|
||||
LIST (hookNames, HOOK_LIST);
|
||||
LIST (hudHookNames, HUD_HOOK_LIST);
|
||||
LIST (stringHookNames, STRING_HOOK_LIST);
|
||||
|
||||
#undef LIST
|
||||
|
||||
typedef struct {
|
||||
int numHooks;
|
||||
|
@ -49,6 +52,7 @@ typedef struct {
|
|||
} stringhook_t;
|
||||
|
||||
static hook_t hookIds[HOOK(MAX)];
|
||||
static hook_t hudHookIds[HUD_HOOK(MAX)];
|
||||
static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)];
|
||||
|
||||
// Lua tables are used to lookup string hook ids.
|
||||
|
@ -56,6 +60,7 @@ static stringhook_t stringHooks[STRING_HOOK(MAX)];
|
|||
|
||||
// This will be indexed by hook id, the value of which fetches the registry.
|
||||
static int * hookRefs;
|
||||
static int nextid;
|
||||
|
||||
// After a hook errors once, don't print the error again.
|
||||
static UINT8 * hooksErrored;
|
||||
|
@ -104,13 +109,13 @@ static void get_table(lua_State *L)
|
|||
lua_remove(L, -2);
|
||||
}
|
||||
|
||||
static void add_hook_to_table(lua_State *L, int id, int n)
|
||||
static void add_hook_to_table(lua_State *L, int n)
|
||||
{
|
||||
lua_pushnumber(L, id);
|
||||
lua_pushnumber(L, nextid);
|
||||
lua_rawseti(L, -2, n);
|
||||
}
|
||||
|
||||
static void add_string_hook(lua_State *L, int type, int id)
|
||||
static void add_string_hook(lua_State *L, int type)
|
||||
{
|
||||
stringhook_t * hook = &stringHooks[type];
|
||||
|
||||
|
@ -146,33 +151,54 @@ static void add_string_hook(lua_State *L, int type, int id)
|
|||
{
|
||||
lua_pushstring(L, string);
|
||||
get_table(L);
|
||||
add_hook_to_table(L, id, 1 + lua_objlen(L, -1));
|
||||
add_hook_to_table(L, 1 + lua_objlen(L, -1));
|
||||
}
|
||||
else
|
||||
add_hook_to_table(L, id, ++hook->numGeneric);
|
||||
add_hook_to_table(L, ++hook->numGeneric);
|
||||
}
|
||||
|
||||
static void add_hook(hook_t *map, int id)
|
||||
static void add_hook(hook_t *map)
|
||||
{
|
||||
Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids,
|
||||
PU_STATIC, &map->ids);
|
||||
map->ids[map->numHooks++] = id;
|
||||
map->ids[map->numHooks++] = nextid;
|
||||
}
|
||||
|
||||
static void add_mobj_hook(lua_State *L, int hook_type, int id)
|
||||
static void add_mobj_hook(lua_State *L, int hook_type)
|
||||
{
|
||||
mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL);
|
||||
|
||||
luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t");
|
||||
|
||||
add_hook(&mobjHookIds[mobj_type][hook_type], id);
|
||||
add_hook(&mobjHookIds[mobj_type][hook_type]);
|
||||
}
|
||||
|
||||
static void add_hud_hook(lua_State *L, int idx)
|
||||
{
|
||||
add_hook(&hudHookIds[luaL_checkoption(L,
|
||||
idx, "game", hudHookNames)]);
|
||||
}
|
||||
|
||||
static void add_hook_ref(lua_State *L, int idx)
|
||||
{
|
||||
if (!(nextid & 7))
|
||||
{
|
||||
Z_Realloc(hooksErrored,
|
||||
BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored,
|
||||
PU_STATIC, &hooksErrored);
|
||||
hooksErrored[nextid >> 3] = 0;
|
||||
}
|
||||
|
||||
Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs);
|
||||
|
||||
// set the hook function in the registry.
|
||||
lua_pushvalue(L, idx);
|
||||
hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
// Takes hook, function, and additional arguments (mobj type to act on, etc.)
|
||||
static int lib_addHook(lua_State *L)
|
||||
{
|
||||
static int nextid;
|
||||
|
||||
const char * name;
|
||||
int type;
|
||||
|
||||
|
@ -185,34 +211,26 @@ static int lib_addHook(lua_State *L)
|
|||
/* this is a very special case */
|
||||
if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX))
|
||||
{
|
||||
add_string_hook(L, type, nextid);
|
||||
add_string_hook(L, type);
|
||||
}
|
||||
else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX))
|
||||
{
|
||||
add_mobj_hook(L, type, nextid);
|
||||
add_mobj_hook(L, type);
|
||||
}
|
||||
else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX))
|
||||
{
|
||||
add_hook(&hookIds[type], nextid);
|
||||
add_hook(&hookIds[type]);
|
||||
}
|
||||
else if (strcmp(name, "HUD") == 0)
|
||||
{
|
||||
add_hud_hook(L, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name));
|
||||
}
|
||||
|
||||
if (!(nextid & 7))
|
||||
{
|
||||
Z_Realloc(hooksErrored,
|
||||
BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored,
|
||||
PU_STATIC, &hooksErrored);
|
||||
hooksErrored[nextid >> 3] = 0;
|
||||
}
|
||||
|
||||
Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs);
|
||||
|
||||
// set the hook function in the registry.
|
||||
lua_pushvalue(L, 2);/* the function */
|
||||
hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
add_hook_ref(L, 2);/* the function */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -227,6 +245,23 @@ int LUA_HookLib(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: remove in next backwards incompatible release */
|
||||
#if MODID == 18
|
||||
int lib_hudadd(lua_State *L);/* yeah compiler */
|
||||
int lib_hudadd(lua_State *L)
|
||||
{
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
|
||||
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
|
||||
add_hud_hook(L, 2);
|
||||
add_hook_ref(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct Hook_State Hook_State;
|
||||
typedef void (*Hook_Callback)(Hook_State *);
|
||||
|
||||
|
@ -259,11 +294,16 @@ static void push_string(void)
|
|||
lua_pushvalue(gL, SINDEX);
|
||||
}
|
||||
|
||||
static boolean start_hook_stack(void)
|
||||
static boolean begin_hook_values(Hook_State *hook)
|
||||
{
|
||||
hook->top = lua_gettop(gL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void start_hook_stack(void)
|
||||
{
|
||||
lua_settop(gL, 0);
|
||||
push_error_handler();
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean init_hook_type
|
||||
|
@ -279,10 +319,11 @@ static boolean init_hook_type
|
|||
|
||||
if (nonzero)
|
||||
{
|
||||
start_hook_stack();
|
||||
hook->hook_type = hook_type;
|
||||
hook->mobj_type = mobj_type;
|
||||
hook->string = string;
|
||||
return start_hook_stack();
|
||||
return begin_hook_values(hook);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@ -323,7 +364,7 @@ static boolean prepare_string_hook
|
|||
stringHooks[hook_type].ref))
|
||||
{
|
||||
lua_pushstring(gL, string);
|
||||
return true;
|
||||
return begin_hook_values(hook);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@ -332,12 +373,12 @@ static boolean prepare_string_hook
|
|||
static void init_hook_call
|
||||
(
|
||||
Hook_State * hook,
|
||||
int values,
|
||||
int results,
|
||||
Hook_Callback results_handler
|
||||
){
|
||||
hook->top = lua_gettop(gL);
|
||||
hook->values = values;
|
||||
const int top = lua_gettop(gL);
|
||||
hook->values = (top - hook->top);
|
||||
hook->top = top;
|
||||
hook->results = results;
|
||||
hook->results_handler = results_handler;
|
||||
}
|
||||
|
@ -447,13 +488,12 @@ static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
|
|||
static int call_hooks
|
||||
(
|
||||
Hook_State * hook,
|
||||
int values,
|
||||
int results,
|
||||
Hook_Callback results_handler
|
||||
){
|
||||
int calls = 0;
|
||||
|
||||
init_hook_call(hook, values, results, results_handler);
|
||||
init_hook_call(hook, results, results_handler);
|
||||
|
||||
if (hook->string)
|
||||
{
|
||||
|
@ -514,7 +554,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type)
|
|||
if (prepare_mobj_hook(&hook, false, hook_type, mobj->type))
|
||||
{
|
||||
LUA_PushUserdata(gL, mobj, META_MOBJ);
|
||||
call_hooks(&hook, 1, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -526,7 +566,7 @@ int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type)
|
|||
{
|
||||
LUA_PushUserdata(gL, t1, META_MOBJ);
|
||||
LUA_PushUserdata(gL, t2, META_MOBJ);
|
||||
call_hooks(&hook, 2, 1, res_force);
|
||||
call_hooks(&hook, 1, res_force);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -535,7 +575,7 @@ void LUA_HookVoid(int type)
|
|||
{
|
||||
Hook_State hook;
|
||||
if (prepare_hook(&hook, 0, type))
|
||||
call_hooks(&hook, 0, 0, res_none);
|
||||
call_hooks(&hook, 0, res_none);
|
||||
}
|
||||
|
||||
void LUA_HookInt(INT32 number, int hook_type)
|
||||
|
@ -544,7 +584,7 @@ void LUA_HookInt(INT32 number, int hook_type)
|
|||
if (prepare_hook(&hook, 0, hook_type))
|
||||
{
|
||||
lua_pushinteger(gL, number);
|
||||
call_hooks(&hook, 1, 0, res_none);
|
||||
call_hooks(&hook, 0, res_none);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,7 +594,7 @@ void LUA_HookBool(boolean value, int hook_type)
|
|||
if (prepare_hook(&hook, 0, hook_type))
|
||||
{
|
||||
lua_pushboolean(gL, value);
|
||||
call_hooks(&hook, 1, 0, res_none);
|
||||
call_hooks(&hook, 0, res_none);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,7 +604,7 @@ int LUA_HookPlayer(player_t *player, int hook_type)
|
|||
if (prepare_hook(&hook, false, hook_type))
|
||||
{
|
||||
LUA_PushUserdata(gL, player, META_PLAYER);
|
||||
call_hooks(&hook, 1, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -580,7 +620,7 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type)
|
|||
if (hook_type == HOOK(PlayerCmd))
|
||||
hook_cmd_running = true;
|
||||
|
||||
call_hooks(&hook, 2, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
|
||||
if (hook_type == HOOK(PlayerCmd))
|
||||
hook_cmd_running = false;
|
||||
|
@ -588,6 +628,35 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type)
|
|||
return hook.status;
|
||||
}
|
||||
|
||||
int LUA_HookKey(event_t *event, int hook_type)
|
||||
{
|
||||
Hook_State hook;
|
||||
if (prepare_hook(&hook, false, hook_type))
|
||||
{
|
||||
LUA_PushUserdata(gL, event, META_KEYEVENT);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
||||
void LUA_HookHUD(int hook_type)
|
||||
{
|
||||
const hook_t * map = &hudHookIds[hook_type];
|
||||
Hook_State hook;
|
||||
if (map->numHooks > 0)
|
||||
{
|
||||
start_hook_stack();
|
||||
begin_hook_values(&hook);
|
||||
|
||||
LUA_SetHudHook(hook_type);
|
||||
|
||||
hud_running = true; // local hook
|
||||
init_hook_call(&hook, 0, res_none);
|
||||
call_mapped(&hook, map);
|
||||
hud_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
SPECIALIZED HOOKS
|
||||
========================================================================= */
|
||||
|
@ -607,7 +676,7 @@ void LUA_HookThinkFrame(void)
|
|||
|
||||
if (prepare_hook(&hook, 0, type))
|
||||
{
|
||||
init_hook_call(&hook, 0, 0, res_none);
|
||||
init_hook_call(&hook, 0, res_none);
|
||||
|
||||
for (k = 0; k < map->numHooks; ++k)
|
||||
{
|
||||
|
@ -642,7 +711,7 @@ int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line)
|
|||
{
|
||||
LUA_PushUserdata(gL, mobj, META_MOBJ);
|
||||
LUA_PushUserdata(gL, line, META_LINE);
|
||||
call_hooks(&hook, 2, 1, res_force);
|
||||
call_hooks(&hook, 1, res_force);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -654,7 +723,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher)
|
|||
{
|
||||
LUA_PushUserdata(gL, special, META_MOBJ);
|
||||
LUA_PushUserdata(gL, toucher, META_MOBJ);
|
||||
call_hooks(&hook, 2, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -667,7 +736,6 @@ static int damage_hook
|
|||
INT32 damage,
|
||||
UINT8 damagetype,
|
||||
int hook_type,
|
||||
int values,
|
||||
Hook_Callback results_handler
|
||||
){
|
||||
Hook_State hook;
|
||||
|
@ -676,10 +744,10 @@ static int damage_hook
|
|||
LUA_PushUserdata(gL, target, META_MOBJ);
|
||||
LUA_PushUserdata(gL, inflictor, META_MOBJ);
|
||||
LUA_PushUserdata(gL, source, META_MOBJ);
|
||||
if (values == 5)
|
||||
if (hook_type != MOBJ_HOOK(MobjDeath))
|
||||
lua_pushinteger(gL, damage);
|
||||
lua_pushinteger(gL, damagetype);
|
||||
call_hooks(&hook, values, 1, results_handler);
|
||||
call_hooks(&hook, 1, results_handler);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -687,19 +755,32 @@ static int damage_hook
|
|||
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
|
||||
{
|
||||
return damage_hook(target, inflictor, source, damage, damagetype,
|
||||
MOBJ_HOOK(ShouldDamage), 5, res_force);
|
||||
MOBJ_HOOK(ShouldDamage), res_force);
|
||||
}
|
||||
|
||||
int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
|
||||
{
|
||||
return damage_hook(target, inflictor, source, damage, damagetype,
|
||||
MOBJ_HOOK(MobjDamage), 5, res_true);
|
||||
MOBJ_HOOK(MobjDamage), res_true);
|
||||
}
|
||||
|
||||
int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
|
||||
{
|
||||
return damage_hook(target, inflictor, source, 0, damagetype,
|
||||
MOBJ_HOOK(MobjDeath), 4, res_true);
|
||||
MOBJ_HOOK(MobjDeath), res_true);
|
||||
}
|
||||
|
||||
int LUA_HookMobjMoveBlocked(mobj_t *t1, mobj_t *t2, line_t *line)
|
||||
{
|
||||
Hook_State hook;
|
||||
if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjMoveBlocked), t1->type))
|
||||
{
|
||||
LUA_PushUserdata(gL, t1, META_MOBJ);
|
||||
LUA_PushUserdata(gL, t2, META_MOBJ);
|
||||
LUA_PushUserdata(gL, line, META_LINE);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -772,7 +853,7 @@ int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
|
||||
hook.userdata = &botai;
|
||||
|
||||
call_hooks(&hook, 2, 8, res_botai);
|
||||
call_hooks(&hook, 8, res_botai);
|
||||
}
|
||||
|
||||
return hook.status;
|
||||
|
@ -787,7 +868,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
|
|||
LUA_PushUserdata(gL, line, META_LINE);
|
||||
LUA_PushUserdata(gL, mo, META_MOBJ);
|
||||
LUA_PushUserdata(gL, sector, META_SECTOR);
|
||||
ps_lua_mobjhooks += call_hooks(&hook, 3, 0, res_none);
|
||||
ps_lua_mobjhooks += call_hooks(&hook, 0, res_none);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -811,7 +892,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg)
|
|||
LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
|
||||
}
|
||||
lua_pushstring(gL, msg); // msg
|
||||
call_hooks(&hook, 4, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -825,7 +906,7 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 d
|
|||
LUA_PushUserdata(gL, inflictor, META_MOBJ);
|
||||
LUA_PushUserdata(gL, source, META_MOBJ);
|
||||
lua_pushinteger(gL, damagetype);
|
||||
call_hooks(&hook, 4, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -844,12 +925,14 @@ void LUA_HookNetArchive(lua_CFunction archFunc)
|
|||
push_error_handler();
|
||||
lua_insert(gL, EINDEX);
|
||||
|
||||
begin_hook_values(&hook);
|
||||
|
||||
// tables becomes an upvalue of archFunc
|
||||
lua_pushvalue(gL, -1);
|
||||
lua_pushcclosure(gL, archFunc, 1);
|
||||
// stack: tables, archFunc
|
||||
|
||||
init_hook_call(&hook, 1, 0, res_none);
|
||||
init_hook_call(&hook, 0, res_none);
|
||||
call_mapped(&hook, map);
|
||||
|
||||
lua_pop(gL, 1); // pop archFunc
|
||||
|
@ -865,7 +948,7 @@ int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing)
|
|||
{
|
||||
LUA_PushUserdata(gL, mobj, META_MOBJ);
|
||||
LUA_PushUserdata(gL, mthing, META_MAPTHING);
|
||||
call_hooks(&hook, 2, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -877,7 +960,7 @@ int LUA_HookFollowMobj(player_t *player, mobj_t *mobj)
|
|||
{
|
||||
LUA_PushUserdata(gL, player, META_PLAYER);
|
||||
LUA_PushUserdata(gL, mobj, META_MOBJ);
|
||||
call_hooks(&hook, 2, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -889,7 +972,7 @@ int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj)
|
|||
{
|
||||
LUA_PushUserdata(gL, player, META_PLAYER);
|
||||
LUA_PushUserdata(gL, mobj, META_MOBJ);
|
||||
call_hooks(&hook, 2, 1, res_force);
|
||||
call_hooks(&hook, 1, res_force);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -901,7 +984,7 @@ void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason)
|
|||
{
|
||||
LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit
|
||||
lua_pushinteger(gL, reason); // Reason for quitting
|
||||
call_hooks(&hook, 2, 0, res_none);
|
||||
call_hooks(&hook, 0, res_none);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -915,7 +998,7 @@ int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, bo
|
|||
lua_pushboolean(gL, fromspectators);
|
||||
lua_pushboolean(gL, tryingautobalance);
|
||||
lua_pushboolean(gL, tryingscramble);
|
||||
call_hooks(&hook, 5, 1, res_false);
|
||||
call_hooks(&hook, 1, res_false);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -930,7 +1013,7 @@ int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolea
|
|||
lua_pushboolean(gL, forced);
|
||||
|
||||
hud_running = true; // local hook
|
||||
call_hooks(&hook, 3, 1, res_force);
|
||||
call_hooks(&hook, 1, res_force);
|
||||
hud_running = false;
|
||||
}
|
||||
return hook.status;
|
||||
|
@ -945,7 +1028,7 @@ int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend)
|
|||
LUA_PushUserdata(gL, seenfriend, META_PLAYER);
|
||||
|
||||
hud_running = true; // local hook
|
||||
call_hooks(&hook, 2, 1, res_false);
|
||||
call_hooks(&hook, 1, res_false);
|
||||
hud_running = false;
|
||||
}
|
||||
return hook.status;
|
||||
|
@ -961,7 +1044,7 @@ int LUA_HookShouldJingleContinue(player_t *player, const char *musname)
|
|||
push_string();
|
||||
|
||||
hud_running = true; // local hook
|
||||
call_hooks(&hook, 2, 1, res_true);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
hud_running = false;
|
||||
}
|
||||
return hook.status;
|
||||
|
@ -1027,7 +1110,8 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param)
|
|||
|
||||
if (prepare_hook(&hook, false, type))
|
||||
{
|
||||
init_hook_call(&hook, 7, 6, res_musicchange);
|
||||
init_hook_call(&hook, 6, res_musicchange);
|
||||
hook.values = 7;/* values pushed later */
|
||||
hook.userdata = param;
|
||||
|
||||
lua_pushstring(gL, oldname);/* the only constant value */
|
||||
|
@ -1073,7 +1157,7 @@ fixed_t LUA_HookPlayerHeight(player_t *player)
|
|||
if (prepare_hook(&hook, -1, HOOK(PlayerHeight)))
|
||||
{
|
||||
LUA_PushUserdata(gL, player, META_PLAYER);
|
||||
call_hooks(&hook, 1, 1, res_playerheight);
|
||||
call_hooks(&hook, 1, res_playerheight);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
@ -1084,18 +1168,7 @@ int LUA_HookPlayerCanEnterSpinGaps(player_t *player)
|
|||
if (prepare_hook(&hook, 0, HOOK(PlayerCanEnterSpinGaps)))
|
||||
{
|
||||
LUA_PushUserdata(gL, player, META_PLAYER);
|
||||
call_hooks(&hook, 1, 1, res_force);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
||||
int LUA_HookKey(INT32 keycode, int hooktype)
|
||||
{
|
||||
Hook_State hook;
|
||||
if (prepare_hook(&hook, 0, hooktype))
|
||||
{
|
||||
lua_pushinteger(gL, keycode);
|
||||
call_hooks(&hook, 1, 0, res_true);
|
||||
call_hooks(&hook, 1, res_force);
|
||||
}
|
||||
return hook.status;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,4 @@ extern boolean hud_running;
|
|||
|
||||
boolean LUA_HudEnabled(enum hud option);
|
||||
|
||||
void LUAh_GameHUD(player_t *stplyr);
|
||||
void LUAh_ScoresHUD(void);
|
||||
void LUAh_TitleHUD(void);
|
||||
void LUAh_TitleCardHUD(player_t *stplayr);
|
||||
void LUAh_IntermissionHUD(boolean failedstage);
|
||||
void LUA_SetHudHook(int hook);
|
||||
|
|
380
src/lua_hudlib.c
380
src/lua_hudlib.c
|
@ -23,18 +23,18 @@
|
|||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "y_inter.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hook.h"
|
||||
|
||||
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
|
||||
|
||||
boolean hud_running = false;
|
||||
static UINT8 hud_enabled[(hud_MAX/8)+1];
|
||||
|
||||
static UINT8 hudAvailable; // hud hooks field
|
||||
|
||||
// must match enum hud in lua_hud.h
|
||||
static const char *const hud_disable_options[] = {
|
||||
"stagetitle",
|
||||
|
@ -95,21 +95,6 @@ static const char *const patch_opt[] = {
|
|||
"topoffset",
|
||||
NULL};
|
||||
|
||||
enum hudhook {
|
||||
hudhook_game = 0,
|
||||
hudhook_scores,
|
||||
hudhook_intermission,
|
||||
hudhook_title,
|
||||
hudhook_titlecard
|
||||
};
|
||||
static const char *const hudhook_opt[] = {
|
||||
"game",
|
||||
"scores",
|
||||
"intermission",
|
||||
"title",
|
||||
"titlecard",
|
||||
NULL};
|
||||
|
||||
// alignment types for v.drawString
|
||||
enum align {
|
||||
align_left = 0,
|
||||
|
@ -280,7 +265,7 @@ static int hudinfo_num(lua_State *L)
|
|||
|
||||
static int colormap_get(lua_State *L)
|
||||
{
|
||||
const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
|
||||
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
|
||||
UINT32 i = luaL_checkinteger(L, 2);
|
||||
if (i >= 256)
|
||||
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
|
||||
|
@ -288,6 +273,23 @@ static int colormap_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int colormap_set(lua_State *L)
|
||||
{
|
||||
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
|
||||
UINT32 i = luaL_checkinteger(L, 2);
|
||||
if (i >= 256)
|
||||
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
|
||||
colormap[i] = (UINT8)luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int colormap_free(lua_State *L)
|
||||
{
|
||||
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
|
||||
Z_Free(colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int patch_get(lua_State *L)
|
||||
{
|
||||
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
|
||||
|
@ -384,6 +386,74 @@ static int camera_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int camera_set(lua_State *L)
|
||||
{
|
||||
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
|
||||
enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt);
|
||||
|
||||
I_Assert(cam != NULL);
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case camera_subsector:
|
||||
case camera_floorz:
|
||||
case camera_ceilingz:
|
||||
case camera_x:
|
||||
case camera_y:
|
||||
return luaL_error(L, LUA_QL("camera_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_TryCameraMove") " or " LUA_QL("P_TeleportCameraMove") " instead.", camera_opt[field]);
|
||||
case camera_chase: {
|
||||
INT32 chase = luaL_checkboolean(L, 3);
|
||||
if (cam == &camera)
|
||||
CV_SetValue(&cv_chasecam, chase);
|
||||
else if (cam == &camera2)
|
||||
CV_SetValue(&cv_chasecam2, chase);
|
||||
else // ??? this should never happen, but ok
|
||||
cam->chase = chase;
|
||||
break;
|
||||
}
|
||||
case camera_aiming:
|
||||
cam->aiming = luaL_checkangle(L, 3);
|
||||
break;
|
||||
case camera_z:
|
||||
cam->z = luaL_checkfixed(L, 3);
|
||||
P_CheckCameraPosition(cam->x, cam->y, cam);
|
||||
cam->floorz = tmfloorz;
|
||||
cam->ceilingz = tmceilingz;
|
||||
break;
|
||||
case camera_angle:
|
||||
cam->angle = luaL_checkangle(L, 3);
|
||||
break;
|
||||
case camera_radius:
|
||||
cam->radius = luaL_checkfixed(L, 3);
|
||||
if (cam->radius < 0)
|
||||
cam->radius = 0;
|
||||
P_CheckCameraPosition(cam->x, cam->y, cam);
|
||||
cam->floorz = tmfloorz;
|
||||
cam->ceilingz = tmceilingz;
|
||||
break;
|
||||
case camera_height:
|
||||
cam->height = luaL_checkfixed(L, 3);
|
||||
if (cam->height < 0)
|
||||
cam->height = 0;
|
||||
P_CheckCameraPosition(cam->x, cam->y, cam);
|
||||
cam->floorz = tmfloorz;
|
||||
cam->ceilingz = tmceilingz;
|
||||
break;
|
||||
case camera_momx:
|
||||
cam->momx = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case camera_momy:
|
||||
cam->momy = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case camera_momz:
|
||||
cam->momz = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
default:
|
||||
return luaL_error(L, LUA_QL("camera_t") " has no field named " LUA_QS, camera_opt[field]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// lib_draw
|
||||
//
|
||||
|
@ -663,6 +733,45 @@ static int libd_drawStretched(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawCropped(lua_State *L)
|
||||
{
|
||||
fixed_t x, y, hscale, vscale, sx, sy, w, h;
|
||||
INT32 flags;
|
||||
patch_t *patch;
|
||||
const UINT8 *colormap = NULL;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
hscale = luaL_checkinteger(L, 3);
|
||||
if (hscale < 0)
|
||||
return luaL_error(L, "negative horizontal scale");
|
||||
vscale = luaL_checkinteger(L, 4);
|
||||
if (vscale < 0)
|
||||
return luaL_error(L, "negative vertical scale");
|
||||
patch = *((patch_t **)luaL_checkudata(L, 5, META_PATCH));
|
||||
flags = luaL_checkinteger(L, 6);
|
||||
if (!lua_isnoneornil(L, 7))
|
||||
colormap = *((UINT8 **)luaL_checkudata(L, 7, META_COLORMAP));
|
||||
sx = luaL_checkinteger(L, 8);
|
||||
if (sx < 0) // Don't crash. Now, we could do "x-=sx*FRACUNIT; sx=0;" here...
|
||||
return luaL_error(L, "negative crop sx");
|
||||
sy = luaL_checkinteger(L, 9);
|
||||
if (sy < 0) // ...but it's more truthful to just deny it, as negative values would crash
|
||||
return luaL_error(L, "negative crop sy");
|
||||
w = luaL_checkinteger(L, 10);
|
||||
if (w < 0) // Again, don't crash
|
||||
return luaL_error(L, "negative crop w");
|
||||
h = luaL_checkinteger(L, 11);
|
||||
if (h < 0)
|
||||
return luaL_error(L, "negative crop h");
|
||||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawCroppedPatch(x, y, hscale, vscale, flags, patch, colormap, sx, sy, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawNum(lua_State *L)
|
||||
{
|
||||
INT32 x, y, flags, num;
|
||||
|
@ -948,7 +1057,7 @@ static int libd_getColormap(lua_State *L)
|
|||
|
||||
// all was successful above, now we generate the colormap at last!
|
||||
|
||||
colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE);
|
||||
colormap = R_GetTranslationColormap(skinnum, color, 0);
|
||||
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
|
||||
return 1;
|
||||
}
|
||||
|
@ -957,10 +1066,14 @@ static int libd_getStringColormap(lua_State *L)
|
|||
{
|
||||
INT32 flags = luaL_checkinteger(L, 1);
|
||||
UINT8* colormap = NULL;
|
||||
UINT8* lua_colormap = NULL;
|
||||
HUDONLY
|
||||
colormap = V_GetStringColormap(flags & V_CHARCOLORMASK);
|
||||
if (colormap) {
|
||||
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
|
||||
lua_colormap = Z_Malloc(256 * sizeof(UINT8), PU_LUA, NULL);
|
||||
memcpy(lua_colormap, colormap, 256 * sizeof(UINT8));
|
||||
|
||||
LUA_PushUserdata(L, lua_colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1121,6 +1234,7 @@ static luaL_Reg lib_draw[] = {
|
|||
{"draw", libd_draw},
|
||||
{"drawScaled", libd_drawScaled},
|
||||
{"drawStretched", libd_drawStretched},
|
||||
{"drawCropped", libd_drawCropped},
|
||||
{"drawNum", libd_drawNum},
|
||||
{"drawPaddedNum", libd_drawPaddedNum},
|
||||
{"drawFill", libd_drawFill},
|
||||
|
@ -1152,6 +1266,8 @@ static luaL_Reg lib_draw[] = {
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static int lib_draw_ref;
|
||||
|
||||
//
|
||||
// lib_hud
|
||||
//
|
||||
|
@ -1186,28 +1302,7 @@ static int lib_hudenabled(lua_State *L)
|
|||
|
||||
|
||||
// add a HUD element for rendering
|
||||
static int lib_hudadd(lua_State *L)
|
||||
{
|
||||
enum hudhook field;
|
||||
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
field = luaL_checkoption(L, 2, "game", hudhook_opt);
|
||||
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
|
||||
I_Assert(lua_istable(L, -1));
|
||||
lua_rawgeti(L, -1, field+2); // HUD[2+]
|
||||
I_Assert(lua_istable(L, -1));
|
||||
lua_remove(L, -2);
|
||||
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1));
|
||||
|
||||
hudAvailable |= 1<<field;
|
||||
return 0;
|
||||
}
|
||||
extern int lib_hudadd(lua_State *L);
|
||||
|
||||
static luaL_Reg lib_hud[] = {
|
||||
{"enable", lib_hudenable},
|
||||
|
@ -1225,26 +1320,9 @@ int LUA_HudLib(lua_State *L)
|
|||
{
|
||||
memset(hud_enabled, 0xff, (hud_MAX/8)+1);
|
||||
|
||||
lua_newtable(L); // HUD registry table
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lib_draw);
|
||||
lua_rawseti(L, -2, 1); // HUD[1] = lib_draw
|
||||
|
||||
lua_newtable(L);
|
||||
lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array
|
||||
|
||||
lua_newtable(L);
|
||||
lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array
|
||||
|
||||
lua_newtable(L);
|
||||
lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array
|
||||
|
||||
lua_newtable(L);
|
||||
lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array
|
||||
|
||||
lua_newtable(L);
|
||||
lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "HUD");
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lib_draw);
|
||||
lib_draw_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
luaL_newmetatable(L, META_HUDINFO);
|
||||
lua_pushcfunction(L, hudinfo_get);
|
||||
|
@ -1270,6 +1348,12 @@ int LUA_HudLib(lua_State *L)
|
|||
luaL_newmetatable(L, META_COLORMAP);
|
||||
lua_pushcfunction(L, colormap_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, colormap_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, colormap_free);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_PATCH);
|
||||
|
@ -1283,6 +1367,9 @@ int LUA_HudLib(lua_State *L)
|
|||
luaL_newmetatable(L, META_CAMERA);
|
||||
lua_pushcfunction(L, camera_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, camera_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_register(L, "hud", lib_hud);
|
||||
|
@ -1296,160 +1383,29 @@ boolean LUA_HudEnabled(enum hud option)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Hook for HUD rendering
|
||||
void LUAh_GameHUD(player_t *stplayr)
|
||||
void LUA_SetHudHook(int hook)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_game)))
|
||||
return;
|
||||
lua_getref(gL, lib_draw_ref);
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
switch (hook)
|
||||
{
|
||||
case HUD_HOOK(game): {
|
||||
camera_t *cam = (splitscreen && stplyr ==
|
||||
&players[secondarydisplayplayer])
|
||||
? &camera2 : &camera;
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
LUA_PushUserdata(gL, stplyr, META_PLAYER);
|
||||
LUA_PushUserdata(gL, cam, META_CAMERA);
|
||||
} break;
|
||||
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
case HUD_HOOK(titlecard):
|
||||
LUA_PushUserdata(gL, stplyr, META_PLAYER);
|
||||
lua_pushinteger(gL, lt_ticker);
|
||||
lua_pushinteger(gL, (lt_endtime + TICRATE));
|
||||
break;
|
||||
|
||||
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
LUA_PushUserdata(gL, stplayr, META_PLAYER);
|
||||
|
||||
if (splitscreen && stplayr == &players[secondarydisplayplayer])
|
||||
LUA_PushUserdata(gL, &camera2, META_CAMERA);
|
||||
else
|
||||
LUA_PushUserdata(gL, &camera, META_CAMERA);
|
||||
|
||||
lua_pushnil(gL);
|
||||
while (lua_next(gL, -5) != 0) {
|
||||
lua_pushvalue(gL, -5); // graphics library (HUD[1])
|
||||
lua_pushvalue(gL, -5); // stplayr
|
||||
lua_pushvalue(gL, -5); // camera
|
||||
LUA_Call(gL, 3, 0, 1);
|
||||
case HUD_HOOK(intermission):
|
||||
lua_pushboolean(gL, intertype == int_spec &&
|
||||
stagefailed);
|
||||
}
|
||||
lua_settop(gL, 0);
|
||||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_ScoresHUD(void)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
|
||||
return;
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
|
||||
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
lua_pushnil(gL);
|
||||
while (lua_next(gL, -3) != 0) {
|
||||
lua_pushvalue(gL, -3); // graphics library (HUD[1])
|
||||
LUA_Call(gL, 1, 0, 1);
|
||||
}
|
||||
lua_settop(gL, 0);
|
||||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_TitleHUD(void)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_title)))
|
||||
return;
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_rawgeti(gL, -1, 2+hudhook_title); // HUD[5] = rendering funcs
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
|
||||
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
lua_pushnil(gL);
|
||||
while (lua_next(gL, -3) != 0) {
|
||||
lua_pushvalue(gL, -3); // graphics library (HUD[1])
|
||||
LUA_Call(gL, 1, 0, 1);
|
||||
}
|
||||
lua_settop(gL, 0);
|
||||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_TitleCardHUD(player_t *stplayr)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_titlecard)))
|
||||
return;
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_rawgeti(gL, -1, 2+hudhook_titlecard); // HUD[6] = rendering funcs
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
|
||||
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
|
||||
LUA_PushUserdata(gL, stplayr, META_PLAYER);
|
||||
lua_pushinteger(gL, lt_ticker);
|
||||
lua_pushinteger(gL, (lt_endtime + TICRATE));
|
||||
lua_pushnil(gL);
|
||||
|
||||
while (lua_next(gL, -6) != 0) {
|
||||
lua_pushvalue(gL, -6); // graphics library (HUD[1])
|
||||
lua_pushvalue(gL, -6); // stplayr
|
||||
lua_pushvalue(gL, -6); // lt_ticker
|
||||
lua_pushvalue(gL, -6); // lt_endtime
|
||||
LUA_Call(gL, 4, 0, 1);
|
||||
}
|
||||
|
||||
lua_settop(gL, 0);
|
||||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_IntermissionHUD(boolean failedstage)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_intermission)))
|
||||
return;
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_rawgeti(gL, -1, 2+hudhook_intermission); // HUD[4] = rendering funcs
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
|
||||
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
|
||||
lua_pushboolean(gL, failedstage); // stagefailed
|
||||
lua_pushnil(gL);
|
||||
|
||||
while (lua_next(gL, -4) != 0) {
|
||||
lua_pushvalue(gL, -4); // graphics library (HUD[1])
|
||||
lua_pushvalue(gL, -4); // stagefailed
|
||||
LUA_Call(gL, 2, 0, 1);
|
||||
}
|
||||
lua_settop(gL, 0);
|
||||
hud_running = false;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
boolean mousegrabbedbylua = true;
|
||||
|
||||
///////////////
|
||||
// FUNCTIONS //
|
||||
///////////////
|
||||
|
@ -26,8 +28,8 @@
|
|||
static int lib_gameControlDown(lua_State *L)
|
||||
{
|
||||
int i = luaL_checkinteger(L, 1);
|
||||
if (i < 0 || i >= num_gamecontrols)
|
||||
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
|
||||
if (i < 0 || i >= NUM_GAMECONTROLS)
|
||||
return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
|
||||
lua_pushinteger(L, PLAYER1INPUTDOWN(i));
|
||||
return 1;
|
||||
}
|
||||
|
@ -35,8 +37,8 @@ static int lib_gameControlDown(lua_State *L)
|
|||
static int lib_gameControl2Down(lua_State *L)
|
||||
{
|
||||
int i = luaL_checkinteger(L, 1);
|
||||
if (i < 0 || i >= num_gamecontrols)
|
||||
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
|
||||
if (i < 0 || i >= NUM_GAMECONTROLS)
|
||||
return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
|
||||
lua_pushinteger(L, PLAYER2INPUTDOWN(i));
|
||||
return 1;
|
||||
}
|
||||
|
@ -44,8 +46,8 @@ static int lib_gameControl2Down(lua_State *L)
|
|||
static int lib_gameControlToKeyNum(lua_State *L)
|
||||
{
|
||||
int i = luaL_checkinteger(L, 1);
|
||||
if (i < 0 || i >= num_gamecontrols)
|
||||
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
|
||||
if (i < 0 || i >= NUM_GAMECONTROLS)
|
||||
return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
|
||||
lua_pushinteger(L, gamecontrol[i][0]);
|
||||
lua_pushinteger(L, gamecontrol[i][1]);
|
||||
return 2;
|
||||
|
@ -54,8 +56,8 @@ static int lib_gameControlToKeyNum(lua_State *L)
|
|||
static int lib_gameControl2ToKeyNum(lua_State *L)
|
||||
{
|
||||
int i = luaL_checkinteger(L, 1);
|
||||
if (i < 0 || i >= num_gamecontrols)
|
||||
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
|
||||
if (i < 0 || i >= NUM_GAMECONTROLS)
|
||||
return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
|
||||
lua_pushinteger(L, gamecontrolbis[i][0]);
|
||||
lua_pushinteger(L, gamecontrolbis[i][1]);
|
||||
return 2;
|
||||
|
@ -75,17 +77,17 @@ static int lib_joy2Axis(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_keyNumToString(lua_State *L)
|
||||
static int lib_keyNumToName(lua_State *L)
|
||||
{
|
||||
int i = luaL_checkinteger(L, 1);
|
||||
lua_pushstring(L, G_KeyNumToString(i));
|
||||
lua_pushstring(L, G_KeyNumToName(i));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_keyStringToNum(lua_State *L)
|
||||
static int lib_keyNameToNum(lua_State *L)
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 1);
|
||||
lua_pushinteger(L, G_KeyStringToNum(str));
|
||||
lua_pushinteger(L, G_KeyNameToNum(str));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -106,14 +108,14 @@ static int lib_shiftKeyNum(lua_State *L)
|
|||
|
||||
static int lib_getMouseGrab(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, I_GetMouseGrab());
|
||||
lua_pushboolean(L, mousegrabbedbylua);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_setMouseGrab(lua_State *L)
|
||||
{
|
||||
boolean grab = luaL_checkboolean(L, 1);
|
||||
I_SetMouseGrab(grab);
|
||||
mousegrabbedbylua = luaL_checkboolean(L, 1);
|
||||
I_UpdateMouseGrab();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -127,19 +129,19 @@ static int lib_getCursorPosition(lua_State *L)
|
|||
}
|
||||
|
||||
static luaL_Reg lib[] = {
|
||||
{"G_GameControlDown", lib_gameControlDown},
|
||||
{"G_GameControl2Down", lib_gameControl2Down},
|
||||
{"G_GameControlToKeyNum", lib_gameControlToKeyNum},
|
||||
{"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum},
|
||||
{"G_JoyAxis", lib_joyAxis},
|
||||
{"G_Joy2Axis", lib_joy2Axis},
|
||||
{"G_KeyNumToString", lib_keyNumToString},
|
||||
{"G_KeyStringToNum", lib_keyStringToNum},
|
||||
{"HU_KeyNumPrintable", lib_keyNumPrintable},
|
||||
{"HU_ShiftKeyNum", lib_shiftKeyNum},
|
||||
{"I_GetMouseGrab", lib_getMouseGrab},
|
||||
{"I_SetMouseGrab", lib_setMouseGrab},
|
||||
{"I_GetCursorPosition", lib_getCursorPosition},
|
||||
{"gameControlDown", lib_gameControlDown},
|
||||
{"gameControl2Down", lib_gameControl2Down},
|
||||
{"gameControlToKeyNum", lib_gameControlToKeyNum},
|
||||
{"gameControl2ToKeyNum", lib_gameControl2ToKeyNum},
|
||||
{"joyAxis", lib_joyAxis},
|
||||
{"joy2Axis", lib_joy2Axis},
|
||||
{"keyNumToName", lib_keyNumToName},
|
||||
{"keyNameToNum", lib_keyNameToNum},
|
||||
{"keyNumPrintable", lib_keyNumPrintable},
|
||||
{"shiftKeyNum", lib_shiftKeyNum},
|
||||
{"getMouseGrab", lib_getMouseGrab},
|
||||
{"setMouseGrab", lib_setMouseGrab},
|
||||
{"getCursorPosition", lib_getCursorPosition},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -172,6 +174,29 @@ static int lib_lenGameKeyDown(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// KEY EVENT //
|
||||
///////////////
|
||||
|
||||
static int keyevent_get(lua_State *L)
|
||||
{
|
||||
event_t *event = *((event_t **)luaL_checkudata(L, 1, META_KEYEVENT));
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
|
||||
I_Assert(event != NULL);
|
||||
|
||||
if (fastcmp(field,"name"))
|
||||
lua_pushstring(L, G_KeyNumToName(event->key));
|
||||
else if (fastcmp(field,"num"))
|
||||
lua_pushinteger(L, event->key);
|
||||
else if (fastcmp(field,"repeated"))
|
||||
lua_pushboolean(L, event->repeated);
|
||||
else
|
||||
return luaL_error(L, "keyevent_t has no field named %s", field);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
///////////
|
||||
// MOUSE //
|
||||
///////////
|
||||
|
@ -227,6 +252,11 @@ int LUA_InputLib(lua_State *L)
|
|||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "gamekeydown");
|
||||
|
||||
luaL_newmetatable(L, META_KEYEVENT);
|
||||
lua_pushcfunction(L, keyevent_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_MOUSE);
|
||||
lua_pushcfunction(L, mouse_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
@ -235,8 +265,6 @@ int LUA_InputLib(lua_State *L)
|
|||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Set global functions
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
luaL_register(L, NULL, lib);
|
||||
luaL_register(L, "input", lib);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
extern lua_State *gL;
|
||||
|
||||
extern boolean mousegrabbedbylua;
|
||||
|
||||
#define MUTABLE_TAGS
|
||||
|
||||
#define LREG_VALID "VALID_USERDATA"
|
||||
|
@ -88,6 +90,7 @@ extern lua_State *gL;
|
|||
|
||||
#define META_LUABANKS "LUABANKS[]*"
|
||||
|
||||
#define META_KEYEVENT "KEYEVENT_T*"
|
||||
#define META_MOUSE "MOUSE_T*"
|
||||
|
||||
boolean luaL_checkboolean(lua_State *L, int narg);
|
||||
|
|
|
@ -370,6 +370,12 @@ static int player_get(lua_State *L)
|
|||
lua_pushboolean(L, plr->outofcoop);
|
||||
else if (fastcmp(field,"bot"))
|
||||
lua_pushinteger(L, plr->bot);
|
||||
else if (fastcmp(field,"botleader"))
|
||||
LUA_PushUserdata(L, plr->botleader, META_PLAYER);
|
||||
else if (fastcmp(field,"lastbuttons"))
|
||||
lua_pushinteger(L, plr->lastbuttons);
|
||||
else if (fastcmp(field,"blocked"))
|
||||
lua_pushboolean(L, plr->blocked);
|
||||
else if (fastcmp(field,"jointime"))
|
||||
lua_pushinteger(L, plr->jointime);
|
||||
else if (fastcmp(field,"quittime"))
|
||||
|
@ -719,6 +725,17 @@ static int player_set(lua_State *L)
|
|||
plr->outofcoop = lua_toboolean(L, 3);
|
||||
else if (fastcmp(field,"bot"))
|
||||
return NOSET;
|
||||
else if (fastcmp(field,"botleader"))
|
||||
{
|
||||
player_t *player = NULL;
|
||||
if (!lua_isnil(L, 3))
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
plr->botleader = player;
|
||||
}
|
||||
else if (fastcmp(field,"lastbuttons"))
|
||||
plr->lastbuttons = (UINT16)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"blocked"))
|
||||
plr->blocked = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"jointime"))
|
||||
plr->jointime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"quittime"))
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "byteptr.h"
|
||||
#include "p_saveg.h"
|
||||
#include "p_local.h"
|
||||
#include "p_slopes.h" // for P_SlopeById
|
||||
#include "p_slopes.h" // for P_SlopeById and slopelist
|
||||
#include "p_polyobj.h" // polyobj_t, PolyObjects
|
||||
#ifdef LUA_ALLOW_BYTECODE
|
||||
#include "d_netfil.h" // for LUA_DumpFile
|
||||
|
@ -393,6 +393,14 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word, "mouse2")) {
|
||||
LUA_PushUserdata(L, &mouse2, META_MOUSE);
|
||||
return 1;
|
||||
} else if (fastcmp(word, "camera")) {
|
||||
LUA_PushUserdata(L, &camera, META_CAMERA);
|
||||
return 1;
|
||||
} else if (fastcmp(word, "camera2")) {
|
||||
if (!splitscreen)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &camera2, META_CAMERA);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -851,6 +859,8 @@ void LUA_InvalidateLevel(void)
|
|||
{
|
||||
LUA_InvalidateUserdata(&lines[i]);
|
||||
LUA_InvalidateUserdata(&lines[i].tags);
|
||||
LUA_InvalidateUserdata(lines[i].args);
|
||||
LUA_InvalidateUserdata(lines[i].stringargs);
|
||||
LUA_InvalidateUserdata(lines[i].sidenum);
|
||||
}
|
||||
for (i = 0; i < numsides; i++)
|
||||
|
@ -863,6 +873,13 @@ void LUA_InvalidateLevel(void)
|
|||
LUA_InvalidateUserdata(&PolyObjects[i].vertices);
|
||||
LUA_InvalidateUserdata(&PolyObjects[i].lines);
|
||||
}
|
||||
for (pslope_t *slope = slopelist; slope; slope = slope->next)
|
||||
{
|
||||
LUA_InvalidateUserdata(slope);
|
||||
LUA_InvalidateUserdata(&slope->normal);
|
||||
LUA_InvalidateUserdata(&slope->o);
|
||||
LUA_InvalidateUserdata(&slope->d);
|
||||
}
|
||||
#ifdef HAVE_LUA_SEGS
|
||||
for (i = 0; i < numsegs; i++)
|
||||
LUA_InvalidateUserdata(&segs[i]);
|
||||
|
@ -885,6 +902,8 @@ void LUA_InvalidateMapthings(void)
|
|||
{
|
||||
LUA_InvalidateUserdata(&mapthings[i]);
|
||||
LUA_InvalidateUserdata(&mapthings[i].tags);
|
||||
LUA_InvalidateUserdata(mapthings[i].args);
|
||||
LUA_InvalidateUserdata(mapthings[i].stringargs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,21 +1392,13 @@ static void ArchiveTables(void)
|
|||
// Write key
|
||||
e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
|
||||
if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise)
|
||||
{
|
||||
lua_pushvalue(gL, -2);
|
||||
CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -1), luaL_typename(gL, -1), i);
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i);
|
||||
// Write value
|
||||
e = ArchiveValue(TABLESINDEX, -1);
|
||||
if (e == 1)
|
||||
n++; // the table contained a new table we'll have to archive. :(
|
||||
else if (e == 2) // invalid value type
|
||||
{
|
||||
lua_pushvalue(gL, -2);
|
||||
CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1));
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -2), luaL_typename(gL, -1));
|
||||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
|
|
|
@ -203,11 +203,11 @@ boolean cht_Responder(event_t *ev)
|
|||
if (ev->type != ev_keydown)
|
||||
return false;
|
||||
|
||||
if (ev->data1 > 0xFF)
|
||||
if (ev->key > 0xFF)
|
||||
{
|
||||
// map some fake (joy) inputs into keys
|
||||
// map joy inputs into keys
|
||||
switch (ev->data1)
|
||||
switch (ev->key)
|
||||
{
|
||||
case KEY_JOY1:
|
||||
case KEY_JOY1 + 2:
|
||||
|
@ -231,7 +231,7 @@ boolean cht_Responder(event_t *ev)
|
|||
}
|
||||
}
|
||||
else
|
||||
ch = (UINT8)ev->data1;
|
||||
ch = (UINT8)ev->key;
|
||||
|
||||
ret += cht_CheckCheat(&cheat_ultimate, (char)ch);
|
||||
ret += cht_CheckCheat(&cheat_ultimate_joy, (char)ch);
|
||||
|
|
120
src/m_menu.c
120
src/m_menu.c
|
@ -1106,55 +1106,55 @@ static menuitem_t OP_ChangeControlsMenu[] =
|
|||
{
|
||||
{IT_HEADER, NULL, "Movement", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Forward", M_ChangeControl, gc_forward },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, gc_backward },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, gc_strafeleft },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, gc_straferight },
|
||||
{IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, gc_jump },
|
||||
{IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_spin },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Forward", M_ChangeControl, GC_FORWARD },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, GC_BACKWARD },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, GC_STRAFELEFT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, GC_STRAFERIGHT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, GC_JUMP },
|
||||
{IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, GC_SPIN },
|
||||
{IT_HEADER, NULL, "Camera", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, gc_turnleft },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, gc_turnright },
|
||||
{IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle},
|
||||
{IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, GC_LOOKUP },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, GC_LOOKDOWN },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, GC_TURNLEFT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, GC_TURNRIGHT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, GC_CENTERVIEW },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, GC_MOUSEAIMING },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, GC_CAMTOGGLE},
|
||||
{IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, GC_CAMRESET },
|
||||
{IT_HEADER, NULL, "Meta", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Game Status",
|
||||
M_ChangeControl, gc_scores },
|
||||
{IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, gc_pause },
|
||||
{IT_CALL | IT_STRING2, NULL, "Screenshot", M_ChangeControl, gc_screenshot },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording", M_ChangeControl, gc_recordgif },
|
||||
{IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu },
|
||||
{IT_CALL | IT_STRING2, NULL, "Change Viewpoint", M_ChangeControl, gc_viewpoint },
|
||||
{IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console },
|
||||
M_ChangeControl, GC_SCORES },
|
||||
{IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, GC_PAUSE },
|
||||
{IT_CALL | IT_STRING2, NULL, "Screenshot", M_ChangeControl, GC_SCREENSHOT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording", M_ChangeControl, GC_RECORDGIF },
|
||||
{IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, GC_SYSTEMMENU },
|
||||
{IT_CALL | IT_STRING2, NULL, "Change Viewpoint", M_ChangeControl, GC_VIEWPOINT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, GC_CONSOLE },
|
||||
{IT_HEADER, NULL, "Multiplayer", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Talk", M_ChangeControl, gc_talkkey },
|
||||
{IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, gc_teamkey },
|
||||
{IT_CALL | IT_STRING2, NULL, "Talk", M_ChangeControl, GC_TALKKEY },
|
||||
{IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, GC_TEAMKEY },
|
||||
{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Fire", M_ChangeControl, gc_fire },
|
||||
{IT_CALL | IT_STRING2, NULL, "Fire Normal", M_ChangeControl, gc_firenormal },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toss Flag", M_ChangeControl, gc_tossflag },
|
||||
{IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, gc_weaponnext },
|
||||
{IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, gc_weaponprev },
|
||||
{IT_CALL | IT_STRING2, NULL, "Normal / Infinity", M_ChangeControl, gc_wepslot1 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Automatic", M_ChangeControl, gc_wepslot2 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Bounce", M_ChangeControl, gc_wepslot3 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Scatter", M_ChangeControl, gc_wepslot4 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Grenade", M_ChangeControl, gc_wepslot5 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Explosion", M_ChangeControl, gc_wepslot6 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Rail", M_ChangeControl, gc_wepslot7 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Fire", M_ChangeControl, GC_FIRE },
|
||||
{IT_CALL | IT_STRING2, NULL, "Fire Normal", M_ChangeControl, GC_FIRENORMAL },
|
||||
{IT_CALL | IT_STRING2, NULL, "Toss Flag", M_ChangeControl, GC_TOSSFLAG },
|
||||
{IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, GC_WEAPONNEXT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, GC_WEAPONPREV },
|
||||
{IT_CALL | IT_STRING2, NULL, "Normal / Infinity", M_ChangeControl, GC_WEPSLOT1 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Automatic", M_ChangeControl, GC_WEPSLOT2 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Bounce", M_ChangeControl, GC_WEPSLOT3 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Scatter", M_ChangeControl, GC_WEPSLOT4 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Grenade", M_ChangeControl, GC_WEPSLOT5 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Explosion", M_ChangeControl, GC_WEPSLOT6 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Rail", M_ChangeControl, GC_WEPSLOT7 },
|
||||
{IT_HEADER, NULL, "Add-ons", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, GC_CUSTOM1 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, GC_CUSTOM2 },
|
||||
{IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, GC_CUSTOM3 },
|
||||
};
|
||||
|
||||
static menuitem_t OP_Joystick1Menu[] =
|
||||
|
@ -3229,7 +3229,7 @@ boolean M_Responder(event_t *ev)
|
|||
if (ev->type == ev_keydown)
|
||||
{
|
||||
keydown++;
|
||||
ch = ev->data1;
|
||||
ch = ev->key;
|
||||
|
||||
// added 5-2-98 remap virtual keys (mouse & joystick buttons)
|
||||
switch (ch)
|
||||
|
@ -3262,44 +3262,44 @@ boolean M_Responder(event_t *ev)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime())
|
||||
else if (ev->type == ev_joystick && ev->key == 0 && joywait < I_GetTime())
|
||||
{
|
||||
const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT;
|
||||
if (ev->data3 != INT32_MAX)
|
||||
if (ev->y != INT32_MAX)
|
||||
{
|
||||
if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone)
|
||||
if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone)
|
||||
{
|
||||
if (ev->data3 < 0 && pjoyy >= 0)
|
||||
if (ev->y < 0 && pjoyy >= 0)
|
||||
{
|
||||
ch = KEY_UPARROW;
|
||||
joywait = I_GetTime() + NEWTICRATE/7;
|
||||
}
|
||||
else if (ev->data3 > 0 && pjoyy <= 0)
|
||||
else if (ev->y > 0 && pjoyy <= 0)
|
||||
{
|
||||
ch = KEY_DOWNARROW;
|
||||
joywait = I_GetTime() + NEWTICRATE/7;
|
||||
}
|
||||
pjoyy = ev->data3;
|
||||
pjoyy = ev->y;
|
||||
}
|
||||
else
|
||||
pjoyy = 0;
|
||||
}
|
||||
|
||||
if (ev->data2 != INT32_MAX)
|
||||
if (ev->x != INT32_MAX)
|
||||
{
|
||||
if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone)
|
||||
if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone)
|
||||
{
|
||||
if (ev->data2 < 0 && pjoyx >= 0)
|
||||
if (ev->x < 0 && pjoyx >= 0)
|
||||
{
|
||||
ch = KEY_LEFTARROW;
|
||||
joywait = I_GetTime() + NEWTICRATE/17;
|
||||
}
|
||||
else if (ev->data2 > 0 && pjoyx <= 0)
|
||||
else if (ev->x > 0 && pjoyx <= 0)
|
||||
{
|
||||
ch = KEY_RIGHTARROW;
|
||||
joywait = I_GetTime() + NEWTICRATE/17;
|
||||
}
|
||||
pjoyx = ev->data2;
|
||||
pjoyx = ev->x;
|
||||
}
|
||||
else
|
||||
pjoyx = 0;
|
||||
|
@ -3307,7 +3307,7 @@ boolean M_Responder(event_t *ev)
|
|||
}
|
||||
else if (ev->type == ev_mouse && mousewait < I_GetTime())
|
||||
{
|
||||
pmousey -= ev->data3;
|
||||
pmousey -= ev->y;
|
||||
if (pmousey < lasty-30)
|
||||
{
|
||||
ch = KEY_DOWNARROW;
|
||||
|
@ -3321,7 +3321,7 @@ boolean M_Responder(event_t *ev)
|
|||
pmousey = lasty += 30;
|
||||
}
|
||||
|
||||
pmousex += ev->data2;
|
||||
pmousex += ev->x;
|
||||
if (pmousex < lastx - 30)
|
||||
{
|
||||
ch = KEY_LEFTARROW;
|
||||
|
@ -3339,11 +3339,11 @@ boolean M_Responder(event_t *ev)
|
|||
keydown = 0;
|
||||
}
|
||||
else if (ev->type == ev_keydown) // Preserve event for other responders
|
||||
ch = ev->data1;
|
||||
ch = ev->key;
|
||||
|
||||
if (ch == -1)
|
||||
return false;
|
||||
else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key
|
||||
else if (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1]) // allow remappable ESC key
|
||||
ch = KEY_ESCAPE;
|
||||
|
||||
// F-Keys
|
||||
|
@ -4185,7 +4185,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_
|
|||
if (staticalong > pw) // simplified for base LSSTATIC
|
||||
staticalong -= pw;
|
||||
|
||||
V_DrawCroppedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT/2, flags, patch, staticalong, 0, sw, h*2); // FixedDiv(h, scale)); -- for scale FRACUNIT/2
|
||||
V_DrawCroppedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT/2, FRACUNIT/2, flags, patch, NULL, staticalong<<FRACBITS, 0, sw<<FRACBITS, h*2<<FRACBITS); // FixedDiv(h, scale)); -- for scale FRACUNIT/2
|
||||
|
||||
staticalong += sw; //M_RandomRange(sw/2, 2*sw); -- turns out less randomisation looks better because immediately adjacent frames can't end up close to each other
|
||||
|
||||
|
@ -12826,13 +12826,13 @@ static void M_DrawControl(void)
|
|||
else
|
||||
{
|
||||
if (keys[0] != KEY_NULL)
|
||||
strcat (tmp, G_KeyNumToString (keys[0]));
|
||||
strcat (tmp, G_KeyNumToName (keys[0]));
|
||||
|
||||
if (keys[0] != KEY_NULL && keys[1] != KEY_NULL)
|
||||
strcat(tmp," or ");
|
||||
|
||||
if (keys[1] != KEY_NULL)
|
||||
strcat (tmp, G_KeyNumToString (keys[1]));
|
||||
strcat (tmp, G_KeyNumToName (keys[1]));
|
||||
|
||||
|
||||
}
|
||||
|
@ -12859,7 +12859,7 @@ static void M_ChangecontrolResponse(event_t *ev)
|
|||
{
|
||||
INT32 control;
|
||||
INT32 found;
|
||||
INT32 ch = ev->data1;
|
||||
INT32 ch = ev->key;
|
||||
|
||||
// ESCAPE cancels; dummy out PAUSE
|
||||
if (ch != KEY_ESCAPE && ch != KEY_PAUSE)
|
||||
|
@ -12878,7 +12878,7 @@ static void M_ChangecontrolResponse(event_t *ev)
|
|||
// keypad arrows are converted for the menu in cursor arrows
|
||||
// so use the event instead of ch
|
||||
case ev_keydown:
|
||||
ch = ev->data1;
|
||||
ch = ev->key;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -12929,7 +12929,7 @@ static void M_ChangecontrolResponse(event_t *ev)
|
|||
static char tmp[158];
|
||||
menu_t *prev = currentMenu->prevMenu;
|
||||
|
||||
if (controltochange == gc_pause)
|
||||
if (controltochange == GC_PAUSE)
|
||||
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit cannot be used to retry runs \nduring Record Attack. \n\nHit another key for\n%s\nESC for Cancel"),
|
||||
controltochangetext);
|
||||
else
|
||||
|
|
25
src/m_misc.c
25
src/m_misc.c
|
@ -1631,14 +1631,14 @@ boolean M_ScreenshotResponder(event_t *ev)
|
|||
if (dedicated || ev->type != ev_keydown)
|
||||
return false;
|
||||
|
||||
ch = ev->data1;
|
||||
ch = ev->key;
|
||||
|
||||
if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus!
|
||||
return false;
|
||||
|
||||
if (ch == KEY_F8 || ch == gamecontrol[gc_screenshot][0] || ch == gamecontrol[gc_screenshot][1]) // remappable F8
|
||||
if (ch == KEY_F8 || ch == gamecontrol[GC_SCREENSHOT][0] || ch == gamecontrol[GC_SCREENSHOT][1]) // remappable F8
|
||||
M_ScreenShot();
|
||||
else if (ch == KEY_F9 || ch == gamecontrol[gc_recordgif][0] || ch == gamecontrol[gc_recordgif][1]) // remappable F9
|
||||
else if (ch == KEY_F9 || ch == gamecontrol[GC_RECORDGIF][0] || ch == gamecontrol[GC_RECORDGIF][1]) // remappable F9
|
||||
((moviemode) ? M_StopMovie : M_StartMovie)();
|
||||
else
|
||||
return false;
|
||||
|
@ -2688,3 +2688,22 @@ const char * M_Ftrim (double f)
|
|||
return &dig[1];/* skip the 0 */
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the string is empty.
|
||||
boolean M_IsStringEmpty(const char *s)
|
||||
{
|
||||
const char *ch = s;
|
||||
|
||||
if (s == NULL || s[0] == '\0')
|
||||
return true;
|
||||
|
||||
for (;;ch++)
|
||||
{
|
||||
if (!(*ch))
|
||||
break;
|
||||
if (!isspace((*ch)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,9 @@ trailing zeros, or "" if the fractional part is zero.
|
|||
*/
|
||||
const char * M_Ftrim (double);
|
||||
|
||||
// Returns true if the string is empty.
|
||||
boolean M_IsStringEmpty(const char *s);
|
||||
|
||||
// counting bits, for weapon ammo code, usually
|
||||
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||
|
||||
|
|
|
@ -744,8 +744,8 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
|
|||
if (player->mo->health <= 0)
|
||||
continue; // dead
|
||||
|
||||
if (player->bot)
|
||||
continue; // ignore bots
|
||||
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN)
|
||||
continue; // ignore followbots
|
||||
|
||||
if (player->quittime)
|
||||
continue; // Ignore uncontrolled bodies
|
||||
|
@ -3591,7 +3591,7 @@ void A_1upThinker(mobj_t *actor)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].bot || players[i].spectator)
|
||||
if (!playeringame[i] || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (!players[i].mo)
|
||||
|
@ -8259,7 +8259,7 @@ void A_Boss3ShockThink(mobj_t *actor)
|
|||
fixed_t x0, y0, x1, y1;
|
||||
|
||||
// Break the link if movements are too different
|
||||
if (FixedHypot(snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale)
|
||||
if (R_PointToDist2(0, 0, snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale)
|
||||
{
|
||||
P_SetTarget(&actor->hnext, NULL);
|
||||
return;
|
||||
|
@ -8270,9 +8270,11 @@ void A_Boss3ShockThink(mobj_t *actor)
|
|||
y0 = actor->y;
|
||||
x1 = snext->x;
|
||||
y1 = snext->y;
|
||||
if (FixedHypot(x1 - x0, y1 - y0) > 2*actor->radius)
|
||||
if (R_PointToDist2(0, 0, x1 - x0, y1 - y0) > 2*actor->radius)
|
||||
{
|
||||
snew = P_SpawnMobj((x0 + x1) >> 1, (y0 + y1) >> 1, (actor->z + snext->z) >> 1, actor->type);
|
||||
snew = P_SpawnMobj((x0 >> 1) + (x1 >> 1),
|
||||
(y0 >> 1) + (y1 >> 1),
|
||||
(actor->z >> 1) + (snext->z >> 1), actor->type);
|
||||
snew->momx = (actor->momx + snext->momx) >> 1;
|
||||
snew->momy = (actor->momy + snext->momy) >> 1;
|
||||
snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed?
|
||||
|
@ -8280,6 +8282,10 @@ void A_Boss3ShockThink(mobj_t *actor)
|
|||
P_SetTarget(&snew->target, actor->target);
|
||||
snew->fuse = actor->fuse;
|
||||
|
||||
P_SetScale(snew, actor->scale);
|
||||
snew->destscale = actor->destscale;
|
||||
snew->scalespeed = actor->scalespeed;
|
||||
|
||||
P_SetTarget(&actor->hnext, snew);
|
||||
P_SetTarget(&snew->hnext, snext);
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ boolean P_CanPickupItem(player_t *player, boolean weapon)
|
|||
if (!player->mo || player->mo->health <= 0)
|
||||
return false;
|
||||
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
{
|
||||
if (weapon)
|
||||
return false;
|
||||
|
@ -178,7 +178,7 @@ void P_DoNightsScore(player_t *player)
|
|||
return; // Don't do any fancy shit for failures.
|
||||
|
||||
dummymo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+player->mo->height/2, MT_NIGHTSCORE);
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
player = &players[consoleplayer];
|
||||
|
||||
if (G_IsSpecialStage(gamemap)) // Global link count? Maybe not a good idea...
|
||||
|
@ -630,7 +630,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
// ***************************** //
|
||||
// Special Stage Token
|
||||
case MT_TOKEN:
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
|
||||
P_AddPlayerScore(player, 1000);
|
||||
|
@ -670,7 +670,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
// Emerald Hunt
|
||||
case MT_EMERHUNT:
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
|
||||
if (hunt1 == special)
|
||||
|
@ -701,7 +701,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
case MT_EMERALD5:
|
||||
case MT_EMERALD6:
|
||||
case MT_EMERALD7:
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
|
||||
if (special->threshold)
|
||||
|
@ -738,7 +738,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
// Secret emblem thingy
|
||||
case MT_EMBLEM:
|
||||
{
|
||||
if (demoplayback || player->bot)
|
||||
if (demoplayback || (player->bot && player->bot != BOT_MPAI))
|
||||
return;
|
||||
emblemlocations[special->health-1].collected = true;
|
||||
|
||||
|
@ -751,7 +751,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
// CTF Flags
|
||||
case MT_REDFLAG:
|
||||
case MT_BLUEFLAG:
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
if (player->powers[pw_flashing] || player->tossdelay)
|
||||
return;
|
||||
|
@ -826,7 +826,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
{
|
||||
boolean spec = G_IsSpecialStage(gamemap);
|
||||
boolean cangiveemmy = false;
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
if (player->exiting)
|
||||
return;
|
||||
|
@ -1072,7 +1072,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
return;
|
||||
case MT_EGGCAPSULE:
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
|
||||
// make sure everything is as it should be, THEN take rings from players in special stages
|
||||
|
@ -1164,7 +1164,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
return;
|
||||
case MT_NIGHTSSUPERLOOP:
|
||||
if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
return;
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
player->powers[pw_nights_superloop] = (UINT16)special->info->speed;
|
||||
|
@ -1186,7 +1186,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
break;
|
||||
case MT_NIGHTSDRILLREFILL:
|
||||
if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
return;
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
player->drillmeter = special->info->speed;
|
||||
|
@ -1208,7 +1208,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
break;
|
||||
case MT_NIGHTSHELPER:
|
||||
if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
return;
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
{
|
||||
|
@ -1240,7 +1240,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
break;
|
||||
case MT_NIGHTSEXTRATIME:
|
||||
if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
return;
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
{
|
||||
|
@ -1272,7 +1272,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
break;
|
||||
case MT_NIGHTSLINKFREEZE:
|
||||
if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
return;
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
{
|
||||
|
@ -1332,7 +1332,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE)
|
||||
players[i].drillmeter += TICRATE/2;
|
||||
}
|
||||
else if (player->bot)
|
||||
else if (player->bot && player->bot != BOT_MPAI)
|
||||
players[consoleplayer].drillmeter += TICRATE/2;
|
||||
else
|
||||
player->drillmeter += TICRATE/2;
|
||||
|
@ -1384,7 +1384,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
thinker_t *th;
|
||||
mobj_t *mo2;
|
||||
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
|
||||
EV_DoElevator(LE_AXE, NULL, bridgeFall);
|
||||
|
@ -1417,7 +1417,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return;
|
||||
}
|
||||
case MT_FIREFLOWER:
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
|
||||
S_StartSound(toucher, sfx_mario3);
|
||||
|
@ -1679,7 +1679,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return; // Only go in the mouth
|
||||
|
||||
// Eaten by player!
|
||||
if ((!player->bot) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1))
|
||||
if ((!player->bot || player->bot == BOT_MPAI) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1))
|
||||
{
|
||||
player->powers[pw_underwater] = underwatertics + 1;
|
||||
P_RestoreMusic(player);
|
||||
|
@ -1690,7 +1690,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
if (!player->climbing)
|
||||
{
|
||||
if (player->bot && toucher->state-states != S_PLAY_GASP)
|
||||
if (player->bot && player->bot != BOT_MPAI && toucher->state-states != S_PLAY_GASP)
|
||||
S_StartSound(toucher, special->info->deathsound); // Force it to play a sound for bots
|
||||
P_SetPlayerMobjState(toucher, S_PLAY_GASP);
|
||||
P_ResetPlayer(player);
|
||||
|
@ -1698,7 +1698,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
toucher->momx = toucher->momy = toucher->momz = 0;
|
||||
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
else
|
||||
break;
|
||||
|
@ -1730,7 +1730,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return;
|
||||
|
||||
case MT_MINECARTSPAWNER:
|
||||
if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15)))
|
||||
if (!player->bot && player->bot != BOT_MPAI && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15)))
|
||||
{
|
||||
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
|
||||
P_SetTarget(&mcart->target, toucher);
|
||||
|
@ -1783,7 +1783,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
return;
|
||||
default: // SOC or script pickup
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
P_SetTarget(&special->target, toucher);
|
||||
break;
|
||||
|
@ -1807,7 +1807,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
|
|||
mobj_t *toucher = player->mo;
|
||||
mobj_t *checkbase = snaptopost ? post : toucher;
|
||||
|
||||
if (player->bot)
|
||||
if (player->bot && player->bot != BOT_MPAI)
|
||||
return;
|
||||
// In circuit, player must have touched all previous starposts
|
||||
if (circuitmap
|
||||
|
@ -2549,7 +2549,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
|
||||
if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0))
|
||||
;
|
||||
else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES)
|
||||
else if ((!target->player->bot || target->player->bot == BOT_MPAI) && !target->player->spectator && (target->player->lives != INFLIVES)
|
||||
&& G_GametypeUsesLives())
|
||||
{
|
||||
if (!(target->player->pflags & PF_FINISHED))
|
||||
|
@ -3469,7 +3469,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
|
|||
if (inflictor && inflictor->type == MT_LHRT)
|
||||
return;
|
||||
|
||||
if (player->powers[pw_shield] || player->bot) //If One-Hit Shield
|
||||
if (player->powers[pw_shield] || (player->bot && player->bot != BOT_MPAI)) //If One-Hit Shield
|
||||
{
|
||||
P_RemoveShield(player);
|
||||
S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss.
|
||||
|
@ -3560,7 +3560,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return false;
|
||||
|
||||
// Make sure that boxes cannot be popped by enemies, red rings, etc.
|
||||
if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot)
|
||||
if (target->flags & MF_MONITOR && ((!source || !source->player || (source->player->bot && source->player->bot != BOT_MPAI))
|
||||
|| (inflictor && (inflictor->type == MT_REDRING || (inflictor->type >= MT_THROWNBOUNCE && inflictor->type <= MT_THROWNGRENADE)))))
|
||||
return false;
|
||||
}
|
||||
|
@ -3695,7 +3695,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
}
|
||||
else if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype))
|
||||
return true;
|
||||
else if (player->powers[pw_shield] || (player->bot && !ultimatemode)) //If One-Hit Shield
|
||||
else if (player->powers[pw_shield] || (player->bot && player->bot != BOT_MPAI && !ultimatemode)) //If One-Hit Shield
|
||||
{
|
||||
P_ShieldDamage(player, inflictor, source, damage, damagetype);
|
||||
damage = 0;
|
||||
|
|
35
src/p_mobj.c
35
src/p_mobj.c
|
@ -1844,12 +1844,10 @@ void P_XYMovement(mobj_t *mo)
|
|||
// blocked move
|
||||
moved = false;
|
||||
|
||||
if (player) {
|
||||
if (player->bot)
|
||||
B_MoveBlocked(player);
|
||||
}
|
||||
if (player)
|
||||
B_MoveBlocked(player);
|
||||
|
||||
if (LUA_HookMobj(mo, MOBJ_HOOK(MobjMoveBlocked)))
|
||||
if (LUA_HookMobjMoveBlocked(mo, tmhitthing, blockingline))
|
||||
{
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return;
|
||||
|
@ -2554,6 +2552,10 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
}
|
||||
|
||||
P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly
|
||||
|
||||
if (P_MobjWasRemoved(mo)) // mobjs can be removed by P_CheckPosition -- Monster Iestyn 31/07/21
|
||||
return false;
|
||||
|
||||
if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM))
|
||||
{
|
||||
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
|
||||
|
@ -4141,7 +4143,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest)
|
|||
|
||||
player = &players[actor->lastlook];
|
||||
|
||||
if (player->pflags & PF_INVIS || player->bot || player->spectator)
|
||||
if (player->pflags & PF_INVIS || player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN || player->spectator)
|
||||
continue; // ignore notarget
|
||||
|
||||
if (!player->mo || P_MobjWasRemoved(player->mo))
|
||||
|
@ -4182,7 +4184,7 @@ boolean P_SupermanLook4Players(mobj_t *actor)
|
|||
if (players[c].pflags & PF_INVIS)
|
||||
continue; // ignore notarget
|
||||
|
||||
if (!players[c].mo || players[c].bot)
|
||||
if (!players[c].mo || players[c].bot == BOT_2PAI || players[c].bot == BOT_2PHUMAN)
|
||||
continue;
|
||||
|
||||
if (players[c].mo->health <= 0)
|
||||
|
@ -7311,7 +7313,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
|
|||
continue;
|
||||
if (!players[i].mo)
|
||||
continue;
|
||||
if (players[i].bot)
|
||||
if (players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN)
|
||||
continue;
|
||||
if (!players[i].mo->health)
|
||||
continue;
|
||||
|
@ -10393,6 +10395,9 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
|
|||
case MT_RING:
|
||||
case MT_FLINGRING:
|
||||
|
||||
case MT_COIN:
|
||||
case MT_FLINGCOIN:
|
||||
|
||||
case MT_BLUESPHERE:
|
||||
case MT_FLINGBLUESPHERE:
|
||||
case MT_BOMBSPHERE:
|
||||
|
@ -11056,7 +11061,7 @@ void P_SpawnPrecipitation(void)
|
|||
subsector_t *precipsector = NULL;
|
||||
precipmobj_t *rainmo = NULL;
|
||||
|
||||
if (dedicated || !(cv_drawdist_precip.value) || curWeather == PRECIP_NONE)
|
||||
if (dedicated || !(cv_drawdist_precip.value) || curWeather == PRECIP_NONE || curWeather == PRECIP_STORM_NORAIN)
|
||||
return;
|
||||
|
||||
// Use the blockmap to narrow down our placing patterns
|
||||
|
@ -11102,22 +11107,14 @@ void P_SpawnPrecipitation(void)
|
|||
continue;
|
||||
|
||||
rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN);
|
||||
if (curWeather == PRECIP_BLANK)
|
||||
rainmo->precipflags |= PCF_INVISIBLE;
|
||||
}
|
||||
|
||||
// Randomly assign a height, now that floorz is set.
|
||||
rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<<FRACBITS;
|
||||
}
|
||||
|
||||
if (curWeather == PRECIP_BLANK)
|
||||
{
|
||||
curWeather = PRECIP_RAIN;
|
||||
P_SwitchWeather(PRECIP_BLANK);
|
||||
}
|
||||
else if (curWeather == PRECIP_STORM_NORAIN)
|
||||
{
|
||||
curWeather = PRECIP_RAIN;
|
||||
P_SwitchWeather(PRECIP_STORM_NORAIN);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -193,6 +193,19 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT32(save_p, players[i].dashmode);
|
||||
WRITEUINT32(save_p, players[i].skidtime);
|
||||
|
||||
//////////
|
||||
// Bots //
|
||||
//////////
|
||||
WRITEUINT8(save_p, players[i].bot);
|
||||
WRITEUINT8(save_p, players[i].botmem.lastForward);
|
||||
WRITEUINT8(save_p, players[i].botmem.lastBlocked);
|
||||
WRITEUINT8(save_p, players[i].botmem.catchup_tics);
|
||||
WRITEUINT8(save_p, players[i].botmem.thinkstate);
|
||||
WRITEUINT8(save_p, players[i].removing);
|
||||
|
||||
WRITEUINT8(save_p, players[i].blocked);
|
||||
WRITEUINT16(save_p, players[i].lastbuttons);
|
||||
|
||||
////////////////////////////
|
||||
// Conveyor Belt Movement //
|
||||
////////////////////////////
|
||||
|
@ -407,6 +420,20 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].dashmode = READUINT32(save_p); // counter for dashmode ability
|
||||
players[i].skidtime = READUINT32(save_p); // Skid timer
|
||||
|
||||
//////////
|
||||
// Bots //
|
||||
//////////
|
||||
players[i].bot = READUINT8(save_p);
|
||||
|
||||
players[i].botmem.lastForward = READUINT8(save_p);
|
||||
players[i].botmem.lastBlocked = READUINT8(save_p);
|
||||
players[i].botmem.catchup_tics = READUINT8(save_p);
|
||||
players[i].botmem.thinkstate = READUINT8(save_p);
|
||||
players[i].removing = READUINT8(save_p);
|
||||
|
||||
players[i].blocked = READUINT8(save_p);
|
||||
players[i].lastbuttons = READUINT16(save_p);
|
||||
|
||||
////////////////////////////
|
||||
// Conveyor Belt Movement //
|
||||
////////////////////////////
|
||||
|
|
126
src/p_setup.c
126
src/p_setup.c
|
@ -1501,6 +1501,22 @@ typedef struct textmap_colormap_s {
|
|||
|
||||
textmap_colormap_t textmap_colormap = { false, 0, 25, 0, 25, 0, 31, 0 };
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PD_A = 1,
|
||||
PD_B = 1<<1,
|
||||
PD_C = 1<<2,
|
||||
PD_D = 1<<3,
|
||||
} planedef_t;
|
||||
|
||||
typedef struct textmap_plane_s {
|
||||
UINT8 defined;
|
||||
fixed_t a, b, c, d;
|
||||
} textmap_plane_t;
|
||||
|
||||
textmap_plane_t textmap_planefloor = {0, 0, 0, 0, 0};
|
||||
textmap_plane_t textmap_planeceiling = {0, 0, 0, 0, 0};
|
||||
|
||||
static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "heightfloor"))
|
||||
|
@ -1539,6 +1555,46 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
|
|||
sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
|
||||
else if (fastcmp(param, "rotationceiling"))
|
||||
sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
|
||||
else if (fastcmp(param, "floorplane_a"))
|
||||
{
|
||||
textmap_planefloor.defined |= PD_A;
|
||||
textmap_planefloor.a = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "floorplane_b"))
|
||||
{
|
||||
textmap_planefloor.defined |= PD_B;
|
||||
textmap_planefloor.b = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "floorplane_c"))
|
||||
{
|
||||
textmap_planefloor.defined |= PD_C;
|
||||
textmap_planefloor.c = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "floorplane_d"))
|
||||
{
|
||||
textmap_planefloor.defined |= PD_D;
|
||||
textmap_planefloor.d = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "ceilingplane_a"))
|
||||
{
|
||||
textmap_planeceiling.defined |= PD_A;
|
||||
textmap_planeceiling.a = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "ceilingplane_b"))
|
||||
{
|
||||
textmap_planeceiling.defined |= PD_B;
|
||||
textmap_planeceiling.b = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "ceilingplane_c"))
|
||||
{
|
||||
textmap_planeceiling.defined |= PD_C;
|
||||
textmap_planeceiling.c = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "ceilingplane_d"))
|
||||
{
|
||||
textmap_planeceiling.defined |= PD_D;
|
||||
textmap_planeceiling.d = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
else if (fastcmp(param, "lightcolor"))
|
||||
{
|
||||
textmap_colormap.used = true;
|
||||
|
@ -1868,6 +1924,10 @@ static void P_LoadTextmap(void)
|
|||
textmap_colormap.fadestart = 0;
|
||||
textmap_colormap.fadeend = 31;
|
||||
textmap_colormap.flags = 0;
|
||||
|
||||
textmap_planefloor.defined = 0;
|
||||
textmap_planeceiling.defined = 0;
|
||||
|
||||
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
|
||||
|
||||
P_InitializeSector(sc);
|
||||
|
@ -1877,6 +1937,19 @@ static void P_LoadTextmap(void)
|
|||
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);
|
||||
}
|
||||
|
||||
if (textmap_planefloor.defined == (PD_A|PD_B|PD_C|PD_D))
|
||||
{
|
||||
sc->f_slope = MakeViaEquationConstants(textmap_planefloor.a, textmap_planefloor.b, textmap_planefloor.c, textmap_planefloor.d);
|
||||
sc->hasslope = true;
|
||||
}
|
||||
|
||||
if (textmap_planeceiling.defined == (PD_A|PD_B|PD_C|PD_D))
|
||||
{
|
||||
sc->c_slope = MakeViaEquationConstants(textmap_planeceiling.a, textmap_planeceiling.b, textmap_planeceiling.c, textmap_planeceiling.d);
|
||||
sc->hasslope = true;
|
||||
}
|
||||
|
||||
TextmapFixFlatOffsets(sc);
|
||||
}
|
||||
|
||||
|
@ -3909,6 +3982,12 @@ static void P_ConvertBinaryMap(void)
|
|||
if (lines[i].flags & ML_NONET)
|
||||
lines[i].args[2] |= TMSL_DYNAMIC;
|
||||
|
||||
if (lines[i].flags & ML_TFERLINE)
|
||||
{
|
||||
lines[i].args[4] |= backfloor ? TMSC_BACKTOFRONTFLOOR : (frontfloor ? TMSC_FRONTTOBACKFLOOR : 0);
|
||||
lines[i].args[4] |= backceil ? TMSC_BACKTOFRONTCEILING : (frontceil ? TMSC_FRONTTOBACKCEILING : 0);
|
||||
}
|
||||
|
||||
lines[i].special = 700;
|
||||
break;
|
||||
}
|
||||
|
@ -5027,6 +5106,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
P_MapStart(); // tmthing can be used starting from this point
|
||||
|
||||
P_InitSlopes();
|
||||
|
||||
if (!P_LoadMapFromFile())
|
||||
return false;
|
||||
|
||||
|
@ -5238,10 +5319,9 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l
|
|||
// Add a wadfile to the active wad files,
|
||||
// replace sounds, musics, patches, textures, sprites and maps
|
||||
//
|
||||
boolean P_AddWadFile(const char *wadfilename)
|
||||
static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
|
||||
{
|
||||
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
||||
UINT16 numlumps, wadnum;
|
||||
char *name;
|
||||
lumpinfo_t *lumpinfo;
|
||||
|
||||
|
@ -5262,18 +5342,10 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
// UINT16 flaPos, flaNum = 0;
|
||||
// UINT16 mapPos, mapNum = 0;
|
||||
|
||||
// Init file.
|
||||
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
switch(wadfiles[wadnum]->type)
|
||||
{
|
||||
case RET_PK3:
|
||||
case RET_FOLDER:
|
||||
// Look for the lumps that act as resource delimitation markers.
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < numlumps; i++, lumpinfo++)
|
||||
|
@ -5437,3 +5509,35 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean P_AddWadFile(const char *wadfilename)
|
||||
{
|
||||
UINT16 numlumps, wadnum;
|
||||
|
||||
// Init file.
|
||||
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
return P_LoadAddon(wadnum, numlumps);
|
||||
}
|
||||
|
||||
boolean P_AddFolder(const char *folderpath)
|
||||
{
|
||||
UINT16 numlumps, wadnum;
|
||||
|
||||
// Init file.
|
||||
if ((numlumps = W_InitFolder(folderpath, false, false)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
return P_LoadAddon(wadnum, numlumps);
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
|
|||
void HWR_LoadLevel(void);
|
||||
#endif
|
||||
boolean P_AddWadFile(const char *wadfilename);
|
||||
boolean P_AddFolder(const char *folderpath);
|
||||
boolean P_RunSOC(const char *socfilename);
|
||||
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
|
|
|
@ -90,6 +90,36 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v
|
|||
}
|
||||
}
|
||||
|
||||
/// Setup slope via constants.
|
||||
static void ReconfigureViaConstants (pslope_t *slope, const fixed_t a, const fixed_t b, const fixed_t c, const fixed_t d)
|
||||
{
|
||||
fixed_t m;
|
||||
vector3_t *normal = &slope->normal;
|
||||
|
||||
// Set origin.
|
||||
FV3_Load(&slope->o, 0, 0, c ? -FixedDiv(d, c) : 0);
|
||||
|
||||
// Get slope's normal.
|
||||
FV3_Load(normal, a, b, c);
|
||||
FV3_Normalize(normal);
|
||||
|
||||
// Invert normal if it's facing down.
|
||||
if (normal->z < 0)
|
||||
FV3_Negate(normal);
|
||||
|
||||
// Get direction vector
|
||||
m = FixedHypot(normal->x, normal->y);
|
||||
slope->d.x = -FixedDiv(normal->x, m);
|
||||
slope->d.y = -FixedDiv(normal->y, m);
|
||||
|
||||
// Z delta
|
||||
slope->zdelta = FixedDiv(m, normal->z);
|
||||
|
||||
// Get angles
|
||||
slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
|
||||
slope->zangle = InvAngle(R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta));
|
||||
}
|
||||
|
||||
/// Recalculate dynamic slopes.
|
||||
void T_DynamicSlopeLine (dynplanethink_t* th)
|
||||
{
|
||||
|
@ -631,13 +661,20 @@ pslope_t *P_SlopeById(UINT16 id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/// Creates a new slope from equation constants.
|
||||
pslope_t *MakeViaEquationConstants(const fixed_t a, const fixed_t b, const fixed_t c, const fixed_t d)
|
||||
{
|
||||
pslope_t* ret = Slope_Add(0);
|
||||
|
||||
ReconfigureViaConstants(ret, a, b, c, d);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Initializes and reads the slopes from the map data.
|
||||
void P_SpawnSlopes(const boolean fromsave) {
|
||||
size_t i;
|
||||
|
||||
slopelist = NULL;
|
||||
slopecount = 0;
|
||||
|
||||
/// Generates vertex slopes.
|
||||
SpawnVertexSlopes();
|
||||
|
||||
|
@ -664,6 +701,9 @@ void P_SpawnSlopes(const boolean fromsave) {
|
|||
for (i = 0; i < numlines; i++)
|
||||
switch (lines[i].special)
|
||||
{
|
||||
case 700:
|
||||
if (lines[i].flags & ML_TFERLINE) P_CopySectorSlope(&lines[i]);
|
||||
break;
|
||||
case 720:
|
||||
P_CopySectorSlope(&lines[i]);
|
||||
default:
|
||||
|
@ -671,6 +711,13 @@ void P_SpawnSlopes(const boolean fromsave) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Initializes slopes.
|
||||
void P_InitSlopes(void)
|
||||
{
|
||||
slopelist = NULL;
|
||||
slopecount = 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
//
|
||||
// Various utilities related to slopes
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef enum
|
|||
void P_LinkSlopeThinkers (void);
|
||||
|
||||
void P_CalculateSlopeNormal(pslope_t *slope);
|
||||
void P_InitSlopes(void);
|
||||
void P_SpawnSlopes(const boolean fromsave);
|
||||
|
||||
//
|
||||
|
@ -86,6 +87,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope);
|
|||
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
|
||||
void P_ButteredSlope(mobj_t *mo);
|
||||
|
||||
pslope_t *MakeViaEquationConstants(const fixed_t a, const fixed_t b, const fixed_t c, const fixed_t d);
|
||||
|
||||
/// Dynamic plane type enum for the thinker. Will have a different functionality depending on this.
|
||||
typedef enum {
|
||||
|
|
110
src/p_spec.c
110
src/p_spec.c
|
@ -1906,6 +1906,22 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean is_rain_type (INT32 weathernum)
|
||||
{
|
||||
switch (weathernum)
|
||||
{
|
||||
case PRECIP_SNOW:
|
||||
case PRECIP_RAIN:
|
||||
case PRECIP_STORM:
|
||||
case PRECIP_STORM_NOSTRIKES:
|
||||
case PRECIP_BLANK:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_SwitchWeather
|
||||
//
|
||||
|
@ -1913,53 +1929,14 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
|
|||
//
|
||||
void P_SwitchWeather(INT32 weathernum)
|
||||
{
|
||||
boolean purge = false;
|
||||
INT32 swap = 0;
|
||||
boolean purge = true;
|
||||
|
||||
switch (weathernum)
|
||||
{
|
||||
case PRECIP_NONE: // None
|
||||
if (curWeather == PRECIP_NONE)
|
||||
return; // Nothing to do.
|
||||
purge = true;
|
||||
break;
|
||||
case PRECIP_STORM: // Storm
|
||||
case PRECIP_STORM_NOSTRIKES: // Storm w/ no lightning
|
||||
case PRECIP_RAIN: // Rain
|
||||
if (curWeather == PRECIP_SNOW || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN)
|
||||
swap = PRECIP_RAIN;
|
||||
break;
|
||||
case PRECIP_SNOW: // Snow
|
||||
if (curWeather == PRECIP_SNOW)
|
||||
return; // Nothing to do.
|
||||
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN)
|
||||
swap = PRECIP_SNOW; // Need to delete the other precips.
|
||||
break;
|
||||
case PRECIP_STORM_NORAIN: // Storm w/o rain
|
||||
if (curWeather == PRECIP_SNOW
|
||||
|| curWeather == PRECIP_STORM
|
||||
|| curWeather == PRECIP_STORM_NOSTRIKES
|
||||
|| curWeather == PRECIP_RAIN
|
||||
|| curWeather == PRECIP_BLANK)
|
||||
swap = PRECIP_STORM_NORAIN;
|
||||
else if (curWeather == PRECIP_STORM_NORAIN)
|
||||
return;
|
||||
break;
|
||||
case PRECIP_BLANK:
|
||||
if (curWeather == PRECIP_SNOW
|
||||
|| curWeather == PRECIP_STORM
|
||||
|| curWeather == PRECIP_STORM_NOSTRIKES
|
||||
|| curWeather == PRECIP_RAIN)
|
||||
swap = PRECIP_BLANK;
|
||||
else if (curWeather == PRECIP_STORM_NORAIN)
|
||||
swap = PRECIP_BLANK;
|
||||
else if (curWeather == PRECIP_BLANK)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
CONS_Debug(DBG_GAMELOGIC, "P_SwitchWeather: Unknown weather type %d.\n", weathernum);
|
||||
break;
|
||||
}
|
||||
if (weathernum == curWeather)
|
||||
return;
|
||||
|
||||
if (is_rain_type(weathernum) &&
|
||||
is_rain_type(curWeather))
|
||||
purge = false;
|
||||
|
||||
if (purge)
|
||||
{
|
||||
|
@ -1976,7 +1953,7 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
P_RemovePrecipMobj(precipmobj);
|
||||
}
|
||||
}
|
||||
else if (swap && !((swap == PRECIP_BLANK && curWeather == PRECIP_STORM_NORAIN) || (swap == PRECIP_STORM_NORAIN && curWeather == PRECIP_BLANK))) // Rather than respawn all that crap, reuse it!
|
||||
else // Rather than respawn all that crap, reuse it!
|
||||
{
|
||||
thinker_t *think;
|
||||
precipmobj_t *precipmobj;
|
||||
|
@ -1988,7 +1965,7 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
continue; // not a precipmobj thinker
|
||||
precipmobj = (precipmobj_t *)think;
|
||||
|
||||
if (swap == PRECIP_RAIN) // Snow To Rain
|
||||
if (weathernum == (PRECIP_RAIN || PRECIP_STORM || PRECIP_STORM_NOSTRIKES)) // Snow To Rain
|
||||
{
|
||||
precipmobj->flags = mobjinfo[MT_RAIN].flags;
|
||||
st = &states[mobjinfo[MT_RAIN].spawnstate];
|
||||
|
@ -2003,7 +1980,7 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
precipmobj->precipflags |= PCF_RAIN;
|
||||
//think->function.acp1 = (actionf_p1)P_RainThinker;
|
||||
}
|
||||
else if (swap == PRECIP_SNOW) // Rain To Snow
|
||||
else if (weathernum == PRECIP_SNOW) // Rain To Snow
|
||||
{
|
||||
INT32 z;
|
||||
|
||||
|
@ -2028,7 +2005,7 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
|
||||
//think->function.acp1 = (actionf_p1)P_SnowThinker;
|
||||
}
|
||||
else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse.
|
||||
else // Remove precip, but keep it around for reuse.
|
||||
{
|
||||
//think->function.acp1 = (actionf_p1)P_NullPrecipThinker;
|
||||
|
||||
|
@ -2042,48 +2019,33 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
case PRECIP_SNOW: // snow
|
||||
curWeather = PRECIP_SNOW;
|
||||
|
||||
if (!swap)
|
||||
if (purge)
|
||||
P_SpawnPrecipitation();
|
||||
|
||||
break;
|
||||
case PRECIP_RAIN: // rain
|
||||
{
|
||||
boolean dontspawn = false;
|
||||
|
||||
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES)
|
||||
dontspawn = true;
|
||||
|
||||
curWeather = PRECIP_RAIN;
|
||||
|
||||
if (!dontspawn && !swap)
|
||||
if (purge)
|
||||
P_SpawnPrecipitation();
|
||||
|
||||
break;
|
||||
}
|
||||
case PRECIP_STORM: // storm
|
||||
{
|
||||
boolean dontspawn = false;
|
||||
|
||||
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES)
|
||||
dontspawn = true;
|
||||
|
||||
curWeather = PRECIP_STORM;
|
||||
|
||||
if (!dontspawn && !swap)
|
||||
if (purge)
|
||||
P_SpawnPrecipitation();
|
||||
|
||||
break;
|
||||
}
|
||||
case PRECIP_STORM_NOSTRIKES: // storm w/o lightning
|
||||
{
|
||||
boolean dontspawn = false;
|
||||
|
||||
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES)
|
||||
dontspawn = true;
|
||||
|
||||
curWeather = PRECIP_STORM_NOSTRIKES;
|
||||
|
||||
if (!dontspawn && !swap)
|
||||
if (purge)
|
||||
P_SpawnPrecipitation();
|
||||
|
||||
break;
|
||||
|
@ -2091,14 +2053,11 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
case PRECIP_STORM_NORAIN: // storm w/o rain
|
||||
curWeather = PRECIP_STORM_NORAIN;
|
||||
|
||||
if (!swap)
|
||||
P_SpawnPrecipitation();
|
||||
|
||||
break;
|
||||
case PRECIP_BLANK:
|
||||
case PRECIP_BLANK: //preloaded
|
||||
curWeather = PRECIP_BLANK;
|
||||
|
||||
if (!swap)
|
||||
if (purge)
|
||||
P_SpawnPrecipitation();
|
||||
|
||||
break;
|
||||
|
@ -7201,7 +7160,8 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
}
|
||||
}
|
||||
|
||||
P_RunLevelLoadExecutors();
|
||||
if (!fromnetsave)
|
||||
P_RunLevelLoadExecutors();
|
||||
}
|
||||
|
||||
/** Adds 3Dfloors as appropriate based on a common control linedef.
|
||||
|
|
76
src/p_user.c
76
src/p_user.c
|
@ -777,7 +777,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
UINT8 oldmare, oldmarelap, oldmarebonuslap;
|
||||
|
||||
// Bots can't be NiGHTSerized, silly!1 :P
|
||||
if (player->bot)
|
||||
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN)
|
||||
return;
|
||||
|
||||
if (player->powers[pw_carry] != CR_NIGHTSMODE)
|
||||
|
@ -969,6 +969,9 @@ pflags_t P_GetJumpFlags(player_t *player)
|
|||
//
|
||||
boolean P_PlayerInPain(player_t *player)
|
||||
{
|
||||
// If the player doesn't have a mobj, it can't be in pain.
|
||||
if (!player->mo)
|
||||
return false;
|
||||
// no silly, sliding isn't pain
|
||||
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
|
||||
return true;
|
||||
|
@ -1189,8 +1192,8 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
|
|||
if (!player)
|
||||
return;
|
||||
|
||||
if (player->bot)
|
||||
player = &players[consoleplayer];
|
||||
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
|
||||
player = player->botleader;
|
||||
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
@ -1234,8 +1237,8 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
|
|||
if (!player)
|
||||
return;
|
||||
|
||||
if (player->bot)
|
||||
player = &players[consoleplayer];
|
||||
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
|
||||
player = player->botleader;
|
||||
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
@ -1261,8 +1264,8 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
|
|||
if (!player)
|
||||
return;
|
||||
|
||||
if (player->bot)
|
||||
player = &players[consoleplayer];
|
||||
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
|
||||
player = player->botleader;
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
|
@ -1367,8 +1370,8 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
|
|||
{
|
||||
UINT32 oldscore;
|
||||
|
||||
if (player->bot)
|
||||
player = &players[consoleplayer];
|
||||
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
|
||||
player = player->botleader;
|
||||
|
||||
// NiGHTS does it different!
|
||||
if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->typeoflevel & TOL_NIGHTS)
|
||||
|
@ -5369,9 +5372,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
|
|||
// disabled because it seemed to disorient people and Z-targeting exists now
|
||||
/*if (!demoplayback)
|
||||
{
|
||||
if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(gc_turnleft) || PLAYER1INPUTDOWN(gc_turnright)))
|
||||
if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(GC_TURNLEFT) || PLAYER1INPUTDOWN(GC_TURNRIGHT)))
|
||||
P_SetPlayerAngle(player, player->mo->angle);;
|
||||
else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(gc_turnleft) || PLAYER2INPUTDOWN(gc_turnright)))
|
||||
else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(GC_TURNLEFT) || PLAYER2INPUTDOWN(GC_TURNRIGHT)))
|
||||
P_SetPlayerAngle(player, player->mo->angle);
|
||||
}*/
|
||||
}
|
||||
|
@ -5390,7 +5393,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
|
|||
player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer
|
||||
|
||||
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH);
|
||||
if (player->bot == 1)
|
||||
if (player->bot == BOT_2PAI)
|
||||
player->pflags |= PF_THOKKED;
|
||||
else
|
||||
player->pflags |= (PF_THOKKED|PF_CANCARRY);
|
||||
|
@ -5636,16 +5639,10 @@ INT32 P_GetPlayerControlDirection(player_t *player)
|
|||
{
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
angle_t controllerdirection, controlplayerdirection;
|
||||
camera_t *thiscam;
|
||||
angle_t dangle;
|
||||
fixed_t tempx = 0, tempy = 0;
|
||||
angle_t tempangle, origtempangle;
|
||||
|
||||
if (splitscreen && player == &players[secondarydisplayplayer])
|
||||
thiscam = &camera2;
|
||||
else
|
||||
thiscam = &camera;
|
||||
|
||||
if (!cmd->forwardmove && !cmd->sidemove)
|
||||
return 0;
|
||||
|
||||
|
@ -5661,17 +5658,15 @@ INT32 P_GetPlayerControlDirection(player_t *player)
|
|||
origtempangle = tempangle = 0; // relative to the axis rather than the player!
|
||||
controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
}
|
||||
else if ((P_ControlStyle(player) & CS_LMAOGALOG) && thiscam->chase)
|
||||
else
|
||||
{
|
||||
if (player->awayviewtics)
|
||||
origtempangle = tempangle = player->awayviewmobj->angle;
|
||||
else if (P_ControlStyle(player) & CS_LMAOGALOG)
|
||||
origtempangle = tempangle = (cmd->angleturn << 16);
|
||||
else
|
||||
origtempangle = tempangle = thiscam->angle;
|
||||
controlplayerdirection = player->mo->angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
origtempangle = tempangle = player->mo->angle;
|
||||
origtempangle = tempangle = player->mo->angle;
|
||||
|
||||
controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
}
|
||||
|
||||
|
@ -5977,22 +5972,6 @@ static void P_3dMovement(player_t *player)
|
|||
acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40;
|
||||
topspeed = normalspd;
|
||||
}
|
||||
else if (player->bot)
|
||||
{ // Bot steals player 1's stats
|
||||
normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale);
|
||||
thrustfactor = players[consoleplayer].thrustfactor;
|
||||
acceleration = players[consoleplayer].accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * players[consoleplayer].acceleration;
|
||||
|
||||
if (player->powers[pw_tailsfly])
|
||||
topspeed = normalspd/2;
|
||||
else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER))
|
||||
{
|
||||
topspeed = normalspd/2;
|
||||
acceleration = 2*acceleration/3;
|
||||
}
|
||||
else
|
||||
topspeed = normalspd;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->powers[pw_super] || player->powers[pw_sneakers])
|
||||
|
@ -9522,11 +9501,11 @@ static void P_DeathThink(player_t *player)
|
|||
if (player->deadtimer < INT32_MAX)
|
||||
player->deadtimer++;
|
||||
|
||||
if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already
|
||||
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) // don't allow followbots to do any of the below, B_CheckRespawn does all they need for respawning already
|
||||
goto notrealplayer;
|
||||
|
||||
// continue logic
|
||||
if (!(netgame || multiplayer) && player->lives <= 0)
|
||||
if (!(netgame || multiplayer) && player->lives <= 0 && player == &players[consoleplayer]) //Extra players in SP can't be allowed to continue or end game
|
||||
{
|
||||
if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_SPIN || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0))
|
||||
G_UseContinue();
|
||||
|
@ -11499,6 +11478,9 @@ void P_PlayerThink(player_t *player)
|
|||
I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri));
|
||||
#endif
|
||||
|
||||
// Reset terrain blocked status for this frame
|
||||
player->blocked = false;
|
||||
|
||||
// todo: Figure out what is actually causing these problems in the first place...
|
||||
if (player->mo->health <= 0 && player->playerstate == PST_LIVE) //you should be DEAD!
|
||||
{
|
||||
|
@ -11506,7 +11488,7 @@ void P_PlayerThink(player_t *player)
|
|||
player->playerstate = PST_DEAD;
|
||||
}
|
||||
|
||||
if (player->bot)
|
||||
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN)
|
||||
{
|
||||
if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD)
|
||||
{
|
||||
|
@ -11650,7 +11632,7 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN)
|
||||
continue;
|
||||
if (players[i].lives <= 0)
|
||||
continue;
|
||||
|
@ -11682,7 +11664,7 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN)
|
||||
continue;
|
||||
if (players[i].quittime > 30 * TICRATE)
|
||||
continue;
|
||||
|
@ -12623,7 +12605,7 @@ void P_PlayerAfterThink(player_t *player)
|
|||
player->mo->momz = tails->momz;
|
||||
}
|
||||
|
||||
if (G_CoopGametype() && tails->player && tails->player->bot != 1)
|
||||
if (G_CoopGametype() && tails->player && tails->player->bot != BOT_2PAI)
|
||||
{
|
||||
player->mo->angle = tails->angle;
|
||||
|
||||
|
|
|
@ -901,9 +901,8 @@ static png_bytep *PNG_Read(
|
|||
png_colorp palette;
|
||||
int palette_size;
|
||||
|
||||
png_bytep trans;
|
||||
int trans_num;
|
||||
png_color_16p trans_values;
|
||||
png_bytep trans = NULL;
|
||||
int num_trans = 0;
|
||||
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
|
@ -998,12 +997,12 @@ static png_bytep *PNG_Read(
|
|||
// color is present on the image, the palette flag is disabled.
|
||||
if (usepal)
|
||||
{
|
||||
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values);
|
||||
png_uint_32 result = png_get_tRNS(png_ptr, png_info_ptr, &trans, &num_trans, NULL);
|
||||
|
||||
if (trans && trans_num > 0)
|
||||
if ((result & PNG_INFO_tRNS) && num_trans > 0 && trans != NULL)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < trans_num; i++)
|
||||
for (i = 0; i < num_trans; i++)
|
||||
{
|
||||
// libpng will transform this image into RGBA even if
|
||||
// the transparent index does not exist in the image,
|
||||
|
|
|
@ -116,9 +116,9 @@ void *Picture_PNGConvert(
|
|||
size_t insize, size_t *outsize,
|
||||
pictureflags_t flags);
|
||||
boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size);
|
||||
#endif
|
||||
|
||||
#define PICTURE_PNG_USELOOKUP
|
||||
#endif
|
||||
|
||||
// SpriteInfo
|
||||
extern spriteinfo_t spriteinfo[NUMSPRITES];
|
||||
|
|
132
src/r_plane.c
132
src/r_plane.c
|
@ -89,8 +89,6 @@ static fixed_t planeheight;
|
|||
fixed_t yslopetab[MAXVIDHEIGHT*16];
|
||||
fixed_t *yslope;
|
||||
|
||||
fixed_t basexscale, baseyscale;
|
||||
|
||||
fixed_t cachedheight[MAXVIDHEIGHT];
|
||||
fixed_t cacheddistance[MAXVIDHEIGHT];
|
||||
fixed_t cachedxstep[MAXVIDHEIGHT];
|
||||
|
@ -114,7 +112,7 @@ void R_InitPlanes(void)
|
|||
// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
|
||||
//
|
||||
|
||||
struct
|
||||
static struct
|
||||
{
|
||||
INT32 offset;
|
||||
fixed_t xfrac, yfrac;
|
||||
|
@ -143,15 +141,6 @@ static void R_UpdatePlaneRipple(void)
|
|||
planeripple.offset = (leveltime * 140);
|
||||
}
|
||||
|
||||
//
|
||||
// R_MapPlane
|
||||
//
|
||||
// Uses global vars:
|
||||
// planeheight
|
||||
// basexscale
|
||||
// baseyscale
|
||||
// centerx
|
||||
|
||||
static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
||||
{
|
||||
angle_t angle, planecos, planesin;
|
||||
|
@ -176,16 +165,13 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]);
|
||||
span = abs(centery - y);
|
||||
|
||||
if (span) // don't divide by zero
|
||||
if (span) // Don't divide by zero
|
||||
{
|
||||
ds_xstep = FixedMul(planesin, planeheight) / span;
|
||||
ds_ystep = FixedMul(planecos, planeheight) / span;
|
||||
}
|
||||
else
|
||||
{
|
||||
ds_xstep = FixedMul(distance, basexscale);
|
||||
ds_ystep = FixedMul(distance, baseyscale);
|
||||
}
|
||||
ds_xstep = ds_ystep = FRACUNIT;
|
||||
|
||||
cachedxstep[y] = ds_xstep;
|
||||
cachedystep[y] = ds_ystep;
|
||||
|
@ -197,6 +183,11 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
ds_ystep = cachedystep[y];
|
||||
}
|
||||
|
||||
// [RH] Instead of using the xtoviewangle array, I calculated the fractional values
|
||||
// at the middle of the screen, then used the calculated ds_xstep and ds_ystep
|
||||
// to step from those to the proper texture coordinate to start drawing at.
|
||||
// That way, the texture coordinate is always calculated by its position
|
||||
// on the screen and not by its position relative to the edge of the visplane.
|
||||
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep;
|
||||
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep;
|
||||
|
||||
|
@ -295,7 +286,6 @@ void R_ClearFFloorClips (void)
|
|||
void R_ClearPlanes(void)
|
||||
{
|
||||
INT32 i, p;
|
||||
angle_t angle;
|
||||
|
||||
// opening / clipping determination
|
||||
for (i = 0; i < viewwidth; i++)
|
||||
|
@ -321,13 +311,6 @@ void R_ClearPlanes(void)
|
|||
|
||||
// texture calculation
|
||||
memset(cachedheight, 0, sizeof (cachedheight));
|
||||
|
||||
// left to right mapping
|
||||
angle = (viewangle-ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
|
||||
// scale will be unit scale at SCREENWIDTH/2 distance
|
||||
basexscale = FixedDiv (FINECOSINE(angle),centerxfrac);
|
||||
baseyscale = -FixedDiv (FINESINE(angle),centerxfrac);
|
||||
}
|
||||
|
||||
static visplane_t *new_visplane(unsigned hash)
|
||||
|
@ -380,9 +363,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
|
|||
{
|
||||
if (polyobj->angle != 0)
|
||||
{
|
||||
angle_t fineshift = polyobj->angle >> ANGLETOFINESHIFT;
|
||||
xoff -= FixedMul(FINECOSINE(fineshift), polyobj->centerPt.x)+FixedMul(FINESINE(fineshift), polyobj->centerPt.y);
|
||||
yoff -= FixedMul(FINESINE(fineshift), polyobj->centerPt.x)-FixedMul(FINECOSINE(fineshift), polyobj->centerPt.y);
|
||||
float ang = ANG2RAD(polyobj->angle);
|
||||
float x = FixedToFloat(polyobj->centerPt.x);
|
||||
float y = FixedToFloat(polyobj->centerPt.y);
|
||||
xoff -= FloatToFixed(x * cos(ang) + y * sin(ang));
|
||||
yoff -= FloatToFixed(x * sin(ang) - y * cos(ang));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -530,53 +515,22 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
|
|||
//
|
||||
// R_ExpandPlane
|
||||
//
|
||||
// This function basically expands the visplane or I_Errors.
|
||||
// This function basically expands the visplane.
|
||||
// The reason for this is that when creating 3D floor planes, there is no
|
||||
// need to create new ones with R_CheckPlane, because 3D floor planes
|
||||
// are created by subsector and there is no way a subsector can graphically
|
||||
// overlap.
|
||||
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop)
|
||||
{
|
||||
// INT32 unionl, unionh;
|
||||
// INT32 x;
|
||||
|
||||
// Don't expand polyobject planes here - we do that on our own.
|
||||
if (pl->polyobj)
|
||||
return;
|
||||
|
||||
if (pl->minx > start) pl->minx = start;
|
||||
if (pl->maxx < stop) pl->maxx = stop;
|
||||
/*
|
||||
if (start < pl->minx)
|
||||
{
|
||||
unionl = start;
|
||||
}
|
||||
else
|
||||
{
|
||||
unionl = pl->minx;
|
||||
}
|
||||
|
||||
if (stop > pl->maxx)
|
||||
{
|
||||
unionh = stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
unionh = pl->maxx;
|
||||
}
|
||||
for (x = start; x <= stop; x++)
|
||||
if (pl->top[x] != 0xffff || pl->bottom[x] != 0x0000)
|
||||
break;
|
||||
|
||||
if (x <= stop)
|
||||
I_Error("R_ExpandPlane: planes in same subsector overlap?!\nminx: %d, maxx: %d, start: %d, stop: %d\n", pl->minx, pl->maxx, start, stop);
|
||||
|
||||
pl->minx = unionl, pl->maxx = unionh;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
|
||||
static void R_MakeSpans(void (*mapfunc)(INT32, INT32, INT32), INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
|
||||
{
|
||||
// Alam: from r_splats's R_RasterizeFloorSplat
|
||||
if (t1 >= vid.height) t1 = vid.height-1;
|
||||
|
@ -587,38 +541,12 @@ static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
|
|||
|
||||
while (t1 < t2 && t1 <= b1)
|
||||
{
|
||||
R_MapPlane(t1, spanstart[t1], x - 1);
|
||||
mapfunc(t1, spanstart[t1], x - 1);
|
||||
t1++;
|
||||
}
|
||||
while (b1 > b2 && b1 >= t1)
|
||||
{
|
||||
R_MapPlane(b1, spanstart[b1], x - 1);
|
||||
b1--;
|
||||
}
|
||||
|
||||
while (t2 < t1 && t2 <= b2)
|
||||
spanstart[t2++] = x;
|
||||
while (b2 > b1 && b2 >= t2)
|
||||
spanstart[b2--] = x;
|
||||
}
|
||||
|
||||
static void R_MakeTiltedSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
|
||||
{
|
||||
// Alam: from r_splats's R_RasterizeFloorSplat
|
||||
if (t1 >= vid.height) t1 = vid.height-1;
|
||||
if (b1 >= vid.height) b1 = vid.height-1;
|
||||
if (t2 >= vid.height) t2 = vid.height-1;
|
||||
if (b2 >= vid.height) b2 = vid.height-1;
|
||||
if (x-1 >= vid.width) x = vid.width;
|
||||
|
||||
while (t1 < t2 && t1 <= b1)
|
||||
{
|
||||
R_MapTiltedPlane(t1, spanstart[t1], x - 1);
|
||||
t1++;
|
||||
}
|
||||
while (b1 > b2 && b1 >= t1)
|
||||
{
|
||||
R_MapTiltedPlane(b1, spanstart[b1], x - 1);
|
||||
mapfunc(b1, spanstart[b1], x - 1);
|
||||
b1--;
|
||||
}
|
||||
|
||||
|
@ -865,11 +793,10 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
{
|
||||
levelflat_t *levelflat;
|
||||
INT32 light = 0;
|
||||
INT32 x;
|
||||
INT32 stop, angle;
|
||||
INT32 x, stop;
|
||||
ffloor_t *rover;
|
||||
INT32 type;
|
||||
INT32 spanfunctype = BASEDRAWFUNC;
|
||||
INT32 type, spanfunctype = BASEDRAWFUNC;
|
||||
void (*mapfunc)(INT32, INT32, INT32) = R_MapPlane;
|
||||
|
||||
if (!(pl->minx <= pl->maxx))
|
||||
return;
|
||||
|
@ -1021,9 +948,6 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
&& viewangle != pl->viewangle+pl->plangle)
|
||||
{
|
||||
memset(cachedheight, 0, sizeof (cachedheight));
|
||||
angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
|
||||
baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
|
||||
viewangle = pl->viewangle+pl->plangle;
|
||||
}
|
||||
|
||||
|
@ -1038,6 +962,8 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
|
||||
if (pl->slope)
|
||||
{
|
||||
mapfunc = R_MapTiltedPlane;
|
||||
|
||||
if (!pl->plangle)
|
||||
{
|
||||
if (ds_powersoftwo)
|
||||
|
@ -1105,16 +1031,8 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
|
||||
stop = pl->maxx + 1;
|
||||
|
||||
if (pl->slope)
|
||||
{
|
||||
for (x = pl->minx; x <= stop; x++)
|
||||
R_MakeTiltedSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = pl->minx; x <= stop; x++)
|
||||
R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]);
|
||||
}
|
||||
for (x = pl->minx; x <= stop; x++)
|
||||
R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]);
|
||||
|
||||
/*
|
||||
QUINCUNX anti-aliasing technique (sort of)
|
||||
|
@ -1181,7 +1099,7 @@ using the palette colors.
|
|||
stop = pl->maxx + 1;
|
||||
|
||||
for (x = pl->minx; x <= stop; x++)
|
||||
R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1],
|
||||
R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1],
|
||||
pl->top[x], pl->bottom[x]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ extern fixed_t cachedheight[MAXVIDHEIGHT];
|
|||
extern fixed_t cacheddistance[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedxstep[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedystep[MAXVIDHEIGHT];
|
||||
extern fixed_t basexscale, baseyscale;
|
||||
|
||||
extern fixed_t *yslope;
|
||||
extern lighttable_t **planezlight;
|
||||
|
|
|
@ -242,6 +242,11 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
|
|||
// Force 3.
|
||||
return true;
|
||||
}
|
||||
if (playernum != -1 && players[playernum].bot)
|
||||
{
|
||||
//Force 4.
|
||||
return true;
|
||||
}
|
||||
|
||||
// We will now check if this skin is supposed to be locked or not.
|
||||
|
||||
|
|
|
@ -155,7 +155,6 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
fixed_t xscale, yscale;
|
||||
fixed_t xoffset, yoffset;
|
||||
fixed_t leftoffset, topoffset;
|
||||
pslope_t *slope = NULL;
|
||||
INT32 i;
|
||||
|
||||
boolean hflip = (spr->xiscale < 0);
|
||||
|
@ -188,7 +187,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD)
|
||||
splatangle = mobj->angle;
|
||||
else
|
||||
splatangle = spr->viewangle;
|
||||
splatangle = spr->viewpoint.angle;
|
||||
|
||||
if (!(spr->cut & SC_ISROTATED))
|
||||
splatangle += mobj->rollangle;
|
||||
|
@ -218,7 +217,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
splat.x = x;
|
||||
splat.y = y;
|
||||
splat.z = mobj->z;
|
||||
splat.tilted = false;
|
||||
splat.slope = NULL;
|
||||
|
||||
// Set positions
|
||||
|
||||
|
@ -238,9 +237,9 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
splat.verts[3].x = w - xoffset;
|
||||
splat.verts[3].y = -h + yoffset;
|
||||
|
||||
angle = -splat.angle;
|
||||
ca = FINECOSINE(angle>>ANGLETOFINESHIFT);
|
||||
sa = FINESINE(angle>>ANGLETOFINESHIFT);
|
||||
angle = -splat.angle>>ANGLETOFINESHIFT;
|
||||
ca = FINECOSINE(angle);
|
||||
sa = FINESINE(angle);
|
||||
|
||||
// Rotate
|
||||
for (i = 0; i < 4; i++)
|
||||
|
@ -255,36 +254,10 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
|
||||
// The slope that was defined for the sprite.
|
||||
if (renderflags & RF_SLOPESPLAT)
|
||||
slope = mobj->floorspriteslope;
|
||||
splat.slope = mobj->floorspriteslope;
|
||||
|
||||
if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT))
|
||||
slope = standingslope;
|
||||
|
||||
// Set splat as tilted
|
||||
splat.tilted = (slope != NULL);
|
||||
}
|
||||
|
||||
if (splat.tilted)
|
||||
{
|
||||
pslope_t *s = &splat.slope;
|
||||
|
||||
s->o.x = slope->o.x;
|
||||
s->o.y = slope->o.y;
|
||||
s->o.z = slope->o.z;
|
||||
|
||||
s->d.x = slope->d.x;
|
||||
s->d.y = slope->d.y;
|
||||
|
||||
s->normal.x = slope->normal.x;
|
||||
s->normal.y = slope->normal.y;
|
||||
s->normal.z = slope->normal.z;
|
||||
|
||||
s->zdelta = slope->zdelta;
|
||||
s->zangle = slope->zangle;
|
||||
s->xydirection = slope->xydirection;
|
||||
|
||||
s->next = NULL;
|
||||
s->flags = 0;
|
||||
splat.slope = standingslope;
|
||||
}
|
||||
|
||||
// Translate
|
||||
|
@ -293,9 +266,9 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
tr_x = rotated[i].x + x;
|
||||
tr_y = rotated[i].y + y;
|
||||
|
||||
if (slope)
|
||||
if (splat.slope)
|
||||
{
|
||||
rot_z = P_GetSlopeZAt(slope, tr_x, tr_y);
|
||||
rot_z = P_GetSlopeZAt(splat.slope, tr_x, tr_y);
|
||||
splat.verts[i].z = rot_z;
|
||||
}
|
||||
else
|
||||
|
@ -305,18 +278,23 @@ void R_DrawFloorSplat(vissprite_t *spr)
|
|||
splat.verts[i].y = tr_y;
|
||||
}
|
||||
|
||||
angle = spr->viewpoint.angle >> ANGLETOFINESHIFT;
|
||||
ca = FINECOSINE(angle);
|
||||
sa = FINESINE(angle);
|
||||
|
||||
// Project
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
v3d = &splat.verts[i];
|
||||
|
||||
// transform the origin point
|
||||
tr_x = v3d->x - viewx;
|
||||
tr_y = v3d->y - viewy;
|
||||
tr_x = v3d->x - spr->viewpoint.x;
|
||||
tr_y = v3d->y - spr->viewpoint.y;
|
||||
|
||||
// rotation around vertical y axis
|
||||
rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
|
||||
rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
|
||||
rot_z = v3d->z - viewz;
|
||||
rot_x = FixedMul(tr_x, sa) - FixedMul(tr_y, ca);
|
||||
rot_y = FixedMul(tr_x, ca) + FixedMul(tr_y, sa);
|
||||
rot_z = v3d->z - spr->viewpoint.z;
|
||||
|
||||
if (rot_y < FRACUNIT)
|
||||
return;
|
||||
|
@ -416,31 +394,32 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
if (R_CheckPowersOfTwo())
|
||||
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
|
||||
|
||||
if (pSplat->tilted)
|
||||
if (pSplat->slope)
|
||||
{
|
||||
R_SetTiltedSpan(0);
|
||||
R_SetScaledSlopePlane(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle);
|
||||
R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle);
|
||||
R_CalculateSlopeVectors();
|
||||
spanfunctype = SPANDRAWFUNC_TILTEDSPRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
planeheight = abs(pSplat->z - viewz);
|
||||
planeheight = abs(pSplat->z - vis->viewpoint.z);
|
||||
|
||||
if (pSplat->angle)
|
||||
{
|
||||
// Add the view offset, rotated by the plane angle.
|
||||
fixed_t a = -pSplat->verts[0].x + viewx;
|
||||
fixed_t b = -pSplat->verts[0].y + viewy;
|
||||
angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT);
|
||||
offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle));
|
||||
offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle));
|
||||
memset(cachedheight, 0, sizeof(cachedheight));
|
||||
|
||||
// Add the view offset, rotated by the plane angle.
|
||||
fixed_t a = -pSplat->verts[0].x + vis->viewpoint.x;
|
||||
fixed_t b = -pSplat->verts[0].y + vis->viewpoint.y;
|
||||
angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT);
|
||||
offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b, FINESINE(angle));
|
||||
offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b, FINECOSINE(angle));
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetx = viewx - pSplat->verts[0].x;
|
||||
offsety = pSplat->verts[0].y - viewy;
|
||||
offsetx = vis->viewpoint.x - pSplat->verts[0].x;
|
||||
offsety = pSplat->verts[0].y - vis->viewpoint.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,7 +440,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
{
|
||||
ds_transmap = vis->transmap;
|
||||
|
||||
if (pSplat->tilted)
|
||||
if (pSplat->slope)
|
||||
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE;
|
||||
else
|
||||
spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
|
||||
|
@ -528,12 +507,12 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
if (x2 < x1)
|
||||
continue;
|
||||
|
||||
if (!pSplat->tilted)
|
||||
if (!pSplat->slope)
|
||||
{
|
||||
fixed_t xstep, ystep;
|
||||
fixed_t distance, span;
|
||||
|
||||
angle_t angle = (vis->viewangle + pSplat->angle)>>ANGLETOFINESHIFT;
|
||||
angle_t angle = (vis->viewpoint.angle + pSplat->angle)>>ANGLETOFINESHIFT;
|
||||
angle_t planecos = FINECOSINE(angle);
|
||||
angle_t planesin = FINESINE(angle);
|
||||
|
||||
|
@ -577,7 +556,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
rastertab[y].maxx = INT32_MIN;
|
||||
}
|
||||
|
||||
if (pSplat->angle && !pSplat->tilted)
|
||||
if (pSplat->angle && !pSplat->slope)
|
||||
memset(cachedheight, 0, sizeof(cachedheight));
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ typedef struct floorsplat_s
|
|||
INT32 width, height;
|
||||
fixed_t scale, xscale, yscale;
|
||||
angle_t angle;
|
||||
boolean tilted; // Uses the tilted drawer
|
||||
pslope_t slope;
|
||||
pslope_t *slope;
|
||||
|
||||
vector3_t verts[4]; // (x,y,z) as viewed from above on map
|
||||
fixed_t x, y, z; // position
|
||||
|
|
|
@ -727,7 +727,7 @@ Rloadflats (INT32 i, INT32 w)
|
|||
texpatch_t *patch;
|
||||
|
||||
// Yes
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
|
||||
|
@ -749,7 +749,7 @@ Rloadflats (INT32 i, INT32 w)
|
|||
size_t lumplength;
|
||||
size_t flatsize = 0;
|
||||
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
|
||||
continue; // If it is then SKIP IT
|
||||
|
@ -839,7 +839,7 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
texpatch_t *patch;
|
||||
|
||||
// Get the lump numbers for the markers in the WAD, if they exist.
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||
|
@ -870,7 +870,7 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
size_t lumplength;
|
||||
#endif
|
||||
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
|
||||
continue; // If it is then SKIP IT
|
||||
|
@ -959,7 +959,7 @@ void R_LoadTextures(void)
|
|||
{
|
||||
#ifdef WALLFLATS
|
||||
// Count flats
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
|
||||
|
@ -973,7 +973,7 @@ void R_LoadTextures(void)
|
|||
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
|
||||
{
|
||||
// PK3s have subfolders, so we can't just make a simple sum
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
for (j = texstart; j < texend; j++)
|
||||
{
|
||||
|
@ -997,7 +997,7 @@ void R_LoadTextures(void)
|
|||
}
|
||||
|
||||
// Count single-patch textures
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||
|
@ -1012,7 +1012,7 @@ void R_LoadTextures(void)
|
|||
continue;
|
||||
|
||||
// PK3s have subfolders, so we can't just make a simple sum
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
for (j = texstart; j < texend; j++)
|
||||
{
|
||||
|
@ -1553,6 +1553,7 @@ lumpnum_t R_GetFlatNumForName(const char *name)
|
|||
continue;
|
||||
break;
|
||||
case RET_PK3:
|
||||
case RET_FOLDER:
|
||||
if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX)
|
||||
continue;
|
||||
if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX)
|
||||
|
|
|
@ -443,6 +443,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
|
|||
end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib.
|
||||
break;
|
||||
case RET_PK3:
|
||||
case RET_FOLDER:
|
||||
start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0);
|
||||
end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start);
|
||||
break;
|
||||
|
@ -1956,9 +1957,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->paperoffset = paperoffset;
|
||||
vis->paperdistance = paperdistance;
|
||||
vis->centerangle = centerangle;
|
||||
vis->viewangle = viewangle;
|
||||
vis->shear.tan = sheartan;
|
||||
vis->shear.offset = 0;
|
||||
vis->viewpoint.x = viewx;
|
||||
vis->viewpoint.y = viewy;
|
||||
vis->viewpoint.z = viewz;
|
||||
vis->viewpoint.angle = viewangle;
|
||||
|
||||
vis->mobj = thing; // Easy access! Tails 06-07-2002
|
||||
|
||||
|
|
|
@ -164,7 +164,12 @@ typedef struct vissprite_s
|
|||
fixed_t xiscale; // negative if flipped
|
||||
|
||||
angle_t centerangle; // for paper sprites
|
||||
angle_t viewangle; // for floor sprites, the viewpoint's current angle
|
||||
|
||||
// for floor sprites
|
||||
struct {
|
||||
fixed_t x, y, z; // the viewpoint's current position
|
||||
angle_t angle; // the viewpoint's current angle
|
||||
} viewpoint;
|
||||
|
||||
struct {
|
||||
fixed_t tan; // The amount to shear the sprite vertically per row
|
||||
|
@ -185,9 +190,10 @@ typedef struct vissprite_s
|
|||
|
||||
extracolormap_t *extra_colormap; // global colormaps
|
||||
|
||||
// Precalculated top and bottom screen coords for the sprite.
|
||||
fixed_t thingheight; // The actual height of the thing (for 3D floors)
|
||||
sector_t *sector; // The sector containing the thing.
|
||||
|
||||
// Precalculated top and bottom screen coords for the sprite.
|
||||
INT16 sz, szt;
|
||||
|
||||
spritecut_e cut;
|
||||
|
|
|
@ -550,7 +550,7 @@ static void I_StartupConsole(void)
|
|||
void I_GetConsoleEvents(void)
|
||||
{
|
||||
// we use this when sending back commands
|
||||
event_t ev = {0,0,0,0};
|
||||
event_t ev = {0};
|
||||
char key = 0;
|
||||
ssize_t d;
|
||||
|
||||
|
@ -572,7 +572,7 @@ void I_GetConsoleEvents(void)
|
|||
tty_con.buffer[tty_con.cursor] = '\0';
|
||||
tty_Back();
|
||||
}
|
||||
ev.data1 = KEY_BACKSPACE;
|
||||
ev.key = KEY_BACKSPACE;
|
||||
}
|
||||
else if (key < ' ') // check if this is a control char
|
||||
{
|
||||
|
@ -580,19 +580,19 @@ void I_GetConsoleEvents(void)
|
|||
{
|
||||
tty_Clear();
|
||||
tty_con.cursor = 0;
|
||||
ev.data1 = KEY_ENTER;
|
||||
ev.key = KEY_ENTER;
|
||||
}
|
||||
else return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// push regular character
|
||||
ev.data1 = tty_con.buffer[tty_con.cursor] = key;
|
||||
ev.key = tty_con.buffer[tty_con.cursor] = key;
|
||||
tty_con.cursor++;
|
||||
// print the current line (this is differential)
|
||||
d = write(STDOUT_FILENO, &key, 1);
|
||||
}
|
||||
if (ev.data1) D_PostEvent(&ev);
|
||||
if (ev.key) D_PostEvent(&ev);
|
||||
//tty_FlushIn();
|
||||
(void)d;
|
||||
}
|
||||
|
@ -626,18 +626,18 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
|
|||
{
|
||||
case VK_ESCAPE:
|
||||
case VK_TAB:
|
||||
event.data1 = KEY_NULL;
|
||||
event.key = KEY_NULL;
|
||||
break;
|
||||
case VK_RETURN:
|
||||
entering_con_command = false;
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
//event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
|
||||
event.data1 = evt.uChar.AsciiChar;
|
||||
//event.key = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
|
||||
event.key = evt.uChar.AsciiChar;
|
||||
}
|
||||
if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
|
||||
{
|
||||
if (event.data1 && event.data1 != KEY_LSHIFT && event.data1 != KEY_RSHIFT)
|
||||
if (event.key && event.key != KEY_LSHIFT && event.key != KEY_RSHIFT)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
WriteConsole(co, &evt.uChar.UnicodeChar, 1, &t, NULL);
|
||||
|
@ -652,7 +652,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (event.data1) D_PostEvent(&event);
|
||||
if (event.key) D_PostEvent(&event);
|
||||
}
|
||||
|
||||
void I_GetConsoleEvents(void)
|
||||
|
@ -917,7 +917,7 @@ INT32 I_GetKey (void)
|
|||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown || ev->type == ev_console)
|
||||
{
|
||||
rc = ev->data1;
|
||||
rc = ev->key;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -977,22 +977,22 @@ void I_ShutdownJoystick(void)
|
|||
INT32 i;
|
||||
event_t event;
|
||||
event.type=ev_keyup;
|
||||
event.data2 = 0;
|
||||
event.data3 = 0;
|
||||
event.x = 0;
|
||||
event.y = 0;
|
||||
|
||||
lastjoybuttons = lastjoyhats = 0;
|
||||
|
||||
// emulate the up of all joystick buttons
|
||||
for (i=0;i<JOYBUTTONS;i++)
|
||||
{
|
||||
event.data1=KEY_JOY1+i;
|
||||
event.key=KEY_JOY1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
// emulate the up of all joystick hats
|
||||
for (i=0;i<JOYHATS*4;i++)
|
||||
{
|
||||
event.data1=KEY_HAT1+i;
|
||||
event.key=KEY_HAT1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1000,7 @@ void I_ShutdownJoystick(void)
|
|||
event.type = ev_joystick;
|
||||
for (i=0;i<JOYAXISSET; i++)
|
||||
{
|
||||
event.data1 = i;
|
||||
event.key = i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -1012,7 +1012,7 @@ void I_ShutdownJoystick(void)
|
|||
|
||||
void I_GetJoystickEvents(void)
|
||||
{
|
||||
static event_t event = {0,0,0,0};
|
||||
static event_t event = {0,0,0,0,false};
|
||||
INT32 i = 0;
|
||||
UINT64 joyhats = 0;
|
||||
#if 0
|
||||
|
@ -1049,7 +1049,7 @@ void I_GetJoystickEvents(void)
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_JOY1 + i;
|
||||
event.key = KEY_JOY1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1080,7 +1080,7 @@ void I_GetJoystickEvents(void)
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_HAT1 + i;
|
||||
event.key = KEY_HAT1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1092,7 +1092,7 @@ void I_GetJoystickEvents(void)
|
|||
|
||||
for (i = JOYAXISSET - 1; i >= 0; i--)
|
||||
{
|
||||
event.data1 = i;
|
||||
event.key = i;
|
||||
if (i*2 + 1 <= JoyInfo.axises)
|
||||
axisx = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 0);
|
||||
else axisx = 0;
|
||||
|
@ -1110,15 +1110,15 @@ void I_GetJoystickEvents(void)
|
|||
{
|
||||
// gamepad control type, on or off, live or die
|
||||
if (axisx < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (axisx > (JOYAXISRANGE/2))
|
||||
event.data2 = 1;
|
||||
else event.data2 = 0;
|
||||
event.x = 1;
|
||||
else event.x = 0;
|
||||
if (axisy < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (axisy > (JOYAXISRANGE/2))
|
||||
event.data3 = 1;
|
||||
else event.data3 = 0;
|
||||
event.y = 1;
|
||||
else event.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1132,8 +1132,8 @@ void I_GetJoystickEvents(void)
|
|||
#endif
|
||||
|
||||
// analog control style , just send the raw data
|
||||
event.data2 = axisx; // x axis
|
||||
event.data3 = axisy; // y axis
|
||||
event.x = axisx; // x axis
|
||||
event.y = axisy; // y axis
|
||||
}
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
@ -1247,22 +1247,22 @@ void I_ShutdownJoystick2(void)
|
|||
INT32 i;
|
||||
event_t event;
|
||||
event.type = ev_keyup;
|
||||
event.data2 = 0;
|
||||
event.data3 = 0;
|
||||
event.x = 0;
|
||||
event.y = 0;
|
||||
|
||||
lastjoy2buttons = lastjoy2hats = 0;
|
||||
|
||||
// emulate the up of all joystick buttons
|
||||
for (i = 0; i < JOYBUTTONS; i++)
|
||||
{
|
||||
event.data1 = KEY_2JOY1 + i;
|
||||
event.key = KEY_2JOY1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
// emulate the up of all joystick hats
|
||||
for (i = 0; i < JOYHATS*4; i++)
|
||||
{
|
||||
event.data1 = KEY_2HAT1 + i;
|
||||
event.key = KEY_2HAT1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -1270,7 +1270,7 @@ void I_ShutdownJoystick2(void)
|
|||
event.type = ev_joystick2;
|
||||
for (i = 0; i < JOYAXISSET; i++)
|
||||
{
|
||||
event.data1 = i;
|
||||
event.key = i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -1282,7 +1282,7 @@ void I_ShutdownJoystick2(void)
|
|||
|
||||
void I_GetJoystick2Events(void)
|
||||
{
|
||||
static event_t event = {0,0,0,0};
|
||||
static event_t event = {0,0,0,0,false};
|
||||
INT32 i = 0;
|
||||
UINT64 joyhats = 0;
|
||||
#if 0
|
||||
|
@ -1321,7 +1321,7 @@ void I_GetJoystick2Events(void)
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2JOY1 + i;
|
||||
event.key = KEY_2JOY1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1352,7 +1352,7 @@ void I_GetJoystick2Events(void)
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2HAT1 + i;
|
||||
event.key = KEY_2HAT1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1364,7 +1364,7 @@ void I_GetJoystick2Events(void)
|
|||
|
||||
for (i = JOYAXISSET - 1; i >= 0; i--)
|
||||
{
|
||||
event.data1 = i;
|
||||
event.key = i;
|
||||
if (i*2 + 1 <= JoyInfo2.axises)
|
||||
axisx = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 0);
|
||||
else axisx = 0;
|
||||
|
@ -1380,17 +1380,17 @@ void I_GetJoystick2Events(void)
|
|||
{
|
||||
// gamepad control type, on or off, live or die
|
||||
if (axisx < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (axisx > (JOYAXISRANGE/2))
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
else
|
||||
event.data2 = 0;
|
||||
event.x = 0;
|
||||
if (axisy < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (axisy > (JOYAXISRANGE/2))
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
else
|
||||
event.data3 = 0;
|
||||
event.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1404,8 +1404,8 @@ void I_GetJoystick2Events(void)
|
|||
#endif
|
||||
|
||||
// analog control style , just send the raw data
|
||||
event.data2 = axisx; // x axis
|
||||
event.data3 = axisy; // y axis
|
||||
event.x = axisx; // x axis
|
||||
event.y = axisy; // y axis
|
||||
}
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
@ -1804,7 +1804,7 @@ void I_GetMouseEvents(void)
|
|||
if (!(button & (1<<j))) //keyup
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2MOUSE1+j;
|
||||
event.key = KEY_2MOUSE1+j;
|
||||
D_PostEvent(&event);
|
||||
om2b ^= 1 << j;
|
||||
}
|
||||
|
@ -1814,18 +1814,18 @@ void I_GetMouseEvents(void)
|
|||
if (button & (1<<j))
|
||||
{
|
||||
event.type = ev_keydown;
|
||||
event.data1 = KEY_2MOUSE1+j;
|
||||
event.key = KEY_2MOUSE1+j;
|
||||
D_PostEvent(&event);
|
||||
om2b ^= 1 << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
event.data2 = ((SINT8)mdata[1])+((SINT8)mdata[3]);
|
||||
event.data3 = ((SINT8)mdata[2])+((SINT8)mdata[4]);
|
||||
if (event.data2 && event.data3)
|
||||
event.x = ((SINT8)mdata[1])+((SINT8)mdata[3]);
|
||||
event.y = ((SINT8)mdata[2])+((SINT8)mdata[4]);
|
||||
if (event.x && event.y)
|
||||
{
|
||||
event.type = ev_mouse2;
|
||||
event.data1 = 0;
|
||||
event.key = 0;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1867,7 +1867,7 @@ static void I_ShutdownMouse2(void)
|
|||
for (i = 0; i < MOUSEBUTTONS; i++)
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2MOUSE1+i;
|
||||
event.key = KEY_2MOUSE1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -1958,7 +1958,7 @@ void I_GetMouseEvents(void)
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2MOUSE1+i;
|
||||
event.key = KEY_2MOUSE1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1966,10 +1966,10 @@ void I_GetMouseEvents(void)
|
|||
if (handlermouse2x != 0 || handlermouse2y != 0)
|
||||
{
|
||||
event.type = ev_mouse2;
|
||||
event.data1 = 0;
|
||||
// event.data1 = buttons; // not needed
|
||||
event.data2 = handlermouse2x << 1;
|
||||
event.data3 = handlermouse2y << 1;
|
||||
event.key = 0;
|
||||
// event.key = buttons; // not needed
|
||||
event.x = handlermouse2x << 1;
|
||||
event.y = handlermouse2y << 1;
|
||||
handlermouse2x = 0;
|
||||
handlermouse2y = 0;
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@
|
|||
#include "../console.h"
|
||||
#include "../command.h"
|
||||
#include "../r_main.h"
|
||||
#include "../lua_script.h"
|
||||
#include "../lua_libs.h"
|
||||
#include "../lua_hook.h"
|
||||
#include "sdlmain.h"
|
||||
#ifdef HWRENDER
|
||||
|
@ -372,6 +374,8 @@ static boolean IgnoreMouse(void)
|
|||
if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION &&
|
||||
gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE)
|
||||
return true;
|
||||
if (!mousegrabbedbylua)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -663,8 +667,9 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
|
|||
{
|
||||
return;
|
||||
}
|
||||
event.data1 = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
|
||||
if (event.data1) D_PostEvent(&event);
|
||||
event.key = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
|
||||
event.repeated = (evt.repeat != 0);
|
||||
if (event.key) D_PostEvent(&event);
|
||||
}
|
||||
|
||||
static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
|
||||
|
@ -742,15 +747,15 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
|
|||
}
|
||||
else return;
|
||||
if (evt.button == SDL_BUTTON_MIDDLE)
|
||||
event.data1 = KEY_MOUSE1+2;
|
||||
event.key = KEY_MOUSE1+2;
|
||||
else if (evt.button == SDL_BUTTON_RIGHT)
|
||||
event.data1 = KEY_MOUSE1+1;
|
||||
event.key = KEY_MOUSE1+1;
|
||||
else if (evt.button == SDL_BUTTON_LEFT)
|
||||
event.data1 = KEY_MOUSE1;
|
||||
event.key = KEY_MOUSE1;
|
||||
else if (evt.button == SDL_BUTTON_X1)
|
||||
event.data1 = KEY_MOUSE1+3;
|
||||
event.key = KEY_MOUSE1+3;
|
||||
else if (evt.button == SDL_BUTTON_X2)
|
||||
event.data1 = KEY_MOUSE1+4;
|
||||
event.key = KEY_MOUSE1+4;
|
||||
if (event.type == ev_keyup || event.type == ev_keydown)
|
||||
{
|
||||
D_PostEvent(&event);
|
||||
|
@ -766,17 +771,17 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
|
|||
|
||||
if (evt.y > 0)
|
||||
{
|
||||
event.data1 = KEY_MOUSEWHEELUP;
|
||||
event.key = KEY_MOUSEWHEELUP;
|
||||
event.type = ev_keydown;
|
||||
}
|
||||
if (evt.y < 0)
|
||||
{
|
||||
event.data1 = KEY_MOUSEWHEELDOWN;
|
||||
event.key = KEY_MOUSEWHEELDOWN;
|
||||
event.type = ev_keydown;
|
||||
}
|
||||
if (evt.y == 0)
|
||||
{
|
||||
event.data1 = 0;
|
||||
event.key = 0;
|
||||
event.type = ev_keyup;
|
||||
}
|
||||
if (event.type == ev_keyup || event.type == ev_keydown)
|
||||
|
@ -795,7 +800,7 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
|
|||
joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
|
||||
|
||||
evt.axis++;
|
||||
event.data1 = event.data2 = event.data3 = INT32_MAX;
|
||||
event.key = event.x = event.y = INT32_MAX;
|
||||
|
||||
if (evt.which == joyid[0])
|
||||
{
|
||||
|
@ -812,14 +817,14 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
|
|||
//vaule
|
||||
if (evt.axis%2)
|
||||
{
|
||||
event.data1 = evt.axis / 2;
|
||||
event.data2 = SDLJoyAxis(evt.value, event.type);
|
||||
event.key = evt.axis / 2;
|
||||
event.x = SDLJoyAxis(evt.value, event.type);
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.axis--;
|
||||
event.data1 = evt.axis / 2;
|
||||
event.data3 = SDLJoyAxis(evt.value, event.type);
|
||||
event.key = evt.axis / 2;
|
||||
event.y = SDLJoyAxis(evt.value, event.type);
|
||||
}
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
@ -839,11 +844,11 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt)
|
|||
|
||||
if (evt.which == joyid[0])
|
||||
{
|
||||
event.data1 = KEY_HAT1 + (evt.hat*4);
|
||||
event.key = KEY_HAT1 + (evt.hat*4);
|
||||
}
|
||||
else if (evt.which == joyid[1])
|
||||
{
|
||||
event.data1 = KEY_2HAT1 + (evt.hat*4);
|
||||
event.key = KEY_2HAT1 + (evt.hat*4);
|
||||
}
|
||||
else return;
|
||||
|
||||
|
@ -862,11 +867,11 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
|
|||
|
||||
if (evt.which == joyid[0])
|
||||
{
|
||||
event.data1 = KEY_JOY1;
|
||||
event.key = KEY_JOY1;
|
||||
}
|
||||
else if (evt.which == joyid[1])
|
||||
{
|
||||
event.data1 = KEY_2JOY1;
|
||||
event.key = KEY_2JOY1;
|
||||
}
|
||||
else return;
|
||||
if (type == SDL_JOYBUTTONUP)
|
||||
|
@ -880,7 +885,7 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
|
|||
else return;
|
||||
if (evt.button < JOYBUTTONS)
|
||||
{
|
||||
event.data1 += evt.button;
|
||||
event.key += evt.button;
|
||||
}
|
||||
else return;
|
||||
|
||||
|
@ -1084,9 +1089,9 @@ void I_GetEvent(void)
|
|||
SDL_GetWindowSize(window, &wwidth, &wheight);
|
||||
//SDL_memset(&event, 0, sizeof(event_t));
|
||||
event.type = ev_mouse;
|
||||
event.data1 = 0;
|
||||
event.data2 = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
|
||||
event.data3 = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
|
||||
event.key = 0;
|
||||
event.x = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
|
||||
event.y = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/// \file
|
||||
/// \brief SDL Mixer interface for sound
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
#ifdef HAVE_ZLIB
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include <zlib.h>
|
||||
#endif // HAVE_ZLIB
|
||||
#endif // HAVE_LIBGME
|
||||
#endif // HAVE_GME
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../doomstat.h" // menuactive
|
||||
|
@ -73,11 +73,11 @@
|
|||
#define MUS_MODPLUG MUS_MODPLUG_UNUSED
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
#include "gme/gme.h"
|
||||
#define GME_TREBLE 5.0f
|
||||
#define GME_BASS 1.0f
|
||||
#endif // HAVE_LIBGME
|
||||
#endif // HAVE_GME
|
||||
|
||||
static UINT16 BUFFERSIZE = 2048;
|
||||
static UINT16 SAMPLERATE = 44100;
|
||||
|
@ -110,7 +110,7 @@ static INT32 fading_id;
|
|||
static void (*fading_callback)(void);
|
||||
static boolean fading_nocleanup;
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
static Music_Emu *gme;
|
||||
static UINT16 current_track;
|
||||
#endif
|
||||
|
@ -220,7 +220,7 @@ static void var_cleanup(void)
|
|||
internal_volume = 100;
|
||||
}
|
||||
|
||||
#if defined (HAVE_LIBGME) && defined (HAVE_ZLIB)
|
||||
#if defined (HAVE_GME) && defined (HAVE_ZLIB)
|
||||
static const char* get_zlib_error(int zErr)
|
||||
{
|
||||
switch (zErr)
|
||||
|
@ -318,7 +318,7 @@ void I_ShutdownSound(void)
|
|||
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
gme_delete(gme);
|
||||
#endif
|
||||
|
@ -453,7 +453,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
void *lump;
|
||||
Mix_Chunk *chunk;
|
||||
SDL_RWops *rw;
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
Music_Emu *emu;
|
||||
gme_info_t *info;
|
||||
#endif
|
||||
|
@ -473,7 +473,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
}
|
||||
|
||||
// Not a doom sound? Try something else.
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
// VGZ format
|
||||
if (((UINT8 *)lump)[0] == 0x1F
|
||||
&& ((UINT8 *)lump)[1] == 0x8B)
|
||||
|
@ -729,7 +729,7 @@ static UINT32 music_fade(UINT32 interval, void *param)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
static void mix_gme(void *udata, Uint8 *stream, int len)
|
||||
{
|
||||
int i;
|
||||
|
@ -797,7 +797,7 @@ void I_ShutdownMusic(void)
|
|||
|
||||
musictype_t I_SongType(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
return MU_GME;
|
||||
else
|
||||
|
@ -828,7 +828,7 @@ musictype_t I_SongType(void)
|
|||
boolean I_SongPlaying(void)
|
||||
{
|
||||
return (
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
(I_SongType() == MU_GME && gme) ||
|
||||
#endif
|
||||
#ifdef HAVE_OPENMPT
|
||||
|
@ -851,7 +851,7 @@ boolean I_SetSongSpeed(float speed)
|
|||
{
|
||||
if (speed > 250.0f)
|
||||
speed = 250.0f; //limit speed up to 250x
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
SDL_LockAudio();
|
||||
|
@ -893,7 +893,7 @@ UINT32 I_GetSongLength(void)
|
|||
{
|
||||
INT32 length;
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
gme_info_t *info;
|
||||
|
@ -963,7 +963,7 @@ boolean I_SetSongLoopPoint(UINT32 looppoint)
|
|||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
INT32 looppoint;
|
||||
|
@ -992,7 +992,7 @@ UINT32 I_GetSongLoopPoint(void)
|
|||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
UINT32 length;
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
// this is unstable, so fail silently
|
||||
|
@ -1055,7 +1055,7 @@ boolean I_SetSongPosition(UINT32 position)
|
|||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
INT32 position = gme_tell(gme);
|
||||
|
@ -1124,7 +1124,7 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
SDL_RWops *rw;
|
||||
|
||||
if (music
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
|| gme
|
||||
#endif
|
||||
#ifdef HAVE_OPENMPT
|
||||
|
@ -1136,7 +1136,7 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
// always do this whether or not a music already exists
|
||||
var_cleanup();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if ((UINT8)data[0] == 0x1F
|
||||
&& (UINT8)data[1] == 0x8B)
|
||||
{
|
||||
|
@ -1271,7 +1271,7 @@ void I_UnloadSong(void)
|
|||
{
|
||||
I_StopSong();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
gme_delete(gme);
|
||||
|
@ -1294,7 +1294,7 @@ void I_UnloadSong(void)
|
|||
|
||||
boolean I_PlaySong(boolean looping)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
|
||||
|
@ -1360,7 +1360,7 @@ void I_StopSong(void)
|
|||
if (!fading_nocleanup)
|
||||
I_StopFadingSong();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
if (gme)
|
||||
{
|
||||
Mix_HookMusic(NULL, NULL);
|
||||
|
@ -1433,7 +1433,7 @@ void I_SetMusicVolume(UINT8 volume)
|
|||
|
||||
boolean I_SetSongTrack(int track)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
#ifdef HAVE_GME
|
||||
// If the specified track is within the number of tracks playing, then change it
|
||||
if (gme)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#endif
|
||||
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hook.h"
|
||||
|
||||
UINT16 objectsdrawn = 0;
|
||||
|
||||
|
@ -1391,7 +1392,7 @@ void ST_drawTitleCard(void)
|
|||
lt_lasttic = lt_ticker;
|
||||
|
||||
luahook:
|
||||
LUAh_TitleCardHUD(stplyr);
|
||||
LUA_HUDHOOK(titlecard);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2732,7 +2733,7 @@ static void ST_overlayDrawer(void)
|
|||
ST_drawPowerupHUD(); // same as it ever was...
|
||||
|
||||
if (!(netgame || multiplayer) || !hu_showscores)
|
||||
LUAh_GameHUD(stplyr);
|
||||
LUA_HUDHOOK(game);
|
||||
|
||||
// draw level title Tails
|
||||
if (stagetitle && (!WipeInAction) && (!WipeStageTitle))
|
||||
|
|
102
src/v_video.c
102
src/v_video.c
|
@ -809,13 +809,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
|||
}
|
||||
|
||||
// Draws a patch cropped and scaled to arbitrary size.
|
||||
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
|
||||
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
|
||||
{
|
||||
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
|
||||
UINT32 alphalevel = 0;
|
||||
// boolean flip = false;
|
||||
|
||||
fixed_t col, ofs, colfrac, rowfrac, fdup;
|
||||
fixed_t col, ofs, colfrac, rowfrac, fdup, vdup;
|
||||
INT32 dupx, dupy;
|
||||
const column_t *column;
|
||||
UINT8 *desttop, *dest;
|
||||
|
@ -830,7 +830,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
//if (rendermode != render_soft && !con_startup) // Not this again
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
HWR_DrawCroppedPatch(patch,x,y,pscale,scrn,sx,sy,w,h);
|
||||
HWR_DrawCroppedPatch(patch,x,y,pscale,vscale,scrn,colormap,sx,sy,w,h);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -857,31 +857,56 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
}
|
||||
}
|
||||
|
||||
// only use one dup, to avoid stretching (har har)
|
||||
dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
fdup = FixedMul(dupx<<FRACBITS, pscale);
|
||||
colfrac = FixedDiv(FRACUNIT, fdup);
|
||||
rowfrac = FixedDiv(FRACUNIT, fdup);
|
||||
v_colormap = NULL;
|
||||
if (colormap)
|
||||
{
|
||||
v_colormap = colormap;
|
||||
patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw;
|
||||
}
|
||||
|
||||
dupx = vid.dupx;
|
||||
dupy = vid.dupy;
|
||||
if (scrn & V_SCALEPATCHMASK) switch ((scrn & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT)
|
||||
{
|
||||
case 1: // V_NOSCALEPATCH
|
||||
dupx = dupy = 1;
|
||||
break;
|
||||
case 2: // V_SMALLSCALEPATCH
|
||||
dupx = vid.smalldupx;
|
||||
dupy = vid.smalldupy;
|
||||
break;
|
||||
case 3: // V_MEDSCALEPATCH
|
||||
dupx = vid.meddupx;
|
||||
dupy = vid.meddupy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// only use one dup, to avoid stretching (har har)
|
||||
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
||||
fdup = vdup = FixedMul(dupx<<FRACBITS, pscale);
|
||||
if (vscale != pscale)
|
||||
vdup = FixedMul(dupx<<FRACBITS, vscale);
|
||||
colfrac = FixedDiv(FRACUNIT, fdup);
|
||||
rowfrac = FixedDiv(FRACUNIT, vdup);
|
||||
|
||||
y -= FixedMul(patch->topoffset<<FRACBITS, pscale);
|
||||
x -= FixedMul(patch->leftoffset<<FRACBITS, pscale);
|
||||
y -= FixedMul(patch->topoffset<<FRACBITS, vscale);
|
||||
|
||||
if (splitscreen && (scrn & V_PERPLAYER))
|
||||
{
|
||||
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
||||
fdup >>= 1;
|
||||
vdup >>= 1;
|
||||
rowfrac <<= 1;
|
||||
y >>= 1;
|
||||
sy >>= 1;
|
||||
h >>= 1;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
|
||||
fdup >>= 1;
|
||||
colfrac <<= 1;
|
||||
x >>= 1;
|
||||
sx >>= 1;
|
||||
w >>= 1;
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
|
@ -897,7 +922,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
sx += adjustx;
|
||||
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[thirddisplayplayer])
|
||||
|
@ -907,7 +931,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
y += adjusty;
|
||||
sy += adjusty;
|
||||
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else //if (stplyr == &players[fourthdisplayplayer])
|
||||
|
@ -917,9 +940,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
sx += adjustx;
|
||||
y += adjusty;
|
||||
sy += adjusty;
|
||||
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
|
@ -938,7 +959,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
y += adjusty;
|
||||
sy += adjusty;
|
||||
scrn &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
|
@ -951,7 +971,8 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
|
||||
deststop = desttop + vid.rowbytes * vid.height;
|
||||
|
||||
if (scrn & V_NOSCALESTART) {
|
||||
if (scrn & V_NOSCALESTART)
|
||||
{
|
||||
x >>= FRACBITS;
|
||||
y >>= FRACBITS;
|
||||
desttop += (y*vid.width) + x;
|
||||
|
@ -999,7 +1020,38 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
desttop += (y*vid.width) + x;
|
||||
}
|
||||
|
||||
for (col = sx<<FRACBITS; (col>>FRACBITS) < patch->width && ((col>>FRACBITS) - sx) < w; col += colfrac, ++x, desttop++)
|
||||
// Auto-crop at splitscreen borders!
|
||||
if (splitscreen && (scrn & V_PERPLAYER))
|
||||
{
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
#error Auto-cropping doesnt take quadscreen into account! Fix it!
|
||||
// Hint: For player 1/2, copy player 1's code below. For player 3/4, copy player 2's code below
|
||||
// For player 1/3 and 2/4, hijack the X wrap prevention lines? That's probably easiest
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
|
||||
{
|
||||
// Just put a big old stop sign halfway through the screen
|
||||
deststop -= vid.rowbytes * (vid.height>>1);
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
|
||||
{
|
||||
if (y < (vid.height>>1)) // If the top is above the border
|
||||
{
|
||||
sy += ((vid.height>>1) - y) * rowfrac; // Start further down on the patch
|
||||
h -= ((vid.height>>1) - y) * rowfrac; // Draw less downwards from the start
|
||||
desttop += ((vid.height>>1) - y) * vid.width; // Start drawing at the border
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++)
|
||||
{
|
||||
INT32 topdelta, prevdelta = -1;
|
||||
if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION)
|
||||
|
@ -1016,15 +1068,15 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
prevdelta = topdelta;
|
||||
source = (const UINT8 *)(column) + 3;
|
||||
dest = desttop;
|
||||
if (topdelta-sy > 0)
|
||||
if ((topdelta<<FRACBITS)-sy > 0)
|
||||
{
|
||||
dest += FixedInt(FixedMul((topdelta-sy)<<FRACBITS,fdup))*vid.width;
|
||||
dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup))*vid.width;
|
||||
ofs = 0;
|
||||
}
|
||||
else
|
||||
ofs = (sy-topdelta)<<FRACBITS;
|
||||
ofs = sy-(topdelta<<FRACBITS);
|
||||
|
||||
for (; dest < deststop && (ofs>>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac)
|
||||
for (; dest < deststop && (ofs>>FRACBITS) < column->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac)
|
||||
{
|
||||
if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
|
||||
*dest = patchdrawfunc(dest, source, ofs);
|
||||
|
|
|
@ -165,7 +165,7 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
|
|||
#define V_DrawSciencePatch(x,y,s,p,sc) V_DrawFixedPatch(x,y,sc,s,p,NULL)
|
||||
#define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c)
|
||||
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
|
||||
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
|
||||
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
|
||||
|
||||
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define SRB2VERSION "2.2.9"/* this must be the first line, for cmake !! */
|
||||
|
||||
// The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/showgroups.php ).
|
||||
// The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/members/?key=ms_admin ).
|
||||
// DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server.
|
||||
// "18" is the default mod ID for version 2.2
|
||||
#define MODID 18
|
||||
|
|
445
src/w_wad.c
445
src/w_wad.c
|
@ -50,16 +50,17 @@
|
|||
|
||||
#include "filesrch.h"
|
||||
|
||||
#include "i_video.h" // rendermode
|
||||
#include "d_main.h"
|
||||
#include "d_netfil.h"
|
||||
#include "dehacked.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "dehacked.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_data.h"
|
||||
#include "r_textures.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_picformats.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "md5.h"
|
||||
#include "lua_script.h"
|
||||
#ifdef SCANTHINGS
|
||||
|
@ -117,10 +118,15 @@ void W_Shutdown(void)
|
|||
{
|
||||
wadfile_t *wad = wadfiles[numwadfiles];
|
||||
|
||||
fclose(wad->handle);
|
||||
if (wad->handle)
|
||||
fclose(wad->handle);
|
||||
Z_Free(wad->filename);
|
||||
if (wad->path)
|
||||
Z_Free(wad->path);
|
||||
while (wad->numlumps--)
|
||||
{
|
||||
if (wad->lumpinfo[wad->numlumps].diskpath)
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].diskpath);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].longname);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].fullname);
|
||||
}
|
||||
|
@ -421,6 +427,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
|
|||
{
|
||||
lump_p->position = LONG(fileinfo->filepos);
|
||||
lump_p->size = lump_p->disksize = LONG(fileinfo->size);
|
||||
lump_p->diskpath = NULL;
|
||||
if (compressed) // wad is compressed, lump might be
|
||||
{
|
||||
UINT32 realsize = 0;
|
||||
|
@ -602,6 +609,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
|
||||
lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
|
||||
lump_p->disksize = zentry.compsize;
|
||||
lump_p->diskpath = NULL;
|
||||
lump_p->size = zentry.size;
|
||||
|
||||
fullname = malloc(zentry.namelen + 1);
|
||||
|
@ -679,6 +687,114 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
return lumpinfo;
|
||||
}
|
||||
|
||||
static INT32 CheckPathsNotEqual(const char *path1, const char *path2)
|
||||
{
|
||||
INT32 stat = samepaths(path1, path2);
|
||||
|
||||
if (stat == 1)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns 1 if the path is valid, 0 if not, and -1 if there was an error.
|
||||
INT32 W_IsPathToFolderValid(const char *path)
|
||||
{
|
||||
INT32 stat;
|
||||
|
||||
// Remove path delimiters.
|
||||
const char *p = path + (strlen(path) - 1);
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if the path is a directory.
|
||||
stat = pathisdirectory(path);
|
||||
if (stat == 0)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
{
|
||||
// The path doesn't exist, so it can't be a directory.
|
||||
if (direrror == ENOENT)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Don't add your home, you sodding tic tac.
|
||||
stat = CheckPathsNotEqual(path, srb2home);
|
||||
if (stat != 1)
|
||||
return stat;
|
||||
|
||||
// Do the same checks for SRB2's path, and the current directory.
|
||||
stat = CheckPathsNotEqual(path, srb2path);
|
||||
if (stat != 1)
|
||||
return stat;
|
||||
|
||||
stat = CheckPathsNotEqual(path, ".");
|
||||
if (stat != 1)
|
||||
return stat;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if the combination of the first path and the second path are valid.
|
||||
// If they are, the concatenated path is returned.
|
||||
static char *CheckConcatFolderPath(const char *startpath, const char *path)
|
||||
{
|
||||
if (concatpaths(path, startpath) == 1)
|
||||
{
|
||||
char *fn;
|
||||
|
||||
if (startpath)
|
||||
{
|
||||
size_t len = strlen(startpath) + strlen(path) + strlen(PATHSEP) + 1;
|
||||
fn = ZZ_Alloc(len);
|
||||
snprintf(fn, len, "%s" PATHSEP "%s", startpath, path);
|
||||
}
|
||||
else
|
||||
fn = Z_StrDup(path);
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Looks for the first valid full path for a folder.
|
||||
// Returns NULL if the folder doesn't exist, or it isn't valid.
|
||||
char *W_GetFullFolderPath(const char *path)
|
||||
{
|
||||
// Check the path by itself first.
|
||||
char *fn = CheckConcatFolderPath(NULL, path);
|
||||
if (fn)
|
||||
return fn;
|
||||
|
||||
#define checkpath(startpath) \
|
||||
fn = CheckConcatFolderPath(startpath, path); \
|
||||
if (fn) \
|
||||
return fn
|
||||
|
||||
checkpath(srb2home); // Then, look in srb2home.
|
||||
checkpath(srb2path); // Now, look in srb2path.
|
||||
checkpath("."); // Finally, look in the current directory.
|
||||
|
||||
#undef checkpath
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Loads files from a folder into a lumpinfo structure.
|
||||
static lumpinfo_t *ResGetLumpsFolder(const char *path, UINT16 *nlmp, UINT16 *nfolders)
|
||||
{
|
||||
return getdirectoryfiles(path, nlmp, nfolders);
|
||||
}
|
||||
|
||||
static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
|
||||
{
|
||||
if (exitworthy)
|
||||
|
@ -694,6 +810,19 @@ static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
|
|||
return INT16_MAX;
|
||||
}
|
||||
|
||||
static void W_ReadFileShaders(wadfile_t *wadfile)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, W_FileHasFolders(wadfile));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#else
|
||||
(void)wadfile;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Allocate a wadfile, setup the lumpinfo (directory) and
|
||||
// lumpcache, add the wadfile to the current active wadfiles
|
||||
//
|
||||
|
@ -760,7 +889,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
// see PutFileNeeded in d_netfil.c
|
||||
if ((important = !important))
|
||||
{
|
||||
packetsize = packetsizetally + nameonlylength(filename) + 22;
|
||||
packetsize = packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE;
|
||||
|
||||
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
|
||||
{
|
||||
|
@ -788,7 +917,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
|
||||
if (important)
|
||||
packetsizetally -= nameonlylength(filename) + 22;
|
||||
packetsizetally -= nameonlylength(filename) + FILENEEDEDSIZE;
|
||||
if (handle)
|
||||
fclose(handle);
|
||||
return W_InitFileError(filename, false);
|
||||
|
@ -831,9 +960,11 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
//
|
||||
wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
|
||||
wadfile->filename = Z_StrDup(filename);
|
||||
wadfile->path = NULL;
|
||||
wadfile->type = type;
|
||||
wadfile->handle = handle;
|
||||
wadfile->numlumps = (UINT16)numlumps;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->foldercount = 0;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
fseek(handle, 0, SEEK_END);
|
||||
|
@ -856,14 +987,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
|
||||
|
||||
#ifdef HWRENDER
|
||||
// Read shaders from file
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#endif // HWRENDER
|
||||
W_ReadFileShaders(wadfile);
|
||||
|
||||
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
|
||||
switch (wadfile->type)
|
||||
|
@ -889,6 +1014,180 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
//
|
||||
// Loads a folder as a WAD.
|
||||
//
|
||||
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
||||
{
|
||||
lumpinfo_t *lumpinfo = NULL;
|
||||
wadfile_t *wadfile;
|
||||
UINT16 numlumps = 0;
|
||||
UINT16 foldercount;
|
||||
size_t i;
|
||||
char *fn, *fullpath;
|
||||
const char *p;
|
||||
int important;
|
||||
INT32 stat;
|
||||
|
||||
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
|
||||
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
|
||||
|
||||
if (refreshdirname)
|
||||
Z_Free(refreshdirname);
|
||||
if (dirmenu)
|
||||
refreshdirname = Z_StrDup(path);
|
||||
else
|
||||
refreshdirname = NULL;
|
||||
|
||||
if (numwadfiles >= MAX_WADFILES)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
refreshdirmenu |= REFRESHDIR_MAX;
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
important = 0; // ???
|
||||
|
||||
/// \todo Implement a W_VerifyFolder.
|
||||
if ((important = !important))
|
||||
{
|
||||
size_t packetsize = packetsizetally + strlen(path) + FILENEEDEDSIZE;
|
||||
|
||||
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
refreshdirmenu |= REFRESHDIR_MAX;
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
packetsizetally = packetsize;
|
||||
}
|
||||
|
||||
// Remove path delimiters.
|
||||
p = path + (strlen(path) - 1);
|
||||
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), path);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
|
||||
// Allocate the new path name.
|
||||
i = (p - path) + 1;
|
||||
fn = ZZ_Alloc(i);
|
||||
strlcpy(fn, path, i);
|
||||
|
||||
// Don't add an empty path.
|
||||
if (M_IsStringEmpty(fn))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder name is empty\n"));
|
||||
Z_Free(fn);
|
||||
|
||||
if (startup)
|
||||
return W_InitFileError("A folder", true);
|
||||
else
|
||||
return W_InitFileError("a folder", false);
|
||||
}
|
||||
|
||||
// Check if the path is valid.
|
||||
stat = W_IsPathToFolderValid(fn);
|
||||
|
||||
if (stat != 1)
|
||||
{
|
||||
if (stat == 0)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), fn);
|
||||
else if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not stat %s: %s\n"), fn, strerror(direrror));
|
||||
#else
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not stat %s\n"), fn);
|
||||
#endif
|
||||
}
|
||||
|
||||
Z_Free(fn);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
// Get the full path for this folder.
|
||||
fullpath = W_GetFullFolderPath(fn);
|
||||
if (fullpath == NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), fn);
|
||||
Z_Free(fn);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
// Check if the folder is already added.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (samepaths(wadfiles[i]->path, fullpath) > 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path);
|
||||
if (important)
|
||||
packetsizetally -= strlen(path) + FILENEEDEDSIZE;
|
||||
Z_Free(fn);
|
||||
Z_Free(fullpath);
|
||||
return W_InitFileError(path, false);
|
||||
}
|
||||
}
|
||||
|
||||
lumpinfo = ResGetLumpsFolder(fullpath, &numlumps, &foldercount);
|
||||
|
||||
if (lumpinfo == NULL)
|
||||
{
|
||||
if (!numlumps)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder %s is empty\n"), path);
|
||||
else if (numlumps == UINT16_MAX)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder %s contains too many files\n"), path);
|
||||
else
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Unknown error enumerating files from folder %s\n"), path);
|
||||
|
||||
Z_Free(fn);
|
||||
Z_Free(fullpath);
|
||||
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
if (important && !mainfile)
|
||||
G_SetGameModified(true);
|
||||
|
||||
wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
|
||||
wadfile->filename = fn;
|
||||
wadfile->path = fullpath;
|
||||
wadfile->type = RET_FOLDER;
|
||||
wadfile->handle = NULL;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->foldercount = foldercount;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
|
||||
// Irrelevant.
|
||||
wadfile->filesize = 0;
|
||||
memset(wadfile->md5sum, 0x00, 16);
|
||||
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache);
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache);
|
||||
|
||||
CONS_Printf(M_GetText("Added folder %s (%u files, %u folders)\n"), fn, numlumps, foldercount);
|
||||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++;
|
||||
|
||||
W_ReadFileShaders(wadfile);
|
||||
W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile);
|
||||
W_InvalidateLumpnumCache();
|
||||
|
||||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
/** Tries to load a series of files.
|
||||
* All files are wads unless they have an extension of ".soc" or ".lua".
|
||||
*
|
||||
|
@ -900,11 +1199,18 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
*/
|
||||
void W_InitMultipleFiles(char **filenames)
|
||||
{
|
||||
// will be realloced as lumps are added
|
||||
for (; *filenames; filenames++)
|
||||
{
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
|
||||
W_InitFile(*filenames, numwadfiles < mainwads, true);
|
||||
const char *fn = (*filenames);
|
||||
char pathsep = fn[strlen(fn) - 1];
|
||||
boolean mainfile = (numwadfiles < mainwads);
|
||||
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", fn);
|
||||
|
||||
if (pathsep == '\\' || pathsep == '/')
|
||||
W_InitFolder(fn, mainfile, true);
|
||||
else
|
||||
W_InitFile(fn, mainfile, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1484,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
|||
if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
|
||||
return (i<<16) + lumpNum;
|
||||
}
|
||||
else if (wadfiles[i]->type == RET_PK3)
|
||||
else if (W_FileHasFolders(wadfiles[i]))
|
||||
{
|
||||
lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0);
|
||||
if (lumpNum != INT16_MAX)
|
||||
|
@ -1276,9 +1582,46 @@ UINT8 W_LumpExists(const char *name)
|
|||
|
||||
size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
lumpinfo_t *l;
|
||||
|
||||
if (!TestValidLump(wad, lump))
|
||||
return 0;
|
||||
return wadfiles[wad]->lumpinfo[lump].size;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_LumpLengthPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_LumpLengthPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_LumpLengthPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
FILE *handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_LumpLengthPwad: could not open file %s", l->diskpath);
|
||||
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
fclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return l->size;
|
||||
}
|
||||
|
||||
/** Returns the buffer size needed to load the given lump.
|
||||
|
@ -1297,7 +1640,7 @@ size_t W_LumpLength(lumpnum_t lumpnum)
|
|||
//
|
||||
boolean W_IsLumpWad(lumpnum_t lumpnum)
|
||||
{
|
||||
if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[WADFILENUM(lumpnum)]))
|
||||
{
|
||||
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname;
|
||||
|
||||
|
@ -1315,7 +1658,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
|
|||
//
|
||||
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
if (wadfiles[wad]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[wad]))
|
||||
{
|
||||
const char *name = wadfiles[wad]->lumpinfo[lump].fullname;
|
||||
|
||||
|
@ -1365,17 +1708,55 @@ void zerr(int ret)
|
|||
*/
|
||||
size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset)
|
||||
{
|
||||
size_t lumpsize;
|
||||
size_t lumpsize, bytesread;
|
||||
lumpinfo_t *l;
|
||||
FILE *handle;
|
||||
FILE *handle = NULL;
|
||||
|
||||
if (!TestValidLump(wad,lump))
|
||||
if (!TestValidLump(wad, lump))
|
||||
return 0;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_ReadLumpHeaderPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_ReadLumpHeaderPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_ReadLumpHeaderPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_ReadLumpHeaderPwad: could not open file %s", l->diskpath);
|
||||
|
||||
// Find length of file
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
}
|
||||
}
|
||||
|
||||
lumpsize = wadfiles[wad]->lumpinfo[lump].size;
|
||||
// empty resource (usually markers like S_START, F_END ..)
|
||||
if (!lumpsize || lumpsize<offset)
|
||||
{
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// zero size means read all the lump
|
||||
if (!size || size+offset > lumpsize)
|
||||
|
@ -1383,24 +1764,22 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
|
||||
// Let's get the raw lump data.
|
||||
// We setup the desired file handle to read the lump data.
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
handle = wadfiles[wad]->handle;
|
||||
if (wadfiles[wad]->type != RET_FOLDER)
|
||||
handle = wadfiles[wad]->handle;
|
||||
fseek(handle, (long)(l->position + offset), SEEK_SET);
|
||||
|
||||
// But let's not copy it yet. We support different compression formats on lumps, so we need to take that into account.
|
||||
switch(wadfiles[wad]->lumpinfo[lump].compression)
|
||||
{
|
||||
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
|
||||
bytesread = fread(dest, 1, size, handle);
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
#ifdef NO_PNG_LUMPS
|
||||
{
|
||||
size_t bytesread = fread(dest, 1, size, handle);
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, bytesread))
|
||||
Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
|
||||
return bytesread;
|
||||
}
|
||||
#else
|
||||
return fread(dest, 1, size, handle);
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, bytesread))
|
||||
Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
|
||||
#endif
|
||||
return bytesread;
|
||||
case CM_LZF: // Is it LZF compressed? Used by ZWADs.
|
||||
{
|
||||
#ifdef ZWAD
|
||||
|
|
14
src/w_wad.h
14
src/w_wad.h
|
@ -69,6 +69,7 @@ typedef struct
|
|||
char name[9]; // filelump_t name[] e.g. "LongEntr"
|
||||
char *longname; // e.g. "LongEntryName"
|
||||
char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension"
|
||||
char *diskpath; // path to the file e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension"
|
||||
size_t size; // real (uncompressed) size
|
||||
compmethod compression; // lump compression method
|
||||
} lumpinfo_t;
|
||||
|
@ -109,17 +110,19 @@ typedef enum restype
|
|||
RET_SOC,
|
||||
RET_LUA,
|
||||
RET_PK3,
|
||||
RET_FOLDER,
|
||||
RET_UNKNOWN,
|
||||
} restype_t;
|
||||
|
||||
typedef struct wadfile_s
|
||||
{
|
||||
char *filename;
|
||||
char *filename, *path;
|
||||
restype_t type;
|
||||
lumpinfo_t *lumpinfo;
|
||||
lumpcache_t *lumpcache;
|
||||
lumpcache_t *patchcache;
|
||||
UINT16 numlumps; // this wad's number of resources
|
||||
UINT16 foldercount; // folder count
|
||||
FILE *handle;
|
||||
UINT32 filesize; // for network
|
||||
UINT8 md5sum[16];
|
||||
|
@ -127,7 +130,7 @@ typedef struct wadfile_s
|
|||
boolean important; // also network - !W_VerifyNMUSlumps
|
||||
} wadfile_t;
|
||||
|
||||
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word
|
||||
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad file number in upper word
|
||||
#define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad
|
||||
|
||||
extern UINT16 numwadfiles;
|
||||
|
@ -141,10 +144,17 @@ void W_Shutdown(void);
|
|||
FILE *W_OpenWadFile(const char **filename, boolean useerrors);
|
||||
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
|
||||
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
|
||||
// Adds a folder as a file
|
||||
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup);
|
||||
|
||||
// W_InitMultipleFiles exits if a file was not found, but not if all is okay.
|
||||
void W_InitMultipleFiles(char **filenames);
|
||||
|
||||
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER)
|
||||
|
||||
INT32 W_IsPathToFolderValid(const char *path);
|
||||
char *W_GetFullFolderPath(const char *path);
|
||||
|
||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
||||
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
||||
|
||||
|
|
|
@ -188,11 +188,11 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
ev.type = ev_keydown;
|
||||
|
||||
handleKeyDoom:
|
||||
ev.data1 = 0;
|
||||
ev.key = 0;
|
||||
if (wParam == VK_PAUSE)
|
||||
// intercept PAUSE key
|
||||
{
|
||||
ev.data1 = KEY_PAUSE;
|
||||
ev.key = KEY_PAUSE;
|
||||
}
|
||||
else if (!keyboard_started)
|
||||
// post some keys during the game startup
|
||||
|
@ -201,14 +201,14 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_ESCAPE: ev.data1 = KEY_ESCAPE; break;
|
||||
case VK_RETURN: ev.data1 = KEY_ENTER; break;
|
||||
case VK_SHIFT: ev.data1 = KEY_LSHIFT; break;
|
||||
default: ev.data1 = MapVirtualKey((DWORD)wParam,2); // convert in to char
|
||||
case VK_ESCAPE: ev.key = KEY_ESCAPE; break;
|
||||
case VK_RETURN: ev.key = KEY_ENTER; break;
|
||||
case VK_SHIFT: ev.key = KEY_LSHIFT; break;
|
||||
default: ev.key = MapVirtualKey((DWORD)wParam,2); // convert in to char
|
||||
}
|
||||
}
|
||||
|
||||
if (ev.data1)
|
||||
if (ev.key)
|
||||
D_PostEvent (&ev);
|
||||
|
||||
return 0;
|
||||
|
@ -240,7 +240,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
if (nodinput)
|
||||
{
|
||||
ev.type = ev_keyup;
|
||||
ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam);
|
||||
ev.key = KEY_MOUSE1 + 3 + HIWORD(wParam);
|
||||
D_PostEvent(&ev);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
if (nodinput)
|
||||
{
|
||||
ev.type = ev_keydown;
|
||||
ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam);
|
||||
ev.key = KEY_MOUSE1 + 3 + HIWORD(wParam);
|
||||
D_PostEvent(&ev);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -258,9 +258,9 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
//I_OutputMsg("MW_WHEEL dispatched.\n");
|
||||
ev.type = ev_keydown;
|
||||
if ((INT16)HIWORD(wParam) > 0)
|
||||
ev.data1 = KEY_MOUSEWHEELUP;
|
||||
ev.key = KEY_MOUSEWHEELUP;
|
||||
else
|
||||
ev.data1 = KEY_MOUSEWHEELDOWN;
|
||||
ev.key = KEY_MOUSEWHEELDOWN;
|
||||
D_PostEvent(&ev);
|
||||
break;
|
||||
|
||||
|
@ -271,7 +271,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0); //to quit while in-game
|
||||
ev.data1 = KEY_ESCAPE; //to exit network synchronization
|
||||
ev.key = KEY_ESCAPE; //to exit network synchronization
|
||||
ev.type = ev_keydown;
|
||||
D_PostEvent (&ev);
|
||||
return 0;
|
||||
|
|
|
@ -322,20 +322,20 @@ static inline VOID I_GetConsoleEvents(VOID)
|
|||
{
|
||||
case VK_ESCAPE:
|
||||
case VK_TAB:
|
||||
ev.data1 = KEY_NULL;
|
||||
ev.key = KEY_NULL;
|
||||
break;
|
||||
case VK_SHIFT:
|
||||
ev.data1 = KEY_LSHIFT;
|
||||
ev.key = KEY_LSHIFT;
|
||||
break;
|
||||
case VK_RETURN:
|
||||
entering_con_command = false;
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
|
||||
ev.key = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
|
||||
}
|
||||
if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
|
||||
{
|
||||
if (ev.data1 && ev.data1 != KEY_LSHIFT && ev.data1 != KEY_RSHIFT)
|
||||
if (ev.key && ev.key != KEY_LSHIFT && ev.key != KEY_RSHIFT)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WriteConsole(co, &input.Event.KeyEvent.uChar.UnicodeChar, 1, &t, NULL);
|
||||
|
@ -356,13 +356,13 @@ static inline VOID I_GetConsoleEvents(VOID)
|
|||
switch (input.Event.KeyEvent.wVirtualKeyCode)
|
||||
{
|
||||
case VK_SHIFT:
|
||||
ev.data1 = KEY_LSHIFT;
|
||||
ev.key = KEY_LSHIFT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ev.data1) D_PostEvent(&ev);
|
||||
if (ev.key) D_PostEvent(&ev);
|
||||
break;
|
||||
case MOUSE_EVENT:
|
||||
case WINDOW_BUFFER_SIZE_EVENT:
|
||||
|
@ -945,7 +945,7 @@ static void I_ShutdownMouse2(VOID)
|
|||
for (i = 0; i < MOUSEBUTTONS; i++)
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2MOUSE1 + i;
|
||||
event.key = KEY_2MOUSE1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -1135,14 +1135,14 @@ VOID I_GetSysMouseEvents(INT mouse_state)
|
|||
if ((mouse_state & (1 << i)) && !(old_mouse_state & (1 << i)))
|
||||
{
|
||||
event.type = ev_keydown;
|
||||
event.data1 = KEY_MOUSE1 + i;
|
||||
event.key = KEY_MOUSE1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
// check if button released
|
||||
if (!(mouse_state & (1 << i)) && (old_mouse_state & (1 << i)))
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_MOUSE1 + i;
|
||||
event.key = KEY_MOUSE1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1156,9 +1156,9 @@ VOID I_GetSysMouseEvents(INT mouse_state)
|
|||
if (xmickeys || ymickeys)
|
||||
{
|
||||
event.type = ev_mouse;
|
||||
event.data1 = 0;
|
||||
event.data2 = xmickeys;
|
||||
event.data3 = -ymickeys;
|
||||
event.key = 0;
|
||||
event.x = xmickeys;
|
||||
event.y = -ymickeys;
|
||||
D_PostEvent(&event);
|
||||
SetCursorPos(center_x, center_y);
|
||||
}
|
||||
|
@ -1240,7 +1240,7 @@ static void I_ShutdownMouse(void)
|
|||
for (i = 0; i < MOUSEBUTTONS; i++)
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_MOUSE1 + i;
|
||||
event.key = KEY_MOUSE1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
if (nodinput)
|
||||
|
@ -1281,7 +1281,7 @@ void I_GetMouseEvents(void)
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2MOUSE1 + i;
|
||||
event.key = KEY_2MOUSE1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -1289,9 +1289,9 @@ void I_GetMouseEvents(void)
|
|||
if (handlermouse2x || handlermouse2y)
|
||||
{
|
||||
event.type = ev_mouse2;
|
||||
event.data1 = 0;
|
||||
event.data2 = handlermouse2x<<1;
|
||||
event.data3 = -handlermouse2y<<1;
|
||||
event.key = 0;
|
||||
event.x = handlermouse2x<<1;
|
||||
event.y = -handlermouse2y<<1;
|
||||
handlermouse2x = 0;
|
||||
handlermouse2y = 0;
|
||||
|
||||
|
@ -1330,7 +1330,7 @@ getBufferedData:
|
|||
else
|
||||
event.type = ev_keyup; // Button up
|
||||
|
||||
event.data1 = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1;
|
||||
event.key = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
else if (rgdod[d].dwOfs == DIMOFS_X)
|
||||
|
@ -1342,9 +1342,9 @@ getBufferedData:
|
|||
{
|
||||
// z-axes the wheel
|
||||
if ((int)rgdod[d].dwData > 0)
|
||||
event.data1 = KEY_MOUSEWHEELUP;
|
||||
event.key = KEY_MOUSEWHEELUP;
|
||||
else
|
||||
event.data1 = KEY_MOUSEWHEELDOWN;
|
||||
event.key = KEY_MOUSEWHEELDOWN;
|
||||
event.type = ev_keydown;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
@ -1354,9 +1354,9 @@ getBufferedData:
|
|||
if (xmickeys || ymickeys)
|
||||
{
|
||||
event.type = ev_mouse;
|
||||
event.data1 = 0;
|
||||
event.data2 = xmickeys;
|
||||
event.data3 = -ymickeys;
|
||||
event.key = 0;
|
||||
event.x = xmickeys;
|
||||
event.y = -ymickeys;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -2395,14 +2395,14 @@ static VOID I_ShutdownJoystick(VOID)
|
|||
// emulate the up of all joystick buttons
|
||||
for (i = 0;i < JOYBUTTONS;i++)
|
||||
{
|
||||
event.data1 = KEY_JOY1+i;
|
||||
event.key = KEY_JOY1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
// emulate the up of all joystick hats
|
||||
for (i = 0;i < JOYHATS*4;i++)
|
||||
{
|
||||
event.data1 = KEY_HAT1+i;
|
||||
event.key = KEY_HAT1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -2410,7 +2410,7 @@ static VOID I_ShutdownJoystick(VOID)
|
|||
event.type = ev_joystick;
|
||||
for (i = 0;i < JOYAXISSET; i++)
|
||||
{
|
||||
event.data1 = i;
|
||||
event.key = i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -2460,14 +2460,14 @@ static VOID I_ShutdownJoystick2(VOID)
|
|||
// emulate the up of all joystick buttons
|
||||
for (i = 0;i < JOYBUTTONS;i++)
|
||||
{
|
||||
event.data1 = KEY_2JOY1+i;
|
||||
event.key = KEY_2JOY1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
// emulate the up of all joystick hats
|
||||
for (i = 0;i < JOYHATS*4;i++)
|
||||
{
|
||||
event.data1 = KEY_2HAT1+i;
|
||||
event.key = KEY_2HAT1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -2475,7 +2475,7 @@ static VOID I_ShutdownJoystick2(VOID)
|
|||
event.type = ev_joystick2;
|
||||
for (i = 0;i < JOYAXISSET; i++)
|
||||
{
|
||||
event.data1 = i;
|
||||
event.key = i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -2598,7 +2598,7 @@ acquire:
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_JOY1 + i;
|
||||
event.key = KEY_JOY1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -2618,7 +2618,7 @@ acquire:
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_HAT1 + i;
|
||||
event.key = KEY_HAT1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -2627,7 +2627,7 @@ acquire:
|
|||
|
||||
// send joystick axis positions
|
||||
event.type = ev_joystick;
|
||||
event.data1 = event.data2 = event.data3 = 0;
|
||||
event.key = event.x = event.y = 0;
|
||||
|
||||
if (Joystick.bGamepadStyle)
|
||||
{
|
||||
|
@ -2635,29 +2635,29 @@ acquire:
|
|||
if (JoyInfo.X)
|
||||
{
|
||||
if (js.lX < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.lX > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo.Y)
|
||||
{
|
||||
if (js.lY < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.lY > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo.X) event.data2 = js.lX; // x axis
|
||||
if (JoyInfo.Y) event.data3 = js.lY; // y axis
|
||||
if (JoyInfo.X) event.x = js.lX; // x axis
|
||||
if (JoyInfo.Y) event.y = js.lY; // y axis
|
||||
}
|
||||
|
||||
D_PostEvent(&event);
|
||||
#if JOYAXISSET > 1
|
||||
event.data1 = 1;
|
||||
event.data2 = event.data3 = 0;
|
||||
event.key = 1;
|
||||
event.x = event.y = 0;
|
||||
|
||||
if (Joystick.bGamepadStyle)
|
||||
{
|
||||
|
@ -2665,30 +2665,30 @@ acquire:
|
|||
if (JoyInfo.Z)
|
||||
{
|
||||
if (js.lZ < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.lZ > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo.Rx)
|
||||
{
|
||||
if (js.lRx < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.lRx > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo.Z) event.data2 = js.lZ; // z axis
|
||||
if (JoyInfo.Rx) event.data3 = js.lRx; // rx axis
|
||||
if (JoyInfo.Z) event.x = js.lZ; // z axis
|
||||
if (JoyInfo.Rx) event.y = js.lRx; // rx axis
|
||||
}
|
||||
|
||||
D_PostEvent(&event);
|
||||
#endif
|
||||
#if JOYAXISSET > 2
|
||||
event.data1 = 2;
|
||||
event.data2 = event.data3 = 0;
|
||||
event.key = 2;
|
||||
event.x = event.y = 0;
|
||||
|
||||
if (Joystick.bGamepadStyle)
|
||||
{
|
||||
|
@ -2696,53 +2696,53 @@ acquire:
|
|||
if (JoyInfo.Rx)
|
||||
{
|
||||
if (js.lRy < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.lRy > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo.Rz)
|
||||
{
|
||||
if (js.lRz < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.lRz > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo.Ry) event.data2 = js.lRy; // ry axis
|
||||
if (JoyInfo.Rz) event.data3 = js.lRz; // rz axis
|
||||
if (JoyInfo.Ry) event.x = js.lRy; // ry axis
|
||||
if (JoyInfo.Rz) event.y = js.lRz; // rz axis
|
||||
}
|
||||
|
||||
D_PostEvent(&event);
|
||||
#endif
|
||||
#if JOYAXISSET > 3
|
||||
event.data1 = 3;
|
||||
event.data2 = event.data3 = 0;
|
||||
event.key = 3;
|
||||
event.x = event.y = 0;
|
||||
if (Joystick.bGamepadStyle)
|
||||
{
|
||||
// gamepad control type, on or off, live or die
|
||||
if (JoyInfo.U)
|
||||
{
|
||||
if (js.rglSlider[0] < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.rglSlider[0] > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo.V)
|
||||
{
|
||||
if (js.rglSlider[1] < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.rglSlider[1] > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo.U) event.data2 = js.rglSlider[0]; // U axis
|
||||
if (JoyInfo.V) event.data3 = js.rglSlider[1]; // V axis
|
||||
if (JoyInfo.U) event.x = js.rglSlider[0]; // U axis
|
||||
if (JoyInfo.V) event.y = js.rglSlider[1]; // V axis
|
||||
}
|
||||
D_PostEvent(&event);
|
||||
#endif
|
||||
|
@ -2842,7 +2842,7 @@ acquire:
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2JOY1 + i;
|
||||
event.key = KEY_2JOY1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -2862,7 +2862,7 @@ acquire:
|
|||
event.type = ev_keydown;
|
||||
else
|
||||
event.type = ev_keyup;
|
||||
event.data1 = KEY_2HAT1 + i;
|
||||
event.key = KEY_2HAT1 + i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -2871,7 +2871,7 @@ acquire:
|
|||
|
||||
// send joystick axis positions
|
||||
event.type = ev_joystick2;
|
||||
event.data1 = event.data2 = event.data3 = 0;
|
||||
event.key = event.x = event.y = 0;
|
||||
|
||||
if (Joystick2.bGamepadStyle)
|
||||
{
|
||||
|
@ -2879,29 +2879,29 @@ acquire:
|
|||
if (JoyInfo2.X)
|
||||
{
|
||||
if (js.lX < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.lX > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo2.Y)
|
||||
{
|
||||
if (js.lY < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.lY > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo2.X) event.data2 = js.lX; // x axis
|
||||
if (JoyInfo2.Y) event.data3 = js.lY; // y axis
|
||||
if (JoyInfo2.X) event.x = js.lX; // x axis
|
||||
if (JoyInfo2.Y) event.y = js.lY; // y axis
|
||||
}
|
||||
|
||||
D_PostEvent(&event);
|
||||
#if JOYAXISSET > 1
|
||||
event.data1 = 1;
|
||||
event.data2 = event.data3 = 0;
|
||||
event.key = 1;
|
||||
event.x = event.y = 0;
|
||||
|
||||
if (Joystick2.bGamepadStyle)
|
||||
{
|
||||
|
@ -2909,30 +2909,30 @@ acquire:
|
|||
if (JoyInfo2.Z)
|
||||
{
|
||||
if (js.lZ < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.lZ > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo2.Rx)
|
||||
{
|
||||
if (js.lRx < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.lRx > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo2.Z) event.data2 = js.lZ; // z axis
|
||||
if (JoyInfo2.Rx) event.data3 = js.lRx; // rx axis
|
||||
if (JoyInfo2.Z) event.x = js.lZ; // z axis
|
||||
if (JoyInfo2.Rx) event.y = js.lRx; // rx axis
|
||||
}
|
||||
|
||||
D_PostEvent(&event);
|
||||
#endif
|
||||
#if JOYAXISSET > 2
|
||||
event.data1 = 2;
|
||||
event.data2 = event.data3 = 0;
|
||||
event.key = 2;
|
||||
event.x = event.y = 0;
|
||||
|
||||
if (Joystick2.bGamepadStyle)
|
||||
{
|
||||
|
@ -2940,53 +2940,53 @@ acquire:
|
|||
if (JoyInfo2.Rx)
|
||||
{
|
||||
if (js.lRy < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.lRy > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo2.Rz)
|
||||
{
|
||||
if (js.lRz < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.lRz > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo2.Ry) event.data2 = js.lRy; // ry axis
|
||||
if (JoyInfo2.Rz) event.data3 = js.lRz; // rz axis
|
||||
if (JoyInfo2.Ry) event.x = js.lRy; // ry axis
|
||||
if (JoyInfo2.Rz) event.y = js.lRz; // rz axis
|
||||
}
|
||||
|
||||
D_PostEvent(&event);
|
||||
#endif
|
||||
#if JOYAXISSET > 3
|
||||
event.data1 = 3;
|
||||
event.data2 = event.data3 = 0;
|
||||
event.key = 3;
|
||||
event.x = event.y = 0;
|
||||
if (Joystick2.bGamepadStyle)
|
||||
{
|
||||
// gamepad control type, on or off, live or die
|
||||
if (JoyInfo2.U)
|
||||
{
|
||||
if (js.rglSlider[0] < -(JOYAXISRANGE/2))
|
||||
event.data2 = -1;
|
||||
event.x = -1;
|
||||
else if (js.rglSlider[0] > JOYAXISRANGE/2)
|
||||
event.data2 = 1;
|
||||
event.x = 1;
|
||||
}
|
||||
if (JoyInfo2.V)
|
||||
{
|
||||
if (js.rglSlider[1] < -(JOYAXISRANGE/2))
|
||||
event.data3 = -1;
|
||||
event.y = -1;
|
||||
else if (js.rglSlider[1] > JOYAXISRANGE/2)
|
||||
event.data3 = 1;
|
||||
event.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// analog control style, just send the raw data
|
||||
if (JoyInfo2.U) event.data2 = js.rglSlider[0]; // U axis
|
||||
if (JoyInfo2.V) event.data3 = js.rglSlider[1]; // V axis
|
||||
if (JoyInfo2.U) event.x = js.rglSlider[0]; // U axis
|
||||
if (JoyInfo2.V) event.y = js.rglSlider[1]; // V axis
|
||||
}
|
||||
D_PostEvent(&event);
|
||||
#endif
|
||||
|
@ -3194,7 +3194,7 @@ INT32 I_GetKey(void)
|
|||
ev = &events[eventtail];
|
||||
eventtail = (eventtail+1) & (MAXEVENTS-1);
|
||||
if (ev->type == ev_keydown || ev->type == ev_console)
|
||||
return ev->data1;
|
||||
return ev->key;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -3308,7 +3308,7 @@ static VOID I_GetKeyboardEvents(VOID)
|
|||
if (!appActive && RepeatKeyCode) // Stop when lost focus
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = RepeatKeyCode;
|
||||
event.key = RepeatKeyCode;
|
||||
D_PostEvent(&event);
|
||||
RepeatKeyCode = 0;
|
||||
}
|
||||
|
@ -3363,9 +3363,9 @@ getBufferedData:
|
|||
|
||||
ch = rgdod[d].dwOfs & 0xFF;
|
||||
if (ASCIINames[ch])
|
||||
event.data1 = ASCIINames[ch];
|
||||
event.key = ASCIINames[ch];
|
||||
else
|
||||
event.data1 = 0x80;
|
||||
event.key = 0x80;
|
||||
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
@ -3378,7 +3378,7 @@ getBufferedData:
|
|||
// delay is tripled for first repeating key
|
||||
RepeatKeyTics = hacktics + (KEY_REPEAT_DELAY*3);
|
||||
if (event.type == ev_keydown) // use the last event!
|
||||
RepeatKeyCode = event.data1;
|
||||
RepeatKeyCode = event.key;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3386,7 +3386,7 @@ getBufferedData:
|
|||
if (RepeatKeyCode && hacktics - RepeatKeyTics > KEY_REPEAT_DELAY)
|
||||
{
|
||||
event.type = ev_keydown;
|
||||
event.data1 = RepeatKeyCode;
|
||||
event.key = RepeatKeyCode;
|
||||
D_PostEvent(&event);
|
||||
|
||||
RepeatKeyTics = hacktics;
|
||||
|
|
|
@ -212,7 +212,7 @@ static void Y_IntermissionTokenDrawer(void)
|
|||
calc = (lowy - y)*2;
|
||||
|
||||
if (calc > 0)
|
||||
V_DrawCroppedPatch(32<<FRACBITS, y<<FRACBITS, FRACUNIT/2, 0, tokenicon, 0, 0, tokenicon->width, calc);
|
||||
V_DrawCroppedPatch(32<<FRACBITS, y<<FRACBITS, FRACUNIT/2, FRACUNIT/2, 0, tokenicon, NULL, 0, 0, tokenicon->width<<FRACBITS, calc<<FRACBITS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -430,7 +430,7 @@ void Y_IntermissionDrawer(void)
|
|||
else if (bgtile)
|
||||
V_DrawPatchFill(bgtile);
|
||||
|
||||
LUAh_IntermissionHUD(intertype == int_spec && stagefailed);
|
||||
LUA_HUDHOOK(intermission);
|
||||
if (!LUA_HudEnabled(hud_intermissiontally))
|
||||
goto skiptallydrawer;
|
||||
|
||||
|
|
Loading…
Reference in a new issue