Saturn v7 #135

Merged
alufolie91 merged 566 commits from Saturn-Next into Saturn 2024-09-15 13:02:42 +02:00
136 changed files with 10780 additions and 9090 deletions

No files matched your search

+346
View File
@@ -0,0 +1,346 @@
#!/bin/bash
set -e # Enable auto-exit for debugging :))
# Make Linux AppImage program data
# https://docs.appimage.org/reference/appdir.html
# PWD: {repo_root}/build
# See deployer.sh for usage
# Terminal stuff
RESET="$(tput sgr0)" #"\e[0m" # Resets terminal colors
# Colors for various information types
FAILURE="$(tput setaf 1)" #"\e[91m"
SUCCESS="$(tput setaf 2)" #"\e[92m"
NOTICE="$(tput setaf 3)" #"\e[93m"
VERBOSE="$(tput setaf 4)" #"\e[94m"
verbosity=0 # By default don't print anything unless it's *ultra* important.
quiet=0 # Also don't print anything if they supplied the quiet argument
# URL from which to download appimagetool if there isn't one available in your $PATH
# at time of writing only aarch64, armhf, i686, and x86_64 versions are available via this method
# in those cases, and honestly even outside of those cases, it's better to just put a working one in your $PATH yourself..
url="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-$(uname -m).AppImage"
# A whitelist of libraries to include into SRB2's AppImage if SRB2 is dynamically linked.
# please don't add a newline at the end of this or i will cry :(
libraryWhitelist="
libbacktrace
libnsl
libSDL2
libSDL2_mixer
libgme
libopenmpt
libpng
libfluidsynth
libpulse
libmodplug
libvorbisfile
libopusfile
libFLAC
libmad
libmpg123
libvorbis
libpulsecommon
libsndfile
libsndio
libogg
libvorbisenc
libjson
libreadline
libwrap
libtinfo
libtirpc
libpng16"
# these kinda look like macros don't they
function print { (( "$quiet" == 0 )) && echo "$@" || :; } # echo if not quiet
function coloredText { printf "$1"; print "${@:2}"; printf "$RESET"; } # use print to inherit quiet
function success { coloredText "$SUCCESS" "$@"; } # use coloredText to inherit quiet
function important { coloredText "$NOTICE" "$@"; } # use coloredText to inherit quiet
function verboseOnly { (( "$verbosity" >= $1 )) && (coloredText "$VERBOSE" "${@:2}") || :; } # use coloredText to inherit quiet
# Parses an argument with a single dash
function parseSingleDashArg() {
while read -n 1 char; do
if [[ "$char" == '-' || "$char" == '' ]]; then
:
elif [[ "$char" == 'h' ]]; then
helppassed=1
elif [[ "$char" == 'q' ]]; then
quiet=1
elif [[ "$char" == 'v' ]]; then
verbosity="$((verbosity + 1))"
elif [[ "$char" == 'd' ]]; then
dry=1
elif [[ "$char" == 's' ]]; then
small=1
else
echo "$0: invalid option -- '$1'"
echo "Try '$0 --help' for more information."
return 1
fi
done <<<"$1"
}
# Simple help argument checker.
currentarg=1; # Which argument is --help...
# For $arg in the argument array...
for arg in "$@"; do
# Is it a help argument?
if [[ "$arg" == "--help" ]]; then
helppassed=1; # Help is passed, set $helppassed!
set -- "${@:1:$currentarg-1}" "${@:$currentarg+1}" # Remove argument from list
elif [[ "$arg" == "--quiet" ]]; then
quiet=1
set -- "${@:1:$currentarg-1}" "${@:$currentarg+1}"
elif [[ "$arg" == "--verbose" ]]; then
verbosity="$((verbosity + 1))" # Increase verbosity!
set -- "${@:1:$currentarg-1}" "${@:$currentarg+1}"
elif [[ "$arg" == "--dry" ]]; then
dry=1; # Show parameters instead of using them.
set -- "${@:1:$currentarg-1}" "${@:$currentarg+1}"
elif [[ "$arg" == "--small" ]]; then
small=1; # Don't copy assets to save on bandwidth.
set -- "${@:1:$currentarg-1}" "${@:$currentarg+1}"
elif [[ ! "$arg" == *'--'* && "$arg" == *'-'* ]]; then
parseSingleDashArg "$arg"
if [[ "$?" == 0 ]]; then
set -- "${@:1:$currentarg-1}" "${@:$currentarg+1}" # Remove argument from list
fi
elif [[ $arg == *'--'* ]]; then
print "$0: invalid option -- '$1'"
print "Try '$0 --help' for more information."
return 1
else
currentarg="$((currentarg+1))" # Increment current argument number otherwise...
fi
done
important "SRB2Kart AppImage Packager v1.0 modified for kart by NepDisk."
important "Orignal for SRB2 my mazmazz and Golden."
# Get root directory from the full path of this script.
__ROOT_DIR="$3"
if [[ -z "$3" ]]; then
# finds out where this script is and goes to that directory and goes up one for the root
scriptdir="$(dirname "${BASH_SOURCE[0]}")"
scriptbase="$(basename "${BASH_SOURCE[0]}")"
__ROOT_DIR="$(cd "$scriptdir" && pwd -P)"
fi
# If it starts with '.', put the current working directory behind it so things work.
if [[ "$__ROOT_DIR" == '.' || "$__ROOT_DIR" == '..' ]]; then
__ROOT_DIR="$PWD/$__ROOT_DIR"
fi
# Set up defaults
__PROGRAM_NAME="${PROGRAM_NAME:-"SRB2Kart Saturn"}"
__PROGRAM_DESCRIPTION="${PROGRAM_DESCRIPTION:-"Modded version of SRB2kart with more features."}"
__PROGRAM_FILENAME="${PROGRAM_FILENAME:-"lsdl2srb2kart"}"
__PROGRAM_ASSETS="${PROGRAM_ASSETS:-"$__ROOT_DIR/assets/installer"}"
__BUILD_DIR="${1:-"$__ROOT_DIR/bin"}"
__OUTPUT_FILENAME="${2:-"$__PROGRAM_FILENAME.AppImage"}"
__APPIMAGETOOL="${4:-"appimagetool"}"
if (! command -v "$__APPIMAGETOOL" &> /dev/null); then
__APPIMAGETOOL=
fi
# Stuff that prints and exits.
# Prints setup text using method given by arguments.
# Example: printSetup "print" # print "Setup for AppImage...
function printSetup {
$@ "Setup for AppImage in BUILD_DIR: '$__BUILD_DIR'..."
$@ "With the OUTPUT_FILENAME: '$__OUTPUT_FILENAME'"
$@ "And SRB2 Repository Root ROOT_DIR: '$__ROOT_DIR'"
$@ "Using APPIMAGETOOL: '$([ -z "$__APPIMAGETOOL" ] && echo '(download)' || echo $__APPIMAGETOOL)'"
$@ ""
$@ "This should be run from a Makefile or from the directory of the build. If it is not, then change to that directory or specify that directory as an argument."
$@ "If ROOT_DIR isn't SRB2's repository root, specify that as an argument too."
$@ "Make must have built the program before you run this script."
$@ ""
$@ "Make sure these Environment Variables are correct."
$@ "If not, then enter: export PROGRAM_VARIABLE=value"
$@ "PROGRAM_NAME: $__PROGRAM_NAME"
$@ "PROGRAM_DESCRIPTION: $__PROGRAM_DESCRIPTION"
$@ "PROGRAM_FILENAME: $__PROGRAM_FILENAME"
$@ "PROGRAM_ASSETS: $__PROGRAM_ASSETS"
}
if [[ "$helppassed" ]]; then
print "Usage: $(basename "$0") [OPTION]... [BUILD_DIR] [OUTPUT_NAME] [ROOT_DIR] [APPIMAGETOOL]"
print "Packages a SRB2 binary into an AppImage."
print "OPTIONs may be included anywhere within the arguments."
print ""
print "Arguments:"
print " -h, --help display this help and exit."
print " -q, --quiet don't display any text."
print " -v, --verbose make commands more verbose, will always print."
print " -s, --small don't copy SRB2 assets to save on bandwidth."
print " parameters regardless of --dry."
print " -d, --dry print parameters and exit."
print ""
if (( "$verbosity" > 0 )) || [[ "$dry" ]]; then
printSetup "print"
else
print "This should be run from a Makefile or from the directory of the build."
print "Make must have built the program before you run this script."
fi
exit;
fi
if (( "$verbosity" > 0 )) || [[ "$dry" ]]; then
printSetup "verboseOnly" "0"
verboseOnly 0 ""
if [[ "$dry" ]]; then
set -n # Enable debug mode and verbose for dry run.
fi
fi
# End stuff that prints and exits.
if (( "$verbosity" >= 4 )); then
set -v # Really verbose? Print *everything*!
fi
# Define AppDir structure
mkdir -p "$__BUILD_DIR/AppDir/usr/bin"
mkdir -p "$__BUILD_DIR/AppDir/lib"
mkdir -p "$__BUILD_DIR/AppDir/usr/share/applications"
mkdir -p "$__BUILD_DIR/AppDir/usr/share/icons/hicolor/256x256/apps"
# Copy program data
if [[ ! $small ]]; then
verboseOnly 1 "Packaging program assets..."
cp -r "$__PROGRAM_ASSETS"/* "$__BUILD_DIR/AppDir/usr/bin/"
cp -r "$__BUILD_DIR/$__PROGRAM_FILENAME" "$__BUILD_DIR/AppDir/usr/bin"
else
verboseOnly 1 "Skipping program asset packing, --small or -s passed..."
fi
verboseOnly 1 "Packaging SRB2..."
verboseOnly 1 "Assuming executable name $__PROGRAM_FILENAME"
cp -r "$__BUILD_DIR/$__PROGRAM_FILENAME" "$__BUILD_DIR/AppDir/usr/bin"
# Copy required dependencies, but only if the program is dynamically linked.
verboseOnly 1 "Testing if this build is dynamically linked..."
set +e # Disable auto-exit for ldd.
srb2Libraries="$(ldd "$__BUILD_DIR/$__PROGRAM_FILENAME")"
exitcode="$?"
set -e # Enable it again!
if (( $exitcode == 0 )); then
verboseOnly 1 "This build *is* dynamically linked! Packaging dependencies."
# read the dynamic libraries of srb2, trim off beginning whitespace, and get the third field seperated by spaces
# this gives us a newline-seperated list of libraries with their full paths.
srb2Libraries="$(echo "$srb2Libraries" | cut -f 2 | cut -d ' ' -f 3)"
# remove any extraneous newlines around the string
libraryWhitelist="$(echo $libraryWhitelist | head -c -1 | tr ' ' '\n')"
# replace e.g. 'abc' with '(/abc\b)', and replace newlines with '|'.
# this converts it into a grep regular expression to check for any whitelisted library names.
libraryWhitelist="$(printf "%s" "$libraryWhitelist" | sed 's|.*|(/\0\\b)|' | tr '\n' '|')"
# grab only the entries that match the regex
__LDD_LIST="$(printf "%s" "$srb2Libraries" | grep -E "$libraryWhitelist")"
# use echo to convert the newline-seperated list into an argument list
__LDD_LIST="$(echo $__LDD_LIST)"
# read into an array because i can't be bothered iterating the lines of a string today
# there's so many other things in this file that'd need to be adjusted to be POSIX-compliant anyway
IFS=' ' read -r -a paths <<< "$__LDD_LIST"
for path in "${paths[@]}"; do
if [ -f "$path" ]; then
verboseOnly 2 "Packaging dependency $(basename "$path")..."
cp "$path" $__BUILD_DIR/AppDir/lib/
else
verboseOnly 2 "Dependency $(basename "$path") not found"
fi
done
else
verboseOnly 1 "This SRB2 build is statically linked, skipping dependency packing."
fi
cd "$__BUILD_DIR/AppDir"
# Copy icons
verboseOnly 1 "Packaging resources..."
cp "$__ROOT_DIR/srb2.png" "./usr/share/icons/hicolor/256x256/apps/$__PROGRAM_FILENAME.png"
ln -sf "./usr/share/icons/hicolor/256x256/apps/$__PROGRAM_FILENAME.png" "./.DirIcon"
ln -sf "./usr/share/icons/hicolor/256x256/apps/$__PROGRAM_FILENAME.png" "./$__PROGRAM_FILENAME.png"
# Make desktop descriptor
cat > "./usr/share/applications/$__PROGRAM_FILENAME.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=$__PROGRAM_NAME
Comment=$__PROGRAM_DESCRIPTION
Icon=$__PROGRAM_FILENAME
Exec=AppRun %F
Categories=Game;
EOF
ln -sf "./usr/share/applications/$__PROGRAM_FILENAME.desktop" "./$__PROGRAM_FILENAME.desktop"
# Make entry point
echo -e '#!'"$(dirname "$SHELL")/sh" > ./AppRun
echo -e 'HERE="$(dirname "$(readlink -f "${0}")")"' >> ./AppRun
echo -e 'SRB2WADDIR=$HERE/usr/bin LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HERE/lib exec $HERE/usr/bin/'"$__PROGRAM_FILENAME"' "$@"' >> ./AppRun
chmod +x ./AppRun
cd .. # now in $__BUILD_DIR
# Package AppImage
if [ -z "$__APPIMAGETOOL" ]; then
verboseOnly 1 "No valid appimagetool path given or detected, downloading appimagetool..."
# Print notice for internet connection.
important "If the command hangs here, check your internet connection, or download appimagetool and add it to your \$PATH and try compiling again."
(( "$verbosity" >= 3 )) && wget "$url" || wget -q "$url"
APPIMAGETOOL="./$(basename "$url")"
chmod a+x "$APPIMAGETOOL"
else
verboseOnly 1 "appimagetool path given or detected, no download required."
APPIMAGETOOL="$__APPIMAGETOOL"
fi
verboseOnly 1 "Packing AppImage $__OUTPUT_FILENAME"
if (( verbosity >= 3 )); then
"$APPIMAGETOOL" ./AppDir "$__OUTPUT_FILENAME"
elif (( verbosity >= 2 )); then
"$APPIMAGETOOL" ./AppDir "$__OUTPUT_FILENAME" >/dev/null
else
"$APPIMAGETOOL" ./AppDir "$__OUTPUT_FILENAME" >/dev/null 2>&1
fi
success "AppImage ready!"
verboseOnly 1 "Cleaning up files..."
rm -r ./AppDir
if [ -z "$__APPIMAGETOOL" ]; then
rm "$APPIMAGETOOL"
fi
cd "$__ROOT_DIR" # snap back to reality
+97
View File
@@ -52,6 +52,70 @@ Returns the displayplayer's HUD color.
Returns true if colorization is enabled, false otherwise.
## v.interpolate(true)
Enables HUD interpolation. Each call to a drawing function will have its coordinates interpolated
by assigning an unique ID to every call.
For example, three successive calls to `v.draw` will each have their own ID and interpolation offsets.
Pass `true` to enable interpolation, `false` to disable.
Alternatively, pass a number to enable interpolation with the specified tag.
Tags allow HUD items drawn by the same call to a drawing function to be differentiated.
Valid tags range from 0-255.
For example, when iterating players, use a unique tag for each player to avoid artifacting:
```lua
for p in players.iterate do
-- enable interpolation, using player numbers as the tag
-- every draw will have different interp offsets per player
v.interpolate(#p)
-- doesn't matter for unconditional draws like this one...
v.draw(...)
-- but it does matter if there's a condition!
-- without tags, this patch would warp between players
-- whenever their `someVar` changes
if p.someVar then v.draw(...) end
end
-- don't want interpolation anymore? then disable it
v.interpolate(false)
```
NOTE: The default tag for `true` is 0.
## v.interpLatch(true)
Enables interpolation offset latching. The next call to a drawing function will have its lerp offsets
saved and reused for all following draw calls. Disable with `false` when done.
Interpolation cannot easily "snap" between two points; latching can help overcome this by manually
setting the lerp offsets.
```lua
v.interpolate(true)
-- X coordinate for the HUD item
-- every so often, this will wrap around to zero
local x = (leveltime*4) % 256
-- draw an interpolated patch, but... when X rolls back to zero,
-- the patch will slide all the way across the screen!
v.draw(x, 100, ...)
-- this is where interpLatch comes into play
-- enable latching, then draw an invisible patch,
-- moving at the same speed as the visible patch
-- the exact coordinates don't matter, it just has to move at the right speed
v.interpLatch(true)
v.draw(leveltime*4, 0, v.cachePatch("K_TRNULL"))
-- now we can draw the patch again, and when X becomes zero,
-- it'll snap right back without sliding across the screen
v.draw(x, 150, ...)
-- don't forget to turn off latching!
v.interpLatch(false)
```
When using a custom string drawer, enable this mode to avoid interpolation artifacting when the string changes.
## mobj.spritexscale, mobj.spriteyscale, mobj.spritexoffset, mobj.spriteyoffset, mobj.rollangle, mobj.sloperoll, mobj.rollmodel fields
Same fields as in SRB2 2.2
@@ -66,3 +130,36 @@ if rawget(_G, "S_StopSoundByNum") ~= nil then
... -- Can use it
end
```
## addHook("ServerJoin", function())
ServerJoin hook called when client joins server (starting a listen server also calls it for host).
Generally it was made to make loading custom config files less hacky, but can be used for anything else too.
## player.viewrollangle field
Returns player's current view roll angle for the Screen Tilting feature, useful for HUD elements.
## G_SetPlayerGamepadIndicatorColor(player, skincolor)
Set a custom color for Supported Gamepads with RGB LED functionality.
To be used with Displayplayers.
Only takes Skincolors.
Best to be used in a Loop to ensure the color wont get overwritten by the game.
## G_PlayerDeviceRumble(player, low_strength, high_strength, -optional- duration)
Add Gamepad Rumble support for things.
To be used with Displayplayers.
Duration is in milliseconds and is optional to set, default value is 84ms.
# Other changes
## P_PlayRinglossSound(source, damager)
Add optional `damager` argument (should be `mobj_t`), which causes hurt sound also play for damager
if `karthitemdialog` option is enabled
## K_PlayHitEmSound(mobj, victim)
Add optional `victim` argument (should be a player's `mobj_t`), which causes "hit em" sound to be
delayed and played for victim too if `karthitemdialog` option is enabled
+1 -1
View File
@@ -1 +1 @@
/lsdlsrb2
/lsdl2srb2kart
+2 -2
View File
@@ -167,6 +167,7 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c
p_tick.c
p_user.c
k_director.c
k_kart.c
i_time.c
@@ -180,6 +181,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h
p_spec.h
p_tick.h
k_director.h
k_kart.h
)
@@ -465,7 +467,6 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
@@ -483,7 +484,6 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_drv.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glob.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h
+40 -2
View File
@@ -106,6 +106,8 @@ ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
else # if you on the *nix
NOUPX=1
system:=$(shell uname -s)
ifeq ($(system),Linux)
@@ -205,6 +207,18 @@ USE_FBO_OGL=1
endif
endif
ifndef NONET
ifndef NOSATURNSYNCH
DOSATURNSYNCH=1
ifndef NOSATURNJOIN
DOSATURNJOIN=1
endif
#ifndef NOSATURNPAK
#DOSATURNPAK=1
#endif
endif
endif
ifdef MINGW
include win32/Makefile.cfg
endif #ifdef MINGW
@@ -278,12 +292,12 @@ ifdef NOHW
OPTS+=-DNOHW
else
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o \
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o \
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o $(OBJDIR)/hw_shaders.o
endif
OPTS += -DCOMPVERSION
OPTS += -DCOMPVERSION -fwrapv
ifndef NONX86
ifndef GCC29
@@ -384,6 +398,18 @@ OPTS+=-DUSE_FBO_OGL
endif
endif
ifndef NONET
ifndef NOSATURNSYNCH
OPTS+=-DDOSATURNSYNCH
ifndef NOSATURNJOIN
OPTS+=-DDOSATURNJOIN
endif
#ifndef NOSATURNPAK
#OPTS+=-DDOSATURNPAK
#endif
endif
endif
ifdef HAVE_MINIUPNPC
ifdef NONET
HAVE_MINIUPNPC=''
@@ -492,6 +518,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/hu_stuff.o \
$(OBJDIR)/y_inter.o \
$(OBJDIR)/st_stuff.o \
$(OBJDIR)/k_director.o \
$(OBJDIR)/k_kart.o \
$(OBJDIR)/m_aatree.o \
$(OBJDIR)/m_anigif.o \
@@ -630,6 +657,17 @@ ifndef NOUPX
-$(UPX) $(UPX_OPTS) $(BIN)/$(EXENAME)
endif
endif
ifdef APPIMAGE
@echo Building AppImage...
ifdef APPIMAGE_NOASSETS
$(.)../AppImage_build.sh --small --quiet $(BIN)/
else
$(.)../AppImage_build.sh -q $(BIN)/
endif
@echo AppImage build complete, please look for $(EXENAME).AppImage in $(BIN)
endif
@echo Build is done, please look for $(EXENAME) in $(BIN), \(checking for post steps\)
reobjdump:
+12 -7
View File
@@ -12,7 +12,7 @@
# to avoid a false positive with the version detection...
SUPPORTED_GCC_VERSIONS:=\
141 14\
142 141 140 14\
132 131 130 13\
123 122 121 120 12\
114 113 112 111 110 11\
@@ -24,7 +24,7 @@ SUPPORTED_GCC_VERSIONS:=\
55 54 53 52 51 50\
49 48 47 46 45 44 43 42 41 40
LATEST_GCC_VERSION=14.1
LATEST_GCC_VERSION=14.2.1
# gcc or g++
ifdef PREFIX
@@ -78,12 +78,20 @@ ifeq (,$(filter GCC%,$(.VARIABLES)))
endif
endif
ifdef GCC141
ifdef GCC142
GCC141=1
endif
ifdef GCC141
GCC140=1
endif
ifdef GCC14
GCC14=1
GCC140=1
endif
ifdef GCC140
GCC132=1
endif
ifdef GCC132
@@ -437,9 +445,6 @@ endif
ifdef GCC44
WFLAGS+=-Wno-error=array-bounds
endif
ifdef GCC45
opts+=-fwrapv
endif
ifdef GCC46
WFLAGS+=-Wno-error=suggest-attribute=noreturn
endif
+3
View File
@@ -1015,6 +1015,9 @@ static inline void AM_drawPlayers(void)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo)
continue;
p = &players[i];
if (p->skincolor > 0)
+109 -8
View File
@@ -43,8 +43,12 @@
#ifdef HAVE_THREADS
I_mutex con_mutex;
# define Lock_state() I_lock_mutex(&con_mutex)
# define Unlock_state() I_unlock_mutex(con_mutex)
// g_in_exiting_signal_handler is an evil hack
// to avoid infinite SIGABRT recursion in the signal handler
// due to poisoned locks or mach-o kernel not supporting locks in signals
// or something like that. idk
# define Lock_state() if (!g_in_exiting_signal_handler) { I_lock_mutex(&con_mutex); }
# define Unlock_state() if (!g_in_exiting_signal_handler) { I_unlock_mutex(con_mutex); }
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
@@ -846,9 +850,36 @@ static void CON_InputAddString(const char *c)
Unlock_state();
}
static void CON_InputDel(size_t start, size_t end)
{
size_t len;
Lock_state();
len = (end - start);
if (end != input_len)
memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-end);
memset(&inputlines[inputline][input_len - len], 0, len);
input_len -= len;
if (input_sel >= end)
input_sel -= len;
else if (input_sel > start)
input_sel = start;
if (input_cur >= end)
input_cur -= len;
else if (input_cur > start)
input_cur = start;
Unlock_state();
}
static void CON_InputDelSelection(void)
{
size_t start, end, len;
size_t start, end;
Lock_state();
@@ -862,18 +893,56 @@ static void CON_InputDelSelection(void)
start = input_cur;
end = input_sel;
}
len = (end - start);
if (end != input_len)
memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-end);
memset(&inputlines[inputline][input_len - len], 0, len);
CON_InputDel(start, end);
input_len -= len;
input_sel = input_cur = start;
Unlock_state();
}
static void CON_ToWordEnd(boolean move_sel)
{
Lock_state();
// Skip spaces
while (input_cur < input_len && isspace(inputlines[inputline][input_cur]))
++input_cur;
// Skip word
while (input_cur < input_len && !isspace(inputlines[inputline][input_cur]))
++input_cur;
if (move_sel) input_sel = input_cur;
Unlock_state();
}
static void CON_ToWordBegin(boolean move_sel)
{
Lock_state();
// Hack, always move back 1 character if possible so if we press ctrl-left at a word beginning
// we move to previous word
if (input_cur) --input_cur;
// Skip spaces
while (input_cur && isspace(inputlines[inputline][input_cur]))
--input_cur;
// Skip word
while (input_cur && !isspace(inputlines[inputline][input_cur]))
--input_cur;
// Unless we reached beginning of line, we're pointing at a space before word, so move cursor
// forward to fix that
if (input_cur) ++input_cur;
if (move_sel) input_sel = input_cur;
Unlock_state();
}
static void CON_InputAddChar(char c)
{
if (input_len >= CON_MAXPROMPTCHARS-1)
@@ -1051,6 +1120,38 @@ boolean CON_Responder(event_t *ev)
completion[0] = 0;
return true;
}
else if (key == 'w' || key == 'W')
{
size_t word_start, word_end, i;
word_end = i = input_cur;
// Unless we're pointing at the beginning of line, decrement i so we only start
// removing symbols that come before the cursor
if (i) --i;
// We might be pointing to spaces, skip them first
while (i && isspace(inputlines[inputline][i]))
--i;
// Now skip the "word"
while (i && !isspace(inputlines[inputline][i]))
--i;
// Unless we reached beginning of line, i is pointing at first space that was found
// before word start, and we don't want to remove it
if (i) ++i;
word_start = i;
if (word_start != word_end)
CON_InputDel(word_start, word_end);
return true;
}
else if (key == KEY_RIGHTARROW)
CON_ToWordEnd(!shiftdown);
else if (key == KEY_LEFTARROW)
CON_ToWordBegin(!shiftdown);
// Select all
if (key == 'a' || key == 'A')
+388 -69
View File
@@ -10,6 +10,7 @@
/// \file d_clisrv.c
/// \brief SRB2 Network game communication and protocol, all OS independent parts.
#include "doomdef.h"
#include <time.h>
#ifdef __GNUC__
#include <unistd.h> //for unlink
@@ -23,6 +24,7 @@
#include "d_netfil.h" // fileneedednum
#include "d_main.h"
#include "g_game.h"
#include "m_menu.h" // M_ClearMenus
#include "hu_stuff.h"
#include "keys.h"
#include "g_input.h" // JOY1
@@ -75,6 +77,8 @@
#define MAX_REASONLENGTH 30
#define FORCECLOSE 0x8000
static long long unsigned packetstat[NUMPACKETTYPE+1] = {0};
boolean server = true; // true or false but !server == client
#define client (!server)
boolean nodownload = false;
@@ -89,6 +93,10 @@ UINT8 playernode[MAXPLAYERS];
// The actual timeout will be longer depending on the savegame length
tic_t jointimeout = (3*TICRATE);
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
#ifdef SATURNSYNCH
static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again?
#endif
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
UINT16 pingmeasurecount = 1;
@@ -121,6 +129,12 @@ static UINT8 resynch_local_inprogress = false; // WE are desynched and getting p
static UINT8 player_joining = false;
UINT8 hu_resynching = 0;
#ifdef SATURNSYNCH
UINT8 hu_redownloadinggamestate = 0;
static boolean can_receive_gamestate[MAXNETNODES];
static UINT8 gamestate_resend_counter[MAXNETNODES];
#endif
// kart, true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks
UINT8 hu_stopped = 0;
@@ -133,6 +147,18 @@ static boolean cl_packetmissed;
// here it is for the secondary local player (splitscreen)
static UINT8 mynode; // my address pointofview server
#ifdef SATURNSYNCH
static boolean cl_redownloadinggamestate = false;
#endif
#ifdef SATURNPAK
boolean is_client_saturn[MAXNETNODES];
#endif
#ifdef SATURNJOIN
#define ISSATURN 69
#endif
static UINT8 localtextcmd[MAXTEXTCMD];
static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen
static UINT8 localtextcmd3[MAXTEXTCMD]; // splitscreen == 2
@@ -169,7 +195,6 @@ typedef struct textcmdtic_s
ticcmd_t netcmds[TICQUEUE][MAXPLAYERS];
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shownodeip = {"showipinnodelist", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -220,7 +245,7 @@ UINT16 software_MAXPACKETLENGTH;
* \return The full tic value
*
*/
tic_t ExpandTics(INT32 low, tic_t basetic)
static inline tic_t ExpandTics(INT32 low, tic_t basetic)
{
INT32 delta;
@@ -1333,9 +1358,13 @@ static inline void CL_DrawConnectionStatus(void)
{
strncpy(tempname, filename, sizeof(tempname)-1);
}
#ifdef HAVE_CURL
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-30, 0,
va(M_GetText("%s downloading"), ((cl_mode == CL_DOWNLOADHTTPFILES) ? "\x82""HTTP" : "\x85""Direct")));
#else
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-30, 0,
va(M_GetText("%s downloading"),("\x85""Direct")));
#endif
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-22, V_YELLOWMAP,
va(M_GetText("\"%s\""), tempname));
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, V_20TRANS|V_MONOSPACE,
@@ -1423,6 +1452,9 @@ static boolean CL_SendJoin(void)
netbuffer->u.clientcfg.subversion = SUBVERSION;
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
sizeof netbuffer->u.clientcfg.application);
#ifdef SATURNJOIN
netbuffer->u.clientcfg.issaturn = ISSATURN;
#endif
return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak));
}
@@ -1720,23 +1752,23 @@ static boolean SV_SendServerConfig(INT32 node)
netbuffer->u.servercfg.discordinvites = (boolean)cv_discordinvites.value;
memcpy(netbuffer->u.servercfg.server_context, server_context, 8);
op = p = netbuffer->u.servercfg.varlengthinputs;
CV_SavePlayerNames(&p);
CV_SaveNetVars(&p, false);
{
const size_t len = sizeof (serverconfig_pak) + (size_t)(p - op);
const size_t len = sizeof (serverconfig_pak) + (size_t)(p - op);
#ifdef DEBUGFILE
if (debugfile)
{
fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n",
sizeu1(len), node);
}
if (debugfile)
{
fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n",
sizeu1(len), node);
}
#endif
waspacketsent = HSendPacket(node, true, 0, len);
}
waspacketsent = HSendPacket(node, true, 0, len);
#ifdef DEBUGFILE
if (debugfile)
@@ -1758,7 +1790,7 @@ static boolean SV_SendServerConfig(INT32 node)
#ifdef JOININGAME
#define SAVEGAMESIZE (768*1024)
static void SV_SendSaveGame(INT32 node)
static void SV_SendSaveGame(INT32 node, boolean resending)
{
size_t length, compressedlen;
UINT8 *savebuffer;
@@ -1776,7 +1808,7 @@ static void SV_SendSaveGame(INT32 node)
// Leave room for the uncompressed length.
save_p = savebuffer + sizeof(UINT32);
P_SaveNetGame();
P_SaveNetGame(resending);
length = save_p - savebuffer;
if (length > SAVEGAMESIZE)
@@ -1849,7 +1881,7 @@ static void SV_SavedGame(void)
return;
}
P_SaveNetGame();
P_SaveNetGame(false);
length = save_p - savebuffer;
if (length > SAVEGAMESIZE)
@@ -1871,8 +1903,7 @@ static void SV_SavedGame(void)
#endif
#define TMPSAVENAME "$$$.sav"
static void CL_LoadReceivedSavegame(void)
static void CL_LoadReceivedSavegame(boolean reloading)
{
UINT8 *savebuffer = NULL;
size_t length, decompressedlen;
@@ -1906,39 +1937,24 @@ static void CL_LoadReceivedSavegame(void)
demo.title = false;
automapactive = false;
if (!postautoloaded)
{
CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfilespost) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfilespost);
postautoloaded = true;
}
// load a base level
if (P_LoadNetGame())
if (P_LoadNetGame(reloading))
{
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
if (!reloading)
{
CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CON_LogMessage(M_GetText(" Zone"));
if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0)
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->actnum));
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
{
CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CON_LogMessage(M_GetText(" Zone"));
if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0)
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->actnum));
}
CON_LogMessage("\"\n");
}
CON_LogMessage("\"\n");
}
else
{
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
Z_Free(savebuffer);
save_p = NULL;
if (unlink(tmpsave) == -1)
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
return;
}
// done
@@ -1948,20 +1964,61 @@ static void CL_LoadReceivedSavegame(void)
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
consistancy[gametic%TICQUEUE] = Consistancy();
CON_ToggleOff();
#ifdef SATURNSYNCH
// Tell the server we have received and reloaded the gamestate
// so they know they can resume the game
if (reloading)
{
netbuffer->packettype = PT_RECEIVEDGAMESTATE;
HSendPacket(servernode, true, 0, 0);
}
#endif
}
#ifdef SATURNSYNCH
static void CL_ReloadReceivedSavegame(void)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
LUA_InvalidatePlayer(&players[i]);
sprintf(player_names[i], "Player %d", i + 1);
}
CL_LoadReceivedSavegame(true);
if (neededtic < gametic)
neededtic = gametic;
maketic = neededtic;
// set camera angle to somewhat match where your player is turning
for (i = 0; i <= splitscreen; i++)
{
localangle[i] = players[displayplayers[i]].cmd.angleturn<<16;
}
camera->subsector = R_PointInSubsector(camera->x, camera->y);
cl_redownloadinggamestate = false;
CONS_Printf(M_GetText("Game state reloaded\n"));
}
#endif
#endif
#ifndef NONET
static void SendAskInfo(INT32 node)
{
tic_t asktime;
#ifdef HOLEPUNCH
#ifdef HOLEPUNCH
if (node != 0 && node != BROADCASTADDR &&
cv_rendezvousserver.string[0])
{
I_NetRequestHolePunch(node);
}
#endif
#endif
asktime = I_GetTime();
@@ -2170,7 +2227,9 @@ static void M_ConfirmConnect(event_t *ev)
static void AbortConnection(void)
{
#ifdef HAVE_CURL
CURLAbortFile();
#endif
D_QuitNetGame();
CL_Reset();
D_StartTitle();
@@ -2559,7 +2618,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (fileneeded[0].status == FS_FOUND)
{
// Gamestate is now handled within CL_LoadReceivedSavegame()
CL_LoadReceivedSavegame();
CL_LoadReceivedSavegame(false);
cl_mode = CL_CONNECTED;
break;
} // don't break case continue to CL_CONNECTED
@@ -2584,7 +2643,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
// Call it only once by tic
if (*oldtic != I_GetTime())
{
INT32 key;
I_OsPolling();
@@ -3040,8 +3098,17 @@ static void Command_connect(void)
if (Playing() || demo.title)
{
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
return;
M_ClearMenus(true);
if (demo.title)
G_CheckDemoStatus();
if (netgame)
{
D_QuitNetGame();
CL_Reset();
}
D_StartTitle();
}
// modified game check: no longer handled
@@ -3100,6 +3167,17 @@ static void Command_connect(void)
botskin = 0;
CL_ConnectToServer();
}
static void Command_Packetstat(void)
{
CONS_Printf("Number of packets handled:\n");
for (UINT8 i = 0; i <= NUMPACKETTYPE; ++i)
{
CONS_Printf("%16s: %llu%s", Net_GetPacketName(i), packetstat[i], (i % 2 == 1) ? "\n" : "\t|\t");
}
}
#endif
static void ResetNode(INT32 node);
@@ -3142,10 +3220,15 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason)
playerpernode[node]--;
if (playerpernode[node] <= 0)
{
// If a resynch was in progress, well, it no longer needs to be.
SV_InitResynchVars(node);
SV_InitResynchVars(node); // If a resynch was in progress, well, it no longer needs to be.
nodeingame[node] = false;
#ifdef SATURNPAK
is_client_saturn[node] = false;
#endif
#ifdef SATURNSYNCH
can_receive_gamestate[node] = false;
#endif
Net_CloseConnection(node);
ResetNode(node);
}
@@ -3251,6 +3334,9 @@ void CL_Reset(void)
if (servernode > 0 && servernode < MAXNETNODES)
{
nodeingame[(UINT8)servernode] = false;
#ifdef SATURNPAK
is_client_saturn[(UINT8)servernode] = false;
#endif
Net_CloseConnection(servernode);
}
D_CloseConnection(); // netgame = false
@@ -3265,6 +3351,7 @@ void CL_Reset(void)
// make sure we don't leave any fileneeded gunk over from a failed join
fileneedednum = 0;
memset(fileneeded, 0, sizeof(fileneeded));
memset(packetstat, 0, sizeof(packetstat));
#ifndef NONET
totalfilesrequestednum = 0;
@@ -3945,6 +4032,36 @@ static void Command_list_http_logins (void)
}
#endif/*HAVE_CURL*/
#ifdef SATURNSYNCH
static void Command_ResendGamestate(void)
{
SINT8 playernum;
if (COM_Argc() == 1)
{
CONS_Printf(M_GetText("resendgamestate <playername/playernum>: resend the game state to a player\n"));
return;
}
else if (client)
{
CONS_Printf(M_GetText("Only the server can use this.\n"));
return;
}
playernum = nametonum(COM_Argv(1));
if (playernum == -1 || playernum == 0)
return;
// Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
if (!HSendPacket(playernode[playernum], true, 0, 0))
{
CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n"));
return;
}
}
#endif
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = {"netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -3954,6 +4071,10 @@ consvar_t cv_joinrefusemessage = {"joinrefusemessage", "The server is not accept
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_CALL, CV_OnOff, Joinable_OnChange, 0, NULL, NULL, 0, 0, NULL};
#ifdef SATURNJOIN
consvar_t cv_allownewsaturnplayer = {"allowsaturnjoin", "On", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
#ifdef VANILLAJOINNEXTROUND
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
#endif
@@ -3966,7 +4087,16 @@ static CV_PossibleValue_t discordinvites_cons_t[] = {{0, "Admins Only"}, {1, "Ev
consvar_t cv_discordinvites = {"discordinvites", "Everyone", CV_SAVE|CV_CALL, discordinvites_cons_t, Joinable_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
consvar_t cv_resynchattempts = {"resynchattempts", "2", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_resynchattempts = {"resynchattempts", "2", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef SATURNSYNCH
static CV_PossibleValue_t gamestateattempts_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}};
consvar_t cv_gamestateattempts = {"gamestateresendattempts", "10", CV_SAVE, gamestateattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchcooldown_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
consvar_t cv_resynchcooldown = {"gamestatecooldown", "5", CV_SAVE, resynchcooldown_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
#endif
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
// max file size to send to a player (in kilobytes)
@@ -3993,6 +4123,11 @@ static void Joinable_OnChange(void)
if (!server)
return;
#ifdef SATURNJOIN
// disabling joins should also disable saturn joins unless its called with CV_StealthSet and vice versa to make life a bit easier
CV_SetValue(&cv_allownewsaturnplayer, cv_allownewplayer.value);
#endif
maxplayer = (UINT8)(min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value));
WRITEUINT8(p, maxplayer);
@@ -4018,7 +4153,11 @@ void D_ClientServerInit(void)
COM_AddCommand("reloadbans", Command_ReloadBan);
COM_AddCommand("connect", Command_connect);
COM_AddCommand("nodes", Command_Nodes);
#ifdef SATURNSYNCH
COM_AddCommand("resendgamestate", Command_ResendGamestate);
#endif
COM_AddCommand("listplayers", Command_Listplayers);
COM_AddCommand("packetstat", Command_Packetstat);
#ifdef HAVE_CURL
COM_AddCommand("set_http_login", Command_set_http_login);
COM_AddCommand("list_http_logins", Command_list_http_logins);
@@ -4055,17 +4194,33 @@ void D_ClientServerInit(void)
static void ResetNode(INT32 node)
{
nodeingame[node] = false;
nodewaiting[node] = 0;
nodetoplayer[node] = -1;
nodetoplayer2[node] = -1;
nodetoplayer3[node] = -1;
nodetoplayer4[node] = -1;
playerpernode[node] = 0;
nettics[node] = gametic;
supposedtics[node] = gametic;
nodewaiting[node] = 0;
playerpernode[node] = 0;
sendingsavegame[node] = false;
bannednode[node].banid = SIZE_MAX;
bannednode[node].timeleft = NO_BAN_TIME;
// SATURN
#ifdef SATURNPAK
is_client_saturn[node] = false;
#endif
#ifdef SATURNSYNCH
resendingsavegame[node] = false;
can_receive_gamestate[node] = false;
savegameresendcooldown[node] = 0;
#endif
//
}
void SV_ResetServer(void)
@@ -4101,6 +4256,9 @@ void SV_ResetServer(void)
mynode = 0;
cl_packetmissed = false;
#ifdef SATURNSYNCH
cl_redownloadinggamestate = false;
#endif
if (dedicated)
{
@@ -4117,6 +4275,7 @@ void SV_ResetServer(void)
// clear server_context
memset(server_context, '-', 8);
memset(packetstat, 0, sizeof(packetstat));
DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n");
}
@@ -4276,8 +4435,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (server && multiplayer && motd[0] != '\0')
COM_BufAddText(va("sayto %d %s\n", newplayernum, motd));
D_AddAutoloadFiles();
LUAh_PlayerJoin(newplayernum);
if (newplayernum == consoleplayer)
LUAh_ServerJoin();
#ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence();
#endif
@@ -4309,7 +4473,6 @@ static void Got_RemovePlayer(UINT8 **p, INT32 playernum)
if (pnum == serverplayer)
{
CONS_Alert(CONS_WARNING, "Attempt to remove server player\n");
return;
}
@@ -4388,6 +4551,14 @@ static boolean SV_AddWaitingPlayers(void)
return newplayer;
}
#ifdef SATURNPAK
static inline void SendSaturnInfo(INT32 node)
{
netbuffer->packettype = PT_ISSATURN;
HSendPacket(node, true, 0, 0);
}
#endif
void CL_AddSplitscreenPlayer(void)
{
if (cl_mode == CL_CONNECTED)
@@ -4573,7 +4744,11 @@ static void HandleConnect(SINT8 node)
{
SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d)"), VERSION, SUBVERSION));
}
#ifdef SATURNJOIN
else if ((!cv_allownewplayer.value && node && netbuffer->u.clientcfg.issaturn != ISSATURN) || (!cv_allownewsaturnplayer.value && node && netbuffer->u.clientcfg.issaturn == ISSATURN))
#else
else if (!cv_allownewplayer.value && node)
#endif
{
SV_SendRefuse(node, M_GetText(cv_joinrefusemessage.string));
}
@@ -4629,6 +4804,7 @@ static void HandleConnect(SINT8 node)
/// \todo fix this !!!
return; // restart the while
}
SV_SendServerInfo(node, 0); // Dunno if 0 time is good idea
//if (gamestate != GS_LEVEL) // GS_INTERMISSION, etc?
// SV_SendPlayerConfigs(node); // send bare minimum player info
G_SetGamestate(backupstate);
@@ -4639,7 +4815,7 @@ static void HandleConnect(SINT8 node)
{
if (node && newnode)
{
SV_SendSaveGame(node); // send a complete game state
SV_SendSaveGame(node, false); // send a complete game state
DEBFILE("send savegame\n");
}
SV_AddWaitingPlayers();
@@ -4705,6 +4881,47 @@ static void HandleServerInfo(SINT8 node)
netbuffer->u.serverinfo.gametype = (UINT8)((netbuffer->u.serverinfo.gametype == VANILLA_GT_MATCH) ? GT_MATCH : GT_RACE);
SL_InsertServer(&netbuffer->u.serverinfo, node);
if (client && cl_mode > CL_SEARCHING && node == servernode)
memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
}
#endif
#ifdef SATURNSYNCH
static void PT_WillResendGamestate(void)
{
char tmpsave[264];
if (server || cl_redownloadinggamestate)
return;
// Send back a PT_CANRECEIVEGAMESTATE packet to the server
// so they know they can start sending the game state
netbuffer->packettype = PT_CANRECEIVEGAMESTATE;
if (!HSendPacket(servernode, true, 0, 0))
return;
CONS_Printf(M_GetText("Reloading game state...\n"));
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
// Don't get a corrupt savegame error because tmpsave already exists
if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1)
I_Error("Can't delete %s\n", tmpsave);
CL_PrepareDownloadSaveGame(tmpsave);
cl_redownloadinggamestate = true;
}
static void PT_CanReceiveGamestate(SINT8 node)
{
if (client || sendingsavegame[node])
return;
CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]);
SV_SendSaveGame(node, true); // Resend a complete game state
resendingsavegame[node] = true;
}
#endif
@@ -4896,6 +5113,9 @@ static void HandlePacketFromAwayNode(SINT8 node)
#endif
DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode));
#ifdef SATURNPAK
SendSaturnInfo(node);
#endif
memset(playeringame, 0, sizeof(playeringame));
for (j = 0; j < MAXPLAYERS; j++)
{
@@ -5009,7 +5229,6 @@ static void HandlePacketFromPlayer(SINT8 node)
tic_t realend, realstart;
UINT8 *pak, *txtpak, numtxtpak;
txtpak = NULL;
if (dedicated && node == 0)
@@ -5133,11 +5352,69 @@ static void HandlePacketFromPlayer(SINT8 node)
--resynch_delay[node];
break;
}
#ifdef SATURNSYNCH
if ((gamestate_resend_counter[node] != 0) && (I_GetTime() % ((max(cv_resynchcooldown.value, 1) * TICRATE) *2) == 0))
gamestate_resend_counter[node]--;
// Check player consistancy during the level
if (((!can_receive_gamestate[node]) && realstart <= gametic && realstart > gametic - TICQUEUE+1 && gamestate == GS_LEVEL
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)) || (can_receive_gamestate[node] && realstart <= gametic && realstart + TICQUEUE - 1 > gametic && gamestate == GS_LEVEL
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()))
{
// we need to send this so the client can tell us if it can receive the savegame
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
HSendPacket(node, true, 0, 0);
if (can_receive_gamestate[node])
resendingsavegame[node] = true;
else
{
SV_RequireResynch(node);
resendingsavegame[node] = false;
}
if ((!can_receive_gamestate[node] && cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) || (can_receive_gamestate[node] && (gamestate_resend_counter[node] < cv_gamestateattempts.value)))
{
if (can_receive_gamestate[node] && resendingsavegame[node])
{
gamestate_resend_counter[node]++;
DEBFILE(va("gamestate counter %d for player %d\n", gamestate_resend_counter[node], netconsole));
}
if (cv_blamecfail.value)
CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
netconsole+1, player_names[netconsole],
consistancy[realstart%TICQUEUE],
SHORT(netbuffer->u.clientpak.consistancy));
DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
netconsole, realstart, consistancy[realstart%TICQUEUE],
SHORT(netbuffer->u.clientpak.consistancy)));
break;
}
else
{
UINT8 buf[3];
buf[0] = (UINT8)netconsole;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
netconsole, realstart, consistancy[realstart%TICQUEUE],
SHORT(netbuffer->u.clientpak.consistancy)));
break;
}
}
else if (resynch_score[node])
--resynch_score[node];
break;
#else
// Check player consistancy during the level
if (realstart <= gametic && realstart > gametic - TICQUEUE+1 && gamestate == GS_LEVEL
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy))
{
SV_RequireResynch(node);
SV_RequireResynch(node);
if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)
{
@@ -5167,6 +5444,8 @@ static void HandlePacketFromPlayer(SINT8 node)
else if (resynch_score[node])
--resynch_score[node];
break;
#endif
case PT_BASICKEEPALIVE:
if (client)
break;
@@ -5301,6 +5580,12 @@ static void HandlePacketFromPlayer(SINT8 node)
}
Net_CloseConnection(node);
nodeingame[node] = false;
#ifdef SATURNPAK
is_client_saturn[node] = false;
#endif
#ifdef SATURNSYNCH
can_receive_gamestate[node] = false;
#endif
break;
// -------------------------------------------- CLIENT RECEIVE ----------
case PT_RESYNCHEND:
@@ -5464,6 +5749,26 @@ static void HandlePacketFromPlayer(SINT8 node)
if (client)
Got_Filetxpak();
break;
#ifdef SATURNSYNCH
case PT_CANRECEIVEGAMESTATE:
can_receive_gamestate[node] = true;
PT_CanReceiveGamestate(node);
break;
case PT_RECEIVEDGAMESTATE:
sendingsavegame[node] = false;
resendingsavegame[node] = false;
savegameresendcooldown[node] = I_GetTime() + cv_resynchcooldown.value * TICRATE; // I_GetTime() + 5 * TICRATE;
break;
case PT_WILLRESENDGAMESTATE:
PT_WillResendGamestate();
break;
#endif
#ifdef SATURNPAK
case PT_ISSATURN:
//CONS_Printf("hi im on saturn%d\n", node);
is_client_saturn[node] = true;
break;
#endif
default:
DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
netbuffer->packettype, node));
@@ -5479,7 +5784,6 @@ static void GetPackets(void)
{
SINT8 node; // The packet sender
player_joining = false;
while (HGetPacket())
@@ -5516,6 +5820,10 @@ static void GetPackets(void)
if (netbuffer->packettype == PT_PLAYERINFO)
continue; // We do nothing with PLAYERINFO, that's for the MS browser.
// We also count unknown packets, hence "<="
if (netbuffer->packettype <= NUMPACKETTYPE)
++packetstat[netbuffer->packettype];
// Packet received from someone already playing
if (nodeingame[node])
HandlePacketFromPlayer(node);
@@ -6292,13 +6600,12 @@ void NetKeepAlive(void)
MasterClient_Ticker();
#endif
#ifdef HOLEPUNCH
#ifdef HOLEPUNCH
if (netgame && serverrunning)
{
RenewHolePunch();
}
#endif
#endif
if (client)
{
@@ -6411,18 +6718,27 @@ void NetUpdate(void)
MasterClient_Ticker(); // Acking the Master Server
#endif
#ifdef HOLEPUNCH
#ifdef HOLEPUNCH
if (netgame && serverrunning)
{
RenewHolePunch();
}
#endif
#endif
if (client)
{
#ifdef SATURNSYNCH
// If the client just finished redownloading the game state, load it
if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND)
CL_ReloadReceivedSavegame();
#endif
if (!resynch_local_inprogress)
CL_SendClientCmd(); // Send tic cmd
hu_resynching = resynch_local_inprogress;
#ifdef SATURNSYNCH
hu_redownloadinggamestate = cl_redownloadinggamestate;
#endif
}
else
{
@@ -6431,6 +6747,9 @@ void NetUpdate(void)
INT32 counts;
hu_resynching = false;
#ifdef SATURNSYNCH
hu_redownloadinggamestate = false;
#endif
firstticstosend = gametic;
for (i = 0; i < MAXNETNODES; i++)
@@ -6532,7 +6851,7 @@ rewind_t *CL_SaveRewindPoint(size_t demopos)
return NULL;
save_p = rewind->savebuffer;
P_SaveNetGame();
P_SaveNetGame(false);
rewind->leveltime = leveltime;
rewind->next = rewindhead;
rewind->demopos = demopos;
@@ -6556,7 +6875,7 @@ rewind_t *CL_RewindToTime(tic_t time)
return NULL;
save_p = rewindhead->savebuffer;
P_LoadNetGame();
P_LoadNetGame(false);
wipegamestate = gamestate; // No fading back in!
timeinmap = leveltime;
+26 -2
View File
@@ -98,6 +98,16 @@ typedef enum
PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)"
PT_PING, // Packet sent to tell clients the other client's latency to server.
#ifdef SATURNSYNCH
PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
// we will reserve this for now even if unused, so order wont get mangled
PT_ISSATURN, // Saturn specific identifier packet
#endif
NUMPACKETTYPE
} packettype_t;
@@ -363,6 +373,9 @@ typedef struct
UINT8 subversion; // Contains build version
UINT8 localplayers; // number of splitscreen players
UINT8 mode;
#ifdef SATURNJOIN
UINT8 issaturn;
#endif
} ATTRPACK clientconfig_pak;
#define SV_SPEEDMASK 0x03 // used to send kartspeed
@@ -567,14 +580,22 @@ extern consvar_t
#ifdef VANILLAJOINNEXTROUND
cv_joinnextround,
#endif
cv_netticbuffer, cv_allownewplayer, cv_joinrefusemessage, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
cv_netticbuffer, cv_allownewplayer,
#ifdef SATURNJOIN
cv_allownewsaturnplayer,
#endif
cv_joinrefusemessage, cv_maxplayers, cv_resynchattempts,
#ifdef SATURNSYNCH
cv_resynchcooldown, cv_gamestateattempts,
#endif
cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
extern consvar_t cv_connectawaittime;
extern consvar_t cv_discordinvites;
// Used in d_net, the only dependence
tic_t ExpandTics(INT32 low, tic_t basetic);
//tic_t ExpandTics(INT32 low, tic_t basetic);
void D_ClientServerInit(void);
// Initialise the other field
@@ -632,6 +653,9 @@ tic_t GetLag(INT32 node);
UINT8 GetFreeXCmdSize(void);
extern UINT8 hu_resynching;
#ifdef SATURNSYNCH
extern UINT8 hu_redownloadinggamestate;
#endif
extern UINT8 hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player
typedef struct rewind_s {
+178 -39
View File
@@ -37,6 +37,7 @@
#include "d_net.h"
#include "f_finale.h"
#include "g_game.h"
#include "g_input.h"
#include "hu_stuff.h"
#include "i_sound.h"
#include "i_system.h"
@@ -103,11 +104,12 @@ static char *startupwadfiles[MAX_WADFILES];
static char *startuppwads[MAX_WADFILES];
// autoloading
static char *autoloadwadfiles[MAX_WADFILES];
char *autoloadwadfiles[MAX_WADFILES];
char *autoloadwadfilespost[MAX_WADFILES];
boolean autoloading;
boolean autoloaded;
boolean postautoloaded;
boolean postautoloaded = false;
boolean wasautoloaded = false;
boolean devparm = false; // started game with -devparm
@@ -149,6 +151,8 @@ INT32 eventhead, eventtail;
boolean dedicated = false;
boolean loaded_config = false;
//
// D_PostEvent
// Called by the I/O functions when input is detected
@@ -166,6 +170,32 @@ UINT8 ctrldown = 0; // 0x1 left, 0x2 right
UINT8 altdown = 0; // 0x1 left, 0x2 right
boolean capslock = 0; // gee i wonder what this does.
static inline void D_DeviceLEDTick(void)
{
UINT8 i;
UINT16 color[MAXSPLITSCREENPLAYERS];
UINT16 curcolor[MAXSPLITSCREENPLAYERS];
if (I_NumJoys() == 0 || (cv_gamepadled[0].value == 0 && cv_gamepadled[1].value == 0 && cv_gamepadled[2].value == 0 && cv_gamepadled[3].value == 0))
{
return;
}
for (i = 0; i <= splitscreen; i++)
{
if (G_GetDeviceForPlayer(i) == 0)
continue;
color[i] = G_GetSkinColor(i);
if (curcolor[i] == color[i]) // dont update if same colour
continue;
G_SetPlayerGamepadIndicatorColor(i, color[i]);
curcolor[i] = color[i];
}
}
//
// D_ProcessEvents
// Send all the events of the given timestamp down the responder chain
@@ -242,8 +272,9 @@ void D_ProcessEvents(void)
// added comment : there is a wipe eatch change of the gamestate
gamestate_t wipegamestate = GS_LEVEL;
static void D_Display(void)
static boolean D_Display(void)
{
boolean ranwipe = false;
boolean forcerefresh = false;
static boolean wipe = false;
INT32 wipedefindex = 0;
@@ -252,7 +283,7 @@ static void D_Display(void)
if (!dedicated)
{
if (nodrawers)
return; // for comparative timing/profiling
return false; // for comparative timing/profiling
// check for change of screen size (video mode)
if (setmodeneeded && !wipe)
@@ -262,7 +293,10 @@ static void D_Display(void)
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
if (rendermode == render_soft && !splitscreen)
{
R_InterpolateViewRollAngle(rendertimefrac);
R_CheckViewMorph();
}
// change the view size if needed
if (setsizeneeded)
@@ -302,6 +336,7 @@ static void D_Display(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
F_WipeEndScreen();
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
ranwipe = true;
}
if (gamestate != GS_LEVEL && rendermode != render_none)
@@ -315,12 +350,13 @@ static void D_Display(void)
else //dedicated servers
{
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
ranwipe = true;
wipegamestate = gamestate;
}
}
if (dedicated) //bail out after wipe logic
return;
return false;
// do buffered drawing
switch (gamestate)
@@ -427,7 +463,7 @@ static void D_Display(void)
viewssnum = i;
#ifdef HWRENDER
if (rendermode != render_soft)
if (rendermode == render_opengl)
HWR_RenderPlayerView(i, &players[displayplayers[i]]);
else
#endif
@@ -482,8 +518,10 @@ static void D_Display(void)
for (i = 0; i <= splitscreen; i++)
{
if (postimgtype[i])
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
if (!postimgtype[i])
continue;
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
}
}
@@ -497,7 +535,6 @@ static void D_Display(void)
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
usebuffer = true;
}
lastdraw = false;
}
@@ -561,11 +598,10 @@ static void D_Display(void)
{
F_WipeEndScreen();
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
ranwipe = true;
}
}
NetUpdate(); // send out any new accumulation
// It's safe to end the game now.
if (G_GetExitGameFlag())
{
@@ -610,6 +646,7 @@ static void D_Display(void)
PS_STOP_TIMING(ps_swaptime);
}
return ranwipe;
}
// =========================================================================
@@ -617,6 +654,7 @@ static void D_Display(void)
// =========================================================================
tic_t rendergametic;
static int menuInputDelayTimer = 0;
void D_SRB2Loop(void)
{
@@ -626,6 +664,7 @@ void D_SRB2Loop(void)
boolean interp = false;
boolean doDisplay = false;
int frameskip = 0;
if (dedicated)
server = true;
@@ -670,6 +709,8 @@ void D_SRB2Loop(void)
capbudget = (precise_t) budget;
}
boolean ranwipe = false;
I_UpdateTime(cv_timescale.value);
if (lastwipetic)
@@ -702,9 +743,11 @@ void D_SRB2Loop(void)
HW3S_BeginFrameUpdate();
#endif
renderisnewtic = (realtics > 0 || singletics);
refreshdirmenu = 0; // not sure where to put this, here as good as any?
if (realtics > 0 || singletics)
if (renderisnewtic)
{
// don't skip more than 10 frames at a time
// (fadein / fadeout cause massive frame skip!)
@@ -723,14 +766,20 @@ void D_SRB2Loop(void)
}
else if (rendertimeout < entertic) // in case the server hang or netsplit
{
// Lagless camera! Yay!
if (cv_laglesscam.value && gamestate == GS_LEVEL && netgame)
{
// Evaluate the chase cam once for every local realtic
// This might actually be better suited inside G_Ticker or TryRunTics
for (tic_t chasecamtics = 0; chasecamtics < realtics; chasecamtics++)
{
P_RunChaseCameras();
}
R_UpdateViewInterpolation();
}
doDisplay = true;
}
renderisnewtic = true;
}
else
{
renderisnewtic = false;
}
if (interp)
@@ -752,9 +801,9 @@ void D_SRB2Loop(void)
rendertimefrac = FRACUNIT;
}
if (interp || doDisplay)
if ((interp || doDisplay) && !frameskip)
{
D_Display();
ranwipe = D_Display();
}
// Only take screenshots after drawing.
@@ -779,8 +828,72 @@ void D_SRB2Loop(void)
}
#endif
// this is absolutely awful and i hate it lmao
if (menuactive && (DPADUPSCROLL || DPADDOWNSCROLL || DPADLEFTSCROLL || DPADRIGHTSCROLL))
{
event_t myev;
myev.type = ev_keydown;
if (renderisnewtic)
{
menuInputDelayTimer++;
if (menuInputDelayTimer >= 19) // TICRATE * ( (k+2) (1 - [wz + h + j - q]^2 - [(gk + 2g + k + 1)(h + j) + h - z]^2 - [16(k + 1)^3(k + 2)(n + 1)^2 + 1 - f^2]^2 calculated by my butt
{
if (DPADUPSCROLL)
{
myev.data1 = KEY_UPARROW;
M_Responder(&myev);
}
else if (DPADDOWNSCROLL)
{
myev.data1 = KEY_DOWNARROW;
M_Responder(&myev);
}
else if (DPADLEFTSCROLL)
{
myev.data1 = KEY_LEFTARROW;
M_Responder(&myev);
}
else if (DPADRIGHTSCROLL)
{
myev.data1 = KEY_RIGHTARROW;
M_Responder(&myev);
}
}
}
}
else
menuInputDelayTimer = 0;
if (!dedicated && renderisnewtic) // idk does this need dedi check??
D_DeviceLEDTick();
// Fully completed frame made.
finishprecise = I_GetPreciseTime();
// Use the time before sleep for frameskip calculations:
// post-sleep time is literally being intentionally wasted
deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision();
deltatics = deltasecs * NEWTICRATE;
// If time spent this game loop exceeds a single tic,
// it's probably because of rendering.
//
// Skip rendering the next frame, up to a limit of 3
// frames before a frame is rendered no matter what.
//
// Wipes run an inner loop and artificially increase
// the measured time.
if (!ranwipe && frameskip < 3 && deltatics > 1.0)
{
frameskip++;
}
else
{
frameskip = 0;
}
if (!singletics)
{
INT64 elapsed = (INT64)(finishprecise - enterprecise);
@@ -906,7 +1019,7 @@ static INT32 D_DetectFileType(const char* filename)
return 5;
else if (!stricmp(&filename[strlen(filename) - 4], ".soc"))
return 6;
else if (!stricmp(&filename[strlen(filename) - 4], ".cfg"))
return 7;
else if (!stricmp(&filename[strlen(filename) - 4], ".txt"))
@@ -930,12 +1043,12 @@ static void D_AutoloadFile(const char *file, char **filearray)
if (!newfile)
I_Error("No more free memory to AutoloadFile %s",file);
if (!fileType)
if (!fileType)
{
CONS_Printf("D_AutoloadFile: File %s is unknown or invalid\n", file);
return;
}
strcpy(newfile, file);
if (fileType <= 6)
@@ -975,7 +1088,10 @@ static void D_FindAddonsToAutoload(void)
// If the file is found, run our shit
if (!autoloadconfigfile) // nope outta here
{
wasautoloaded = postautoloaded = true; // so D_AddAutoloadFiles can skip everything since nothings there to autoload
return;
}
while (fgets(wadsToAutoload, sizeof wadsToAutoload, autoloadconfigfile) != NULL)
{
@@ -1042,6 +1158,32 @@ static void D_FindAddonsToAutoload(void)
fclose(autoloadconfigfile);
}
void D_AddAutoloadFiles(void)
{
if (wasautoloaded && postautoloaded)
return;
if (!wasautoloaded && !modeattacking)
{
CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfiles) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfiles);
wasautoloaded = true;
}
if ((!postautoloaded) && netgame)
{
CONS_Printf("D_AutoloadFile(): Loading postloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfilespost) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfilespost);
postautoloaded = true;
}
}
void D_CleanFile(char **filearray)
{
size_t pnumwadfiles;
@@ -1147,13 +1289,13 @@ static void IdentifyVersion(void)
D_AddFile(va(pandf,srb2waddir,"extra.kart"), startupwadfiles);
found_extra_kart = true;
}
// completely optional 2: Back with a vengence
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra2.kart"))) {
D_AddFile(va(pandf,srb2waddir,"extra2.kart"), startupwadfiles);
found_extra2_kart = true;
}
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra3.kart"))) {
D_AddFile(va(pandf,srb2waddir,"extra3.kart"), startupwadfiles);
found_extra3_kart = true;
@@ -1456,7 +1598,7 @@ void D_SRB2Main(void)
if (found_extra_kart || found_extra2_kart || found_extra3_kart) // found the funny, add it in!
{
// HAYA: These are seperated for a reason lmao
if (found_extra_kart)
if (found_extra_kart)
mainwads++;
if (found_extra2_kart)
mainwads++;
@@ -1484,7 +1626,7 @@ void D_SRB2Main(void)
achi_speedo_clr = true;
// check for bigger lap count
if (W_CheckMultipleLumps("K_STLAPB", "K_STLA2B", NULL))
if (W_CheckMultipleLumps("K_STLAPB", "K_STLA2B", NULL))
big_lap = true;
// now check for colour hud stuff
@@ -1493,7 +1635,7 @@ void D_SRB2Main(void)
clr_hud = true;
// check for bigger lap count but color** its color bitch
if (W_CheckMultipleLumps("K_SCLAPB", "K_SCLA2B", NULL))
if (W_CheckMultipleLumps("K_SCLAPB", "K_SCLA2B", NULL))
big_lap_color = true;
// kartzspeedo
@@ -1508,16 +1650,16 @@ void D_SRB2Main(void)
// stat display for extended player setup
if (W_CheckMultipleLumps("K_STATNB", "K_STATN1", "K_STATN2", "K_STATN3", "K_STATN4", \
"K_STATN5", "K_STATN6", NULL))
"K_STATN5", "K_STATN6", NULL))
statdp = true;
// Nametag stuffs
if (W_CheckMultipleLumps("NTLINE", "NTLINEV", "NTSP", "NTWH", NULL))
if (W_CheckMultipleLumps("NTLINE", "NTLINEV", "NTSP", "NTWH", NULL))
nametaggfx = true;
if (W_CheckMultipleLumps("K_DGAU","K_DCAU","K_DGSU","K_DCSU", NULL))
if (W_CheckMultipleLumps("K_DGAU","K_DCAU","K_DGSU","K_DCSU", NULL))
driftgaugegfx = true;
if (found_extra3_kart)
{
// 80x11 speedometer crap
@@ -1530,7 +1672,7 @@ void D_SRB2Main(void)
if (W_LumpExists("SC_SM3TC"))
xtra_speedo_clr3 = true;
}
}
}
#undef PUSHSPEEDO
memcpy(speedo_cons_t, speedo_cons_temp, sizeof(speedo_cons_t));
@@ -1644,6 +1786,8 @@ void D_SRB2Main(void)
savedata.lives = 0; // flag this as not-used
loaded_config = true; // so pallettechange doesent get called 500 times at startup lol
//------------------------------------------------ COMMAND LINE PARAMS
// this must be done after loading gamedata,
@@ -1728,11 +1872,6 @@ void D_SRB2Main(void)
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();
CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfiles) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfiles);
// Set up splitscreen players before joining!
if (!dedicated && (M_CheckParm("-splitscreen") && M_IsNextParm()))
{
@@ -1937,7 +2076,7 @@ void D_SRB2Main(void)
pagename = "TITLESKY";
levelstarttic = gametic;
G_SetGamestate(GS_LEVEL);
if (!P_SetupLevel(false))
if (!P_SetupLevel(false, false))
I_Quit(); // fail so reset game stuff
}
+5
View File
@@ -20,6 +20,8 @@
// make sure not to write back the config until it's been correctly loaded
extern tic_t rendergametic;
extern boolean loaded_config;
extern char srb2home[256]; //Alam: My Home
extern boolean usehome; //Alam: which path?
extern const char *pandf; //Alam: how to path?
@@ -43,12 +45,15 @@ extern boolean statdp; // stat display for extended player setup
extern boolean nametaggfx; // Nametag stuffs
extern boolean driftgaugegfx;
void D_AddAutoloadFiles(void);
extern boolean autoloading;
extern boolean autoloaded;
extern boolean postautoloaded;
extern boolean wasautoloaded;
extern char *autoloadwadfilespost[MAX_WADFILES];
extern char *autoloadwadfiles[MAX_WADFILES];
// the infinite loop of D_SRB2Loop() called from win_main for windows version
void D_SRB2Loop(void) FUNCNORETURN;
+22 -29
View File
@@ -64,9 +64,6 @@ static doomdata_t reboundstore[MAXREBOUND];
static INT16 reboundsize[MAXREBOUND];
static INT32 rebound_head, rebound_tail;
/// \brief bandwith of netgame
INT32 net_bandwidth;
/// \brief max length per packet
INT16 hardware_MAXPACKETLENGTH;
@@ -793,7 +790,7 @@ static void fprintfstringnewline(char *s, size_t len)
}
/// \warning Keep this up-to-date if you add/remove/rename packet types
static const char *packettypename[NUMPACKETTYPE] =
const char *packettypename[NUMPACKETTYPE] =
{
"NOTHING",
"SERVERCFG",
@@ -836,13 +833,31 @@ static const char *packettypename[NUMPACKETTYPE] =
"MOREFILESNEEDED",
"PING"
#ifdef SATURNSYNCH
,
"WILLRESENDGAMESTATE",
"CANRECEIVEGAMESTATE",
"RECEIVEDGAMESTATE",
// we will reserve this for now even if unused, so order wont get mangled
"ISSATURN"
#endif
};
const char *Net_GetPacketName(UINT8 packettype)
{
if (packettype >= NUMPACKETTYPE)
return "UNKNOWN";
return packettypename[packettype];
}
static void DebugPrintpacket(const char *header)
{
fprintf(debugfile, "%-12s (node %d,ack %d,ackret %d,size %d) type(%d) : %s\n",
header, doomcom->remotenode, netbuffer->ack, netbuffer->ackreturn, doomcom->datalength,
netbuffer->packettype, packettypename[netbuffer->packettype]);
netbuffer->packettype, Net_GetPacketName(netbuffer->packettype));
switch (netbuffer->packettype)
{
@@ -1208,7 +1223,7 @@ boolean HGetPacket(void)
}
break;
}
#endif // ndef NONET
#endif // ifndef NONET
return true;
}
@@ -1258,10 +1273,7 @@ void D_SetDoomcom(void)
{
if (doomcom) return;
doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL);
doomcom->id = DOOMCOM_ID;
doomcom->numslots = doomcom->numnodes = 1;
doomcom->gametype = 0;
doomcom->consoleplayer = 0;
doomcom->extratics = 0;
}
@@ -1286,7 +1298,6 @@ boolean D_CheckNetGame(void)
I_NetMakeNodewPort = NULL;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
net_bandwidth = 30000;
// I_InitNetwork sets doomcom and netgame
// check and initialize the network driver
multiplayer = false;
@@ -1306,7 +1317,6 @@ boolean D_CheckNetGame(void)
server = true; // WTF? server always true???
// no! The deault mode is server. Client is set elsewhere
// when the client executes connect command.
doomcom->ticdup = 1;
if (M_CheckParm("-extratic"))
{
@@ -1317,21 +1327,6 @@ boolean D_CheckNetGame(void)
CONS_Printf(M_GetText("Set extratics to %d\n"), doomcom->extratics);
}
if (M_CheckParm("-bandwidth"))
{
if (M_IsNextParm())
{
net_bandwidth = atoi(M_GetNextParm());
if (net_bandwidth < 1000)
net_bandwidth = 1000;
if (net_bandwidth > 100000)
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
CONS_Printf(M_GetText("Network bandwidth set to %d\n"), net_bandwidth);
}
else
I_Error("usage: -bandwidth <byte_per_sec>");
}
software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH;
if (M_CheckParm("-packetsize"))
{
@@ -1351,8 +1346,6 @@ boolean D_CheckNetGame(void)
if (netgame)
multiplayer = true;
if (doomcom->id != DOOMCOM_ID)
I_Error("Doomcom buffer invalid!");
if (doomcom->numnodes > MAXNETNODES)
I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES);
@@ -1365,7 +1358,7 @@ boolean D_CheckNetGame(void)
if (M_CheckParm("-debugfile"))
{
char filename[21];
INT32 k = doomcom->consoleplayer - 1;
INT32 k = consoleplayer - 1;
if (M_IsNextParm())
k = atoi(M_GetNextParm()) - 1;
while (!debugfile && k < MAXPLAYERS)
+1
View File
@@ -65,5 +65,6 @@ void Net_ConnectionTimeout(INT32 node);
void Net_AbortPacketType(UINT8 packettype);
void Net_SendAcks(INT32 node);
void Net_WaitAllAckReceived(UINT32 timeout);
const char *Net_GetPacketName(UINT8 packettype);
#endif
+66 -8
View File
@@ -299,6 +299,9 @@ consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t,
//WTF
consvar_t cv_mouseturn = {"mouseturn", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// Lagless camera! Yay!
consvar_t cv_laglesscam = {"laglesscamera", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#if defined(HAVE_SDL) || defined(_WINDOWS) //joystick 1 and 2
consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick, 0, NULL, NULL, 0, 0, NULL};
@@ -394,6 +397,7 @@ static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometer
consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_karthitemdialog = {"karthitemdialog", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_karteliminatelast = {"karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOSHOWHELP, CV_YesNo, KartEliminateLast_OnChange, 0, NULL, NULL, 0, 0, NULL};
@@ -561,6 +565,10 @@ static CV_PossibleValue_t ps_descriptor_cons_t[] = {
{1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}};
consvar_t cv_ps_descriptor = {"ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_director = {"director", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartdebugdirector = {"debugdirector", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showdirectorhud = {"showdirectorhud", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showtrackaddon = {"showtrackaddon", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t skinselectmenu_t[] = {{SKINMENUTYPE_SCROLL, "Scroll"}, {SKINMENUTYPE_2D, "2d"}, {SKINMENUTYPE_GRID, "Grid"}, {SKINMENUTYPE_EXTENDED, "Extended"}, {0, NULL}};
@@ -577,6 +585,9 @@ static CV_PossibleValue_t skinselectgridsort_t[] ={
};
consvar_t cv_skinselectgridsort ={ "skinselectgridsort", "Real name", CV_SAVE|CV_CALL|CV_NOINIT, skinselectgridsort_t, sortSkinGrid, 0, NULL, NULL, 0, 0, NULL };
static CV_PossibleValue_t betainterscreen_t[] = {{0, "Off"}, {1, "On"}, {2, "NoBG"}, {0, NULL}};
consvar_t cv_betainterscreen = {"betaintermissionscreen", "Off", CV_SAVE, betainterscreen_t, NULL, 0, NULL, NULL, 0, 0, NULL};
INT16 gametype = GT_RACE; // SRB2kart
boolean forceresetplayers = false;
boolean deferencoremode = false;
@@ -777,6 +788,10 @@ void D_RegisterServerCommands(void)
// d_clisrv
CV_RegisterVar(&cv_maxplayers);
CV_RegisterVar(&cv_resynchattempts);
#ifdef SATURNSYNCH
CV_RegisterVar(&cv_gamestateattempts);
CV_RegisterVar(&cv_resynchcooldown);
#endif
CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed);
@@ -784,6 +799,9 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_httpsource);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
#ifdef SATURNJOIN
CV_RegisterVar(&cv_allownewsaturnplayer);
#endif
CV_RegisterVar(&cv_joinrefusemessage);
CV_RegisterVar(&cv_chatlogsize);
#ifdef VANILLAJOINNEXTROUND
@@ -821,6 +839,8 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_recordmultiplayerdemos);
CV_RegisterVar(&cv_netdemosyncquality);
CV_RegisterVar(&cv_maxdemosize);
CV_RegisterVar(&cv_demochangemap);
CV_RegisterVar(&cv_keyboardlayout);
}
@@ -975,6 +995,10 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_showtrackaddon);
CV_RegisterVar(&cv_showviewpointtext);
CV_RegisterVar(&cv_director);
CV_RegisterVar(&cv_kartdebugdirector);
CV_RegisterVar(&cv_showdirectorhud);
CV_RegisterVar(&cv_luaimmersion);
CV_RegisterVar(&cv_fakelocalskin);
@@ -988,6 +1012,7 @@ void D_RegisterClientCommands(void)
//CV_RegisterVar(&cv_alwaysfreelook2);
//CV_RegisterVar(&cv_chasefreelook);
//CV_RegisterVar(&cv_chasefreelook2);
CV_RegisterVar(&cv_replaysearchrate);
CV_RegisterVar(&cv_showfocuslost);
CV_RegisterVar(&cv_pauseifunfocused);
@@ -1062,6 +1087,21 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_controlperkey);
CV_RegisterVar(&cv_turnsmooth);
CV_RegisterVar(&cv_rumble[0]);
CV_RegisterVar(&cv_rumble[1]);
CV_RegisterVar(&cv_rumble[2]);
CV_RegisterVar(&cv_rumble[3]);
CV_RegisterVar(&cv_gamepadled[0]);
CV_RegisterVar(&cv_gamepadled[1]);
CV_RegisterVar(&cv_gamepadled[2]);
CV_RegisterVar(&cv_gamepadled[3]);
CV_RegisterVar(&cv_ledpowerup[0]);
CV_RegisterVar(&cv_ledpowerup[1]);
CV_RegisterVar(&cv_ledpowerup[2]);
CV_RegisterVar(&cv_ledpowerup[3]);
CV_RegisterVar(&cv_usemouse);
CV_RegisterVar(&cv_usemouse2);
CV_RegisterVar(&cv_invertmouse);
@@ -1154,6 +1194,10 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_showmusicfilename);
CV_RegisterVar(&cv_betainterscreen);
CV_RegisterVar(&cv_laglesscam);
// ingame object placing
COM_AddCommand("objectplace", Command_ObjectPlace_f);
COM_AddCommand("writethings", Command_Writethings_f);
@@ -1650,8 +1694,9 @@ static void SendNameAndColor(void)
cv_skin.value = R_SkinAvailable(cv_skin.string);
if (cv_skin.value < 0)
{
CV_StealthSet(&cv_skin, DEFAULTSKIN);
cv_skin.value = 0;
INT32 skinnum = players[consoleplayer].skin;
CV_StealthSet(&cv_skin, skins[skinnum].name);
cv_skin.value = skinnum;
}
// Finally write out the complete packet and send it off.
@@ -1779,8 +1824,9 @@ static void SendNameAndColor2(void)
cv_skin2.value = R_SkinAvailable(cv_skin2.string);
if (cv_skin2.value < 0)
{
CV_StealthSet(&cv_skin2, DEFAULTSKIN);
cv_skin2.value = 0;
INT32 skinnum = players[displayplayers[1]].skin;
CV_StealthSet(&cv_skin2, skins[skinnum].name);
cv_skin2.value = skinnum;
}
// Finally write out the complete packet and send it off.
@@ -1899,8 +1945,9 @@ static void SendNameAndColor3(void)
cv_skin3.value = R_SkinAvailable(cv_skin3.string);
if (cv_skin3.value < 0)
{
CV_StealthSet(&cv_skin3, DEFAULTSKIN);
cv_skin3.value = 0;
INT32 skinnum = players[displayplayers[2]].skin;
CV_StealthSet(&cv_skin3, skins[skinnum].name);
cv_skin3.value = skinnum;
}
// Finally write out the complete packet and send it off.
@@ -2027,8 +2074,9 @@ static void SendNameAndColor4(void)
cv_skin4.value = R_SkinAvailable(cv_skin4.string);
if (cv_skin4.value < 0)
{
CV_StealthSet(&cv_skin4, DEFAULTSKIN);
cv_skin4.value = 0;
INT32 skinnum = players[displayplayers[3]].skin;
CV_StealthSet(&cv_skin4, skins[skinnum].name);
cv_skin4.value = skinnum;
}
// Finally write out the complete packet and send it off.
@@ -2933,6 +2981,10 @@ static void Command_Map_f(void)
}
}
// spend atleast 35 seconds in one map
if (cv_demochangemap.value && demo.recording && demo.savemode != DSM_NOTSAVING && (timeinmap > 1463) && ((cv_demochangemap.value == 2 && newmapnum == gamemap) || newmapnum != gamemap))
G_SaveDemo();
fromlevelselect = false;
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false);
@@ -5661,6 +5713,12 @@ void Command_ExitGame_f(void)
{
INT32 i;
if (dedicated)
{
CONS_Printf("This command cannot be used on dedicated server\n");
return;
}
D_QuitNetGame();
CL_Reset();
CV_ClearChangedFlags();
+7
View File
@@ -128,6 +128,7 @@ extern consvar_t cv_kartvoterulechanges;
extern consvar_t cv_kartgametypepreference;
extern consvar_t cv_kartspeedometer;
extern consvar_t cv_kartvoices;
extern consvar_t cv_karthitemdialog;
extern consvar_t cv_karteliminatelast;
@@ -201,10 +202,16 @@ extern consvar_t cv_ps_thinkframe_page;
extern consvar_t cv_ps_samplesize;
extern consvar_t cv_ps_descriptor;
extern consvar_t cv_director, cv_kartdebugdirector, cv_showdirectorhud;
extern consvar_t cv_showtrackaddon;
extern consvar_t cv_showspecstuff;
extern consvar_t cv_betainterscreen;
extern consvar_t cv_laglesscam;
typedef enum
{
SKINMENUTYPE_SCROLL = 0,
+2 -2
View File
@@ -833,7 +833,6 @@ void SV_FileSendTicker(void)
netbuffer->packettype = PT_FILEFRAGMENT;
// (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth)
while (packetsent-- && filestosend != 0)
{
for (i = currentnode, j = 0; j < MAXNETNODES;
@@ -1300,8 +1299,9 @@ void CURLPrepareFile(const char* url, int dfilenum)
curl_starttime = time(NULL);
curl_running = true;
#ifdef HAVE_THREADS
I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL);
#endif
}
}
+12 -5
View File
@@ -347,6 +347,14 @@ typedef enum
RW_RAIL = 32
} ringweapons_t;
// enum for saved lap times
typedef enum
{
LAP_CUR,
LAP_LAST,
LAP__MAX
} laptime_e;
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@@ -465,6 +473,7 @@ typedef struct player_s
INT16 numboxes; // Number of item boxes obtained for Race Mode
INT16 totalring; // Total number of rings obtained for Race Mode
tic_t realtime; // integer replacement for leveltime
tic_t laptime[LAP__MAX];
UINT8 laps; // Number of laps (optional)
////////////////////
@@ -537,15 +546,13 @@ typedef struct player_s
tic_t grieftime;
UINT8 griefstrikes;
tic_t hitemtimer;
UINT8 hitemvictim;
UINT8 splitscreenindex;
#ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering
#endif
struct {
angle_t aiming, awayviewaiming, frameangle;
angle_t viewrollangle;
} lerp;
} player_t;
#endif
+23 -163
View File
@@ -291,8 +291,6 @@ static void readPlayer(MYFILE *f, INT32 num)
INT32 i;
boolean slotfound = false;
DEH_WriteUndoline("PLAYERTEXT", description[num].notes, UNDO_ENDTEXT);
do
{
if (myfgets(s, MAXLINELEN, f))
@@ -362,7 +360,6 @@ static void readPlayer(MYFILE *f, INT32 num)
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE);
PlayerMenu[num].status = IT_CALL;
strncpy(description[num].picname, word2, 8);
}
@@ -386,7 +383,6 @@ static void readPlayer(MYFILE *f, INT32 num)
*/
if (i != IT_DISABLED && !slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, va("%d", PlayerMenu[num].status), UNDO_NONE);
PlayerMenu[num].status = (INT16)i;
}
else if (fastcmp(word, "SKINNAME"))
@@ -394,7 +390,6 @@ static void readPlayer(MYFILE *f, INT32 num)
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE);
PlayerMenu[num].status = IT_CALL;
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
@@ -557,122 +552,98 @@ static void readthing(MYFILE *f, INT32 num)
if (fastcmp(word, "MAPTHINGNUM") || fastcmp(word, "DOOMEDNUM"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].doomednum), UNDO_NONE);
mobjinfo[num].doomednum = (INT32)atoi(word2);
}
else if (fastcmp(word, "SPAWNSTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnstate), UNDO_NONE);
mobjinfo[num].spawnstate = get_number(word2);
}
else if (fastcmp(word, "SPAWNHEALTH"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnhealth), UNDO_NONE);
mobjinfo[num].spawnhealth = (INT32)get_number(word2);
}
else if (fastcmp(word, "SEESTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].seestate), UNDO_NONE);
mobjinfo[num].seestate = get_number(word2);
}
else if (fastcmp(word, "SEESOUND"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].seesound), UNDO_NONE);
mobjinfo[num].seesound = get_number(word2);
}
else if (fastcmp(word, "REACTIONTIME"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].reactiontime), UNDO_NONE);
mobjinfo[num].reactiontime = (INT32)get_number(word2);
}
else if (fastcmp(word, "ATTACKSOUND"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].attacksound), UNDO_NONE);
mobjinfo[num].attacksound = get_number(word2);
}
else if (fastcmp(word, "PAINSTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].painstate), UNDO_NONE);
mobjinfo[num].painstate = get_number(word2);
}
else if (fastcmp(word, "PAINCHANCE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].painchance), UNDO_NONE);
mobjinfo[num].painchance = (INT32)get_number(word2);
}
else if (fastcmp(word, "PAINSOUND"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].painsound), UNDO_NONE);
mobjinfo[num].painsound = get_number(word2);
}
else if (fastcmp(word, "MELEESTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].meleestate), UNDO_NONE);
mobjinfo[num].meleestate = get_number(word2);
}
else if (fastcmp(word, "MISSILESTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].missilestate), UNDO_NONE);
mobjinfo[num].missilestate = get_number(word2);
}
else if (fastcmp(word, "DEATHSTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathstate), UNDO_NONE);
mobjinfo[num].deathstate = get_number(word2);
}
else if (fastcmp(word, "DEATHSOUND"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathsound), UNDO_NONE);
mobjinfo[num].deathsound = get_number(word2);
}
else if (fastcmp(word, "XDEATHSTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].xdeathstate), UNDO_NONE);
mobjinfo[num].xdeathstate = get_number(word2);
}
else if (fastcmp(word, "SPEED"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].speed), UNDO_NONE);
mobjinfo[num].speed = get_number(word2);
}
else if (fastcmp(word, "RADIUS"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].radius), UNDO_NONE);
mobjinfo[num].radius = get_number(word2);
}
else if (fastcmp(word, "HEIGHT"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].height), UNDO_NONE);
mobjinfo[num].height = get_number(word2);
}
else if (fastcmp(word, "DISPOFFSET"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].dispoffset), UNDO_NONE);
mobjinfo[num].dispoffset = get_number(word2);
}
else if (fastcmp(word, "MASS"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].mass), UNDO_NONE);
mobjinfo[num].mass = (INT32)get_number(word2);
}
else if (fastcmp(word, "DAMAGE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].damage), UNDO_NONE);
mobjinfo[num].damage = (INT32)get_number(word2);
}
else if (fastcmp(word, "ACTIVESOUND"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].activesound), UNDO_NONE);
mobjinfo[num].activesound = get_number(word2);
}
else if (fastcmp(word, "FLAGS"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].flags), UNDO_NONE);
mobjinfo[num].flags = (INT32)get_number(word2);
}
else if (fastcmp(word, "RAISESTATE"))
{
DEH_WriteUndoline(word, va("%d", mobjinfo[num].raisestate), UNDO_NONE);
mobjinfo[num].raisestate = get_number(word2);
}
else
@@ -1110,8 +1081,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
UINT16 usi;
UINT8 picid;
DEH_WriteUndoline("SCENETEXT", cutscenes[num]->scene[scenenum].text, UNDO_ENDTEXT);
do
{
if (myfgets(s, MAXLINELEN, f))
@@ -1188,7 +1157,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
if (fastcmp(word, "NUMBEROFPICS"))
{
DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].numpics), UNDO_NONE);
cutscenes[num]->scene[scenenum].numpics = (UINT8)i;
}
else if (fastncmp(word, "PIC", 3))
@@ -1203,27 +1171,22 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
if (fastcmp(word+4, "NAME"))
{
DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].picname[picid], UNDO_NONE);
strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8);
}
else if (fastcmp(word+4, "HIRES"))
{
DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].pichires[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word+4, "DURATION"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].picduration[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].picduration[picid] = usi;
}
else if (fastcmp(word+4, "XCOORD"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].xcoord[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].xcoord[picid] = usi;
}
else if (fastcmp(word+4, "YCOORD"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].ycoord[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].ycoord[picid] = usi;
}
else
@@ -1231,14 +1194,12 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
}
else if (fastcmp(word, "MUSIC"))
{
DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7);
cutscenes[num]->scene[scenenum].musswitch[6] = 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (fastcmp(word, "MUSICSLOT"))
{
DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
i = get_mus(word2, true);
if (i && i <= 1035)
snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i));
@@ -1251,42 +1212,34 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
#endif
else if (fastcmp(word, "MUSICTRACK"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
}
else if (fastcmp(word, "MUSICPOS"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchposition), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2);
}
else if (fastcmp(word, "MUSICLOOP"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
cutscenes[num]->scene[scenenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TEXTXPOS"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textxpos), UNDO_NONE);
cutscenes[num]->scene[scenenum].textxpos = usi;
}
else if (fastcmp(word, "TEXTYPOS"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textypos), UNDO_NONE);
cutscenes[num]->scene[scenenum].textypos = usi;
}
else if (fastcmp(word, "FADEINID"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadeinid = (UINT8)i;
}
else if (fastcmp(word, "FADEOUTID"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadeoutid = (UINT8)i;
}
else if (fastcmp(word, "FADECOLOR"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i;
}
else
@@ -1346,8 +1299,6 @@ static void readcutscene(MYFILE *f, INT32 num)
if (1 <= value && value <= 128)
{
readcutscenescene(f, num, value - 1);
DEH_WriteUndoline(word, word2, UNDO_SPACE|UNDO_CUTLINE);
DEH_WriteUndoline("NUMSCENES", va("%d", oldnumscenes), UNDO_SPACE);
}
else
deh_warning("Scene number %d out of range (1 - 128)", value);
@@ -1403,12 +1354,10 @@ static void readhuditem(MYFILE *f, INT32 num)
if (fastcmp(word, "X"))
{
DEH_WriteUndoline(word, va("%d", hudinfo[num].x), UNDO_NONE);
hudinfo[num].x = i;
}
else if (fastcmp(word, "Y"))
{
DEH_WriteUndoline(word, va("%d", hudinfo[num].y), UNDO_NONE);
hudinfo[num].y = i;
}
else
@@ -1419,25 +1368,10 @@ static void readhuditem(MYFILE *f, INT32 num)
Z_Free(s);
}
/*
Sprite number = 10
Sprite subnumber = 32968
Duration = 200
Next frame = 200
*/
/** Action pointer for reading actions from Dehacked lumps.
*/
typedef struct
{
actionf_t action; ///< Function pointer corresponding to the actual action.
const char *name; ///< Name of the action in ALL CAPS.
} actionpointer_t;
/** Array mapping action names to action functions.
* Names must be in ALL CAPS for case insensitive comparisons.
*/
static actionpointer_t actionpointers[] =
// IMPORTANT!
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONNUM ENUM IN INFO.H
actionpointer_t actionpointers[] =
{
{{A_Explode}, "A_EXPLODE"},
{{A_Pain}, "A_PAIN"},
@@ -1592,6 +1526,7 @@ static actionpointer_t actionpointers[] =
{{A_FZBoomSmoke}, "A_FZBOOMSMOKE"}, //SRB2kart
{{A_RandomShadowFrame}, "A_RANDOMSHADOWFRAME"}, //SRB2kart
{{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart
{{A_MayonakaArrow}, "A_MAYONAKAARROW"}, //SRB2kart
{{A_ReaperThinker}, "A_REAPERTHINKER"}, //SRB2kart
{{A_MementosTPParticles}, "A_MEMENTOSTPPARTICLES"}, //SRB2kart
{{A_FlameParticle}, "A_FLAMEPARTICLE"}, // SRB2kart
@@ -1684,32 +1619,26 @@ static void readframe(MYFILE *f, INT32 num)
if (fastcmp(word1, "SPRITENUMBER") || fastcmp(word1, "SPRITENAME"))
{
DEH_WriteUndoline(word1, va("%u", states[num].sprite), UNDO_NONE);
states[num].sprite = get_sprite(word2);
}
else if (fastcmp(word1, "SPRITESUBNUMBER") || fastcmp(word1, "SPRITEFRAME"))
{
DEH_WriteUndoline(word1, va("%d", states[num].frame), UNDO_NONE);
states[num].frame = (INT32)get_number(word2); // So the FF_ flags get calculated
}
else if (fastcmp(word1, "DURATION"))
{
DEH_WriteUndoline(word1, va("%u", states[num].tics), UNDO_NONE);
states[num].tics = (INT32)get_number(word2); // So TICRATE can be used
}
else if (fastcmp(word1, "NEXT"))
{
DEH_WriteUndoline(word1, va("%d", states[num].nextstate), UNDO_NONE);
states[num].nextstate = get_state(word2);
}
else if (fastcmp(word1, "VAR1"))
{
DEH_WriteUndoline(word1, va("%d", states[num].var1), UNDO_NONE);
states[num].var1 = (INT32)get_number(word2);
}
else if (fastcmp(word1, "VAR2"))
{
DEH_WriteUndoline(word1, va("%d", states[num].var2), UNDO_NONE);
states[num].var2 = (INT32)get_number(word2);
}
else if (fastcmp(word1, "ACTION"))
@@ -1735,7 +1664,6 @@ static void readframe(MYFILE *f, INT32 num)
{
if (actionpointers[z].action.acv == states[num].action.acv)
{
DEH_WriteUndoline(word1, actionpointers[z].name, UNDO_NONE);
break;
}
}
@@ -1795,17 +1723,14 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
if (fastcmp(word, "SINGULAR"))
{
DEH_WriteUndoline(word, va("%d", S_sfx[num].singularity), UNDO_NONE);
S_sfx[num].singularity = value;
}
else if (fastcmp(word, "PRIORITY"))
{
DEH_WriteUndoline(word, va("%d", S_sfx[num].priority), UNDO_NONE);
S_sfx[num].priority = value;
}
else if (fastcmp(word, "FLAGS"))
{
DEH_WriteUndoline(word, va("%d", S_sfx[num].pitch), UNDO_NONE);
S_sfx[num].pitch = value;
}
else
@@ -1865,16 +1790,6 @@ static void reademblemdata(MYFILE *f, INT32 num)
INT32 value;
// Reset all data initially
DEH_WriteUndoline("TYPE", va("%d", emblemlocations[num-1].type), UNDO_NONE);
DEH_WriteUndoline("X", va("%d", emblemlocations[num-1].x), UNDO_NONE);
DEH_WriteUndoline("Y", va("%d", emblemlocations[num-1].y), UNDO_NONE);
DEH_WriteUndoline("Z", va("%d", emblemlocations[num-1].z), UNDO_NONE);
DEH_WriteUndoline("MAPNUM", va("%d", emblemlocations[num-1].level), UNDO_NONE);
DEH_WriteUndoline("VAR", va("%d", emblemlocations[num-1].var), UNDO_NONE);
DEH_WriteUndoline("SPRITE", va("%d", emblemlocations[num-1].sprite), UNDO_NONE);
DEH_WriteUndoline("COLOR", va("%d", emblemlocations[num-1].color), UNDO_NONE);
DEH_WriteUndoline("HINT", extraemblems[num-1].hint, UNDO_NONE);
memset(&emblemlocations[num-1], 0, sizeof(emblem_t));
do
@@ -2002,12 +1917,6 @@ static void readextraemblemdata(MYFILE *f, INT32 num)
INT32 value;
// Reset all data initially
DEH_WriteUndoline("NAME", extraemblems[num-1].name, UNDO_NONE);
DEH_WriteUndoline("OBJECTIVE", extraemblems[num-1].description, UNDO_NONE);
DEH_WriteUndoline("CONDITIONSET", va("%d", extraemblems[num-1].conditionset), UNDO_NONE);
DEH_WriteUndoline("SPRITE", va("%d", extraemblems[num-1].sprite), UNDO_NONE);
DEH_WriteUndoline("COLOR", va("%d", extraemblems[num-1].color), UNDO_NONE);
memset(&extraemblems[num-1], 0, sizeof(extraemblem_t));
do
@@ -2086,15 +1995,6 @@ static void readunlockable(MYFILE *f, INT32 num)
INT32 i;
// Same deal with unlockables, clear all first
DEH_WriteUndoline("NAME", unlockables[num].name, UNDO_NONE);
DEH_WriteUndoline("OBJECTIVE", unlockables[num].objective, UNDO_NONE);
DEH_WriteUndoline("HEIGHT", va("%d", unlockables[num].height), UNDO_NONE);
DEH_WriteUndoline("CONDITIONSET", va("%d", unlockables[num].conditionset), UNDO_NONE);
DEH_WriteUndoline("TYPE", va("%d", unlockables[num].type), UNDO_NONE);
DEH_WriteUndoline("NOCECHO", va("%d", unlockables[num].nocecho), UNDO_NONE);
DEH_WriteUndoline("NOCHECKLIST", va("%d", unlockables[num].nochecklist), UNDO_NONE);
DEH_WriteUndoline("VAR", va("%d", unlockables[num].variable), UNDO_NONE);
memset(&unlockables[num], 0, sizeof(unlockable_t));
do
@@ -2473,13 +2373,11 @@ static void readpatch(MYFILE *f, const char *name, UINT16 wad)
// X position of the patch in the texture.
if (fastcmp(word, "X"))
{
//DEH_WriteUndoline(word, va("%d", patch->originx), UNDO_NONE);
patch.originx = (INT16)value;
}
// Y position of the patch in the texture.
else if (fastcmp(word, "Y"))
{
//DEH_WriteUndoline(word, va("%d", patch->originy), UNDO_NONE);
patch.originy = (INT16)value;
}
else
@@ -2548,7 +2446,6 @@ static void readmaincfg(MYFILE *f)
else
value = get_number(word2);
DEH_WriteUndoline(word, va("%d", spstage_start), UNDO_NONE);
spstage_start = (INT16)value;
}
else if (fastcmp(word, "SSTAGE_START"))
@@ -2562,79 +2459,64 @@ static void readmaincfg(MYFILE *f)
else
value = get_number(word2);
DEH_WriteUndoline(word, va("%d", sstage_start), UNDO_NONE);
sstage_start = (INT16)value;
sstage_end = (INT16)(sstage_start+6); // 7 special stages total
}
else if (fastcmp(word, "USENIGHTSSS"))
{
DEH_WriteUndoline(word, va("%d", useNightsSS), UNDO_NONE);
useNightsSS = (value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "REDTEAM"))
{
DEH_WriteUndoline(word, va("%d", skincolor_redteam), UNDO_NONE);
skincolor_redteam = (UINT8)get_number(word2);
}
else if (fastcmp(word, "BLUETEAM"))
{
DEH_WriteUndoline(word, va("%d", skincolor_blueteam), UNDO_NONE);
skincolor_blueteam = (UINT8)get_number(word2);
}
else if (fastcmp(word, "REDRING"))
{
DEH_WriteUndoline(word, va("%d", skincolor_redring), UNDO_NONE);
skincolor_redring = (UINT8)get_number(word2);
}
else if (fastcmp(word, "BLUERING"))
{
DEH_WriteUndoline(word, va("%d", skincolor_bluering), UNDO_NONE);
skincolor_bluering = (UINT8)get_number(word2);
}
else if (fastcmp(word, "INVULNTICS"))
{
DEH_WriteUndoline(word, va("%u", invulntics), UNDO_NONE);
invulntics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SNEAKERTICS"))
{
DEH_WriteUndoline(word, va("%u", sneakertics), UNDO_NONE);
sneakertics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "FLASHINGTICS"))
{
DEH_WriteUndoline(word, va("%u", flashingtics), UNDO_NONE);
flashingtics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "TAILSFLYTICS"))
{
DEH_WriteUndoline(word, va("%u", tailsflytics), UNDO_NONE);
tailsflytics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "UNDERWATERTICS"))
{
DEH_WriteUndoline(word, va("%u", underwatertics), UNDO_NONE);
underwatertics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SPACETIMETICS"))
{
DEH_WriteUndoline(word, va("%u", spacetimetics), UNDO_NONE);
spacetimetics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "EXTRALIFETICS"))
{
DEH_WriteUndoline(word, va("%u", extralifetics), UNDO_NONE);
extralifetics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "GAMEOVERTICS"))
{
DEH_WriteUndoline(word, va("%u", gameovertics), UNDO_NONE);
gameovertics = get_number(word2);
}
else if (fastcmp(word, "INTROTOPLAY"))
{
DEH_WriteUndoline(word, va("%d", introtoplay), UNDO_NONE);
introtoplay = (UINT8)get_number(word2);
// range check, you morons.
if (introtoplay > 128)
@@ -2642,17 +2524,14 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "LOOPTITLE"))
{
DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE);
looptitle = (value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TITLESCROLLSPEED"))
{
DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE);
titlescrollspeed = get_number(word2);
}
else if (fastcmp(word, "CREDITSCUTSCENE"))
{
DEH_WriteUndoline(word, va("%d", creditscutscene), UNDO_NONE);
creditscutscene = (UINT8)get_number(word2);
// range check, you morons.
if (creditscutscene > 128)
@@ -2660,27 +2539,22 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "NUMDEMOS"))
{
DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE);
numDemos = (UINT8)get_number(word2);
}
else if (fastcmp(word, "DEMODELAYTIME"))
{
DEH_WriteUndoline(word, va("%d", demoDelayTime), UNDO_NONE);
demoDelayTime = get_number(word2);
}
else if (fastcmp(word, "DEMOIDLETIME"))
{
DEH_WriteUndoline(word, va("%d", demoIdleTime), UNDO_NONE);
demoIdleTime = get_number(word2);
}
else if (fastcmp(word, "USE1UPSOUND"))
{
DEH_WriteUndoline(word, va("%u", use1upSound), UNDO_NONE);
use1upSound = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "MAXXTRALIFE"))
{
DEH_WriteUndoline(word, va("%u", maxXtraLife), UNDO_NONE);
maxXtraLife = (UINT8)get_number(word2);
}
@@ -2694,7 +2568,6 @@ static void readmaincfg(MYFILE *f)
I_Error("Maincfg: bad data file name '%s'\n", word2);
G_SaveGameData(false);
DEH_WriteUndoline(word, gamedatafilename, UNDO_NONE);
strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
strlwr(gamedatafilename);
savemoddata = true;
@@ -2715,12 +2588,10 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "RESETDATA"))
{
DEH_WriteUndoline(word, "0", UNDO_TODO); /// \todo
P_ResetData(value);
}
else if (fastcmp(word, "CUSTOMVERSION"))
{
DEH_WriteUndoline(word, customversionstring, UNDO_NONE);
strlcpy(customversionstring, word2, sizeof (customversionstring));
}
else
@@ -2980,13 +2851,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
{
G_SetGameModified(multiplayer, true);
readmaincfg(f);
DEH_WriteUndoline(word, "", UNDO_HEADER);
continue;
}
else if (fastcmp(word, "WIPES"))
{
readwipes(f);
DEH_WriteUndoline(word, "", UNDO_HEADER);
// This is not a major mod.
continue;
}
@@ -3007,7 +2876,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Character %d out of range (0 - 31)", i);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
continue;
}
@@ -3021,7 +2889,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
{
// Read patch from spec file.
readpatch(f, word2, wad);
DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
}
else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
@@ -3039,13 +2906,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Thing %d out of range (0 - %d)", i, NUMMOBJTYPES-1);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
/* else if (fastcmp(word, "ANIMTEX"))
{
readAnimTex(f, i);
// This is not a major mod.
}*/
else if (fastcmp(word, "LEVEL"))
{
// Support using the actual map name,
@@ -3066,7 +2927,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CUTSCENE"))
{
@@ -3077,8 +2937,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Cutscene number %d out of range (1 - 128)", i);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
//G_SetGameModified(multiplayer, true); -- might have to reconsider in a future update
}
else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE"))
{
@@ -3095,7 +2953,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Frame %d out of range (0 - %d)", i, NUMSTATES-1);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "SOUND"))
{
@@ -3108,7 +2965,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Sound %d out of range (0 - %d)", i, NUMSFX-1);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
}
else if (fastcmp(word, "HUDITEM"))
@@ -3122,7 +2978,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("HUD item number %d out of range (0 - %d)", i, NUMHUDITEMS-1);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
}
else if (fastcmp(word, "EMBLEM"))
@@ -3143,7 +2998,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Emblem number %d out of range (1 - %d)", i, MAXEMBLEMS);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "EXTRAEMBLEM"))
{
@@ -3163,7 +3017,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Extra emblem number %d out of range (1 - %d)", i, MAXEXTRAEMBLEMS);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "UNLOCKABLE"))
{
@@ -3179,7 +3032,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Unlockable number %d out of range (1 - %d)", i, MAXUNLOCKABLES);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CONDITIONSET"))
{
@@ -3195,15 +3047,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Condition set number %d out of range (1 - %d)", i, MAXCONDITIONSETS);
ignorelines(f);
}
// no undo support for this insanity yet
//DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "SRB2KART"))
{
INT32 ver = searchvalue(strtok(NULL, "\n"));
if (ver != PATCHVERSION)
deh_warning("Patch is for SRB2Kart version %d,\nonly version %d is supported", ver, PATCHVERSION);
//DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE);
}
else if (fastcmp(word, "SRB2"))
{
@@ -3282,7 +3131,6 @@ void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump)
f.curpos = f.data;
f.data[f.size] = 0;
DEH_LoadDehackedFile(&f, wad);
DEH_WriteUndoline(va("# uload for wad: %u, lump: %u", wad, lump), NULL, UNDO_DONE);
Z_Free(f.data);
}
@@ -9130,12 +8978,15 @@ int LUA_EnumLib(lua_State *L)
char *str = NULL;
int size = 0;
// Sound enum tables preallocated for sfx_freeslot0 elements because using NUMSFX may be too
// much if number of skins increased a lot (because of skinsound freeslots)
/* SFX (SFX_) */
lua_pushcfunction(L, lua_glib_new_enum);
lua_createtable(L, 0, NUMSFX);
lua_createtable(L, 0, sfx_freeslot0);
for (int i = 0; i < NUMSFX; i++)
{
if (!S_sfx[i].name) continue;
if (!S_sfx[i].name || !S_sfx[i].priority) continue;
if (lua_enumlib_sprintf_upper(&str, &size, "SFX_%s", S_sfx[i].name) == NULL)
return luaL_error(L, "Ran out of memory.");
@@ -9150,10 +9001,10 @@ int LUA_EnumLib(lua_State *L)
/* SFX (DS) */
lua_pushcfunction(L, lua_glib_new_enum);
lua_createtable(L, 0, NUMSFX);
lua_createtable(L, 0, sfx_freeslot0);
for (int i = 0; i < NUMSFX; i++)
{
if (!S_sfx[i].name) continue;
if (!S_sfx[i].name || !S_sfx[i].priority) continue;
if (lua_enumlib_sprintf_upper(&str, &size, "DS%s", S_sfx[i].name) == NULL)
return luaL_error(L, "Ran out of memory.");
@@ -9188,10 +9039,10 @@ int LUA_EnumLib(lua_State *L)
{
/* SFX (sfx_) */
lua_pushcfunction(L, lua_glib_new_enum);
lua_createtable(L, 0, NUMSFX);
lua_createtable(L, 0, sfx_freeslot0);
for (int i = 0; i < NUMSFX; i++)
{
if (!S_sfx[i].name) continue;
if (!S_sfx[i].name || !S_sfx[i].priority) continue;
lua_pushfstring(L, "sfx_%s", S_sfx[i].name);
lua_pushinteger(L, i);
@@ -9422,4 +9273,13 @@ void LUA_SetActionByName(void *state, const char *actiontocompare)
return;
}
}
}
}
enum actionnum LUA_GetActionNumByName(const char *actiontocompare)
{
size_t z;
for (z = 0; actionpointers[z].name; z++)
if (fasticmp(actiontocompare, actionpointers[z].name))
return z;
return z;
}
+1 -14
View File
@@ -15,20 +15,6 @@
#include "m_fixed.h" // for get_number
typedef enum
{
UNDO_NONE = 0x00,
UNDO_NEWLINE = 0x01,
UNDO_SPACE = 0x02,
UNDO_CUTLINE = 0x04,
UNDO_HEADER = 0x07,
UNDO_ENDTEXT = 0x08,
UNDO_TODO = 0,
UNDO_DONE = 0,
} undotype_f;
#define DEH_WriteUndoline(a,b,c)
void DEH_LoadDehackedLump(lumpnum_t lumpnum);
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump);
@@ -41,6 +27,7 @@ fixed_t get_number(const char *word);
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
enum actionnum LUA_GetActionNumByName(const char *actiontocompare);
extern boolean deh_loaded;
+32 -4
View File
@@ -128,11 +128,11 @@ extern char logfilename[1024];
#define VERSION 1 // Game version
#define SUBVERSION 6 // more precise version number
#ifndef USE_FBO_OGL
#define VERSIONSTRING "Saturn v6.2 "
#define VERSIONSTRINGW L"Saturn v6.2"
#define VERSIONSTRING "Saturn v7"
#define VERSIONSTRINGW L"Saturn v7"
#else
#define VERSIONSTRING "Saturn v6.2 - FBO "
#define VERSIONSTRINGW L"Saturn v6.2 - FBO"
#define VERSIONSTRING "Saturn v7 - FBO "
#define VERSIONSTRINGW L"Saturn v7 - FBO"
#endif
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt (not src/, but in root), for CMake users!
@@ -211,6 +211,7 @@ extern char logfilename[1024];
#define MAXPLAYERS 16
#define MAXSKINS 255
#define MAXLOCALSKINS 32
#define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21
@@ -528,6 +529,10 @@ INT32 I_GetKey(void);
#define max(x, y) (((x) > (y)) ? (x) : (y))
#endif
#ifndef CLAMP
#define CLAMP(x, min_val, max_val) ((x) < (min_val) ? (min_val) : ((x) > (max_val) ? (max_val) : (x)))
#endif
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
@@ -563,6 +568,29 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
// None of these that are disabled in the normal build are guaranteed to work perfectly
// Compile them at your own risk!
#ifndef NONET
//-- SATURN __
/// Enable gamestate resynching between Saturn servers and clients
/// Like SRB2 and RR does
/// Still highly experimental
#ifdef DOSATURNSYNCH
#define SATURNSYNCH
/// Detect if a client is on Saturn in the clientconfig.
/// To seperately allow them to join or block joining from vanilla clients.
#ifdef DOSATURNJOIN
#define SATURNJOIN
#endif
#endif
/// Server detection for if a connecting client is on Saturn.
/// For stuff like extra synching, etc.
//#ifdef DOSATURNPAK
//#define SATURNPAK
//#endif
//-- <( ̄︶ ̄)> __
#endif
/// Undefine to use the new method of Gamma correction see colour cube in v_video.c
#define BACKWARDSCOMPATCORRECTION
+12
View File
@@ -510,6 +510,18 @@ extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
#define WAYPOINTSEQUENCESIZE 256
#define NUMWAYPOINTSEQUENCES 256
extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint);
mobj_t *P_GetFirstWaypoint(UINT8 sequence);
mobj_t *P_GetLastWaypoint(UINT8 sequence);
mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap);
mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap);
mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo);
// =====================================
// Internal parameters, used for engine.
// =====================================
+2 -1
View File
@@ -349,7 +349,8 @@ typedef enum
postimg_motion,
postimg_flip,
postimg_heat,
postimg_mirror
postimg_mirror,
postimg_mirrorflip
} postimg_t;
typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num)
+9 -11
View File
@@ -37,7 +37,6 @@
#include <tchar.h>
#define SUFFIX "*"
#define SLASH "\\"
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#ifndef INVALID_FILE_ATTRIBUTES
@@ -135,7 +134,7 @@ opendir (const CHAR *szPath)
/* Allocate enough space to store DIR structure and the complete
* directory path given. */
nd = (DIR *) malloc (sizeof (DIR) + (strlen(szFullPath) + strlen (SLASH) +
strlen(SUFFIX) + 1) * sizeof (CHAR));
strlen(PATHSEP) + 1) * sizeof (CHAR));
if (!nd)
{
@@ -149,10 +148,9 @@ opendir (const CHAR *szPath)
/* Add on a slash if the path does not end with one. */
if (nd->dd_name[0] != '\0' &&
nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
nd->dd_name[strlen (nd->dd_name) - 1] != PATHSEP[0])
{
strcat (nd->dd_name, SLASH);
strcat (nd->dd_name, PATHSEP);
}
/* Add on the search pattern */
@@ -382,9 +380,9 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
return FS_NOTFOUND;
}
if (searchpath[searchpathindex[depthleft]-2] != '/')
if (searchpath[searchpathindex[depthleft]-2] != PATHSEP[0])
{
searchpath[searchpathindex[depthleft]-1] = '/';
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
searchpath[searchpathindex[depthleft]] = 0;
}
else
@@ -392,7 +390,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
while ((!found) && (depthleft < maxsearchdepth))
{
searchpath[searchpathindex[depthleft]]=0;
searchpath[searchpathindex[depthleft]] = 0;
dent = readdir(dirhandle[depthleft]);
if (!dent)
@@ -419,7 +417,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
if (S_ISDIR(fsstat.st_mode))
dent->d_type = DT_DIR;
else if (S_ISLNK(fsstat.st_mode))
dent->d_type = DT_LNK;
dent->d_type = DT_LNK;
}
// Symlinks aren't always directory symlinks. Dunno if this would resolve recursive
@@ -447,8 +445,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
depthleft++;
}
searchpath[searchpathindex[depthleft]-1]='/';
searchpath[searchpathindex[depthleft]]=0;
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
searchpath[searchpathindex[depthleft]] = 0;
}
else if (!strcasecmp(searchname, dent->d_name))
{
+129 -81
View File
@@ -50,6 +50,7 @@
#include "b_bot.h"
#include "m_cond.h" // condition sets
#include "md5.h" // demo checksums
#include "k_director.h" // SRB2kart
#include "k_kart.h" // SRB2kart
#include "r_fps.h" // frame interpolation/uncapped
@@ -335,6 +336,11 @@ boolean precache = true; // if true, load all graphics at start
INT16 prevmap, nextmap;
// save if director is enabled
// so demos can disable it by default and restore it after
static int directorstate = 0;
tic_t directortoggletimer = 0;
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}};
consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -345,6 +351,9 @@ consvar_t cv_netdemosyncquality = {"netdemo_syncquality", "1", CV_SAVE, netdemos
static CV_PossibleValue_t maxdemosize_cons_t[] = {{10, "MIN"}, {100, "MAX"}, {0, NULL}};
consvar_t cv_maxdemosize = {"maxdemosize", "10", CV_SAVE, maxdemosize_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t demochangemap_cons_t[] = {{0, "Disabled"}, {1, "Diff Map"}, {2, "Always"}, {0, NULL}};
consvar_t cv_demochangemap = {"netdemo_savemapchange", "Disabled", CV_SAVE, demochangemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static UINT8 *savebuffer;
// Analog Control
@@ -417,8 +426,9 @@ consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NUL
consvar_t cv_showfreeplay = { "showfreeplay", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// We can disable special tunes!
consvar_t cv_growmusic = {"growmusic", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_supermusic = {"supermusic", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t powermusic_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "SFX"}, {0, NULL}};
consvar_t cv_growmusic = {"growmusic", "On", CV_SAVE, powermusic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_supermusic = {"supermusic", "On", CV_SAVE, powermusic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
/*consvar_t cv_crosshair = {"crosshair", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1187,7 +1197,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn.
// Kart, don't build a ticcmd if someone is resynching or the server is stopped too so we don't fly off course in bad conditions
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN) || hu_resynching)
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN) || hu_resynching
#ifdef SATURNSYNCH
|| hu_redownloadinggamestate
#endif
)
{
cmd->angleturn = (INT16)(lang >> 16);
cmd->aiming = G_ClipAimingPitch(&laim);
@@ -1637,7 +1651,7 @@ void G_DoLoadLevel(boolean resetplayer)
}
// Setup the level.
if (!P_SetupLevel(false))
if (!P_SetupLevel(false,false))
{
// fail so reset game stuff
Command_ExitGame_f();
@@ -1934,6 +1948,12 @@ boolean G_Responder(event_t *ev)
COM_ImmedExecute("changeteam4 spectator");
}
}
if (ev->data1 == gamecontrol[gc_director][0]
|| ev->data1 == gamecontrol[gc_director][1])
{
K_ToggleDirector();
directortoggletimer = 0;
}
return true;
@@ -2108,7 +2128,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive)
olddisplayplayer = (*displayplayerp);
/* Check if anyone is available to view. */
if (( playernum = G_FindView(playernum, viewnum, onlyactive, playernum < olddisplayplayer) ) == -1)
if ((playernum = G_FindView(playernum, viewnum, onlyactive, playernum < olddisplayplayer)) == -1)
return;
/* Focus our target view first so that we don't take its player. */
@@ -2118,6 +2138,8 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive)
camerap = &camera[viewnum-1];
P_ResetCamera(&players[(*displayplayerp)], camerap);
// Make sure the viewport doesn't interpolate at all into
// its new position -- just snap instantly into place.
R_ResetViewInterpolation(viewnum);
}
@@ -2131,6 +2153,11 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive)
(*displayplayerp) = G_FindView(0, viewd, onlyactive, false);
P_ResetCamera(&players[(*displayplayerp)], camerap);
// Make sure the viewport doesn't interpolate at all into
// its new position -- just snap instantly into place.
R_ResetViewInterpolation(viewd);
}
}
@@ -2244,13 +2271,14 @@ void G_Ticker(boolean run)
buf = gametic % TICQUEUE;
if (!demo.playback)
// read/write demo and check turbo cheat
for (i = 0; i < MAXPLAYERS; i++)
{
cmd = &players[i].cmd;
if (playeringame[i])
for (i = 0; i < MAXPLAYERS; i++) // read/write demo and check turbo cheat
{
cmd = &players[i].cmd;
if (!playeringame[i])
continue;
//@TODO all this throwdir stuff shouldn't be here! But it stays for now to maintain 1.0.4 compat...
// Remove for 1.1!
@@ -2485,6 +2513,10 @@ void G_PlayerReborn(INT32 player)
boolean fade;
boolean playing;
tic_t laptime[LAP__MAX];
INT32 i;
score = players[player].score;
marescore = players[player].marescore;
lives = players[player].lives;
@@ -2526,6 +2558,21 @@ void G_PlayerReborn(INT32 player)
bot = players[player].bot;
pity = players[player].pity;
if (leveltime <= starttime) // man i really hope this crap works kek but need to reset this somehow at mapstart
{
for (i = 0; i < LAP__MAX; i++)
{
laptime[i] = 0;
}
}
else
{
for (i = 0; i < LAP__MAX; i++)
{
laptime[i] = players[player].laptime[i];
}
}
// SRB2kart
if (leveltime <= starttime || spectator == true)
{
@@ -2617,6 +2664,11 @@ void G_PlayerReborn(INT32 player)
p->laps = laps;
p->totalring = totalring;
for (i = 0; i < LAP__MAX; i++)
{
p->laptime[i] = laptime[i];
}
p->mare = mare;
if (bot)
p->bot = 1; // reset to AI-controlled
@@ -2666,8 +2718,7 @@ void G_PlayerReborn(INT32 player)
}
/* I'm putting this here because lol */
fade = (cv_fading.value && cv_birdmusic.value && P_IsLocalPlayer(p));
fade = (cv_birdmusic.value && cv_fading.value && P_IsLocalPlayer(p));
if (fade)
{
@@ -2677,7 +2728,7 @@ void G_PlayerReborn(INT32 player)
Fade it in with the same call to avoid
max volume for a few milliseconds (?).
*/
if (! playing)
if (!playing)
S_SetRestoreMusicFadeInCvar(&cv_respawnfademusicback);
}
@@ -3033,12 +3084,6 @@ void G_DoReborn(INT32 playernum)
player_t *player = &players[playernum];
boolean starpost = false;
/*if (modeattacking) // Not needed for SRB2Kart.
{
M_EndModeAttackRun();
return;
}*/
// Make sure objectplace is OFF when you first start the level!
OP_ResetObjectplace();
@@ -3058,68 +3103,6 @@ void G_DoReborn(INT32 playernum)
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
}
/*else if (countdowntimeup || (!multiplayer && !modeattacking))
{
// reload the level from scratch
if (countdowntimeup)
{
player->starpostangle = 0;
player->starposttime = 0;
player->starpostx = 0;
player->starposty = 0;
player->starpostz = 0;
player->starpostnum = 0;
}
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD))
{
INT32 i;
player->playerstate = PST_REBORN;
P_LoadThingsOnly();
// Do a wipe
wipegamestate = -1;
if (player->starpostnum) // SRB2kart
starpost = true;
for (i = 0; i <= splitscreen; i++)
{
if (camera[i].chase)
P_ResetCamera(&players[displayplayers[i]], &camera[i]);
}
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
for (i = 0;i < JOYAXISSET; i++)
{
joyxmove[i] = joyymove[i] = 0;
joy2xmove[i] = joy2ymove[i] = 0;
joy3xmove[i] = joy3ymove[i] = 0;
joy4xmove[i] = joy4ymove[i] = 0;
}
mousex = mousey = 0;
mouse2x = mouse2y = 0;
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
// Starpost support
G_SpawnPlayer(playernum, starpost);
if (botingame)
{ // Bots respawn next to their master.
players[displayplayers[1]].playerstate = PST_REBORN;
G_SpawnPlayer(displayplayers[1], false);
}
}
else
{
LUAh_MapChange(gamemap);
G_DoLoadLevel(true);
}
}*/
else
{
// respawn at the start
@@ -4446,6 +4429,11 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
players[i].lives = 1; // SRB2Kart
// This should be cleared in P_SpawnPlayer but address sanitizer says "use-after-free"
// when reloading map sometimes
players[i].awayviewtics = 0;
players[i].awayviewmobj = NULL;
// The latter two should clear by themselves, but just in case
players[i].pflags &= ~(PF_TAGIT|PF_TAGGED|PF_FULLSTASIS);
@@ -7161,6 +7149,57 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
Z_Free(infobuffer);
}
void G_LoadDemoTitle(menudemo_t *pdemo)
{
UINT8 infobuffer[96], *info_p;
UINT16 pdemoversion;
size_t count;
FILE *handle = fopen(pdemo->filepath, "rb");
if (!handle)
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath);
sprintf(pdemo->title, "INVALID REPLAY");
return;
}
count = fread(infobuffer, 1, 96, handle);
fclose(handle);
info_p = infobuffer;
// First check isn't too accurate technically, but well, valid replays should be larger than that anyway
if (count < 96 || memcmp(info_p, DEMOHEADER, 12))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath);
sprintf(pdemo->title, "INVALID REPLAY");
return;
}
info_p += 12; // DEMOHEADER
READUINT8(info_p);
READUINT8(info_p);
pdemoversion = READUINT16(info_p);
switch(pdemoversion)
{
case DEMOVERSION: // latest always supported
// demo title
M_Memcpy(pdemo->title, info_p, 64);
break;
#ifdef DEMO_COMPAT_100
case 0x0001:
sprintf(pdemo->title, "Legacy Replay");
break;
#endif
// too old, cannot support.
default:
CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath);
sprintf(pdemo->title, "INVALID REPLAY");
}
}
//
// G_PlayDemo
//
@@ -7690,6 +7729,9 @@ post_compat:
players[i].kartweight = kartweight[i];
}
directorstate = cv_director.value;
CV_SetValue(&cv_director, 0);
demo.deferstart = true;
}
#undef SKIPERRORS
@@ -8256,6 +8298,11 @@ void G_StopDemo(void)
{
Z_Free(demobuffer);
demobuffer = NULL;
if (demo.playback)
{
CV_SetValue(&cv_director, directorstate);
directorstate = 0;
}
demo.playback = false;
if (demo.title)
modeattacking = false;
@@ -8493,6 +8540,7 @@ boolean G_DemoTitleResponder(event_t *ev)
void G_SetGamestate(gamestate_t newstate)
{
gamestate = newstate;
#ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence();
#endif
+4 -1
View File
@@ -39,7 +39,7 @@ extern UINT8 *demo_p;
// ======================================
// demoplaying back and demo recording
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_maxdemosize;
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_maxdemosize, cv_demochangemap;
// Publicly-accessible demo vars
struct demovars_s {
@@ -218,6 +218,8 @@ extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
extern boolean camspin[MAXSPLITSCREENPLAYERS]; // SRB2Kart
extern tic_t directortoggletimer;
//
// GAME
//
@@ -265,6 +267,7 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar
void G_DoLoadLevel(boolean resetplayer);
void G_LoadDemoInfo(menudemo_t *pdemo);
void G_LoadDemoTitle(menudemo_t *pdemo); // For use in replay search feature
void G_DeferedPlayDemo(const char *demo);
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
+216
View File
@@ -14,11 +14,17 @@
#include "doomdef.h"
#include "doomstat.h"
#include "g_input.h"
#include "g_game.h"
#include "keys.h"
#include "hu_stuff.h" // need HUFONT start & end
#include "d_net.h"
#include "console.h"
#include "i_system.h"
#include "i_video.h"
#include "r_draw.h"
#include "v_video.h"
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY, "MAX"}, {0, NULL}};
@@ -33,6 +39,89 @@ consvar_t cv_mouseysens2 = {"mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL
consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnsmooth = {"turnsmoothing", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static void G_ResetPlayerDeviceRumble(INT32 player);
static void rumble_off_handle(void);
static void rumble_off_handle2(void);
static void rumble_off_handle3(void);
static void rumble_off_handle4(void);
static void G_ResetPlayerGamepadIndicatorColor(INT32 player);
static void led_off_handle(void);
static void led_off_handle2(void);
static void led_off_handle3(void);
static void led_off_handle4(void);
consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = {
{"rumble", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, rumble_off_handle, 0, NULL, NULL, 0, 0, NULL},
{"rumble2", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, rumble_off_handle2, 0, NULL, NULL, 0, 0, NULL},
{"rumble3", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, rumble_off_handle3, 0, NULL, NULL, 0, 0, NULL},
{"rumble4", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, rumble_off_handle4, 0, NULL, NULL, 0, 0, NULL}
};
consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS] = {
{"gamepadled", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled2", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle2, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled3", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle3, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled4", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle4, 0, NULL, NULL, 0, 0, NULL}
};
consvar_t cv_ledpowerup[MAXSPLITSCREENPLAYERS] = {
{"ledpowerup", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
{"ledpowerup2", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle2, 0, NULL, NULL, 0, 0, NULL},
{"ledpowerup3", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle3, 0, NULL, NULL, 0, 0, NULL},
{"ledpowerup4", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle4, 0, NULL, NULL, 0, 0, NULL}
};
static void rumble_off_handle(void)
{
if (cv_rumble[0].value == 0)
G_ResetPlayerDeviceRumble(0);
}
static void rumble_off_handle2(void)
{
if (cv_rumble[1].value == 0)
G_ResetPlayerDeviceRumble(1);
}
static void rumble_off_handle3(void)
{
if (cv_rumble[2].value == 0)
G_ResetPlayerDeviceRumble(2);
}
static void rumble_off_handle4(void)
{
if (cv_rumble[3].value == 0)
G_ResetPlayerDeviceRumble(3);
}
static void led_off_handle(void)
{
G_ResetPlayerGamepadIndicatorColor(0);
}
static void led_off_handle2(void)
{
G_ResetPlayerGamepadIndicatorColor(1);
}
static void led_off_handle3(void)
{
G_ResetPlayerGamepadIndicatorColor(2);
}
static void led_off_handle4(void)
{
G_ResetPlayerGamepadIndicatorColor(3);
}
INT32 mousex, mousey;
INT32 mlooky; // like mousey but with a custom sensitivity for mlook
@@ -812,10 +901,137 @@ static const char *gamecontrolname[num_gamecontrols] =
"custom1",
"custom2",
"custom3",
"director",
};
#define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t))
#include "k_kart.h"
INT32 G_GetDeviceForPlayer(INT32 player)
{
switch (player)
{
case 0:
return cv_usejoystick.value;
break;
case 1:
return cv_usejoystick2.value;
break;
case 2:
return cv_usejoystick3.value;
break;
case 3:
return cv_usejoystick4.value;
break;
default:
return 0;
break;
}
}
inline UINT16 G_GetSkinColor(INT32 player)
{
// make rgb rainbow vomit when invul or flash blue when grow
if (cv_ledpowerup[player].value && gamestate == GS_LEVEL && players[displayplayers[player]].mo && (players[displayplayers[player]].kartstuff[k_invincibilitytimer] || players[displayplayers[player]].powers[pw_invulnerability] || players[displayplayers[player]].kartstuff[k_growshrinktimer]))
return players[displayplayers[player]].mo->color;
// take actual player skincolour when ingame
if (gamestate == GS_LEVEL && players[displayplayers[player]].skincolor)
return players[displayplayers[player]].skincolor;
// otherwise just fallback to whatever the cvar is
switch (player)
{
case 0:
return cv_playercolor.value;
break;
case 1:
return cv_playercolor2.value;
break;
case 2:
return cv_playercolor3.value;
break;
case 3:
return cv_playercolor4.value;
break;
default:
return 0;
break;
}
}
void G_SetPlayerGamepadIndicatorColor(INT32 player, UINT16 color)
{
INT32 device;
UINT16 skincolor;
byteColor_t byte_color;
I_Assert(player >= 0 && player < MAXSPLITSCREENPLAYERS);
if (cv_gamepadled[player].value == 0)
return;
device = G_GetDeviceForPlayer(player);
if (device <= 0)
{
return;
}
skincolor = color ? color : G_GetSkinColor(player);
byte_color = V_GetColor(colortranslations[skincolor][8]).s;
I_SetGamepadIndicatorColor(device, byte_color.red, byte_color.green, byte_color.blue);
}
static void G_ResetPlayerGamepadIndicatorColor(INT32 player)
{
if (cv_gamepadled[player].value == 0)
{
INT32 device = G_GetDeviceForPlayer(player);
if (device <= 0)
return;
I_SetGamepadIndicatorColor(device, 0, 0, 255);
}
else
G_SetPlayerGamepadIndicatorColor(player, 0);
}
static void G_ResetPlayerDeviceRumble(INT32 player)
{
INT32 device_id;
device_id = G_GetDeviceForPlayer(player);
if (device_id < 1)
{
return;
}
I_GamepadRumble(device_id, 0, 0, 0);
}
void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
{
INT32 device_id;
if (cv_rumble[player].value == 0)
{
return;
}
device_id = G_GetDeviceForPlayer(player);
if (device_id < 1)
{
return;
}
I_GamepadRumble(device_id, low_strength, high_strength, duration);
}
//
// Detach any keys associated to the given game control
// - pass the pointer to the gamecontrol table for the player being edited
+10
View File
@@ -15,6 +15,7 @@
#define __G_INPUT__
#include "d_event.h"
#include "doomstat.h"
#include "keys.h"
#include "command.h"
@@ -98,6 +99,7 @@ typedef enum
gc_custom1, // Lua scriptable
gc_custom2, // Lua scriptable
gc_custom3, // Lua scriptable
gc_director,
num_gamecontrols
} gamecontrols_e;
@@ -105,6 +107,9 @@ typedef enum
extern consvar_t cv_mousesens, cv_mouseysens;
extern consvar_t cv_mousesens2, cv_mouseysens2;
extern consvar_t cv_controlperkey, cv_turnsmooth;
extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_ledpowerup[MAXSPLITSCREENPLAYERS];
extern INT32 mousex, mousey;
extern INT32 mlooky; //mousey with mlookSensitivity
@@ -129,6 +134,11 @@ extern INT32 gamecontrol4[num_gamecontrols][2];
// peace to my little coder fingers!
// check a gamecontrol being active or not
UINT16 G_GetSkinColor(INT32 player);
INT32 G_GetDeviceForPlayer(INT32 player);
void G_SetPlayerGamepadIndicatorColor(INT32 player, UINT16 color);
void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
// remaps the input event to a game control.
void G_MapEventsToControls(event_t *ev);
+57 -57
View File
@@ -35,7 +35,7 @@ int finalVertexArrayAllocSize = 65536;
PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed
int polygonArraySize = 0;
UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray
PolygonArrayEntry **polygonArraySorted = NULL;// contains sorted pointers to polygonArray
int polygonArrayAllocSize = 65536;
FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon
@@ -47,7 +47,9 @@ int unsortedVertexArrayAllocSize = 65536;
void HWR_StartBatching(void)
{
if (currently_batching)
{
I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches");
}
// init arrays if that has not been done yet
if (!finalVertexArray)
@@ -55,7 +57,7 @@ void HWR_StartBatching(void)
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
}
@@ -96,8 +98,8 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
free(polygonArray);
polygonArray = new_array;
// also need to redo the index array, dont need to copy it though
free(polygonIndexArray);
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
free(polygonArraySorted);
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
}
while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize)
@@ -134,10 +136,8 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
static int comparePolygons(const void *p1, const void *p2)
{
unsigned int index1 = *(const unsigned int*)p1;
unsigned int index2 = *(const unsigned int*)p2;
PolygonArrayEntry* poly1 = &polygonArray[index1];
PolygonArrayEntry* poly2 = &polygonArray[index2];
PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
int diff;
INT64 diff64;
UINT32 downloaded1 = 0;
@@ -155,7 +155,7 @@ static int comparePolygons(const void *p1, const void *p2)
// skywalls and horizon lines must retain their order for horizon lines to work
if (shader1 == -1 && shader2 == -1)
return index1 - index2;
return poly1 - poly2;
if (poly1->texture)
downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons
@@ -184,10 +184,8 @@ static int comparePolygons(const void *p1, const void *p2)
static int comparePolygonsNoShaders(const void *p1, const void *p2)
{
unsigned int index1 = *(const unsigned int*)p1;
unsigned int index2 = *(const unsigned int*)p2;
PolygonArrayEntry* poly1 = &polygonArray[index1];
PolygonArrayEntry* poly2 = &polygonArray[index2];
PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
int diff;
INT64 diff64;
@@ -205,7 +203,7 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2)
downloaded2 = texture2->downloaded;
// skywalls and horizon lines must retain their order for horizon lines to work
if (!texture1 && !texture2)
return index1 - index2;
return poly1 - poly2;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
@@ -225,7 +223,7 @@ void HWR_RenderBatches(void)
int finalVertexWritePos = 0;// position in finalVertexArray
int finalIndexWritePos = 0;// position in finalVertexIndexArray
int polygonReadPos = 0;// position in polygonIndexArray
int polygonReadPos = 0;// position in polygonArraySorted
int currentShader;
int nextShader = 0;
@@ -258,18 +256,18 @@ void HWR_RenderBatches(void)
ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0;
ps_hw_numshaders.value.i = ps_hw_numtextures.value.i
= ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1;
// init polygonIndexArray
// init polygonArraySorted
for (i = 0; i < polygonArraySize; i++)
{
polygonIndexArray[i] = i;
polygonArraySorted[i] = &polygonArray[i];
}
// sort polygons
PS_START_TIMING(ps_hw_batchsorttime);
if (cv_grshaders.value && gr_shadersavailable)
qs22j(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
qs22j(polygonArraySorted, polygonArraySize, sizeof(PolygonArrayEntry *), comparePolygons);
else
qs22j(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
qs22j(polygonArraySorted, polygonArraySize, sizeof(PolygonArrayEntry *), comparePolygonsNoShaders);
PS_STOP_TIMING(ps_hw_batchsorttime);
// sort order
// 1. shader
@@ -280,10 +278,10 @@ void HWR_RenderBatches(void)
PS_START_TIMING(ps_hw_batchdrawtime);
currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture;
currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags;
currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf;
currentShader = polygonArraySorted[0]->shader;
currentTexture = polygonArraySorted[0]->texture;
currentPolyFlags = polygonArraySorted[0]->polyFlags;
currentSurfaceInfo = polygonArraySorted[0]->surf;
// For now, will sort and track the colors. Vertex attributes could be used instead of uniforms
// and a color array could replace the color calls.
@@ -322,8 +320,8 @@ void HWR_RenderBatches(void)
// reset write pos
// repeat loop
int index = polygonIndexArray[polygonReadPos++];
int numVerts = polygonArray[index].numVerts;
PolygonArrayEntry *entry = polygonArraySorted[polygonReadPos++];
int numVerts = entry->numVerts;
// before writing, check if there is enough room
// using 'while' instead of 'if' here makes sure that there will *always* be enough room.
// probably never will this loop run more than once though
@@ -344,7 +342,7 @@ void HWR_RenderBatches(void)
finalVertexIndexArray = new_index_array;
}
// write the vertices of the polygon
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex],
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[entry->vertsIndex],
numVerts * sizeof(FOutVector));
// write the indexes, pointing to the fan vertexes but in triangles format
firstIndex = finalVertexWritePos;
@@ -364,11 +362,11 @@ void HWR_RenderBatches(void)
else
{
// check if a state change is required, set the change bools and next vars
int nextIndex = polygonIndexArray[polygonReadPos];
nextShader = polygonArray[nextIndex].shader;
nextTexture = polygonArray[nextIndex].texture;
nextPolyFlags = polygonArray[nextIndex].polyFlags;
nextSurfaceInfo = polygonArray[nextIndex].surf;
PolygonArrayEntry *nextEntry = polygonArraySorted[polygonReadPos];
nextShader = nextEntry->shader;
nextTexture = nextEntry->texture;
nextPolyFlags = nextEntry->polyFlags;
nextSurfaceInfo = nextEntry->surf;
if (nextPolyFlags & PF_NoTexture)
nextTexture = 0;
if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable)
@@ -426,38 +424,40 @@ void HWR_RenderBatches(void)
if (stopFlag) break;
// change state according to change bools and next vars, update current vars and reset bools
if (changeShader)
if (changeState)
{
HWD.pfnSetShader(nextShader);
currentShader = nextShader;
changeShader = false;
if (changeShader)
{
HWD.pfnSetShader(nextShader);
currentShader = nextShader;
changeShader = false;
ps_hw_numshaders.value.i++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to SetTexture during batch collection
HWD.pfnSetTexture(nextTexture);
currentTexture = nextTexture;
changeTexture = false;
ps_hw_numshaders.value.i++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to SetTexture during batch collection
HWD.pfnSetTexture(nextTexture);
currentTexture = nextTexture;
changeTexture = false;
ps_hw_numtextures.value.i++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
ps_hw_numtextures.value.i++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
ps_hw_numpolyflags.value.i++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
ps_hw_numpolyflags.value.i++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
ps_hw_numcolors.value.i++;
ps_hw_numcolors.value.i++;
}
}
// and that should be it?
}
// reset the arrays (set sizes to 0)
polygonArraySize = 0;
+1 -1
View File
@@ -17,7 +17,7 @@
#include "hw_data.h"
#include "hw_drv.h"
typedef struct
typedef struct
{
FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused
unsigned int vertsIndex;// location of verts in unsortedVertexArray
+18 -8
View File
@@ -667,9 +667,15 @@ static boolean PointInSeg(polyvertex_t *a,polyvertex_t *v1,polyvertex_t *v2)
// v1 = origine
ax= v2->x-v1->x;
ay= v2->y-v1->y;
norm = (float)hypot(ax, ay);
ax /= norm;
ay /= norm;
norm = hypotf(ax, ay);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
if (norm != 0) // yes, this can be exactly 0
#pragma GCC diagnostic pop
{
ax /= norm;
ay /= norm;
}
bx = a->x-v1->x;
by = a->y-v1->y;
//d = a.b
@@ -772,9 +778,11 @@ static INT32 SolveTProblem(void)
for (l = 0; l < addsubsector; l++)
{
p = extrasubsectors[l].planepoly;
if (p)
for (i = 0; i < p->numpts; i++)
SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p);
if (!p)
continue;
for (i = 0; i < p->numpts; i++)
SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p);
}
//CONS_Debug(DBG_RENDER, "numsplitpoly %d\n", numsplitpoly);
return numsplitpoly;
@@ -802,8 +810,10 @@ static void AdjustSegs(void)
count = subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline];
p = extrasubsectors[i].planepoly;
//if (!p)
//continue;
if (!p)
continue;
for (; count--; lseg++)
{
float distv1,distv2,tmp;
+24 -17
View File
@@ -26,6 +26,7 @@
#include "../z_zone.h"
#include "../v_video.h"
#include "../r_draw.h"
#include "../r_main.h"
#include "../r_patch.h" // patch rotation
INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes
@@ -344,7 +345,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, boolean noe
#ifdef GLENCORE
if (encoremap && !noencore)
grtex->mipmap.colormap += (256*32);
grtex->mipmap.colormap += COLORMAP_REMAPOFFSET;
#endif
blockwidth = texture->width;
@@ -378,18 +379,19 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, boolean noe
blockwidth, blockheight,
texture, patch,
realpatch);
Z_Unlock(realpatch);
Z_ChangeTag(realpatch, PU_HWRCACHE_UNLOCKED);
}
//Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :(
if (format2bpp(grtex->mipmap.format)==4)
{
for (i = 3; i < blocksize*4; i += 4) // blocksize*4 because blocksize doesn't include the bpp
{
if (block[i] == 0)
{
grtex->mipmap.flags |= TF_TRANSPARENT;
break;
}
if (block[i] != 0)
continue;
grtex->mipmap.flags |= TF_TRANSPARENT;
break;
}
}
@@ -571,7 +573,6 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean noencore)
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now.
@@ -628,8 +629,12 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
#ifdef GLENCORE
flat = grMipmap->data;
for (steppy = 0; steppy < size; steppy++)
if (flat[steppy] != HWR_PATCHES_CHROMAKEY_COLORINDEX)
flat[steppy] = grMipmap->colormap[flat[steppy]];
{
if (flat[steppy] == HWR_PATCHES_CHROMAKEY_COLORINDEX)
continue;
flat[steppy] = grMipmap->colormap[flat[steppy]];
}
#endif
}
@@ -647,7 +652,7 @@ void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap)
#ifdef GLENCORE
if (!noencoremap && encoremap)
grmip->colormap += (256*32);
grmip->colormap += COLORMAP_REMAPOFFSET;
#endif
if (!grmip->downloaded && !grmip->data)
@@ -729,7 +734,8 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
{
GLMipmap_t *grmip, *newmip;
if (colormap == colormaps || colormap == NULL)
// Blatant hack for encore colormapping aside...
if (colormap == colormaps || colormap == NULL || colormap == (const UINT8*)(COLORMAP_REMAPOFFSET))
{
// Load the default (green) color in doom cache (temporary?) AND hardware cache
HWR_GetPatch(gpatch);
@@ -741,11 +747,12 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
for (grmip = gpatch->mipmap; grmip->nextcolormap; )
{
grmip = grmip->nextcolormap;
if (grmip->colormap == colormap)
{
HWR_LoadMappedPatch(grmip, gpatch);
return;
}
if (grmip->colormap != colormap)
continue;
HWR_LoadMappedPatch(grmip, gpatch);
return;
}
// not found, create it!
// If we are here, the sprite with the current colormap is not already in hardware memory
+2 -2
View File
@@ -337,16 +337,16 @@ angle_t gld_FrustumAngle(angle_t tiltangle)
floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * clipfov / 90.0f;
if (floatangle >= 180.0)
return 0xffffffff;
a1 = ANG1 * (int)floatangle;
a1 = (angle_t)(ANG1 * (int)floatangle);
return a1;
}
// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
// compiler complains about (p)glGetFloatv anyway, in case anyone wants this
// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
#ifdef HAVE_SPHEREFRUSTRUM
//
// gld_FrustumSetup
//
-1
View File
@@ -44,7 +44,6 @@ struct GLMipmap_s
UINT16 width, height;
UINT32 downloaded; // tex_downloaded
struct GLMipmap_s *nextmipmap;
struct GLMipmap_s *nextcolormap;
const UINT8 *colormap;
};
+3 -1
View File
@@ -153,6 +153,7 @@ typedef struct
FLOAT centerx, centery;
#ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode
boolean mirrorflip; // Encore Mode with Flipcam
#endif
boolean shearing; // 14042019
angle_t viewaiming; // 17052019
@@ -172,9 +173,10 @@ enum
{
SHADER_NONE = -1,
SHADER_FLOOR = 0,
SHADER_SHADOW,
SHADER_WALL,
SHADER_MODEL,
SHADER_SPRITE,
SHADER_MODEL,
SHADER_WATER,
SHADER_FOG,
SHADER_SKY,
+1 -3
View File
@@ -28,13 +28,11 @@ typedef struct gr_vissprite_s
float x1, x2;
float z1, z2;
float gz, gzt;
float tz, ty;
float tz;
float scale;
//lumpnum_t patchlumpnum;
float spritexscale, spriteyscale;
float spritexoffset, spriteyoffset;
UINT32 renderflags;
UINT8 rotateflags;
GLPatch_t *gpatch;
boolean flip;
UINT8 translucency; //alpha level 0-255
-27
View File
@@ -1,27 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2019 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file
#include "../doomdef.h"
#ifdef HWRENDER
#include "hw_light.h"
#include "hw_drv.h"
#include "../i_video.h"
#include "../z_zone.h"
#include "../m_random.h"
#include "../m_bbox.h"
#include "../w_wad.h"
#include "../r_state.h"
#include "../r_main.h"
#include "../p_local.h"
#endif // HWRENDER
-20
View File
@@ -1,20 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2019 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file
/// \brief Dynamic lighting & coronas add on by Hurdler
#ifndef _HW_LIGHTS_
#define _HW_LIGHTS_
#include "hw_glob.h"
#include "hw_defs.h"
#endif
+698 -977
View File
File diff suppressed because it is too large. Load diff
+2 -7
View File
@@ -120,7 +120,6 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc
void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap);
void HWR_AddPolyObjectPlanes(void);
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
// hw_main.c: Segs
@@ -132,12 +131,10 @@ void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo * pSurf, INT32 t
void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf);
void HWR_DrawSkyBackground(float fpov);
void HWR_AddPolyObjectSegs(void);
// hw_main.c: Sprites
void HWR_AddSprites(sector_t *sec);
void HWR_ProjectSprite(mobj_t *thing);
void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
//void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
void HWR_DrawSprites(void);
// hw_bsp.c
@@ -155,10 +152,7 @@ extern consvar_t cv_grshaders;
#ifdef USE_FBO_OGL
extern consvar_t cv_grframebuffer;
#endif
extern consvar_t cv_grfofcut;
extern consvar_t cv_fofzfightfix;
extern consvar_t cv_splitwallfix;
extern consvar_t cv_slopepegfix;
extern consvar_t cv_grshearing;
extern consvar_t cv_grfov;
extern consvar_t cv_grmdls;
@@ -179,6 +173,7 @@ extern consvar_t cv_grrenderdistance;
extern consvar_t cv_grpaletterendering;
extern consvar_t cv_grpalettedepth;
extern consvar_t cv_grflashpal;
extern consvar_t cv_lightdither;
extern consvar_t cv_grscreentextures;
extern consvar_t cv_grportals;
extern consvar_t cv_nostencil;
+4 -3
View File
@@ -26,7 +26,6 @@
#ifdef HWRENDER
#include "hw_drv.h"
#include "hw_light.h"
#include "hw_md2.h"
#include "../d_main.h"
#include "../r_bsp.h"
@@ -75,7 +74,7 @@
md2_t md2_models[NUMSPRITES];
md2_t md2_playermodels[MAXSKINS];
md2_t md2_localplayermodels[MAXSKINS];
md2_t md2_localplayermodels[MAXLOCALSKINS];
/*
@@ -494,7 +493,9 @@ void HWR_InitMD2(void)
md2_playermodels[s].skin = -1;
md2_playermodels[s].notfound = true;
md2_playermodels[s].error = false;
}
for (s = 0; s < MAXLOCALSKINS; s++)
{
md2_localplayermodels[s].scale = -1.0f;
md2_localplayermodels[s].model = NULL;
md2_localplayermodels[s].grpatch = NULL;
+1 -1
View File
@@ -37,7 +37,7 @@ typedef struct
extern md2_t md2_models[NUMSPRITES];
extern md2_t md2_playermodels[MAXSKINS];
extern md2_t md2_localplayermodels[MAXSKINS];
extern md2_t md2_localplayermodels[MAXLOCALSKINS];
void HWR_InitMD2(void);
void HWR_DrawMD2(gr_vissprite_t *spr);
+119 -1
View File
@@ -29,6 +29,9 @@ static struct {
// Floor shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FLOOR_FRAGMENT_SHADER},
// Shadow shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SHADOW_FRAGMENT_SHADER},
// Wall shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
@@ -79,6 +82,7 @@ static shadertarget_t gl_shadertargets[NUMSHADERTARGETS];
#define WHITESPACE_CHARS " \t"
#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING"
#define LIGHT_DITHERING_DEFINE "#define SRB2_LIGHT_DITHER"
// Initialize shader variables and the backend's shader system. Load the base shaders.
// Returns false if shaders cannot be used.
@@ -279,6 +283,9 @@ static char *HWR_PreprocessShader(char *original)
if (cv_grpaletterendering.value)
ADD_TO_LEN(PALETTE_RENDERING_DEFINE)
if (cv_lightdither.value)
ADD_TO_LEN(LIGHT_DITHERING_DEFINE)
#undef ADD_TO_LEN
#define VERSION_PART "#version "
@@ -320,6 +327,9 @@ static char *HWR_PreprocessShader(char *original)
if (cv_grpaletterendering.value)
WRITE_DEFINE(PALETTE_RENDERING_DEFINE)
if (cv_lightdither.value)
WRITE_DEFINE(LIGHT_DITHERING_DEFINE)
#undef WRITE_DEFINE
// Write a #line directive, so compiler errors will report line numbers from the
@@ -422,6 +432,7 @@ static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
customshaderxlat_t shaderxlat[] =
{
{"Flat", SHADER_FLOOR},
{"Shadow", SHADER_SHADOW},
{"WallTexture", SHADER_WALL},
{"Sprite", SHADER_SPRITE},
{"Model", SHADER_MODEL},
@@ -442,6 +453,106 @@ void HWR_LoadAllCustomShaders(void)
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
}
static const char version_directives[][14] = {
"#version 330\n",
"#version 150\n",
"#version 140\n",
"#version 130\n",
"#version 120\n",
"#version 110\n",
};
static boolean HWR_VersionDirectiveExists(const char* source)
{
return strncmp(source, "#version", 8) == 0;
}
static char* HWR_PrependVersionDirective(const char* source, UINT32 version_index)
{
const UINT32 version_len = sizeof(version_directives[version_index]) - 1;
const UINT32 source_len = strlen(source);
char* result = Z_Malloc(source_len + version_len + 1, PU_STATIC, NULL);
strcpy(result, version_directives[version_index]);
strcpy(result + version_len, source);
return result;
}
static void HWR_ReplaceVersionInplace(char* shader, UINT32 version_index)
{
shader[9] = version_directives[version_index][9];
shader[10] = version_directives[version_index][10];
shader[11] = version_directives[version_index][11];
}
static boolean HWR_CheckVersionDirectives(const char* vert, const char* frag)
{
return HWR_VersionDirectiveExists(vert) && HWR_VersionDirectiveExists(frag);
}
static void HWR_TryToCompileShaderWithImplicitVersion(INT32 shader_index, INT32 shaderxlat_id)
{
char* vert_shader = gl_shaders[shader_index].vertex;
char* frag_shader = gl_shaders[shader_index].fragment;
boolean vert_shader_version_exists = HWR_VersionDirectiveExists(vert_shader);
boolean frag_shader_version_exists = HWR_VersionDirectiveExists(frag_shader);
if (!vert_shader_version_exists)
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: vertex shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id));
if (!frag_shader_version_exists)
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: fragment shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id));
// try to compile as is
HWR_CompileShader(shader_index);
if (gl_shaders[shader_index].compiled)
return;
// try each version directive
for (UINT32 i = 0; i < sizeof(version_directives) / sizeof(version_directives[0]); ++i)
{
CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Trying %s\n", version_directives[i]);
if (!vert_shader_version_exists)
{
// first time reallocation would have to be made
if (i == 0)
{
void* old = (void*)gl_shaders[shader_index].vertex;
vert_shader = gl_shaders[shader_index].vertex = HWR_PrependVersionDirective(vert_shader, i);
Z_Free(old);
}
else
HWR_ReplaceVersionInplace(vert_shader, i);
}
if (!frag_shader_version_exists)
{
if (i == 0)
{
void* old = (void*)gl_shaders[shader_index].fragment;
frag_shader = gl_shaders[shader_index].fragment = HWR_PrependVersionDirective(frag_shader, i);
Z_Free(old);
}
else
HWR_ReplaceVersionInplace(frag_shader, i);
}
HWR_CompileShader(shader_index);
if (gl_shaders[shader_index].compiled)
{
CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Compiled with %s\n",
version_directives[i]);
CONS_Alert(CONS_WARNING, "Implicit GLSL version is used. Correct behavior is not guaranteed\n");
return;
}
}
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
{
UINT16 lump;
@@ -598,13 +709,20 @@ skip_field:
{
int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders
gl_shadertargets[i].custom_shader = shader_index;
// if only one stage (vertex/fragment) is defined, the other one
// is copied from the base shaders.
if (!gl_shaders[shader_index].fragment)
gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment);
if (!gl_shaders[shader_index].vertex)
gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex);
HWR_CompileShader(shader_index);
if (!HWR_CheckVersionDirectives(gl_shaders[shader_index].vertex, gl_shaders[shader_index].fragment))
HWR_TryToCompileShaderWithImplicitVersion(shader_index, i);
else
HWR_CompileShader(shader_index);
if (!gl_shaders[shader_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
}
+68 -4
View File
@@ -51,15 +51,53 @@
//
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
#define GLSL_DOOM_COLORMAP_DITHER \
"float baseValue = max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
"float endResolutionx = scr_resolution.x;\n" \
"float endResolutiony = scr_resolution.y;\n" \
"if (scr_resolution.x > 1280.0) {\n" \
"endResolutionx = scr_resolution.x * 0.5;\n" \
"}\n" \
"if (scr_resolution.y > 720.0) {\n" \
"endResolutiony = scr_resolution.y * 0.5;\n" \
"}\n" \
"float zFactor = clamp((z - 192.0) / (6144.0 - 192.0), 0.0, 1.0);\n" \
"int scaleFactor = int(mix(1.0, 8.0, zFactor));\n" \
"endResolutionx = endResolutionx * scaleFactor;\n" \
"endResolutiony = endResolutiony * scaleFactor;\n" \
"vec2 normalizedPosition = position * vec2(endResolutionx / scr_resolution.x, endResolutiony / scr_resolution.y);\n" \
"int x = int(mod(normalizedPosition.x, 4.0));\n" \
"int y = int(mod(normalizedPosition.y, 4.0));\n" \
"float bayerMatrix[4*4] = float[4*4](\n" \
"0.0, 8.0, 2.0, 10.0,\n" \
"12.0, 4.0, 14.0, 6.0,\n" \
"3.0, 11.0, 1.0, 9.0,\n" \
"15.0, 7.0, 13.0, 5.0\n" \
");\n" \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"float threshold = (1.0 - pow(zFactor, 2.0)) * (bayerMatrix[y*4 + x] / 11.0);\n" \
"#else\n" \
"float threshold = (1.0 - pow(zFactor, 2.0)) * (bayerMatrix[y*4 + x] / 16.0);\n" \
"#endif\n" \
"return mix(baseValue + threshold - 0.5 / 16.0, baseValue, zFactor);\n"
#define GLSL_DOOM_COLORMAP_NODITHER \
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
#define GLSL_DOOM_COLORMAP \
"float R_DoomColormap(float light, float z)\n" \
"uniform vec2 scr_resolution;\n" \
"float R_DoomColormap(float light, float z, vec2 position)\n" \
"{\n" \
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
"float startmap = (15.0 - lightnum) * 4.0;\n" \
"float scale = 160.0 / (lightz + 1.0);\n" \
"float cap = (155.0 - light) * 0.26;\n" \
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
"#ifdef SRB2_LIGHT_DITHER\n" \
GLSL_DOOM_COLORMAP_DITHER \
"#else\n" \
GLSL_DOOM_COLORMAP_NODITHER \
"#endif\n" \
"}\n"
// lighting cap adjustment:
// first num (155.0), increase to make it start to go dark sooner
@@ -69,7 +107,7 @@
"float R_DoomLightingEquation(float light)\n" \
"{\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
"float colormap = floor(R_DoomColormap(light, z, gl_FragCoord.xy)) + 0.5;\n" \
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
"}\n"
@@ -95,7 +133,7 @@
#define GLSL_PALETTE_RENDERING \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \
"float light_y = clamp(floor(R_DoomColormap(lighting, z, gl_FragCoord.xy)), 0.0, 31.0);\n" \
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
"final_color.a = texel.a * poly_color.a;\n" \
@@ -133,13 +171,35 @@
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
#define GLSL_SOFTWARE_FRAGMENT_SHADER_NOPAL \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
// hand tuned adjustments for light level calculation
#define GLSL_FLOOR_FUDGES \
"#version 120\n" \
"#define STARTMAP_FUDGE 1.06\n" \
"#define SCALE_FUDGE 1.15\n"
#define GLSL_WALL_FUDGES \
"#version 120\n" \
"#define STARTMAP_FUDGE 1.05\n" \
"#define SCALE_FUDGE 2.2\n"
@@ -150,6 +210,10 @@
#define GLSL_WALL_FRAGMENT_SHADER \
GLSL_WALL_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER
#define GLSL_SHADOW_FRAGMENT_SHADER \
GLSL_FLOOR_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER_NOPAL
//
// Water surface shader
+73 -46
View File
@@ -120,8 +120,6 @@ GLfloat projMatrix[16];
static GLint viewport[4];
#ifdef USE_FBO_OGL
static boolean GLFramebuffer_IsFuncAvailible(void);
GLuint FramebufferObject, FramebufferTexture, RenderbufferObject;
GLboolean FrameBufferEnabled = GL_FALSE, RenderToFramebuffer = GL_FALSE;
@@ -608,6 +606,7 @@ typedef void (APIENTRY *PFNglDeleteProgram) (GLuint);
typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint);
typedef void (APIENTRY *PFNglLinkProgram) (GLuint);
typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*);
typedef void (APIENTRY *PFNglGetProgramInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*);
typedef void (APIENTRY *PFNglUseProgram) (GLuint);
typedef void (APIENTRY *PFNglUniform1i) (GLint, GLint);
typedef void (APIENTRY *PFNglUniform1f) (GLint, GLfloat);
@@ -630,6 +629,7 @@ static PFNglDeleteProgram pglDeleteProgram;
static PFNglAttachShader pglAttachShader;
static PFNglLinkProgram pglLinkProgram;
static PFNglGetProgramiv pglGetProgramiv;
static PFNglGetProgramInfoLog pglGetProgramInfoLog;
static PFNglUseProgram pglUseProgram;
static PFNglUniform1i pglUniform1i;
static PFNglUniform1f pglUniform1f;
@@ -669,6 +669,8 @@ typedef enum
// misc.
gluniform_leveltime,
gluniform_scr_resolution,
gluniform_max,
} gluniform_t;
@@ -703,6 +705,9 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
#ifdef USE_FBO_OGL
static boolean GLFramebuffer_IsFuncAvailible(void);
#endif
void SetupGLFunc4(void)
{
@@ -735,6 +740,7 @@ void SetupGLFunc4(void)
pglAttachShader = GetGLFunc("glAttachShader");
pglLinkProgram = GetGLFunc("glLinkProgram");
pglGetProgramiv = GetGLFunc("glGetProgramiv");
pglGetProgramInfoLog = GetGLFunc("glGetProgramInfoLog");
pglUseProgram = GetGLFunc("glUseProgram");
pglUniform1i = GetGLFunc("glUniform1i");
pglUniform1f = GetGLFunc("glUniform1f");
@@ -759,6 +765,8 @@ void SetupGLFunc4(void)
pglDeleteRenderbuffers = GetGLFunc("glDeleteRenderbuffers");
pglRenderbufferStorage = GetGLFunc("glRenderbufferStorage");
pglFramebufferRenderbuffer = GetGLFunc("glFramebufferRenderbuffer");
supportFBO = true;
}
#endif
}
@@ -770,9 +778,7 @@ static boolean GLFramebuffer_IsFuncAvailible(void)
if (majorGL < 3)
return false;
return((isExtAvailable("GL_ARB_framebuffer_no_attachments",gl_extensions)) &&
(isExtAvailable("GL_ARB_framebuffer_object",gl_extensions)) &&
(isExtAvailable("GL_ARB_framebuffer_sRGB",gl_extensions)));
return (isExtAvailable("GL_ARB_framebuffer_no_attachments",gl_extensions) && isExtAvailable("GL_ARB_framebuffer_object",gl_extensions) && isExtAvailable("GL_ARB_framebuffer_sRGB",gl_extensions));
return false;
}
@@ -846,7 +852,7 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value)
switch (info)
{
case HWD_SHADERINFO_LEVELTIME:
shader_leveltime = value;
shader_leveltime = (((float)(value-1)) + FIXED_TO_FLOAT(rendertimefrac)) / TICRATE;
break;
default:
break;
@@ -1038,37 +1044,9 @@ EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *pTexInfo)
}
#ifdef USE_FBO_OGL
void GLFramebuffer_Generate(void)
static void GLFramebuffer_GenerateAttachments(void)
{
if (!GLFramebuffer_IsFuncAvailible())
return;
// Generate the framebuffer
if (FramebufferObject == 0)
pglGenFramebuffers(1, &FramebufferObject);
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
GLFramebuffer_GenerateAttachments();
}
void GLFramebuffer_Delete(void)
{
if (!GLFramebuffer_IsFuncAvailible())
return;
// Unbind the framebuffer
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
if (FramebufferObject)
pglDeleteFramebuffers(1, &FramebufferObject);
GLFramebuffer_DeleteAttachments();
FramebufferObject = 0;
}
void GLFramebuffer_GenerateAttachments(void)
{
if (!GLFramebuffer_IsFuncAvailible())
if (!supportFBO)
return;
// Bind the framebuffer
@@ -1109,11 +1087,12 @@ void GLFramebuffer_GenerateAttachments(void)
void GLFramebuffer_DeleteAttachments(void)
{
if (!GLFramebuffer_IsFuncAvailible())
if (!supportFBO)
return;
// Unbind the framebuffer
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
pglBindRenderbuffer(GL_RENDERBUFFER, 0);
if (FramebufferTexture)
pglDeleteTextures(1, &FramebufferTexture);
@@ -1125,9 +1104,43 @@ void GLFramebuffer_DeleteAttachments(void)
RenderbufferObject = 0;
}
void GLFramebuffer_Enable(void)
static void GLFramebuffer_Generate(void)
{
if (!GLFramebuffer_IsFuncAvailible())
if (!supportFBO)
return;
// Generate the framebuffer
if (FramebufferObject == 0)
pglGenFramebuffers(1, &FramebufferObject);
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
GLFramebuffer_GenerateAttachments();
}
static void GLFramebuffer_Delete(void)
{
if (!supportFBO)
return;
if (FramebufferObject)
pglDeleteFramebuffers(1, &FramebufferObject);
GLFramebuffer_DeleteAttachments();
FramebufferObject = 0;
}
inline void GLFramebuffer_Unbind(void)
{
if (!supportFBO)
return;
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
pglBindRenderbuffer(GL_RENDERBUFFER, 0);
}
inline void GLFramebuffer_Enable(void)
{
if (!supportFBO)
return;
if (FramebufferObject == 0)
@@ -1141,11 +1154,13 @@ void GLFramebuffer_Enable(void)
void GLFramebuffer_Disable(void)
{
if (!GLFramebuffer_IsFuncAvailible())
if (!supportFBO)
return;
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
pglBindRenderbuffer(GL_RENDERBUFFER, 0);
GLFramebuffer_Delete();
}
#endif
@@ -1834,7 +1849,9 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
UNIFORM_1(shader->uniforms[gluniform_fade_end], (GLfloat)Surface->LightInfo.fade_end, pglUniform1f);
}
UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f);
UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f);
UNIFORM_2(shader->uniforms[gluniform_scr_resolution], vid.width, vid.height, pglUniform2f);
#undef UNIFORM_1
#undef UNIFORM_2
@@ -1850,6 +1867,7 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
GLint result;
const GLchar *vert_shader = shader->vertex_shader;
const GLchar *frag_shader = shader->fragment_shader;
GLchar info_log[512];
if (shader->program)
pglDeleteProgram(shader->program);
@@ -1879,7 +1897,10 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
GL_MSG_Error("Error compiling vertex shader", gl_vertShader, i);
pglGetShaderInfoLog(gl_vertShader, 512, NULL, info_log);
GL_MSG_Error("Error compiling vertex shader: %s\n", info_log);
pglDeleteShader(gl_vertShader);
return false;
}
@@ -1906,7 +1927,9 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
GL_MSG_Error("Error compiling fragment shader", gl_fragShader, i);
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
GL_MSG_Error("Error compiling fragment shader: %s\n", info_log);
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
return false;
@@ -1932,7 +1955,8 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
// couldn't link?
if (result != GL_TRUE)
{
GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i));
pglGetProgramInfoLog(shader->program, 512, NULL, info_log);
GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s: %s\n", HWR_GetShaderName(i), info_log);
pglDeleteProgram(shader->program);
return false;
}
@@ -1953,6 +1977,8 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
// misc.
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
@@ -2327,7 +2353,6 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
#ifdef USE_FBO_OGL
case HWD_SET_FRAMEBUFFER:
FrameBufferEnabled = Value ? GL_TRUE : GL_FALSE;
supportFBO = GLFramebuffer_IsFuncAvailible();
if (!supportFBO)
{
@@ -2927,6 +2952,8 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
// mirroring from Kart
if (stransform->mirror)
pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez);
else if (stransform->mirrorflip)
pglScalef(-stransform->scalex, -stransform->scaley, -stransform->scalez);
else
#endif
if (stransform->flip)
@@ -2958,7 +2985,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
if (shearing)
{
float dy = FIXED_TO_FLOAT(AIMINGTODY((stransform->viewaiming)) * 2)* ((float)vid.width / vid.height) / ((float)BASEVIDWIDTH / BASEVIDHEIGHT); //screen_width/BASEVIDWIDTH;
if (stransform->flip)
if (stransform->flip || stransform->mirrorflip)
dy *= -1.0f;
pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f);
}
+1 -4
View File
@@ -105,12 +105,9 @@ static PFNglEnableClientState pglEnableClientState;
#endif
#ifdef USE_FBO_OGL
void GLFramebuffer_Generate(void);
void GLFramebuffer_Delete(void);
void GLFramebuffer_GenerateAttachments(void);
void GLFramebuffer_DeleteAttachments(void);
void GLFramebuffer_Unbind(void);
void GLFramebuffer_Enable(void);
void GLFramebuffer_Disable(void);
+6 -1
View File
@@ -532,7 +532,9 @@ HMS_fetch_rules (char *buffer, size_t buffer_size)
if (! hms)
return NULL;
if (HMS_do(hms))
boolean ok = HMS_do(hms);
if (ok)
{
char *p = strstr(hms->buffer, "\n\n");
@@ -550,6 +552,9 @@ HMS_fetch_rules (char *buffer, size_t buffer_size)
HMS_end(hms);
if (!ok)
return NULL;
return buffer;
}
+14 -3
View File
@@ -594,7 +594,10 @@ void HU_AddChatText(const char *text, boolean playsound)
if (OLDCHAT) // if we're using oldchat, print directly in console
CONS_Printf("%s\n", text);
else // if we aren't, still save the message to log.txt
CON_LogMessage(va("%s\n", text));
{
CON_LogMessage(text);
CON_LogMessage("\n"); // Add newline. Don't use va for that, since `text` might be refering to va's buffer itself
}
#else
(void)playsound;
CONS_Printf("%s\n", text);
@@ -1253,7 +1256,11 @@ void HU_Ticker(void)
if (cechotimer > 0) --cechotimer;
// Animate the desynch dots
if (hu_resynching)
if (hu_resynching
#ifdef SATURNSYNCH
|| hu_redownloadinggamestate
#endif
)
resynch_ticker++; //tic tic tic tic tic
HU_TickSongCredits();
@@ -2418,7 +2425,11 @@ void HU_Drawer(void)
HU_DrawSongCredits();
// draw desynch text
if (hu_resynching)
if (hu_resynching
#ifdef SATURNSYNCH
|| hu_redownloadinggamestate
#endif
)
{
char resynch_text[14];
UINT32 i;
-20
View File
@@ -34,7 +34,6 @@
#define NO_BAN_TIME (time_t)(-1)
extern INT16 hardware_MAXPACKETLENGTH;
extern INT32 net_bandwidth; // in byte/s
#if defined(_MSC_VER)
#pragma pack(1)
@@ -42,36 +41,17 @@ extern INT32 net_bandwidth; // in byte/s
typedef struct
{
/// Supposed to be DOOMCOM_ID
INT32 id;
/// SRB2 executes an INT32 to execute commands.
INT16 intnum;
/// Communication between SRB2 and the driver.
/// Is CMD_SEND or CMD_GET.
INT16 command;
/// Is dest for send, set by get (-1 = no packet).
INT16 remotenode;
/// Number of bytes in doomdata to be sent
INT16 datalength;
/// Info common to all nodes.
/// Console is always node 0.
INT16 numnodes;
/// Flag: 1 = no duplication, 2-5 = dup for slow nets.
INT16 ticdup;
/// Flag: 1 = send a backup tic in every packet.
INT16 extratics;
/// kind of game
INT16 gametype;
/// Flag: -1 = new game, 0-5 = load savegame
INT16 savegame;
/// currect map
INT16 map;
/// Info specific to this node.
INT16 consoleplayer;
/// Number of "slots": the highest player number in use plus one.
INT16 numslots;
-1
View File
@@ -159,7 +159,6 @@ boolean I_SetSongPosition(UINT32 position);
UINT32 I_GetSongPosition(void);
void I_UpdateSongLagThreshold (void);
void I_UpdateSongLagConditions (void);
/// ------------------------
// MUSIC PLAYBACK
+6
View File
@@ -34,6 +34,9 @@ extern UINT8 graphics_started;
*/
extern UINT8 keyboard_started;
/** \brief Set to true when inside a signal handler that will exit the program. */
extern boolean g_in_exiting_signal_handler;
/** \brief The I_GetFreeMem function
\param total total memory in the system
@@ -227,6 +230,9 @@ INT32 I_NumJoys(void);
*/
const char *I_GetJoyName(INT32 joyindex);
void I_GamepadRumble(INT32 device_id, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 blue);
#ifndef NOMUMBLE
#include "p_mobj.h" // mobj_t
#include "s_sound.h" // listener_t
-6
View File
@@ -1692,8 +1692,6 @@ boolean I_InitTcpNetwork(void)
// FIXME: for dedicated server, numnodes needs to be set to 0 upon start
if (dedicated)
doomcom->numnodes = 0;
/* else if (M_IsNextParm())
doomcom->numnodes = (INT16)atoi(M_GetNextParm());*/
else
doomcom->numnodes = 1;
@@ -1707,7 +1705,6 @@ boolean I_InitTcpNetwork(void)
// FIXME:
// ??? and now ?
// server on a big modem ??? 4*isdn
net_bandwidth = 16000;
hardware_MAXPACKETLENGTH = INETPACKETLENGTH;
ret = true;
@@ -1738,7 +1735,6 @@ boolean I_InitTcpNetwork(void)
// so we're on a LAN
COM_BufAddText("connect any\n");
net_bandwidth = 800000;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
}
}
@@ -1763,8 +1759,6 @@ boolean I_InitTcpNetwork(void)
{
// so we're on a LAN
COM_BufAddText("connect any\n");
net_bandwidth = 800000;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
}
}
+4
View File
@@ -140,6 +140,10 @@ UINT32 I_GetRefreshRate(void);
boolean I_UseNativeKeyboard(void);
#ifdef USE_FBO_OGL
#if defined (__unix__)
extern boolean xwaylandcrap;
#endif
void RefreshOGLSDLSurface(void);
void I_DownSample(void);
extern boolean downsample;
+10 -10
View File
@@ -1822,7 +1822,7 @@ state_t states[NUMSTATES] =
// Rain
{SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1
{SPR_RAIN, FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RAINRETURN
// Snowflake
{SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1
@@ -1841,9 +1841,9 @@ state_t states[NUMSTATES] =
{SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9
// Water Splash
{SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1
{SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2
{SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_RAINRETURN}, // S_SPLASH3
{SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1
{SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2
{SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_NULL}, // S_SPLASH3
// Smoke
{SPR_SMOK, FF_TRANS50 , 4, {NULL}, 0, 0, S_SMOKE2}, // S_SMOKE1
@@ -11198,22 +11198,22 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_RAIN1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_rainin, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_SPLASH1, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
-72*FRACUNIT, // speed -- -24*FRACUNIT originally, srb2kart x3 (nya)
1*FRACUNIT, // radius
8*FRACUNIT, // height
0, // display offset
4, // mass
80, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP, // flags
@@ -11226,7 +11226,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
@@ -11240,7 +11240,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
4*FRACUNIT, // radius
4*FRACUNIT, // height
0, // display offset
4, // mass
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP, // flags
+430 -203
View File
@@ -22,211 +22,438 @@
// dehacked.c now has lists for the more named enums! PLEASE keep them up to date!
// For great modding!!
/** Action pointer for reading actions from Dehacked lumps.
*/
typedef struct
{
actionf_t action; ///< Function pointer corresponding to the actual action.
const char *name; ///< Name of the action in ALL CAPS.
} actionpointer_t;
/** Array mapping action names to action functions.
* Names must be in ALL CAPS for case insensitive comparisons.
*/
extern actionpointer_t actionpointers[];
// IMPORTANT!
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONPOINTERS ARRAY IN DEHACKED.C
enum actionnum
{
A_EXPLODE = 0,
A_PAIN,
A_FALL,
A_MONITORPOP,
A_LOOK,
A_CHASE,
A_FACESTABCHASE,
A_FACETARGET,
A_FACETRACER,
A_SCREAM,
A_BOSSDEATH,
A_CUSTOMPOWER,
A_GIVEWEAPON,
A_RINGSHIELD,
A_RINGBOX,
A_INVINCIBILITY,
A_SUPERSNEAKERS,
A_BUNNYHOP,
A_BUBBLESPAWN,
A_FANBUBBLESPAWN,
A_BUBBLERISE,
A_BUBBLECHECK,
A_AWARDSCORE,
A_EXTRALIFE,
A_BOMBSHIELD,
A_JUMPSHIELD,
A_WATERSHIELD,
A_FORCESHIELD,
A_PITYSHIELD,
A_GRAVITYBOX,
A_SCORERISE,
A_PARTICLESPAWN,
A_ATTRACTCHASE,
A_DROPMINE,
A_FISHJUMP,
A_THROWNRING,
A_GRENADERING, // SRB2kart
A_SETSOLIDSTEAM,
A_UNSETSOLIDSTEAM,
A_SIGNPLAYER,
A_OVERLAYTHINK,
A_JETCHASE,
A_JETBTHINK,
A_JETGTHINK,
A_JETGSHOOT,
A_SHOOTBULLET,
A_MINUSDIGGING,
A_MINUSPOPUP,
A_MINUSCHECK,
A_CHICKENCHECK,
A_MOUSETHINK,
A_DETONCHASE,
A_CAPECHASE,
A_ROTATESPIKEBALL,
A_SLINGAPPEAR,
A_MACEROTATE,
A_UNIDUSBALL,
A_ROCKSPAWN,
A_SETFUSE,
A_CRAWLACOMMANDERTHINK,
A_SMOKETRAILER,
A_RINGEXPLODE,
A_OLDRINGEXPLODE,
A_MIXUP,
A_RECYCLEPOWERS,
A_BOSS1CHASE,
A_FOCUSTARGET,
A_BOSS2CHASE,
A_BOSS2POGO,
A_BOSSZOOM,
A_BOSSSCREAM,
A_BOSS2TAKEDAMAGE,
A_BOSS7CHASE,
A_GOOPSPLAT,
A_BOSS2POGOSFX,
A_BOSS2POGOTARGET,
A_BOSSJETFUME,
A_EGGMANBOX,
A_TURRETFIRE,
A_SUPERTURRETFIRE,
A_TURRETSTOP,
A_JETJAWROAM,
A_JETJAWCHOMP,
A_POINTYTHINK,
A_CHECKBUDDY,
A_HOODTHINK,
A_ARROWCHECK,
A_SNAILERTHINK,
A_SHARPCHASE,
A_SHARPSPIN,
A_VULTUREVTOL,
A_VULTURECHECK,
A_SKIMCHASE,
A_1UPTHINKER,
A_SKULLATTACK,
A_LOBSHOT,
A_FIRESHOT,
A_SUPERFIRESHOT,
A_BOSSFIRESHOT,
A_BOSS7FIREMISSILES,
A_BOSS1LASER,
A_BOSS4REVERSE,
A_BOSS4SPEEDUP,
A_BOSS4RAISE,
A_SPARKFOLLOW,
A_BUZZFLY,
A_GUARDCHASE,
A_EGGSHIELD,
A_SETREACTIONTIME,
A_BOSS1SPIKEBALLS,
A_BOSS3TAKEDAMAGE,
A_BOSS3PATH,
A_LINEDEFEXECUTE,
A_PLAYSEESOUND,
A_PLAYATTACKSOUND,
A_PLAYACTIVESOUND,
A_SPAWNOBJECTABSOLUTE,
A_SPAWNOBJECTRELATIVE,
A_CHANGEANGLERELATIVE,
A_CHANGEANGLEABSOLUTE,
A_ROLLANGLE,
A_CHANGEROLLANGLERELATIVE,
A_CHANGEROLLANGLEABSOLUTE,
A_PLAYSOUND,
A_FINDTARGET,
A_FINDTRACER,
A_SETTICS,
A_SETRANDOMTICS,
A_CHANGECOLORRELATIVE,
A_CHANGECOLORABSOLUTE,
A_MOVERELATIVE,
A_MOVEABSOLUTE,
A_THRUST,
A_ZTHRUST,
A_SETTARGETSTARGET,
A_SETOBJECTFLAGS,
A_SETOBJECTFLAGS2,
A_RANDOMSTATE,
A_RANDOMSTATERANGE,
A_DUALACTION,
A_REMOTEACTION,
A_TOGGLEFLAMEJET,
A_ITEMPOP, // SRB2kart
A_JAWZCHASE, // SRB2kart
A_JAWZEXPLODE, // SRB2kart
A_SPBCHASE, // SRB2kart
A_MINEEXPLODE, // SRB2kart
A_BALLHOGEXPLODE, // SRB2kart
A_LIGHTNINGFOLLOWPLAYER, //SRB2kart
A_FZBOOMFLASH, //SRB2kart
A_FZBOOMSMOKE, //SRB2kart
A_RANDOMSHADOWFRAME, //SRB2kart
A_ROAMINGSHADOWTHINKER, //SRB2kart
A_MAYONAKAARROW, //SRB2kart
A_REAPERTHINKER, //SRB2kart
A_MEMENTOSTPPARTICLES, //SRB2kart
A_FLAMEPARTICLE, // SRB2kart
A_ORBITNIGHTS,
A_GHOSTME,
A_SETOBJECTSTATE,
A_SETOBJECTTYPESTATE,
A_KNOCKBACK,
A_PUSHAWAY,
A_RINGDRAIN,
A_SPLITSHOT,
A_MISSILESPLIT,
A_MULTISHOT,
A_INSTALOOP,
A_CUSTOM3DROTATE,
A_SEARCHFORPLAYERS,
A_CHECKRANDOM,
A_CHECKTARGETRINGS,
A_CHECKRINGS,
A_CHECKTOTALRINGS,
A_CHECKHEALTH,
A_CHECKRANGE,
A_CHECKHEIGHT,
A_CHECKTRUERANGE,
A_CHECKTHINGCOUNT,
A_CHECKAMBUSH,
A_CHECKCUSTOMVALUE,
A_CHECKCUSVALMEMO,
A_SETCUSTOMVALUE,
A_USECUSVALMEMO,
A_RELAYCUSTOMVALUE,
A_CUSVALACTION,
A_FORCESTOP,
A_FORCEWIN,
A_SPIKERETRACT,
A_INFOSTATE,
A_REPEAT,
A_SETSCALE,
A_REMOTEDAMAGE,
A_HOMINGCHASE,
A_TRAPSHOT,
A_VILETARGET,
A_VILEATTACK,
A_VILEFIRE,
A_BRAKCHASE,
A_BRAKFIRESHOT,
A_BRAKLOBSHOT,
A_NAPALMSCATTER,
A_SPAWNFRESHCOPY,
NUMACTIONS
};
struct mobj_s;
// IMPORTANT NOTE: If you add/remove from this list of action
// functions, don't forget to update them in dehacked.c!
void A_Explode();
void A_Pain();
void A_Fall();
void A_MonitorPop();
void A_Look();
void A_Chase();
void A_FaceStabChase();
void A_FaceTarget();
void A_FaceTracer();
void A_Scream();
void A_BossDeath();
void A_CustomPower(); // Use this for a custom power
void A_GiveWeapon(); // Gives the player weapon(s)
void A_JumpShield(); // Obtained Jump Shield
void A_RingShield(); // Obtained Ring Shield
void A_RingBox(); // Obtained Ring Box Tails
void A_Invincibility(); // Obtained Invincibility Box
void A_SuperSneakers(); // Obtained Super Sneakers Box
void A_BunnyHop(); // have bunny hop tails
void A_BubbleSpawn(); // Randomly spawn bubbles
void A_FanBubbleSpawn();
void A_BubbleRise(); // Bubbles float to surface
void A_BubbleCheck(); // Don't draw if not underwater
void A_AwardScore();
void A_ExtraLife(); // Extra Life
void A_BombShield(); // Obtained Bomb Shield
void A_WaterShield(); // Obtained Water Shield
void A_ForceShield(); // Obtained Force Shield
void A_PityShield(); // Obtained Pity Shield. We're... sorry.
void A_GravityBox();
void A_ScoreRise(); // Rise the score logo
void A_ParticleSpawn();
void A_AttractChase(); // Ring Chase
void A_DropMine(); // Drop Mine from Skim or Jetty-Syn Bomber
void A_FishJump(); // Fish Jump
void A_ThrownRing(); // Sparkle trail for red ring
void A_GrenadeRing(); // SRB2kart
void A_SetSolidSteam();
void A_UnsetSolidSteam();
void A_SignPlayer();
void A_OverlayThink();
void A_JetChase();
void A_JetbThink(); // Jetty-Syn Bomber Thinker
void A_JetgThink(); // Jetty-Syn Gunner Thinker
void A_JetgShoot(); // Jetty-Syn Shoot Function
void A_ShootBullet(); // JetgShoot without reactiontime setting
void A_MinusDigging();
void A_MinusPopup();
void A_MinusCheck();
void A_ChickenCheck();
void A_MouseThink(); // Mouse Thinker
void A_DetonChase(); // Deton Chaser
void A_CapeChase(); // Fake little Super Sonic cape
void A_RotateSpikeBall(); // Spike ball rotation
void A_SlingAppear();
void A_MaceRotate();
void A_UnidusBall();
void A_RockSpawn();
void A_SetFuse();
void A_CrawlaCommanderThink(); // Crawla Commander
void A_SmokeTrailer();
void A_RingExplode();
void A_OldRingExplode();
void A_MixUp();
void A_RecyclePowers();
void A_BossScream();
void A_Boss2TakeDamage();
void A_GoopSplat();
void A_Boss2PogoSFX();
void A_Boss2PogoTarget();
void A_EggmanBox();
void A_TurretFire();
void A_SuperTurretFire();
void A_TurretStop();
void A_JetJawRoam();
void A_JetJawChomp();
void A_PointyThink();
void A_CheckBuddy();
void A_HoodThink();
void A_ArrowCheck();
void A_SnailerThink();
void A_SharpChase();
void A_SharpSpin();
void A_VultureVtol();
void A_VultureCheck();
void A_SkimChase();
void A_SkullAttack();
void A_LobShot();
void A_FireShot();
void A_SuperFireShot();
void A_BossFireShot();
void A_Boss7FireMissiles();
void A_Boss1Laser();
void A_FocusTarget();
void A_Boss4Reverse();
void A_Boss4SpeedUp();
void A_Boss4Raise();
void A_SparkFollow();
void A_BuzzFly();
void A_GuardChase();
void A_EggShield();
void A_SetReactionTime();
void A_Boss1Spikeballs();
void A_Boss3TakeDamage();
void A_Boss3Path();
void A_LinedefExecute();
void A_PlaySeeSound();
void A_PlayAttackSound();
void A_PlayActiveSound();
void A_1upThinker();
void A_BossZoom(); //Unused
void A_Boss1Chase();
void A_Boss2Chase();
void A_Boss2Pogo();
void A_Boss7Chase();
void A_BossJetFume();
void A_SpawnObjectAbsolute();
void A_SpawnObjectRelative();
void A_ChangeAngleRelative();
void A_ChangeAngleAbsolute();
void A_RollAngle();
void A_ChangeRollAngleRelative();
void A_ChangeRollAngleAbsolute();
void A_PlaySound();
void A_FindTarget();
void A_FindTracer();
void A_SetTics();
void A_SetRandomTics();
void A_ChangeColorRelative();
void A_ChangeColorAbsolute();
void A_MoveRelative();
void A_MoveAbsolute();
void A_Thrust();
void A_ZThrust();
void A_SetTargetsTarget();
void A_SetObjectFlags();
void A_SetObjectFlags2();
void A_RandomState();
void A_RandomStateRange();
void A_DualAction();
void A_RemoteAction();
void A_ToggleFlameJet();
void A_ItemPop(); // SRB2kart
void A_JawzChase(); // SRB2kart
void A_JawzExplode(); // SRB2kart
void A_SPBChase(); // SRB2kart
void A_MineExplode(); // SRB2kart
void A_BallhogExplode(); // SRB2kart
void A_LightningFollowPlayer(); // SRB2kart: Lightning shield effect player chasing
void A_FZBoomFlash(); // SRB2kart
void A_FZBoomSmoke(); // SRB2kart
void A_RandomShadowFrame(); //SRB2kart: Shadow spawner frame randomizer
void A_RoamingShadowThinker(); // SRB2kart: Roaming Shadow moving + attacking players.
void A_MayonakaArrow(); //SRB2kart: midnight channel arrow sign
void A_ReaperThinker(); //SRB2kart: mementos reaper
void A_MementosTPParticles(); //SRB2kart: mementos teleporter particles. Man that's a lot of actions for my shite.
void A_FlameParticle(); // SRB2kart
void A_OrbitNights();
void A_GhostMe();
void A_SetObjectState();
void A_SetObjectTypeState();
void A_KnockBack();
void A_PushAway();
void A_RingDrain();
void A_SplitShot();
void A_MissileSplit();
void A_MultiShot();
void A_InstaLoop();
void A_Custom3DRotate();
void A_SearchForPlayers();
void A_CheckRandom();
void A_CheckTargetRings();
void A_CheckRings();
void A_CheckTotalRings();
void A_CheckHealth();
void A_CheckRange();
void A_CheckHeight();
void A_CheckTrueRange();
void A_CheckThingCount();
void A_CheckAmbush();
void A_CheckCustomValue();
void A_CheckCusValMemo();
void A_SetCustomValue();
void A_UseCusValMemo();
void A_RelayCustomValue();
void A_CusValAction();
void A_ForceStop();
void A_ForceWin();
void A_SpikeRetract();
void A_InfoState();
void A_Repeat();
void A_SetScale();
void A_RemoteDamage();
void A_HomingChase();
void A_TrapShot();
void A_VileTarget();
void A_VileAttack();
void A_VileFire();
void A_BrakChase();
void A_BrakFireShot();
void A_BrakLobShot();
void A_NapalmScatter();
void A_SpawnFreshCopy();
void A_Explode(struct mobj_s *actor);
void A_Pain(struct mobj_s *actor);
void A_Fall(struct mobj_s *actor);
void A_MonitorPop(struct mobj_s *actor);
void A_Look(struct mobj_s *actor);
void A_Chase(struct mobj_s *actor);
void A_FaceStabChase(struct mobj_s *actor);
void A_FaceTarget(struct mobj_s *actor);
void A_FaceTracer(struct mobj_s *actor);
void A_Scream(struct mobj_s *actor);
void A_BossDeath(struct mobj_s *actor);
void A_CustomPower(struct mobj_s *actor); // Use this for a custom power
void A_GiveWeapon(struct mobj_s *actor); // Gives the player weapon(s)
void A_JumpShield(struct mobj_s *actor); // Obtained Jump Shield
void A_RingShield(struct mobj_s *actor); // Obtained Ring Shield
void A_RingBox(struct mobj_s *actor); // Obtained Ring Box Tails
void A_Invincibility(struct mobj_s *actor); // Obtained Invincibility Box
void A_SuperSneakers(struct mobj_s *actor); // Obtained Super Sneakers Box
void A_BunnyHop(struct mobj_s *actor); // have bunny hop tails
void A_BubbleSpawn(struct mobj_s *actor); // Randomly spawn bubbles
void A_FanBubbleSpawn(struct mobj_s *actor);
void A_BubbleRise(struct mobj_s *actor); // Bubbles float to surface
void A_BubbleCheck(struct mobj_s *actor); // Don't draw if not underwater
void A_AwardScore(struct mobj_s *actor);
void A_ExtraLife(struct mobj_s *actor); // Extra Life
void A_BombShield(struct mobj_s *actor); // Obtained Bomb Shield
void A_WaterShield(struct mobj_s *actor); // Obtained Water Shield
void A_ForceShield(struct mobj_s *actor); // Obtained Force Shield
void A_PityShield(struct mobj_s *actor); // Obtained Pity Shield. We're... sorry.
void A_GravityBox(struct mobj_s *actor);
void A_ScoreRise(struct mobj_s *actor); // Rise the score logo
void A_ParticleSpawn(struct mobj_s *actor);
void A_AttractChase(struct mobj_s *actor); // Ring Chase
void A_DropMine(struct mobj_s *actor); // Drop Mine from Skim or Jetty-Syn Bomber
void A_FishJump(struct mobj_s *actor); // Fish Jump
void A_ThrownRing(struct mobj_s *actor); // Sparkle trail for red ring
void A_GrenadeRing(struct mobj_s *actor); // SRB2kart
void A_SetSolidSteam(struct mobj_s *actor);
void A_UnsetSolidSteam(struct mobj_s *actor);
void A_SignPlayer(struct mobj_s *actor);
void A_OverlayThink(struct mobj_s *actor);
void A_JetChase(struct mobj_s *actor);
void A_JetbThink(struct mobj_s *actor); // Jetty-Syn Bomber Thinker
void A_JetgThink(struct mobj_s *actor); // Jetty-Syn Gunner Thinker
void A_JetgShoot(struct mobj_s *actor); // Jetty-Syn Shoot Function
void A_ShootBullet(struct mobj_s *actor); // JetgShoot without reactiontime setting
void A_MinusDigging(struct mobj_s *actor);
void A_MinusPopup(struct mobj_s *actor);
void A_MinusCheck(struct mobj_s *actor);
void A_ChickenCheck(struct mobj_s *actor);
void A_MouseThink(struct mobj_s *actor); // Mouse Thinker
void A_DetonChase(struct mobj_s *actor); // Deton Chaser
void A_CapeChase(struct mobj_s *actor); // Fake little Super Sonic cape
void A_RotateSpikeBall(struct mobj_s *actor); // Spike ball rotation
void A_SlingAppear(struct mobj_s *actor);
void A_MaceRotate(struct mobj_s *actor);
void A_UnidusBall(struct mobj_s *actor);
void A_RockSpawn(struct mobj_s *actor);
void A_SetFuse(struct mobj_s *actor);
void A_CrawlaCommanderThink(struct mobj_s *actor); // Crawla Commander
void A_SmokeTrailer(struct mobj_s *actor);
void A_RingExplode(struct mobj_s *actor);
void A_OldRingExplode(struct mobj_s *actor);
void A_MixUp(struct mobj_s *actor);
void A_RecyclePowers(struct mobj_s *actor);
void A_BossScream(struct mobj_s *actor);
void A_Boss2TakeDamage(struct mobj_s *actor);
void A_GoopSplat(struct mobj_s *actor);
void A_Boss2PogoSFX(struct mobj_s *actor);
void A_Boss2PogoTarget(struct mobj_s *actor);
void A_EggmanBox(struct mobj_s *actor);
void A_TurretFire(struct mobj_s *actor);
void A_SuperTurretFire(struct mobj_s *actor);
void A_TurretStop(struct mobj_s *actor);
void A_JetJawRoam(struct mobj_s *actor);
void A_JetJawChomp(struct mobj_s *actor);
void A_PointyThink(struct mobj_s *actor);
void A_CheckBuddy(struct mobj_s *actor);
void A_HoodThink(struct mobj_s *actor);
void A_ArrowCheck(struct mobj_s *actor);
void A_SnailerThink(struct mobj_s *actor);
void A_SharpChase(struct mobj_s *actor);
void A_SharpSpin(struct mobj_s *actor);
void A_VultureVtol(struct mobj_s *actor);
void A_VultureCheck(struct mobj_s *actor);
void A_SkimChase(struct mobj_s *actor);
void A_SkullAttack(struct mobj_s *actor);
void A_LobShot(struct mobj_s *actor);
void A_FireShot(struct mobj_s *actor);
void A_SuperFireShot(struct mobj_s *actor);
void A_BossFireShot(struct mobj_s *actor);
void A_Boss7FireMissiles(struct mobj_s *actor);
void A_Boss1Laser(struct mobj_s *actor);
void A_FocusTarget(struct mobj_s *actor);
void A_Boss4Reverse(struct mobj_s *actor);
void A_Boss4SpeedUp(struct mobj_s *actor);
void A_Boss4Raise(struct mobj_s *actor);
void A_SparkFollow(struct mobj_s *actor);
void A_BuzzFly(struct mobj_s *actor);
void A_GuardChase(struct mobj_s *actor);
void A_EggShield(struct mobj_s *actor);
void A_SetReactionTime(struct mobj_s *actor);
void A_Boss1Spikeballs(struct mobj_s *actor);
void A_Boss3TakeDamage(struct mobj_s *actor);
void A_Boss3Path(struct mobj_s *actor);
void A_LinedefExecute(struct mobj_s *actor);
void A_PlaySeeSound(struct mobj_s *actor);
void A_PlayAttackSound(struct mobj_s *actor);
void A_PlayActiveSound(struct mobj_s *actor);
void A_1upThinker(struct mobj_s *actor);
void A_BossZoom(struct mobj_s *actor); //Unused
void A_Boss1Chase(struct mobj_s *actor);
void A_Boss2Chase(struct mobj_s *actor);
void A_Boss2Pogo(struct mobj_s *actor);
void A_Boss7Chase(struct mobj_s *actor);
void A_BossJetFume(struct mobj_s *actor);
void A_SpawnObjectAbsolute(struct mobj_s *actor);
void A_SpawnObjectRelative(struct mobj_s *actor);
void A_ChangeAngleRelative(struct mobj_s *actor);
void A_ChangeAngleAbsolute(struct mobj_s *actor);
void A_RollAngle(struct mobj_s *actor);
void A_ChangeRollAngleRelative(struct mobj_s *actor);
void A_ChangeRollAngleAbsolute(struct mobj_s *actor);
void A_PlaySound(struct mobj_s *actor);
void A_FindTarget(struct mobj_s *actor);
void A_FindTracer(struct mobj_s *actor);
void A_SetTics(struct mobj_s *actor);
void A_SetRandomTics(struct mobj_s *actor);
void A_ChangeColorRelative(struct mobj_s *actor);
void A_ChangeColorAbsolute(struct mobj_s *actor);
void A_MoveRelative(struct mobj_s *actor);
void A_MoveAbsolute(struct mobj_s *actor);
void A_Thrust(struct mobj_s *actor);
void A_ZThrust(struct mobj_s *actor);
void A_SetTargetsTarget(struct mobj_s *actor);
void A_SetObjectFlags(struct mobj_s *actor);
void A_SetObjectFlags2(struct mobj_s *actor);
void A_RandomState(struct mobj_s *actor);
void A_RandomStateRange(struct mobj_s *actor);
void A_DualAction(struct mobj_s *actor);
void A_RemoteAction(struct mobj_s *actor);
void A_ToggleFlameJet(struct mobj_s *actor);
void A_ItemPop(struct mobj_s *actor); // SRB2kart
void A_JawzChase(struct mobj_s *actor); // SRB2kart
void A_JawzExplode(struct mobj_s *actor); // SRB2kart
void A_SPBChase(struct mobj_s *actor); // SRB2kart
void A_MineExplode(struct mobj_s *actor); // SRB2kart
void A_BallhogExplode(struct mobj_s *actor); // SRB2kart
void A_LightningFollowPlayer(struct mobj_s *actor); // SRB2kart: Lightning shield effect player chasing
void A_FZBoomFlash(struct mobj_s *actor); // SRB2kart
void A_FZBoomSmoke(struct mobj_s *actor); // SRB2kart
void A_RandomShadowFrame(struct mobj_s *actor); //SRB2kart: Shadow spawner frame randomizer
void A_RoamingShadowThinker(struct mobj_s *actor); // SRB2kart: Roaming Shadow moving + attacking players.
void A_MayonakaArrow(struct mobj_s *actor); //SRB2kart: midnight channel arrow sign
void A_ReaperThinker(struct mobj_s *actor); //SRB2kart: mementos reaper
void A_MementosTPParticles(struct mobj_s *actor); //SRB2kart: mementos teleporter particles. Man that's a lot of actions for my shite.
void A_FlameParticle(struct mobj_s *actor); // SRB2kart
void A_OrbitNights(struct mobj_s *actor);
void A_GhostMe(struct mobj_s *actor);
void A_SetObjectState(struct mobj_s *actor);
void A_SetObjectTypeState(struct mobj_s *actor);
void A_KnockBack(struct mobj_s *actor);
void A_PushAway(struct mobj_s *actor);
void A_RingDrain(struct mobj_s *actor);
void A_SplitShot(struct mobj_s *actor);
void A_MissileSplit(struct mobj_s *actor);
void A_MultiShot(struct mobj_s *actor);
void A_InstaLoop(struct mobj_s *actor);
void A_Custom3DRotate(struct mobj_s *actor);
void A_SearchForPlayers(struct mobj_s *actor);
void A_CheckRandom(struct mobj_s *actor);
void A_CheckTargetRings(struct mobj_s *actor);
void A_CheckRings(struct mobj_s *actor);
void A_CheckTotalRings(struct mobj_s *actor);
void A_CheckHealth(struct mobj_s *actor);
void A_CheckRange(struct mobj_s *actor);
void A_CheckHeight(struct mobj_s *actor);
void A_CheckTrueRange(struct mobj_s *actor);
void A_CheckThingCount(struct mobj_s *actor);
void A_CheckAmbush(struct mobj_s *actor);
void A_CheckCustomValue(struct mobj_s *actor);
void A_CheckCusValMemo(struct mobj_s *actor);
void A_SetCustomValue(struct mobj_s *actor);
void A_UseCusValMemo(struct mobj_s *actor);
void A_RelayCustomValue(struct mobj_s *actor);
void A_CusValAction(struct mobj_s *actor);
void A_ForceStop(struct mobj_s *actor);
void A_ForceWin(struct mobj_s *actor);
void A_SpikeRetract(struct mobj_s *actor);
void A_InfoState(struct mobj_s *actor);
void A_Repeat(struct mobj_s *actor);
void A_SetScale(struct mobj_s *actor);
void A_RemoteDamage(struct mobj_s *actor);
void A_HomingChase(struct mobj_s *actor);
void A_TrapShot(struct mobj_s *actor);
void A_VileTarget(struct mobj_s *actor);
void A_VileAttack(struct mobj_s *actor);
void A_VileFire(struct mobj_s *actor);
void A_BrakChase(struct mobj_s *actor);
void A_BrakFireShot(struct mobj_s *actor);
void A_BrakLobShot(struct mobj_s *actor);
void A_NapalmScatter(struct mobj_s *actor);
void A_SpawnFreshCopy(struct mobj_s *actor);
extern boolean actionsoverridden[NUMACTIONS];
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 1024
+403
View File
@@ -0,0 +1,403 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by AJ "Tyron" Martinez.
// Copyright (C) 2024 by James Robert Roman.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_director.c
/// \brief SRB2kart automatic spectator camera.
//#include "k_kart.h"
#include "doomdef.h"
#include "g_game.h"
#include "v_video.h"
#include "k_director.h"
#include "d_netcmd.h"
#include "p_local.h"
#define SWITCHTIME TICRATE * 5 // cooldown between unforced switches
#define BOREDOMTIME 3 * TICRATE / 2 // how long until players considered far apart?
#define TRANSFERTIME TICRATE // how long to delay reaction shots?
#define BREAKAWAYDIST 2000 // how *far* until players considered far apart?
#define WALKBACKDIST 600 // how close should a trailing player be before we switch?
#define PINCHDIST 20000 // how close should the leader be to be considered "end of race"?
struct directorinfo
{
tic_t cooldown; // how long has it been since we last switched?
tic_t freeze; // when nonzero, fixed switch pending, freeze logic!
INT32 attacker; // who to switch to when freeze delay elapses
INT32 maxdist; // how far is the closest player from finishing?
INT32 sortedplayers[MAXPLAYERS]; // position-1 goes in, player index comes out.
INT32 gap[MAXPLAYERS]; // gap between a given position and their closest pursuer
INT32 boredom[MAXPLAYERS]; // how long has a given position had no credible attackers?
} directorinfo;
static inline boolean race_rules(void)
{
return gametype == GT_RACE;
}
static fixed_t ScaleFromMap(fixed_t n, fixed_t scale)
{
return FixedMul(n, FixedDiv(scale, mapobjectscale));
}
static boolean K_DirectorIsEnabled(void)
{
return cv_director.value && !splitscreen && (gamestate == GS_LEVEL && (!playeringame[consoleplayer] || players[consoleplayer].spectator || (demo.playback && (!demo.title || !modeattacking))));
}
void K_InitDirector(void)
{
INT32 playernum;
directorinfo.cooldown = SWITCHTIME;
directorinfo.freeze = 0;
directorinfo.attacker = 0;
directorinfo.maxdist = 0;
for (playernum = 0; playernum < MAXPLAYERS; playernum++)
{
directorinfo.sortedplayers[playernum] = -1;
directorinfo.gap[playernum] = INT32_MAX;
directorinfo.boredom[playernum] = 0;
}
}
static fixed_t K_GetDistanceToFinish(player_t player)
{
mobj_t *mo;
fixed_t dist = 0;
INT16 maxMoveCount = -1;
INT16 maxAngle = -1;
if (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE))
{
for (mo = waypointcap; mo != NULL; mo = mo->tracer)
{
if (mo->spawnpoint->angle != 0)
continue;
dist = P_AproxDistance(P_AproxDistance(mo->x - player.mo->x,
mo->y - player.mo->y),
mo->z - player.mo->z) / FRACUNIT;
break;
}
}
else // crappy optimization weeeee
{
for (mo = waypointcap; mo != NULL; mo = mo->tracer)
{
if (mo->movecount > maxMoveCount)
maxMoveCount = mo->movecount;
if (mo->spawnpoint->angle > maxAngle)
maxAngle = mo->spawnpoint->angle;
if (!(mo->movecount == maxMoveCount && mo->spawnpoint->angle == maxAngle)) // sprint maps finishline waypoint is the one with highest movecount AND angle
continue;
dist = P_AproxDistance(P_AproxDistance(mo->x - player.mo->x,
mo->y - player.mo->y),
mo->z - player.mo->z) / FRACUNIT;
break;
}
}
return dist;
}
static fixed_t K_GetFinishGap(INT32 leader, INT32 follower)
{
fixed_t dista = K_GetDistanceToFinish(players[follower]);
fixed_t distb = K_GetDistanceToFinish(players[leader]);
if (players[follower].kartstuff[k_position] < players[leader].kartstuff[k_position])
{
return distb - dista;
}
else
{
return dista - distb;
}
}
static void K_UpdateDirectorPositions(void)
{
INT32 playernum;
INT32 position;
player_t* target;
memset(directorinfo.sortedplayers, -1, sizeof(directorinfo.sortedplayers));
for (playernum = 0; playernum < MAXPLAYERS; playernum++)
{
target = &players[playernum];
if (playeringame[playernum] && !target->spectator && target->kartstuff[k_position] > 0)
{
directorinfo.sortedplayers[target->kartstuff[k_position] - 1] = playernum;
}
}
for (position = 0; position < MAXPLAYERS - 1; position++)
{
directorinfo.gap[position] = INT32_MAX;
if (directorinfo.sortedplayers[position] == -1 || directorinfo.sortedplayers[position + 1] == -1)
{
continue;
}
directorinfo.gap[position] = ScaleFromMap(K_GetFinishGap(directorinfo.sortedplayers[position], directorinfo.sortedplayers[position + 1]), FRACUNIT);
if (directorinfo.gap[position] >= BREAKAWAYDIST)
{
directorinfo.boredom[position] = (INT32)(min(BOREDOMTIME * 2, directorinfo.boredom[position] + 1));
}
else if (directorinfo.boredom[position] > 0)
{
directorinfo.boredom[position]--;
}
}
if (directorinfo.sortedplayers[0] == -1)
{
directorinfo.maxdist = -1;
return;
}
directorinfo.maxdist = ScaleFromMap(K_GetDistanceToFinish(players[directorinfo.sortedplayers[0]]), FRACUNIT);
}
static boolean K_CanSwitchDirector(void)
{
if (directorinfo.cooldown > 0)
{
return false;
}
return true;
}
static void K_DirectorSwitch(INT32 player, boolean force)
{
if (!K_DirectorIsEnabled())
{
return;
}
if (P_IsDisplayPlayer(&players[player]))
{
return;
}
if (players[player].exiting)
{
return;
}
if (!force && !K_CanSwitchDirector())
{
return;
}
G_ResetView(1, player, true);
directorinfo.cooldown = SWITCHTIME;
}
static void K_DirectorForceSwitch(INT32 player, INT32 time)
{
if (players[player].exiting)
{
return;
}
directorinfo.attacker = player;
directorinfo.freeze = time;
}
void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source)
{
if (!K_DirectorIsEnabled())
{
return;
}
if (!P_IsDisplayPlayer(player))
{
return;
}
if (inflictor && inflictor->player)
{
K_DirectorForceSwitch(inflictor->player - players, TRANSFERTIME);
}
else if (source && source->player)
{
K_DirectorForceSwitch(source->player - players, TRANSFERTIME);
}
}
void K_DrawDirectorDebugger(void)
{
INT32 position;
INT32 leader;
INT32 follower;
INT32 ytxt;
if (!cv_kartdebugdirector.value)
{
return;
}
V_DrawThinString(10, 0, V_70TRANS, va("PLACE"));
V_DrawThinString(40, 0, V_70TRANS, va("CONF?"));
V_DrawThinString(80, 0, V_70TRANS, va("GAP"));
V_DrawThinString(120, 0, V_70TRANS, va("BORED"));
V_DrawThinString(150, 0, V_70TRANS, va("COOLDOWN: %d", directorinfo.cooldown));
V_DrawThinString(230, 0, V_70TRANS, va("MAXDIST: %d", directorinfo.maxdist));
for (position = 0; position < MAXPLAYERS - 1; position++)
{
ytxt = 10 * (position + 1);
leader = directorinfo.sortedplayers[position];
follower = directorinfo.sortedplayers[position + 1];
if (leader == -1 || follower == -1)
break;
V_DrawThinString(10, ytxt, V_70TRANS, va("%d", position));
V_DrawThinString(20, ytxt, V_70TRANS, va("%d", position + 1));
if (players[leader].kartstuff[k_positiondelay])
{
V_DrawThinString(40, ytxt, V_70TRANS, va("NG"));
}
V_DrawThinString(80, ytxt, V_70TRANS, va("%d", directorinfo.gap[position]));
if (directorinfo.boredom[position] >= BOREDOMTIME)
{
V_DrawThinString(120, ytxt, V_70TRANS, va("BORED"));
}
else
{
V_DrawThinString(120, ytxt, V_70TRANS, va("%d", directorinfo.boredom[position]));
}
V_DrawThinString(150, ytxt, V_70TRANS, va("%s", player_names[leader]));
V_DrawThinString(230, ytxt, V_70TRANS, va("%s", player_names[follower]));
}
}
void K_UpdateDirector(void)
{
INT32 *displayplayerp = &displayplayers[0];
INT32 targetposition;
if (!K_DirectorIsEnabled())
{
return;
}
K_UpdateDirectorPositions();
if (directorinfo.cooldown > 0) {
directorinfo.cooldown--;
}
// handle pending forced switches
if (directorinfo.freeze > 0)
{
if (!(--directorinfo.freeze))
K_DirectorSwitch(directorinfo.attacker, true);
return;
}
// if there's only one player left in the list, just switch to that player
if (directorinfo.sortedplayers[0] != -1 && (directorinfo.sortedplayers[1] == -1 ||
// TODO: Battle; I just threw this together quick. Focus on leader.
!race_rules()))
{
K_DirectorSwitch(directorinfo.sortedplayers[0], false);
return;
}
// aaight, time to walk through the standings to find the first interesting pair
// NB: targetposition/sortedplayers is 0-indexed, aiming at the "back half" of a given pair by default.
// we adjust for this when comparing to player->position or when looking at the leading player, Don't Freak Out
for (targetposition = 1; targetposition < MAXPLAYERS; targetposition++)
{
INT32 target;
// you are out of players, try again
if (directorinfo.sortedplayers[targetposition] == -1)
{
break;
}
// pair too far apart? try the next one
if (directorinfo.boredom[targetposition - 1] >= BOREDOMTIME)
{
continue;
}
// pair finished? try the next one
if (players[directorinfo.sortedplayers[targetposition]].exiting)
{
continue;
}
// don't risk switching away from forward pairs at race end, might miss something!
if (directorinfo.maxdist > PINCHDIST)
{
// if the "next" player is close enough, they should be able to see everyone fine!
// walk back through the standings to find a vantage that gets everyone in frame.
// (also creates a pretty cool effect w/ overtakes at speed)
while (targetposition < MAXPLAYERS && directorinfo.gap[targetposition] < WALKBACKDIST)
{
targetposition++;
}
}
target = directorinfo.sortedplayers[targetposition];
// stop here since we're already viewing this player
if (*displayplayerp == target)
{
break;
}
// if we're certain the back half of the pair is actually in this position, try to switch
if (!players[target].kartstuff[k_positiondelay])
{
K_DirectorSwitch(target, false);
}
// even if we're not certain, if we're certain we're watching the WRONG player, try to switch
if (players[*displayplayerp].kartstuff[k_position] != targetposition+1 && !players[*displayplayerp].kartstuff[k_positiondelay])
{
K_DirectorSwitch(target, false);
}
break;
}
}
void K_ToggleDirector(void)
{
if (!K_DirectorIsEnabled())
{
directorinfo.cooldown = 0; // switch immediately
}
COM_ImmedExecute("add director 1");
}
+17
View File
@@ -0,0 +1,17 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by AJ "Tyron" Martinez.
// Copyright (C) 2024 by James Robert Roman.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_director.h
/// \brief SRB2kart automatic spectator camera.
void K_InitDirector(void);
void K_UpdateDirector(void);
void K_DrawDirectorDebugger(void);
void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_ToggleDirector(void);
+268 -165
View File
@@ -16,6 +16,7 @@
#include "m_random.h"
#include "m_menu.h" // ffdhidshfuisduifigergho9igj89dgodhfih AAAAAAAAAA
#include "p_local.h"
#include "p_setup.h"
#include "p_slopes.h"
#include "r_defs.h"
#include "r_draw.h"
@@ -31,12 +32,14 @@
#include "z_zone.h"
#include "m_misc.h"
#include "m_cond.h"
#include "k_director.h"
#include "k_kart.h"
#include "f_finale.h"
#include "lua_hud.h" // For Lua hud checks
#include "lua_hook.h" // For MobjDamage and ShouldDamage
#include "d_main.h" // found_extra_kart
#include "i_video.h"
#ifdef HWRENDER
@@ -74,6 +77,7 @@ IMPL_HUD_OFFSET(stat); // Stats
//extra hud things
consvar_t cv_showstats = {"showstats", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showinput = {"showinput", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showlaptimes = {"showlaptimes", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
CV_PossibleValue_t speedo_cons_t[NUMSPEEDOSTUFF];
consvar_t cv_newspeedometer = {"newspeedometer", "Default", CV_SAVE, speedo_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -84,7 +88,7 @@ consvar_t cv_saltyhopsfx = {"hardcodehopsfx", "On", CV_SAVE, CV_OnOff, NULL, 0,
consvar_t cv_saltysquish = {"hardcodehopsquish", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
//Colourized HUD
consvar_t cv_colorizedhud = {"colorizedhud", "Off", CV_SAVE|CV_CALL, CV_OnOff, Saturn_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_colorizedhud = {"colorizedhud", "Off", CV_SAVE|CV_CALL, CV_OnOff, SaturnHud_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_colorizeditembox = {"colorizeditembox", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t HudColor_cons_t[MAXSKINCOLORS+1];
@@ -613,10 +617,8 @@ UINT8 K_GetKartColorByName(const char *name)
UINT8 K_GetHudColor(void)
{
if (cv_colorizedhud.value){
if (cv_colorizedhudcolor.value) return cv_colorizedhudcolor.value;
}
if (stplyr && P_IsLocalPlayer(stplyr) && gamestate == GS_LEVEL) return stplyr->skincolor;
if (cv_colorizedhud.value && cv_colorizedhudcolor.value) return cv_colorizedhudcolor.value;
return ((stplyr && gamestate == GS_LEVEL) ? stplyr->skincolor : cv_playercolor.value);
}
@@ -678,6 +680,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartgametypepreference);
CV_RegisterVar(&cv_kartspeedometer);
CV_RegisterVar(&cv_kartvoices);
CV_RegisterVar(&cv_karthitemdialog);
CV_RegisterVar(&cv_karteliminatelast);
CV_RegisterVar(&cv_votetime);
@@ -720,6 +723,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_showstats);
CV_RegisterVar(&cv_showinput);
CV_RegisterVar(&cv_showlaptimes);
CV_RegisterVar(&cv_newspeedometer);
CV_RegisterVar(&cv_battlespeedo);
@@ -1896,6 +1900,31 @@ static void K_RegularVoiceTimers(player_t *player)
player->kartstuff[k_tauntvoices] = 4*TICRATE;
}
static void K_PlayGenericCombatSound(mobj_t *source, mobj_t *other, sfxenum_t sfx_id)
{
skin_t *skin = NULL;
// I HATE LOCALSKINS! I HATE LOCALSKINS! :AAAAAAAAAA:
if (source->player)
{
INT32 skinnum = source->player->skinlocal ? (source->player->localskin - 1) : source->player->skin;
skin = &(source->player->skinlocal ? localskins : skins)[skinnum];
}
if (!skin)
return;
boolean alwaysHear = false;
if (other != NULL && P_MobjWasRemoved(other) == false && other->player != NULL)
alwaysHear = P_IsDisplayPlayer(other->player);
if (cv_kartvoices.value)
S_StartSound(alwaysHear ? NULL : source, skin->soundsid[S_sfx[sfx_id].skinsound]);
K_RegularVoiceTimers(source->player);
}
void K_PlayAttackTaunt(mobj_t *source)
{
sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons
@@ -1944,10 +1973,34 @@ void K_PlayOvertakeSound(mobj_t *source)
K_RegularVoiceTimers(source->player);
}
void K_PlayHitEmSound(mobj_t *source)
static boolean K_SetDelayedHitEm(player_t *player, player_t *victim)
{
player_t *prevvictim = NULL;
if (player->hitemtimer)
prevvictim = &players[player->hitemvictim];
// We prioritize local players to hear "hit em" sfx
if (prevvictim && P_IsDisplayPlayer(prevvictim) && !P_IsDisplayPlayer(victim))
return false;
player->hitemtimer = TICRATE/2;
player->hitemvictim = victim - players;
return true;
}
void K_PlayHitEmSound(mobj_t *source, mobj_t *victim)
{
if (cv_kartvoices.value)
{
if (cv_karthitemdialog.value
&& source->player && victim && victim->player
&& K_SetDelayedHitEm(source->player, victim->player))
return; // Don't call K_RegularVoiceTimers yet, we didn't do any sound
S_StartSound(source, sfx_khitem);
}
else
S_StartSound(source, sfx_s1c9); // The only lost gameplay functionality with voices disabled
@@ -1962,6 +2015,33 @@ void K_PlayPowerGloatSound(mobj_t *source)
K_RegularVoiceTimers(source->player);
}
static void K_HandleDelayedHitByEm(player_t *player)
{
if (player->hitemtimer == 0)
{
return;
}
player->hitemtimer--;
if (player->hitemtimer == 0)
{
mobj_t *victim = NULL;
if (player->hitemvictim < MAXPLAYERS && playeringame[player->hitemvictim])
{
player_t *victimPlayer = &players[player->hitemvictim];
if (victimPlayer != NULL && victimPlayer->spectator == false)
{
victim = victimPlayer->mo;
}
}
K_PlayGenericCombatSound(player->mo, victim, sfx_khitem);
}
}
void K_MomentumToFacing(player_t *player)
{
angle_t dangle = player->mo->angle - R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
@@ -2233,6 +2313,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
// PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too.
boolean force = false; // Used to check if Lua ShouldSpin should get us damaged reguardless of flashtics or heck knows what.
UINT8 shouldForce = LUAh_ShouldSpin(player, inflictor, source);
if (P_MobjWasRemoved(player->mo))
return; // mobj was removed (in theory that shouldn't happen)
if (shouldForce == 1)
@@ -2240,6 +2321,8 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
else if (shouldForce == 2)
return;
K_DirectorFollowAttack(player, inflictor, source);
if (!trapitem && G_BattleGametype())
{
if (K_IsPlayerWanted(player))
@@ -2266,7 +2349,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
return;
if (source && source != player->mo && source->player)
K_PlayHitEmSound(source);
K_PlayHitEmSound(source, player->mo);
//player->kartstuff[k_sneakertimer] = 0;
player->kartstuff[k_driftboost] = 0;
@@ -2466,7 +2549,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor)
if (player->mo->state != &states[S_KART_SQUISH]) // Squash
P_SetPlayerMobjState(player->mo, S_KART_SQUISH);
P_PlayRinglossSound(player->mo);
P_PlayRinglossSound(player->mo, source);
player->kartstuff[k_instashield] = 15;
if (cv_kartdebughuddrop.value && !modeattacking)
@@ -2490,6 +2573,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
else if (shouldForce == 2)
return;
K_DirectorFollowAttack(player, inflictor, source);
if (G_BattleGametype())
{
if (K_IsPlayerWanted(player))
@@ -2516,7 +2601,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
return;
if (source && source != player->mo && source->player)
K_PlayHitEmSound(source);
K_PlayHitEmSound(source, player->mo);
player->kartstuff[k_sneakertimer] = 0;
player->kartstuff[k_driftboost] = 0;
@@ -2597,7 +2682,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
P_PlayRinglossSound(player->mo);
P_PlayRinglossSound(player->mo, source);
if (P_IsLocalPlayer(player))
{
@@ -4406,6 +4491,7 @@ static void K_MoveHeldObjects(player_t *player)
if (!player->mo->hnext)
{
player->kartstuff[k_bananadrag] = 0;
if (player->kartstuff[k_eggmanheld])
player->kartstuff[k_eggmanheld] = 0;
else if (player->kartstuff[k_itemheld])
@@ -4421,6 +4507,7 @@ static void K_MoveHeldObjects(player_t *player)
// we need this here too because this is done in afterthink - pointers are cleaned up at the START of each tic...
P_SetTarget(&player->mo->hnext, NULL);
player->kartstuff[k_bananadrag] = 0;
if (player->kartstuff[k_eggmanheld])
player->kartstuff[k_eggmanheld] = 0;
else if (player->kartstuff[k_itemheld])
@@ -4915,23 +5002,14 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd)
static void K_UpdateInvincibilitySounds(player_t *player)
{
INT32 sfxnum = sfx_None;
boolean localplayer = P_IsLocalPlayer(player);
if (player->mo->health > 0 && !P_IsLocalPlayer(player))
if (player->mo->health > 0)
{
if (cv_kartinvinsfx.value)
{
if (player->kartstuff[k_growshrinktimer] > 0) // Prioritize Grow
sfxnum = sfx_alarmg;
else if (player->kartstuff[k_invincibilitytimer] > 0)
sfxnum = sfx_alarmi;
}
else
{
if (player->kartstuff[k_growshrinktimer] > 0)
sfxnum = sfx_kgrow;
else if (player->kartstuff[k_invincibilitytimer] > 0)
sfxnum = sfx_kinvnc;
}
if (player->kartstuff[k_growshrinktimer] > 0 && (!localplayer || cv_growmusic.value == 2)) // Prioritize Grow
sfxnum = cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow;
else if (player->kartstuff[k_invincibilitytimer] > 0 && (!localplayer || cv_supermusic.value == 2))
sfxnum = cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc;
}
if (sfxnum != sfx_None && !S_SoundPlaying(player->mo, sfxnum))
@@ -5276,6 +5354,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// Roulette Code
K_KartItemRoulette(player, cmd);
// Used when karthitemdialog is On
K_HandleDelayedHitByEm(player);
// Handle invincibility sfx
K_UpdateInvincibilitySounds(player); // Also thanks, VAda!
@@ -5993,7 +6074,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
P_SetScale(overlay, player->mo->scale);
}
player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds
if (P_IsLocalPlayer(player) && cv_supermusic.value && cv_birdmusic.value)
if (P_IsLocalPlayer(player) && cv_supermusic.value == 1 && cv_birdmusic.value)
S_ChangeMusicSpecial("kinvnc");
else
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc));
@@ -6198,7 +6279,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
player->mo->destscale = (6*player->mo->destscale)/8;
player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds
if (P_IsLocalPlayer(player) && cv_growmusic.value && cv_birdmusic.value )
if (P_IsLocalPlayer(player) && cv_growmusic.value == 1 && cv_birdmusic.value )
S_ChangeMusicSpecial("kgrow");
else
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow));
@@ -7507,55 +7588,55 @@ static void K_initKartHUD(void)
if (splitscreen) // Splitscreen
{
ITEM_X = 5 + cv_item_xoffset.value;
ITEM_Y = 3 + cv_item_yoffset.value;
ITEM_X = 5;
ITEM_Y = 3;
LAPS_Y = (BASEVIDHEIGHT/2)-24 + cv_laps_yoffset.value;
LAPS_Y = (BASEVIDHEIGHT/2)-24;
POSI_Y = (BASEVIDHEIGHT/2)- 2 + cv_posi_yoffset.value;
POSI_Y = (BASEVIDHEIGHT/2)- 2;
STCD_Y = BASEVIDHEIGHT/4 + cv_stcd_yoffset.value;
STCD_Y = BASEVIDHEIGHT/4;
MINI_Y = (BASEVIDHEIGHT/2) + cv_mini_yoffset.value;
MINI_Y = (BASEVIDHEIGHT/2);
if (splitscreen > 1) // 3P/4P Small Splitscreen
{
// 1P (top left)
ITEM_X = -9 + cv_item_xoffset.value;
ITEM_Y = -8 + cv_item_yoffset.value;
ITEM_X = -9;
ITEM_Y = -8;
LAPS_X = 3 + cv_laps_xoffset.value;
LAPS_Y = (BASEVIDHEIGHT/2)-13 + cv_laps_yoffset.value;
LAPS_X = 3;
LAPS_Y = (BASEVIDHEIGHT/2)-13;
POSI_X = 24 + cv_posi_xoffset.value;
POSI_Y = (BASEVIDHEIGHT/2)- 16 + cv_posi_yoffset.value;
POSI_X = 24;
POSI_Y = (BASEVIDHEIGHT/2)- 16;
// 2P (top right)
ITEM2_X = BASEVIDWIDTH-39 + cv_item_xoffset.value;
ITEM2_Y = -8 + cv_item_yoffset.value;
ITEM2_X = BASEVIDWIDTH-39;
ITEM2_Y = -8;
LAPS2_X = BASEVIDWIDTH-3 + cv_laps_xoffset.value;
LAPS2_Y = (BASEVIDHEIGHT/2)-13 + cv_laps_yoffset.value;
LAPS2_X = BASEVIDWIDTH-3;
LAPS2_Y = (BASEVIDHEIGHT/2)-13;
POSI2_X = BASEVIDWIDTH -4 + cv_posi_xoffset.value;
POSI2_Y = (BASEVIDHEIGHT/2)- 16 + cv_posi_yoffset.value;
POSI2_X = BASEVIDWIDTH -4;
POSI2_Y = (BASEVIDHEIGHT/2)- 16;
// Reminder that 3P and 4P are just 1P and 2P splitscreen'd to the bottom.
STCD_X = BASEVIDWIDTH/4 + cv_stcd_xoffset.value;
STCD_X = BASEVIDWIDTH/4;
MINI_X = (3*BASEVIDWIDTH/4) + cv_mini_xoffset.value;
MINI_Y = (3*BASEVIDHEIGHT/4) + cv_mini_yoffset.value;
MINI_X = (3*BASEVIDWIDTH/4);
MINI_Y = (3*BASEVIDHEIGHT/4);
if (splitscreen > 2) // 4P-only
{
MINI_X = (BASEVIDWIDTH/2) + cv_mini_xoffset.value;
MINI_Y = (BASEVIDHEIGHT/2) + cv_mini_yoffset.value;
MINI_X = (BASEVIDWIDTH/2);
MINI_Y = (BASEVIDHEIGHT/2);
}
}
}
if (timeinmap > 113)
if (timeinmap > 113 || forceshowhud)
hudtrans = cv_translucenthud.value;
else if (timeinmap > 105)
hudtrans = ((((INT32)timeinmap) - 105)*cv_translucenthud.value)/(113-105);
@@ -7710,49 +7791,6 @@ static void K_drawKartStats(void)
if (!LUA_HudEnabled(hud_statdisplay))
return;
// I tried my best, but this is still mess :/
if (splitscreen)
{
if (splitscreen == 1)
{
// If we are in 2-player splitscreen, for player 1 we move hud to up and remove snapping
// to bottom
if (splitnum == 0)
{
y /= 2;
flags = V_SNAPTOLEFT;
}
else
{
// Can move it down a bit
y += 20;
}
}
else
{
// In 4-player splitscreen...
flags = 0;
// ...For players 2 and 4, which are at right side, we move x coordinate...
if (splitnum == 1 || splitnum == 3)
x += BASEVIDWIDTH/2;
// ...Else, for players on left side we can snap position to left...
else
flags |= V_SNAPTOLEFT;
// ...For players 1 and 2, which are at top side, we move y coordinate...
if (splitnum == 0 || splitnum == 1)
y /= 2;
// ...Else, for players on bottom side we can snap position to bottom
else
{
flags |= V_SNAPTOBOTTOM;
// Can move it down a bit
y += 20;
}
}
}
//Internal offset for speedometer
if (cv_kartspeedometer.value)
@@ -7764,10 +7802,49 @@ static void K_drawKartStats(void)
}
else
spdoffset = 0;
// Customizations c:
x += 18 + cv_stat_xoffset.value;
y += cv_stat_yoffset.value + (G_BattleGametype() ? (stplyr->kartstuff[k_bumper] ? -5 : -8) : 0) + spdoffset;
if (!splitscreen)
{
x += 18 + cv_stat_xoffset.value;
y += cv_stat_yoffset.value + (G_BattleGametype() ? (stplyr->kartstuff[k_bumper] ? -5 : -8) : 0) + spdoffset;
}
else if (splitscreen == 1) // I tried my best, but this is still mess :/ < :Blobcatpats: c:
{
x -= 10;
y -= 40;
y += (G_BattleGametype() ? (stplyr->kartstuff[k_bumper] ? -5 : -8) : 0);
// If we are in 2-player splitscreen, for player 1 we move hud to up and remove snapping
// to bottom
if (splitnum == 0)
{
y /= 2;
flags = V_SNAPTOLEFT;
}
else
{
// Can move it down a bit
y += 45;
}
}
else
{
if (splitnum == 0 || splitnum == 2) // If we are P1 or P3...
{
// ye i just align it to position number lol
x = POSI_X + 19;
y = POSI_Y - 6;
flags = V_SNAPTOLEFT|((splitnum == 2) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
}
else // else, that means we're P2 or P4.
{
x = POSI2_X - 75;
y = POSI2_Y - 6;
flags = V_SNAPTORIGHT|((splitnum == 3) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
}
}
flags |= V_HUDTRANS;
skin_t *fakeskin;
@@ -8111,8 +8188,6 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
{
// TIME_X = BASEVIDWIDTH-124; // 196
// TIME_Y = 6; // 6
tic_t worktime;
INT32 splitflags = 0;
if (!mode)
@@ -8137,63 +8212,51 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
TX += 33;
worktime = drawtime/(60*TICRATE);
if (mode && !drawtime)
V_DrawKartString(TX, TY+3, splitflags, va("--'--\"--"));
else if (worktime < 100) // 99:99:99 only
if (drawtime == UINT32_MAX)
;
else if (mode && !drawtime)
{
if ((cv_timelimit.value && G_BattleGametype()) && (!players[consoleplayer].exiting && (leveltime > (timelimitintics + starttime + TICRATE/2)) && cv_overtime.value)) // i hate this so much
{
V_DrawKartString(TX, TY+3, splitflags, va("OVERTIME"));
return;
}
// zero minute
if (worktime < 10)
{
V_DrawKartString(TX, TY+3, splitflags, va("0"));
// minutes time 0 __ __
V_DrawKartString(TX+12, TY+3, splitflags, va("%d", worktime));
}
// minutes time 0 __ __
else
V_DrawKartString(TX, TY+3, splitflags, va("%d", worktime));
// apostrophe location _'__ __
V_DrawKartString(TX+24, TY+3, splitflags, va("'"));
worktime = (drawtime/TICRATE % 60);
// zero second _ 0_ __
if (worktime < 10)
{
V_DrawKartString(TX+36, TY+3, splitflags, va("0"));
// seconds time _ _0 __
V_DrawKartString(TX+48, TY+3, splitflags, va("%d", worktime));
}
// zero second _ 00 __
else
V_DrawKartString(TX+36, TY+3, splitflags, va("%d", worktime));
// quotation mark location _ __"__
V_DrawKartString(TX+60, TY+3, splitflags, va("\""));
worktime = G_TicsToCentiseconds(drawtime);
// zero tick _ __ 0_
if (worktime < 10)
{
V_DrawKartString(TX+72, TY+3, splitflags, va("0"));
// tics _ __ _0
V_DrawKartString(TX+84, TY+3, splitflags, va("%d", worktime));
}
// zero tick _ __ 00
else
V_DrawKartString(TX+72, TY+3, splitflags, va("%d", worktime));
}
else if ((drawtime/TICRATE) & 1)
V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99"));
else
{
tic_t worktime = drawtime/(60*TICRATE);
if ((G_BattleGametype() && cv_timelimit.value) && (!players[consoleplayer].exiting && (leveltime > (timelimitintics + starttime + TICRATE/2)) && cv_overtime.value)) // i hate this so much
{
V_DrawKartString(TX, TY+3, splitflags, va("OVERTIME"));
}
else if (worktime < 100)
{
// minutes time 00 __ __
V_DrawKartString(TX, TY+3, splitflags, va("%d", worktime/10));
V_DrawKartString(TX+12, TY+3, splitflags, va("%d", worktime%10));
// apostrophe location _'__ __
V_DrawKartString(TX+24, TY+3, splitflags, va("'"));
worktime = (drawtime/TICRATE % 60);
// seconds time _ 00 __
V_DrawKartString(TX+36, TY+3, splitflags, va("%d", worktime/10));
V_DrawKartString(TX+48, TY+3, splitflags, va("%d", worktime%10));
// quotation mark location _ __"__
V_DrawKartString(TX+60, TY+3, splitflags, va("\""));
worktime = G_TicsToCentiseconds(drawtime);
// tics _ __ 00
V_DrawKartString(TX+72, TY+3, splitflags, va("%d", worktime/10));
V_DrawKartString(TX+84, TY+3, splitflags, va("%d", worktime%10));
}
else if ((drawtime/TICRATE) & 1)
V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99"));
}
if (emblemmap && (modeattacking || (mode == 1)) && !demo.playback) // emblem time!
{
@@ -8707,7 +8770,7 @@ static void K_drawKartLaps(void)
else
V_DrawMappedPatch(fx, fy, V_HUDTRANS|splitflags, kp_lapstickerclr, colormap);
}
if (stplyr->exiting)
V_DrawKartString(fx+33, fy+3, V_HUDTRANS|splitflags, "FIN");
else
@@ -8722,7 +8785,7 @@ static void K_drawKartSpeedometer(void)
return;
fixed_t convSpeed = 0;
//KartZ speedo
fixed_t fuspeed = 0;
INT32 spdpatch = 0;
@@ -8860,6 +8923,14 @@ static void K_drawKartBumpersOrKarma(void)
fy = info.y;
fflags = info.flags;
if (cv_battlespeedo.value && !splitscreen)
{
if ((cv_newspeedometer.value == 2 && xtra_speedo) || (cv_newspeedometer.value == 3 && achi_speedo) || (cv_newspeedometer.value == 5 && xtra_speedo3))
fy += 5;
else
fy += 7;
}
if (splitscreen > 1)
{
if (stplyr->kartstuff[k_bumper] <= 0)
@@ -8996,11 +9067,11 @@ static boolean K_GetScreenCoords(vector2_t *vec, player_t *player, mobj_t *targe
offset = FixedMul(FINETANGENT(((aimingangle+ANGLE_90)>>ANGLETOFINESHIFT) & 4095), xres);
// this isn't fovtan... what am i even doing anymore
if (splitscreen == 1)
offset = 17*offset/10;
// OpenGL with software perspective is miscentered on non-16:10 resolutions
offset = 17*offset/120;
#ifdef HWRENDER
if (rendermode == render_opengl)
offset = FixedMul(offset, FixedDiv(104857, FixedDiv(xres, yres)));
// OpenGL with software perspective is miscentered on non-16:10 resolutions
//if (rendermode == render_opengl)
//offset = FixedMul(offset, FixedDiv(104857, FixedDiv(xres, yres)));
#endif
// thanks fickle
offset = FixedDiv(offset, fovratio);
@@ -9023,12 +9094,14 @@ static boolean K_GetScreenCoords(vector2_t *vec, player_t *player, mobj_t *targe
int splitindex = stplyrnum;
// adjust coords for splitscreen
if (splitscreen == 1){ // 2P
if (splitscreen == 1) // 2P
{
y = y>>1;
if (splitindex)
y = y + yres;
}
if (splitscreen >= 2) { // 3P or 4P
if (splitscreen >= 2) // 3P or 4P
{
x = x>>1;
y = y>>1;
if (splitindex & 1)
@@ -9297,9 +9370,17 @@ static void K_drawDriftGauge(void)
0, 31, 47, 63, 79, 95, 111, 119, 127, 143, 159, 175, 183, 191, 199, 207, 223, 247
};
if (!stplyr->mo || !stplyr->kartstuff[k_drift] || (!splitscreen && !camera->chase))
if (!stplyr->mo || (!splitscreen && !camera->chase))
return;
if (forceshowhud)
goto skipcrap; // i will skip the drift early return and you cant stop me!
if (!stplyr->kartstuff[k_drift])
return;
skipcrap:
if (!K_GetScreenCoords(&pos, stplyr, stplyr->mo, FixedMul(cv_driftgaugeofs.value, cv_driftgaugeofs.value > 0 ? stplyr->mo->scale : mapobjectscale), false))
return;
@@ -9352,9 +9433,7 @@ static void K_drawDriftGauge(void)
{
cmap = R_GetTranslationColormap(TC_RAINBOW, 1 + leveltime % (MAXSKINCOLORS-1),GTC_CACHE);
for (i = 0; i < 4; i++)
{
V_DrawFill(barx, bary+dup*1+dup*i, BAR_WIDTH, dup, (driftrainbow[(leveltime % 18) + 1] + i*2) | V_NOSCALESTART|drifttrans);
}
V_DrawFill(barx, bary+dup*1+dup*i, BAR_WIDTH, dup, (driftrainbow[min((leveltime % 18) + 1, 18 - 1)] + i*2) | V_NOSCALESTART|drifttrans);
}
else // none/blue/red
{
@@ -9679,7 +9758,9 @@ static void K_drawKartMinimap(void)
splitflags = info.flags;
if (timeinmap > 105)
if (forceshowhud)
minimaptrans = cv_kartminimap.value;
else if (timeinmap > 105)
{
minimaptrans = cv_kartminimap.value;
if (timeinmap <= 113)
@@ -10492,9 +10573,27 @@ void K_drawKartHUD(void)
// If not splitscreen, draw...
if (!splitscreen && !demo.title)
{
tic_t realtime = stplyr->realtime;
if (cv_showlaptimes.value
&& stplyr->kartstuff[k_lapanimation]
&& !stplyr->exiting
&& stplyr->laptime[LAP_LAST] != 0
&& !midgamejoin)
{
if ((stplyr->kartstuff[k_lapanimation] / 5) & 1)
{
realtime = stplyr->laptime[LAP_LAST];
}
else
{
realtime = UINT32_MAX;
}
}
// Draw the timestamp
if (LUA_HudEnabled(hud_time))
K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, gamemap, 0);
K_drawKartTimestamp(realtime, TIME_X, TIME_Y, gamemap, 0);
if (!modeattacking)
{
@@ -10521,6 +10620,7 @@ void K_drawKartHUD(void)
if (demo.title) // Draw title logo instead in demo.titles
{
INT32 x = (BASEVIDWIDTH - 32)*FRACUNIT, y = 128*FRACUNIT, offs;
INT32 logoflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM;
if (splitscreen == 3)
{
@@ -10539,8 +10639,8 @@ void K_drawKartHUD(void)
x += offs - frac;
}
V_DrawSciencePatch(x - (54*FRACUNIT), y, 0, W_CachePatchName("TTKBANNR", PU_CACHE), FRACUNIT/4);
V_DrawSciencePatch(x - (54*FRACUNIT), y + (25*FRACUNIT), 0, W_CachePatchName("TTKART", PU_CACHE), FRACUNIT/4);
V_DrawSciencePatch(x - (54*FRACUNIT), y, logoflags, W_CachePatchName("TTKBANNR", PU_CACHE), FRACUNIT/4);
V_DrawSciencePatch(x - (54*FRACUNIT), y + (25*FRACUNIT), logoflags, W_CachePatchName("TTKART", PU_CACHE), FRACUNIT/4);
}
else if (G_RaceGametype()) // Race-only elements
{
@@ -10636,6 +10736,9 @@ void K_drawKartHUD(void)
if (cv_kartdebugcheckpoint.value)
K_drawCheckpointDebugger();
if (cv_kartdebugdirector.value)
K_DrawDirectorDebugger();
if (cv_kartdebugnodes.value)
{
UINT8 p;
+2 -1
View File
@@ -31,6 +31,7 @@ extern consvar_t cv_highresportrait;
extern consvar_t cv_stat_xoffset;
extern consvar_t cv_stat_yoffset;
extern consvar_t cv_showstats;
extern consvar_t cv_showlaptimes;
extern consvar_t cv_battlespeedo;
#define NUMSPEEDOSTUFF 6
@@ -91,7 +92,7 @@ void K_UpdateSpectateGrief(void);
void K_PlayAttackTaunt(mobj_t *source);
void K_PlayBoostTaunt(mobj_t *source);
void K_PlayOvertakeSound(mobj_t *source);
void K_PlayHitEmSound(mobj_t *source);
void K_PlayHitEmSound(mobj_t *source, mobj_t *victim);
void K_PlayPowerGloatSound(mobj_t *source);
const char *K_GetItemPatch(UINT8 item, boolean tiny);
+80 -3
View File
@@ -20,6 +20,7 @@
#include "m_random.h"
#include "s_sound.h"
#include "g_game.h"
#include "g_input.h"
#include "hu_stuff.h" // HU_AddChatText
#include "console.h"
#include "k_kart.h" // SRB2Kart
@@ -1258,6 +1259,7 @@ static int lib_pPlayRinglossSound(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
mobj_t *damager = NULL;
NOHUD
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
@@ -1267,8 +1269,15 @@ static int lib_pPlayRinglossSound(lua_State *L)
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnoneornil(L, 3))
{
damager = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!damager)
return LUA_ErrInvalid(L, "mobj_t");
}
if (!player || P_IsLocalPlayer(player))
P_PlayRinglossSound(source);
P_PlayRinglossSound(source, damager);
return 0;
}
@@ -2556,10 +2565,22 @@ static int lib_kOvertakeSound(lua_State *L)
static int lib_kHitEmSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *victim = NULL;
if (!lua_isnoneornil(L, 2))
{
victim = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!victim)
return LUA_ErrInvalid(L, "mobj_t");
}
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayHitEmSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayHitEmSound(mobj);
if (victim && !victim->player)
return luaL_error(L, "K_PlayHitEmSound: mobj_t isn't a player object."); //Same as above
K_PlayHitEmSound(mobj, victim);
return 0;
}
@@ -3000,6 +3021,58 @@ static int lib_kSetHyuCountdown(lua_State *L)
return 0;
}
// G_INPUT
////////////
static int lib_gSetPlayerGamepadIndicatorColor(lua_State *L)
{
INT32 player = -1;
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
UINT16 color = (UINT16)luaL_checkinteger(L, 2); // skincolor
for (int i = 0; i < MAXSPLITSCREENPLAYERS; ++i)
{
if (plr - players == displayplayers[i])
{
player = i;
break;
}
}
// Not a local player
if (player == -1) return 0;
// pls update with color 0 when youre done with changing led stuff so it can get player color again
G_SetPlayerGamepadIndicatorColor(player, color);
return 0;
}
static int lib_gPlayerDeviceRumble(lua_State *L)
{
INT32 player = -1;
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
UINT16 low_strength = (UINT16)luaL_checkinteger(L, 2); // low frequency rumble motor strenght
UINT16 high_strength = (UINT16)luaL_checkinteger(L, 3); // high frequency rumble motor strenght
UINT32 duration = (UINT32)luaL_optinteger(L, 4, 84); // duration of rumble in ms
for (int i = 0; i < MAXSPLITSCREENPLAYERS; ++i)
{
if (plr - players == displayplayers[i])
{
player = i;
break;
}
}
// Not a local player
if (player == -1) return 0;
G_PlayerDeviceRumble(player, low_strength, high_strength, duration);
return 0;
}
static luaL_Reg lib[] = {
{"print", lib_print},
{"chatprint", lib_chatprint},
@@ -3247,6 +3320,10 @@ static luaL_Reg lib[] = {
{"K_SetIndirectItemCooldown",lib_kSetIndirectItemCountdown},
{"K_SetHyudoroCooldown",lib_kSetHyuCountdown},
//g_input
{"G_SetPlayerGamepadIndicatorColor",lib_gSetPlayerGamepadIndicatorColor},
{"G_PlayerDeviceRumble",lib_gPlayerDeviceRumble},
{NULL, NULL}
};
@@ -3266,4 +3343,4 @@ int LUA_BaseLib(lua_State *L)
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_register(L, NULL, lib);
return 0;
}
}
+50 -12
View File
@@ -453,9 +453,11 @@ static int lib_cvRegisterVar(lua_State *L)
if (!(((cvar->flags & CV_HIDEN)) || (cvar->flags & CV_NOSHOWHELP)) && (cvar->PossibleValue || !(cvar->value == 0 && stricmp(cvar->string, "0"))))
{
char *temp = NULL;
if (!category)
{
char *temp = strdup(wadfiles[numwadfiles - 1]->filename);
temp = strdup(wadfiles[numwadfiles - 1]->filename);
nameonly(temp);
category = temp;
@@ -465,6 +467,8 @@ static int lib_cvRegisterVar(lua_State *L)
M_SlotCvarIntoModMenu(cvar, category, menu_name);
else
M_SlotCvarIntoModMenu(cvar, category, cvar->name);
free (temp);
}
// return cvar userdata
@@ -580,27 +584,59 @@ static luaL_Reg lib[] = {
{NULL, NULL}
};
enum cvar_e
{
cvar_name,
cvar_defaultvalue,
cvar_flags,
cvar_value,
cvar_string,
cvar_changed,
};
static const char *const cvar_opt[] = {
"name",
"defaultvalue",
"flags",
"value",
"string",
"changed",
NULL,
};
static int cvar_fields_ref = LUA_NOREF;
static int cvar_get(lua_State *L)
{
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
const char *field = luaL_checkstring(L, 2);
enum cvar_e field = Lua_optoption(L, 2, -1, cvar_fields_ref);
if(fastcmp(field,"name"))
switch (field)
{
case cvar_name:
lua_pushstring(L, cvar->name);
else if(fastcmp(field,"defaultvalue"))
break;
case cvar_defaultvalue:
lua_pushstring(L, cvar->defaultvalue);
else if(fastcmp(field,"flags"))
break;
case cvar_flags:
lua_pushinteger(L, cvar->flags);
else if(fastcmp(field,"value"))
break;
case cvar_value:
lua_pushinteger(L, cvar->value);
else if(fastcmp(field,"string"))
break;
case cvar_string:
lua_pushstring(L, cvar->string);
else if(fastcmp(field,"changed"))
break;
case cvar_changed:
lua_pushboolean(L, cvar->changed);
else if (devparm)
return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field);
else
return 0;
break;
default:
if (devparm)
return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field);
else
return 0;
}
return 1;
}
@@ -612,6 +648,8 @@ int LUA_ConsoleLib(lua_State *L)
lua_setfield(L, -2, "__index");
lua_pop(L,1);
cvar_fields_ref = Lua_CreateFieldTable(L, cvar_opt);
// Set empty registry tables
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "COM_Command");
+4 -1
View File
@@ -55,6 +55,7 @@ enum hook {
hook_PlayerCmd, //SRB2KART
hook_IntermissionThinker, //SRB2KART
hook_VoteThinker, //SRB2KART
hook_ServerJoin, // SRB2KART - Saturn 32p
hook_MAX // last hook
};
@@ -106,8 +107,10 @@ boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); //
boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior.
boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior.
void LUAh_ServerJoin(void); // SRB2KART - Saturn 32p: called by client when joining a server, allows lua to load any sort of config file
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
void LUAh_VoteThinker(void); // Hook for Y_VoteTicker
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
+1032 -811
View File
File diff suppressed because it is too large. Load diff
+7 -1
View File
@@ -42,9 +42,15 @@ enum hud {
extern boolean hud_running;
extern boolean hud_interpolate; // interpolation enabled
extern UINT8 hud_interptag; // current tag
extern UINT32 hud_interpcounter; // number of HUD hooks ran
extern boolean hud_interpstring; // string mode
extern boolean hud_interplatch; // string mode was toggled
boolean LUA_HudEnabled(enum hud option);
void LUAh_GameHUD(player_t *stplyr, huddrawlist_h list);
void LUAh_GameHUD(huddrawlist_h list);
void LUAh_ScoresHUD(huddrawlist_h list);
void LUAh_IntermissionHUD(huddrawlist_h list);
void LUAh_VoteHUD(huddrawlist_h list);
+70 -26
View File
@@ -32,6 +32,12 @@
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
boolean hud_running = false;
boolean hud_interpolate = false;
UINT8 hud_interptag = 0;
UINT32 hud_interpcounter = 0;
boolean hud_interpstring = false;
boolean hud_interplatch = false;
static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field
@@ -100,6 +106,8 @@ static const char *const hudhook_opt[] = {
"vote",
NULL};
static int patch_fields_ref = LUA_NOREF;
// alignment types for v.drawString
enum align {
align_left = 0,
@@ -223,6 +231,8 @@ static const char *const hud_drawinfo_options[] = {
"minimap",
NULL};
static int camera_fields_ref = LUA_NOREF;
static int lib_getHudInfo(lua_State *L)
{
UINT32 i;
@@ -292,7 +302,7 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref);
// patches are CURRENTLY always valid, expected to be cached with PU_STATIC
// this may change in the future, so patch.valid still exists
@@ -327,7 +337,7 @@ static int patch_set(lua_State *L)
static int camera_get(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt);
enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref);
// cameras should always be valid unless I'm a nutter
I_Assert(cam != NULL);
@@ -1178,6 +1188,41 @@ static int libd_getDrawInfo(lua_State *L)
return 3;
}
static int libd_interpolate(lua_State *L)
{
HUDONLY
// do type checking even if interpolation is disabled
boolean newinterpolate;
UINT8 newtag;
if (lua_isnumber(L, 1))
{
newinterpolate = true;
newtag = luaL_checkinteger(L, 1);
}
else
{
newinterpolate = luaL_checkboolean(L, 1);
newtag = 0;
}
if (!cv_uncappedhud.value)
return 0;
hud_interpolate = newinterpolate;
hud_interptag = newtag;
return 0;
}
static int libd_interpLatch(lua_State *L)
{
HUDONLY
hud_interpstring = hud_interplatch = luaL_checkboolean(L, 1);
return 0;
}
static luaL_Reg lib_draw[] = {
{"patchExists", libd_patchExists},
{"cachePatch", libd_cachePatch},
@@ -1205,6 +1250,8 @@ static luaL_Reg lib_draw[] = {
{"getDrawInfo", libd_getDrawInfo},
{"getHudColor", libd_getHudColor},
{"useColorHud", libd_useColorHud},
{"interpolate", libd_interpolate},
{"interpLatch", libd_interpLatch},
{NULL, NULL}
};
@@ -1396,11 +1443,15 @@ int LUA_HudLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
patch_fields_ref = Lua_CreateFieldTable(L, patch_opt);
luaL_newmetatable(L, META_CAMERA);
lua_pushcfunction(L, camera_get);
lua_setfield(L, -2, "__index");
lua_pop(L,1);
camera_fields_ref = Lua_CreateFieldTable(L, camera_opt);
luaL_register(L, "hud", lib_hud);
return 0;
}
@@ -1413,7 +1464,7 @@ boolean LUA_HudEnabled(enum hud option)
}
// Hook for HUD rendering
void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
void LUAh_GameHUD(huddrawlist_h list)
{
if (!gL || !(hudAvailable & (1<<hudhook_game)))
return;
@@ -1434,33 +1485,17 @@ void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
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 > 2 && stplayr == &players[displayplayers[3]])
{
LUA_PushUserdata(gL, &camera[3], META_CAMERA);
camnum = 4;
}
else if (splitscreen > 1 && stplayr == &players[displayplayers[2]])
{
LUA_PushUserdata(gL, &camera[2], META_CAMERA);
camnum = 3;
}
else if (splitscreen && stplayr == &players[displayplayers[1]])
{
LUA_PushUserdata(gL, &camera[1], META_CAMERA);
camnum = 2;
}
else
{
LUA_PushUserdata(gL, &camera[0], META_CAMERA);
camnum = 1;
}
LUA_PushUserdata(gL, stplyr, META_PLAYER);
LUA_PushUserdata(gL, &camera[stplyrnum], META_CAMERA);
camnum = stplyrnum + 1;
hud_interpcounter = 0;
lua_pushnil(gL);
while (lua_next(gL, -5) != 0) {
hud_interpolate = hud_interpstring = hud_interplatch = false;
hud_interpcounter++;
lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // stplyr
lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3, 0, 1);
}
@@ -1493,7 +1528,10 @@ void LUAh_ScoresHUD(huddrawlist_h list)
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
hud_interpcounter = 0;
while (lua_next(gL, -3) != 0) {
hud_interpolate = hud_interpstring = hud_interplatch = false;
hud_interpcounter++;
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
@@ -1526,7 +1564,10 @@ void LUAh_IntermissionHUD(huddrawlist_h list)
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
hud_interpcounter = 0;
while (lua_next(gL, -3) != 0) {
hud_interpolate = hud_interpstring = hud_interplatch = false;
hud_interpcounter++;
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
@@ -1559,7 +1600,10 @@ void LUAh_VoteHUD(huddrawlist_h list)
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
hud_interpcounter = 0;
while (lua_next(gL, -3) != 0) {
hud_interpolate = hud_interpstring = hud_interplatch = false;
hud_interpcounter++;
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
+287 -52
View File
@@ -11,11 +11,16 @@
/// \brief a data structure for managing cached drawlists for the Lua hud lib
#include "lua_hudlib_drawlist.h"
#include "lua_hud.h"
#include "blua/lstate.h" // shhhhhh
#include "lua_libs.h"
#include <string.h>
#include "v_video.h"
#include "z_zone.h"
#include "r_main.h"
#include "r_fps.h"
enum drawitem_e {
DI_Draw = 0,
@@ -34,37 +39,45 @@ enum drawitem_e {
// A single draw item with all possible arguments needed for a draw call.
typedef struct drawitem_s {
UINT64 id;
enum drawitem_e type;
fixed_t x;
fixed_t y;
fixed_t w;
fixed_t h;
INT32 c;
fixed_t scale;
fixed_t hscale;
fixed_t vscale;
patch_t *patch;
INT32 flags;
UINT16 basecolor;
UINT16 outlinecolor;
union {
INT32 flags;
INT32 c;
};
union {
fixed_t scale; // drawScaled
fixed_t hscale; // drawStretched
fixed_t w; // drawFill
INT32 align; // drawString
INT32 num; // drawNum, drawPaddedNum, drawPingNum
UINT16 color; // fadeScreen
};
union {
fixed_t vscale; // drawStretched
fixed_t h; // drawFill
INT32 digits; // drawPaddedNum
UINT8 strength; // fadeScreen
};
// pointers (and size_t's) last, for potentially better packing
union {
patch_t *patch;
size_t stroffset; // offset into strbuf to get str
};
const UINT8 *colormap;
UINT8 *basecolormap;
UINT8 *outlinecolormap;
fixed_t sx;
fixed_t sy;
INT32 num;
INT32 digits;
size_t stroffset; // offset into strbuf to get str
UINT16 color;
UINT8 strength;
INT32 align;
} drawitem_t;
// The internal structure of a drawlist.
struct huddrawlist_s {
drawitem_t *items;
size_t items_capacity;
size_t items_len;
drawitem_t *olditems;
size_t olditems_len;
size_t capacity;
char *strbuf;
size_t strbuf_capacity;
size_t strbuf_len;
@@ -88,8 +101,10 @@ huddrawlist_h LUA_HUD_CreateDrawList(void)
drawlist = (huddrawlist_h) Z_Calloc(sizeof(struct huddrawlist_s), PU_STATIC, NULL);
drawlist->items = NULL;
drawlist->items_capacity = 0;
drawlist->items_len = 0;
drawlist->olditems = NULL;
drawlist->olditems_len = 0;
drawlist->capacity = 0;
drawlist->strbuf = NULL;
drawlist->strbuf_capacity = 0;
drawlist->strbuf_len = 0;
@@ -99,15 +114,14 @@ huddrawlist_h LUA_HUD_CreateDrawList(void)
void LUA_HUD_ClearDrawList(huddrawlist_h list)
{
// swap the old and new lists
void *tmp = list->olditems;
list->olditems = list->items;
list->items = tmp;
// rather than deallocate, we'll just save the existing allocation and empty
// it out for reuse
// this memset probably isn't necessary
if (list->items)
{
memset(list->items, 0, sizeof(drawitem_t) * list->items_capacity);
}
list->olditems_len = list->items_len;
list->items_len = 0;
if (list->strbuf)
@@ -125,6 +139,10 @@ void LUA_HUD_DestroyDrawList(huddrawlist_h list)
{
Z_Free(list->items);
}
if (list->olditems)
{
Z_Free(list->olditems);
}
if (list->strbuf)
{
Z_Free(list->strbuf);
@@ -143,11 +161,11 @@ boolean LUA_HUD_IsDrawListValid(huddrawlist_h list)
static size_t AllocateDrawItem(huddrawlist_h list)
{
if (!list) I_Error("can't allocate draw item: invalid list");
if (list->items_capacity <= list->items_len + 1)
if (list->capacity <= list->items_len)
{
if (list->items_capacity == 0) list->items_capacity = 128;
else list->items_capacity *= 2;
list->items = (drawitem_t *) Z_Realloc(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL);
list->capacity = list->capacity == 0 ? 128 : list->capacity * 2;
list->items = Z_Realloc(list->items, sizeof(struct drawitem_s) * list->capacity, PU_STATIC, NULL);
list->olditems = Z_Realloc(list->olditems, sizeof(struct drawitem_s) * list->capacity, PU_STATIC, NULL);
}
return list->items_len++;
@@ -178,6 +196,149 @@ static size_t CopyString(huddrawlist_h list, const char* str)
}
}
static void CalcStringCoords(drawitem_t *item, const char *string)
{
if (!(item->flags & V_NOSCALESTART) && cv_uncappedhud.value)
{
INT32 dupx = vid.dupx;
INT32 dupy = vid.dupy;
item->flags |= V_NOSCALESTART;
if (item->flags & V_SCALEPATCHMASK) switch ((item->flags & 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);
INT32 x = item->x * dupx;
INT32 y = item->y * dupy;
if (item->flags & V_SPLITSCREEN)
y += (BASEVIDHEIGHT * (dupy - 1))/2;
if (item->flags & V_HORZSCREEN)
x += (BASEVIDWIDTH * (dupx - 1))/2;
if (vid.width != BASEVIDWIDTH * dupx)
{
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if ((item->flags & (V_HORZSCREEN|V_SNAPTOLEFT)) == (V_HORZSCREEN|V_SNAPTOLEFT))
x += (vid.width/2 - (BASEVIDWIDTH/2 * dupx));
else if (item->flags & V_SNAPTORIGHT)
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(item->flags & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if ((item->flags & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
else if (item->flags & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(item->flags & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
}
// need to compensate for dup here
if (item->type == DI_DrawString)
{
if (item->align == align_center)
x -= (V_StringWidth(string, item->flags) * (dupx - 1))/2;
if (item->align == align_right)
x -= V_StringWidth(string, item->flags) * (dupx - 1);
if (item->align == align_smallright)
x -= V_SmallStringWidth(string, item->flags) * (dupx - 1);
if (item->align == align_thinright)
x -= V_ThinStringWidth(string, item->flags) * (dupx - 1);
}
item->x = x;
item->y = y;
}
}
static void CalcFillCoords(drawitem_t *item)
{
if (!(item->flags & V_NOSCALESTART) && cv_uncappedhud.value)
{
INT32 dupx = vid.dupx;
INT32 dupy = vid.dupy;
INT32 x = item->x * dupx;
INT32 y = item->y * dupy;
INT32 c = item->c;
item->flags |= V_NOSCALESTART;
item->w *= dupx;
item->h *= dupy;
// Center it if necessary
if (vid.width != BASEVIDWIDTH * dupx)
{
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if (c & V_SNAPTORIGHT)
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(c & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if (c & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(c & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
}
if (c & V_SPLITSCREEN)
y += (BASEVIDHEIGHT * dupy)/2;
if (c & V_HORZSCREEN)
x += (BASEVIDWIDTH * dupx)/2;
item->x = x;
item->y = y;
}
}
#define INTERP_LATCH 1
#define INTERP_STRING 2
#define INTERP_FLAGMASK 0x3
static UINT64 GetItemId(void)
{
if (!hud_interpolate)
return 0;
// leave bits 0 and 1 free for the string mode
UINT64 id = ((UINT64)(uintptr_t)gL->savedpc << 32) | (hud_interpcounter << 10) | (hud_interptag << 2);
if (hud_interplatch)
{
id |= INTERP_LATCH;
hud_interplatch = false;
}
if (hud_interpstring)
id |= INTERP_STRING;
return id;
}
void LUA_HUD_AddDraw(
huddrawlist_h list,
INT32 x,
@@ -189,9 +350,10 @@ void LUA_HUD_AddDraw(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_Draw;
item->x = x;
item->y = y;
item->x = x << FRACBITS;
item->y = y << FRACBITS;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
@@ -209,6 +371,7 @@ void LUA_HUD_AddDrawScaled(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawScaled;
item->x = x;
item->y = y;
@@ -231,6 +394,7 @@ void LUA_HUD_AddDrawStretched(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawStretched;
item->x = x;
item->y = y;
@@ -251,11 +415,13 @@ void LUA_HUD_AddDrawNum(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawNum;
item->x = x;
item->y = y;
item->num = num;
item->flags = flags;
CalcStringCoords(item, NULL);
}
void LUA_HUD_AddDrawPaddedNum(
@@ -269,12 +435,14 @@ void LUA_HUD_AddDrawPaddedNum(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawPaddedNum;
item->x = x;
item->y = y;
item->num = num;
item->digits = digits;
item->flags = flags;
CalcStringCoords(item, NULL);
}
void LUA_HUD_AddDrawPingNum(
@@ -288,12 +456,14 @@ void LUA_HUD_AddDrawPingNum(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawPingNum;
item->x = x;
item->y = y;
item->num = num;
item->flags = flags;
item->colormap = colormap;
CalcStringCoords(item, NULL);
}
void LUA_HUD_AddDrawFill(
@@ -307,12 +477,14 @@ void LUA_HUD_AddDrawFill(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawFill;
item->x = x;
item->y = y;
item->w = w;
item->h = h;
item->c = c;
CalcFillCoords(item);
}
void LUA_HUD_AddDrawString(
@@ -326,12 +498,15 @@ void LUA_HUD_AddDrawString(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawString;
item->x = x;
item->y = y;
item->stroffset = CopyString(list, str);
item->flags = flags;
item->align = align;
if (item->align != align_fixed)
CalcStringCoords(item, str);
}
void LUA_HUD_AddDrawKartString(
@@ -344,11 +519,13 @@ void LUA_HUD_AddDrawKartString(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawKartString;
item->x = x;
item->y = y;
item->stroffset = CopyString(list, str);
item->flags = flags;
CalcStringCoords(item, str);
}
void LUA_HUD_AddDrawLevelTitle(
@@ -361,11 +538,13 @@ void LUA_HUD_AddDrawLevelTitle(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->id = GetItemId();
item->type = DI_DrawLevelTitle;
item->x = x;
item->y = y;
item->stroffset = CopyString(list, str);
item->flags = flags;
CalcStringCoords(item, str);
}
void LUA_HUD_AddFadeScreen(
@@ -376,6 +555,8 @@ void LUA_HUD_AddFadeScreen(
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
// nothing to interpolate here
item->id = 0;
item->type = DI_FadeScreen;
item->color = color;
item->strength = strength;
@@ -384,6 +565,11 @@ void LUA_HUD_AddFadeScreen(
void LUA_HUD_DrawList(huddrawlist_h list)
{
size_t i;
size_t j = 0;
fixed_t frac = R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT;
fixed_t lerpx = 0, lerpy = 0;
drawitem_t *latchitem = NULL;
drawitem_t *oldlatchitem = NULL;
if (!list) I_Error("HUD drawlist invalid");
if (list->items_len <= 0) return;
@@ -392,68 +578,117 @@ void LUA_HUD_DrawList(huddrawlist_h list)
for (i = 0; i < list->items_len; i++)
{
drawitem_t *item = &list->items[i];
drawitem_t *olditem = NULL;
const char *itemstr = &list->strbuf[item->stroffset];
if (item->id)
{
// find the old one too
// this is kinda cursed... we need to check every item
// but stop when the first-checked item is reached again
size_t stop = j;
do
{
if (j == list->olditems_len)
{
j = 0;
continue;
}
drawitem_t *old = &list->olditems[j++];
if ((old->id & ~INTERP_FLAGMASK) == (item->id & ~INTERP_FLAGMASK))
{
// gotcha!
olditem = old;
if (item->id & INTERP_LATCH)
{
lerpx = FixedMul(frac, item->x - olditem->x);
lerpy = FixedMul(frac, item->y - olditem->y);
latchitem = item;
oldlatchitem = olditem;
}
else if (!(item->id & INTERP_STRING))
{
lerpx = FixedMul(frac, item->x - olditem->x);
lerpy = FixedMul(frac, item->y - olditem->y);
latchitem = NULL;
}
break;
}
}
while (j != stop);
}
else
{
lerpx = lerpy = 0;
latchitem = NULL;
}
#define LERP(it) (olditem ? olditem->it + FixedMul(frac, item->it - olditem->it) : item->it)
// half of this could be done when the coordinates are latched... zzzzzz
#define LERPS(it) (latchitem ? ((latchitem->it + (item->it - latchitem->it)) - (latchitem->it - oldlatchitem->it)) + lerp##it : (olditem ? olditem->it + lerp##it : item->it))
//define LERPS(it) (olditem ? (latchitem ? (latchitem->it + (item->it - latchitem->it)) - (latchitem->it - oldlatchitem->it) : olditem->it) + lerp##it : item->it)
switch (item->type)
{
case DI_Draw:
V_DrawFixedPatch(item->x<<FRACBITS, item->y<<FRACBITS, FRACUNIT, item->flags, item->patch, item->colormap);
V_DrawFixedPatch(LERPS(x), LERPS(y), FRACUNIT, item->flags, item->patch, item->colormap);
break;
case DI_DrawScaled:
V_DrawFixedPatch(item->x, item->y, item->scale, item->flags, item->patch, item->colormap);
V_DrawFixedPatch(LERPS(x), LERPS(y), LERP(scale), item->flags, item->patch, item->colormap);
break;
case DI_DrawStretched:
V_DrawStretchyFixedPatch(item->x, item->y, item->hscale, item->vscale, item->flags, item->patch, item->colormap);
V_DrawStretchyFixedPatch(LERPS(x), LERPS(y), LERP(hscale), LERP(vscale), item->flags, item->patch, item->colormap);
break;
case DI_DrawNum:
V_DrawTallNum(item->x, item->y, item->flags, item->num);
V_DrawTallNum(LERPS(x), LERPS(y), item->flags, item->num);
break;
case DI_DrawPaddedNum:
V_DrawPaddedTallNum(item->x, item->y, item->flags, item->num, item->digits);
V_DrawPaddedTallNum(LERPS(x), LERPS(y), item->flags, item->num, item->digits);
break;
case DI_DrawPingNum:
V_DrawPingNum(item->x, item->y, item->flags, item->num, item->colormap);
V_DrawPingNum(LERPS(x), LERPS(y), item->flags, item->num, item->colormap);
break;
case DI_DrawFill:
V_DrawFill(item->x, item->y, item->w, item->h, item->c);
V_DrawFill(LERPS(x), LERPS(y), LERP(w), LERP(h), item->c);
break;
case DI_DrawString:
switch(item->align)
{
// hu_font
case align_left:
V_DrawString(item->x, item->y, item->flags, itemstr);
V_DrawString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case align_center:
V_DrawCenteredString(item->x, item->y, item->flags, itemstr);
V_DrawCenteredString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case align_right:
V_DrawRightAlignedString(item->x, item->y, item->flags, itemstr);
V_DrawRightAlignedString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case align_fixed:
V_DrawStringAtFixed(item->x, item->y, item->flags, itemstr);
V_DrawStringAtFixed(LERPS(x), LERPS(y), item->flags, itemstr);
break;
// hu_font, 0.5x scale
case align_small:
V_DrawSmallString(item->x, item->y, item->flags, itemstr);
V_DrawSmallString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case align_smallright:
V_DrawRightAlignedSmallString(item->x, item->y, item->flags, itemstr);
V_DrawRightAlignedSmallString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
// tny_font
case align_thin:
V_DrawThinString(item->x, item->y, item->flags, itemstr);
V_DrawThinString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case align_thinright:
V_DrawRightAlignedThinString(item->x, item->y, item->flags, itemstr);
V_DrawRightAlignedThinString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
}
break;
case DI_DrawKartString:
V_DrawKartString(item->x, item->y, item->flags, itemstr);
V_DrawKartString(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case DI_DrawLevelTitle:
V_DrawLevelTitle(item->x, item->y, item->flags, itemstr);
V_DrawLevelTitle(LERPS(x), LERPS(y), item->flags, itemstr);
break;
case DI_FadeScreen:
V_DrawFadeScreen(item->color, item->strength);
+354 -162
View File
@@ -23,34 +23,10 @@
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // cmd errors
boolean LUA_CallAction(const char *action, mobj_t *actor);
boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor);
state_t *astate;
enum sfxinfo_read {
sfxinfor_name = 0,
sfxinfor_singular,
sfxinfor_priority,
sfxinfor_flags, // "pitch"
sfxinfor_skinsound
};
const char *const sfxinfo_ropt[] = {
"name",
"singular",
"priority",
"flags",
"skinsound",
NULL};
enum sfxinfo_write {
sfxinfow_singular = 0,
sfxinfow_priority,
sfxinfow_flags // "pitch"
};
const char *const sfxinfo_wopt[] = {
"singular",
"priority",
"flags",
NULL};
boolean actionsoverridden[NUMACTIONS] = {false};
//
// Sprite Names
@@ -101,7 +77,7 @@ static void A_Lua(mobj_t *actor)
{
boolean found = false;
I_Assert(actor != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
@@ -276,27 +252,21 @@ boolean LUA_SetLuaAction(void *stv, const char *action)
return true; // action successfully set.
}
boolean LUA_CallAction(const char *csaction, mobj_t *actor)
boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
{
I_Assert(csaction != NULL);
I_Assert(actor != NULL);
if (!gL) // Lua isn't loaded,
if (!actionsoverridden[actionnum]) // The action is not overriden,
return false; // action not called.
if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself,
return false; // let it call the hardcoded function instead.
if (superstack && fasticmp(actionpointers[actionnum].name, superactions[superstack-1])) // the action is calling itself,
return false; // let it call the hardcoded function
lua_pushcfunction(gL, LUA_GetErrorMessage);
// grab function by uppercase name.
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
{
char *action = Z_StrDup(csaction);
strupr(action);
lua_getfield(gL, -1, action);
Z_Free(action);
}
lua_getfield(gL, -1, actionpointers[actionnum].name);
lua_remove(gL, -2); // pop LREG_ACTIONS
if (lua_isnil(gL, -1)) // no match
@@ -319,7 +289,7 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2);
superactions[superstack] = csaction;
superactions[superstack] = actionpointers[actionnum].name;
++superstack;
LUA_Call(gL, 3, 0, -(2 + 3));
@@ -330,49 +300,93 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
return true; // action successfully called.
}
enum state_e {
state_sprite = 0,
state_frame,
state_tics,
state_action,
state_var1,
state_var2,
state_nextstate,
};
const char *const state_opt[] = {
"sprite",
"frame",
"tics",
"action",
"var1",
"var2",
"nextstate",
NULL
};
static int state_fields_ref = LUA_NOREF;
// state_t *, field -> number
static int state_get(lua_State *L)
{
state_t *st = *((state_t **)luaL_checkudata(L, 1, META_STATE));
const char *field = luaL_checkstring(L, 2);
enum state_e field = Lua_optoption(L, 2, -1, state_fields_ref);
lua_Integer number;
if (fastcmp(field,"sprite"))
number = st->sprite;
else if (fastcmp(field,"frame"))
number = st->frame;
else if (fastcmp(field,"tics"))
number = st->tics;
else if (fastcmp(field,"action")) {
const char *name;
if (!st->action.acp1) // Action is NULL.
return 0; // return nil.
if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function?
lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, st); // Push the state pointer and
lua_rawget(L, -2); // use it to get the actual Lua function.
lua_remove(L, -2); // pop LREG_STATEACTION
return 1; // Return the Lua function.
switch (field)
{
case state_sprite:
number = st->sprite;
break;
case state_frame:
number = st->frame;
break;
case state_tics:
number = st->tics;
break;
case state_action:
{
const char *name;
if (!st->action.acp1) // Action is NULL.
return 0; // return nil.
if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function?
lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, st); // Push the state pointer and
lua_rawget(L, -2); // use it to get the actual Lua function.
lua_remove(L, -2); // pop LREG_STATEACTION
return 1; // Return the Lua function.
}
name = LUA_GetActionName(&st->action); // find a hardcoded function name
if (!name) // If it's not a hardcoded function and it's not a Lua function...
return 0; // Just what is this??
// get the function from the global
// because the metatable will trigger.
lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a new C closure if not.
lua_pushstring(L, name); // push the name we found.
return 2; // return both the function and its name, in case somebody wanted to do a comparison by name or something?
}
name = LUA_GetActionName(&st->action); // find a hardcoded function name
if (!name) // If it's not a hardcoded function and it's not a Lua function...
return 0; // Just what is this??
// get the function from the global
// because the metatable will trigger.
lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a new C closure if not.
lua_pushstring(L, name); // push the name we found.
return 2; // return both the function and its name, in case somebody wanted to do a comparison by name or something?
} else if (fastcmp(field,"var1"))
number = st->var1;
else if (fastcmp(field,"var2"))
number = st->var2;
else if (fastcmp(field,"nextstate"))
number = st->nextstate;
else if (devparm)
return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field);
else
return 0;
break;
case state_var1:
number = st->var1;
break;
case state_var2:
number = st->var2;
break;
case state_nextstate:
number = st->nextstate;
break;
default:
{
if (devparm)
return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field);
return 0;
}
}
lua_pushinteger(L, number);
return 1;
@@ -382,7 +396,7 @@ static int state_get(lua_State *L)
static int state_set(lua_State *L)
{
state_t *st = *((state_t **)luaL_checkudata(L, 1, META_STATE));
const char *field = luaL_checkstring(L, 2);
enum state_e field = Lua_optoption(L, 2, -1, state_fields_ref);
lua_Integer value;
if (hud_running)
@@ -390,16 +404,24 @@ static int state_set(lua_State *L)
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in BuildCMD code!");
if (fastcmp(field,"sprite")) {
switch (field)
{
case state_sprite:
value = luaL_checknumber(L, 3);
if (value < SPR_NULL || value >= NUMSPRITES)
return luaL_error(L, "sprite number %d is invalid.", value);
st->sprite = (spritenum_t)value;
} else if (fastcmp(field,"frame"))
break;
case state_frame:
st->frame = (UINT32)luaL_checknumber(L, 3);
else if (fastcmp(field,"tics"))
break;
case state_tics:
st->tics = (INT32)luaL_checknumber(L, 3);
else if (fastcmp(field,"action")) {
break;
case state_action:
switch(lua_type(L, 3))
{
case LUA_TNIL: // Null? Set the action to nothing, then.
@@ -420,17 +442,26 @@ static int state_set(lua_State *L)
default: // ?!
return luaL_typerror(L, 3, "function");
}
} else if (fastcmp(field,"var1"))
break;
case state_var1:
st->var1 = (INT32)luaL_checknumber(L, 3);
else if (fastcmp(field,"var2"))
break;
case state_var2:
st->var2 = (INT32)luaL_checknumber(L, 3);
else if (fastcmp(field,"nextstate")) {
break;
case state_nextstate:
value = luaL_checkinteger(L, 3);
if (value < S_NULL || value >= NUMSTATES)
return luaL_error(L, "nextstate number %d is invalid.", value);
st->nextstate = (statenum_t)value;
} else
break;
default:
return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field);
}
return 0;
}
@@ -565,75 +596,161 @@ static int lib_mobjinfolen(lua_State *L)
return 1;
}
enum mobjinfo_e
{
mobjinfo_doomednum,
mobjinfo_spawnstate,
mobjinfo_spawnhealth,
mobjinfo_seestate,
mobjinfo_seesound,
mobjinfo_reactiontime,
mobjinfo_attacksound,
mobjinfo_painstate,
mobjinfo_painchance,
mobjinfo_painsound,
mobjinfo_meleestate,
mobjinfo_missilestate,
mobjinfo_deathstate,
mobjinfo_xdeathstate,
mobjinfo_deathsound,
mobjinfo_speed,
mobjinfo_radius,
mobjinfo_height,
mobjinfo_dispoffset,
mobjinfo_mass,
mobjinfo_damage,
mobjinfo_activesound,
mobjinfo_flags,
mobjinfo_raisestate,
};
const char *const mobjinfo_opt[] = {
"doomednum",
"spawnstate",
"spawnhealth",
"seestate",
"seesound",
"reactiontime",
"attacksound",
"painstate",
"painchance",
"painsound",
"meleestate",
"missilestate",
"deathstate",
"xdeathstate",
"deathsound",
"speed",
"radius",
"height",
"dispoffset",
"mass",
"damage",
"activesound",
"flags",
"raisestate",
NULL,
};
static int mobjinfo_fields_ref = LUA_NOREF;
// mobjinfo_t *, field -> number
static int mobjinfo_get(lua_State *L)
{
mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO));
const char *field = luaL_checkstring(L, 2);
enum mobjinfo_e field = Lua_optoption(L, 2, -1, mobjinfo_fields_ref);
I_Assert(info != NULL);
I_Assert(info >= mobjinfo);
if (fastcmp(field,"doomednum"))
switch (field)
{
case mobjinfo_doomednum:
lua_pushinteger(L, info->doomednum);
else if (fastcmp(field,"spawnstate"))
break;
case mobjinfo_spawnstate:
lua_pushinteger(L, info->spawnstate);
else if (fastcmp(field,"spawnhealth"))
break;
case mobjinfo_spawnhealth:
lua_pushinteger(L, info->spawnhealth);
else if (fastcmp(field,"seestate"))
break;
case mobjinfo_seestate:
lua_pushinteger(L, info->seestate);
else if (fastcmp(field,"seesound"))
break;
case mobjinfo_seesound:
lua_pushinteger(L, info->seesound);
else if (fastcmp(field,"reactiontime"))
break;
case mobjinfo_reactiontime:
lua_pushinteger(L, info->reactiontime);
else if (fastcmp(field,"attacksound"))
break;
case mobjinfo_attacksound:
lua_pushinteger(L, info->attacksound);
else if (fastcmp(field,"painstate"))
break;
case mobjinfo_painstate:
lua_pushinteger(L, info->painstate);
else if (fastcmp(field,"painchance"))
break;
case mobjinfo_painchance:
lua_pushinteger(L, info->painchance);
else if (fastcmp(field,"painsound"))
break;
case mobjinfo_painsound:
lua_pushinteger(L, info->painsound);
else if (fastcmp(field,"meleestate"))
break;
case mobjinfo_meleestate:
lua_pushinteger(L, info->meleestate);
else if (fastcmp(field,"missilestate"))
break;
case mobjinfo_missilestate:
lua_pushinteger(L, info->missilestate);
else if (fastcmp(field,"deathstate"))
break;
case mobjinfo_deathstate:
lua_pushinteger(L, info->deathstate);
else if (fastcmp(field,"xdeathstate"))
break;
case mobjinfo_xdeathstate:
lua_pushinteger(L, info->xdeathstate);
else if (fastcmp(field,"deathsound"))
break;
case mobjinfo_deathsound:
lua_pushinteger(L, info->deathsound);
else if (fastcmp(field,"speed"))
break;
case mobjinfo_speed:
lua_pushinteger(L, info->speed); // sometimes it's fixed_t, sometimes it's not...
else if (fastcmp(field,"radius"))
break;
case mobjinfo_radius:
lua_pushfixed(L, info->radius);
else if (fastcmp(field,"height"))
break;
case mobjinfo_height:
lua_pushfixed(L, info->height);
else if (fastcmp(field,"dispoffset"))
break;
case mobjinfo_dispoffset:
lua_pushinteger(L, info->dispoffset);
else if (fastcmp(field,"mass"))
break;
case mobjinfo_mass:
lua_pushinteger(L, info->mass);
else if (fastcmp(field,"damage"))
break;
case mobjinfo_damage:
lua_pushinteger(L, info->damage);
else if (fastcmp(field,"activesound"))
break;
case mobjinfo_activesound:
lua_pushinteger(L, info->activesound);
else if (fastcmp(field,"flags"))
break;
case mobjinfo_flags:
lua_pushinteger(L, info->flags);
else if (fastcmp(field,"raisestate"))
break;
case mobjinfo_raisestate:
lua_pushinteger(L, info->raisestate);
else {
break;
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, info);
lua_rawget(L, -2);
if (!lua_istable(L, -1)) { // no extra values table
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2));
return 0;
}
lua_getfield(L, -1, field);
lua_pushvalue(L, 2); // field name
lua_gettable(L, -2);
if (lua_isnil(L, -1)) // no value for this field
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2));
break;
}
return 1;
}
@@ -642,7 +759,7 @@ static int mobjinfo_get(lua_State *L)
static int mobjinfo_set(lua_State *L)
{
mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO));
const char *field = luaL_checkstring(L, 2);
enum mobjinfo_e field = Lua_optoption(L, 2, -1, mobjinfo_fields_ref);
if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
@@ -652,55 +769,81 @@ static int mobjinfo_set(lua_State *L)
I_Assert(info != NULL);
I_Assert(info >= mobjinfo);
if (fastcmp(field,"doomednum"))
switch (field)
{
case mobjinfo_doomednum:
info->doomednum = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"spawnstate"))
break;
case mobjinfo_spawnstate:
info->spawnstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"spawnhealth"))
break;
case mobjinfo_spawnhealth:
info->spawnhealth = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"seestate"))
break;
case mobjinfo_seestate:
info->seestate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"seesound"))
break;
case mobjinfo_seesound:
info->seesound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"reactiontime"))
break;
case mobjinfo_reactiontime:
info->reactiontime = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"attacksound"))
break;
case mobjinfo_attacksound:
info->attacksound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"painstate"))
break;
case mobjinfo_painstate:
info->painstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"painchance"))
break;
case mobjinfo_painchance:
info->painchance = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"painsound"))
break;
case mobjinfo_painsound:
info->painsound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"meleestate"))
break;
case mobjinfo_meleestate:
info->meleestate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"missilestate"))
break;
case mobjinfo_missilestate:
info->missilestate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"deathstate"))
break;
case mobjinfo_deathstate:
info->deathstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"xdeathstate"))
break;
case mobjinfo_xdeathstate:
info->xdeathstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"deathsound"))
break;
case mobjinfo_deathsound:
info->deathsound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"speed"))
break;
case mobjinfo_speed:
info->speed = luaL_checkfixed(L, 3);
else if (fastcmp(field,"radius"))
break;
case mobjinfo_radius:
info->radius = luaL_checkfixed(L, 3);
else if (fastcmp(field,"height"))
break;
case mobjinfo_height:
info->height = luaL_checkfixed(L, 3);
else if (fastcmp(field,"dispoffset"))
break;
case mobjinfo_dispoffset:
info->dispoffset = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"mass"))
break;
case mobjinfo_mass:
info->mass = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"damage"))
break;
case mobjinfo_damage:
info->damage = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"activesound"))
break;
case mobjinfo_activesound:
info->activesound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"flags"))
break;
case mobjinfo_flags:
info->flags = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"raisestate"))
break;
case mobjinfo_raisestate:
info->raisestate = luaL_checkinteger(L, 3);
else {
break;
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, info);
@@ -708,18 +851,17 @@ static int mobjinfo_set(lua_State *L)
if (lua_isnil(L, -1)) {
// This index doesn't have a table for extra values yet, let's make one.
lua_pop(L, 1);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", field);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", lua_tostring(L, 2));
lua_newtable(L);
lua_pushlightuserdata(L, info);
lua_pushvalue(L, -2); // ext value table
lua_rawset(L, -4); // LREG_EXTVARS table
}
lua_pushvalue(L, 2); // key
lua_pushvalue(L, 3); // value to store
lua_setfield(L, -2, field);
lua_settable(L, -3);
lua_pop(L, 2);
}
//else
//return luaL_error(L, LUA_QL("mobjinfo_t") " has no field named " LUA_QS, field);
return 0;
}
@@ -752,6 +894,25 @@ static int lib_getSfxInfo(lua_State *L)
return 1;
}
enum sfxinfo_e {
sfxinfo_name = 0,
sfxinfo_singular,
sfxinfo_priority,
sfxinfo_flags, // "pitch"
sfxinfo_skinsound
};
const char *const sfxinfo_opt[] = {
"name",
"singular",
"priority",
"flags",
"skinsound",
NULL
};
static int sfxinfo_fields_ref = LUA_NOREF;
// stack: dummy, S_sfx[] table index, table of values to set.
static int lib_setSfxInfo(lua_State *L)
{
@@ -775,22 +936,44 @@ static int lib_setSfxInfo(lua_State *L)
lua_pushnil(L);
while (lua_next(L, 1)) {
enum sfxinfo_write i;
enum sfxinfo_e i;
if (lua_isnumber(L, 2))
i = lua_tointeger(L, 2) - 1; // lua is one based, this enum is zero based.
{
int j = lua_tointeger(L, 2) - 1;
// Read and Write enums were combined, need to do this switch now
switch (j)
{
case 1:
i = sfxinfo_singular;
break;
case 2:
i = sfxinfo_priority;
break;
case 3:
i = sfxinfo_flags;
break;
default:
i = -1;
break;
}
}
else
i = luaL_checkoption(L, 2, NULL, sfxinfo_wopt);
i = Lua_optoption(L, 2, -1, sfxinfo_fields_ref);
switch(i)
{
case sfxinfow_singular:
case sfxinfo_singular:
info->singularity = luaL_checkboolean(L, 3);
break;
case sfxinfow_priority:
case sfxinfo_priority:
info->priority = (INT32)luaL_checkinteger(L, 3);
break;
case sfxinfow_flags:
case sfxinfo_flags:
info->pitch = (INT32)luaL_checkinteger(L, 3);
break;
default:
@@ -812,29 +995,29 @@ static int lib_sfxlen(lua_State *L)
static int sfxinfo_get(lua_State *L)
{
sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO));
enum sfxinfo_read field = luaL_checkoption(L, 2, NULL, sfxinfo_ropt);
enum sfxinfo_e field = Lua_optoption(L, 2, -1, sfxinfo_fields_ref);
I_Assert(sfx != NULL);
switch (field)
{
case sfxinfor_name:
case sfxinfo_name:
lua_pushstring(L, sfx->name);
return 1;
case sfxinfor_singular:
case sfxinfo_singular:
lua_pushboolean(L, sfx->singularity);
return 1;
case sfxinfor_priority:
case sfxinfo_priority:
lua_pushinteger(L, sfx->priority);
return 1;
case sfxinfor_flags:
case sfxinfo_flags:
lua_pushinteger(L, sfx->pitch);
return 1;
case sfxinfor_skinsound:
case sfxinfo_skinsound:
lua_pushinteger(L, sfx->skinsound);
return 1;
default:
return luaL_error(L, "impossible error");
return luaL_error(L, LUA_QL("sfxinfo_t") " has no field named " LUA_QS, lua_tostring(L, 2));
}
return 0;
}
@@ -843,7 +1026,7 @@ static int sfxinfo_get(lua_State *L)
static int sfxinfo_set(lua_State *L)
{
sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO));
enum sfxinfo_write field = luaL_checkoption(L, 2, NULL, sfxinfo_wopt);
int field = Lua_optoption(L, 2, -1, sfxinfo_fields_ref);
if (hud_running)
return luaL_error(L, "Do not alter S_sfx in HUD rendering code!");
@@ -858,17 +1041,20 @@ static int sfxinfo_set(lua_State *L)
switch (field)
{
case sfxinfow_singular:
case sfxinfo_singular:
sfx->singularity = luaL_checkboolean(L, 1);
break;
case sfxinfow_priority:
case sfxinfo_priority:
sfx->priority = luaL_checkinteger(L, 1);
break;
case sfxinfow_flags:
case sfxinfo_flags:
sfx->pitch = luaL_checkinteger(L, 1);
break;
default:
return luaL_error(L, "impossible error");
if (field == -1)
return luaL_error(L, LUA_QL("sfxinfo_t") " has no field named " LUA_QS, lua_tostring(L, 2));
else
return luaL_error(L, LUA_QL("sfxinfo_t") " field " LUA_QS " is read-only", lua_tostring(L, 2));
}
return 0;
}
@@ -910,6 +1096,8 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
state_fields_ref = Lua_CreateFieldTable(L, state_opt);
luaL_newmetatable(L, META_MOBJINFO);
lua_pushcfunction(L, mobjinfo_get);
lua_setfield(L, -2, "__index");
@@ -921,6 +1109,8 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
mobjinfo_fields_ref = Lua_CreateFieldTable(L, mobjinfo_opt);
luaL_newmetatable(L, META_SFXINFO);
lua_pushcfunction(L, sfxinfo_get);
lua_setfield(L, -2, "__index");
@@ -932,6 +1122,8 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
sfxinfo_fields_ref = Lua_CreateFieldTable(L, sfxinfo_opt);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSprname);
@@ -983,4 +1175,4 @@ int LUA_InfoLib(lua_State *L)
lua_setglobal(L, "S_sfx");
lua_setglobal(L, "sfxinfo");
return 0;
}
}
+193 -49
View File
@@ -71,6 +71,8 @@ enum subsector_e {
subsector_firstline,
};
static int sector_fields_ref = LUA_NOREF;
static const char *const subsector_opt[] = {
"valid",
"sector",
@@ -78,6 +80,8 @@ static const char *const subsector_opt[] = {
"firstline",
NULL};
static int subsector_fields_ref = LUA_NOREF;
enum line_e {
line_valid = 0,
line_v1,
@@ -120,6 +124,8 @@ static const char *const line_opt[] = {
"callcount",
NULL};
static int line_fields_ref = LUA_NOREF;
enum side_e {
side_valid = 0,
side_textureoffset,
@@ -146,6 +152,8 @@ static const char *const side_opt[] = {
"text",
NULL};
static int side_fields_ref = LUA_NOREF;
enum vertex_e {
vertex_valid = 0,
vertex_x,
@@ -160,6 +168,8 @@ static const char *const vertex_opt[] = {
"z",
NULL};
static int vertex_fields_ref = LUA_NOREF;
enum ffloor_e {
ffloor_valid = 0,
ffloor_topheight,
@@ -196,6 +206,8 @@ static const char *const ffloor_opt[] = {
"alpha",
NULL};
static int ffloor_fields_ref = LUA_NOREF;
enum slope_e {
slope_valid = 0,
slope_o,
@@ -222,6 +234,8 @@ static const char *const slope_opt[] = {
"flags",
NULL};
static int slope_fields_ref = LUA_NOREF;
// shared by both vector2_t and vector3_t
enum vector_e {
vector_x = 0,
@@ -387,7 +401,7 @@ static int sectorlines_num(lua_State *L)
static int sector_get(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref);
INT16 i;
if (!sector)
@@ -473,7 +487,7 @@ static int sector_get(lua_State *L)
static int sector_set(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref);
if (!sector)
return luaL_error(L, "accessed sector_t doesn't exist anymore.");
@@ -551,7 +565,7 @@ static int sector_num(lua_State *L)
static int subsector_get(lua_State *L)
{
subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
enum subsector_e field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt);
enum subsector_e field = Lua_optoption(L, 2, subsector_valid, subsector_fields_ref);
if (!subsector)
{
@@ -590,7 +604,7 @@ static int subsector_num(lua_State *L)
static int line_get(lua_State *L)
{
line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
enum line_e field = luaL_checkoption(L, 2, line_opt[0], line_opt);
enum line_e field = Lua_optoption(L, 2, line_valid, line_fields_ref);
if (!line)
{
@@ -715,7 +729,7 @@ static int sidenum_get(lua_State *L)
static int side_get(lua_State *L)
{
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref);
if (!side)
{
@@ -765,7 +779,7 @@ static int side_get(lua_State *L)
static int side_set(lua_State *L)
{
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref);
if (!side)
{
@@ -816,7 +830,7 @@ static int side_num(lua_State *L)
static int vertex_get(lua_State *L)
{
vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
enum vertex_e field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt);
enum vertex_e field = Lua_optoption(L, 2, vertex_valid, vertex_fields_ref);
if (!vertex)
{
@@ -1085,7 +1099,7 @@ static int lib_numvertexes(lua_State *L)
static int ffloor_get(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref);
INT16 i;
if (!ffloor)
@@ -1161,7 +1175,7 @@ static int ffloor_get(lua_State *L)
static int ffloor_set(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref);
if (!ffloor)
return luaL_error(L, "accessed ffloor_t doesn't exist anymore.");
@@ -1239,7 +1253,7 @@ static int ffloor_set(lua_State *L)
static int slope_get(lua_State *L)
{
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt);
enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref);
if (!slope)
{
@@ -1289,7 +1303,7 @@ static int slope_get(lua_State *L)
static int slope_set(lua_State *L)
{
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt);
enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref);
if (!slope)
return luaL_error(L, "accessed pslope_t doesn't exist anymore.");
@@ -1446,93 +1460,207 @@ static int lib_nummapheaders(lua_State *L)
return 1;
}
enum mapheaderinfo_e
{
mapheaderinfo_lvlttl,
mapheaderinfo_subttl,
mapheaderinfo_zonttl,
mapheaderinfo_actnum,
mapheaderinfo_typeoflevel,
mapheaderinfo_nextlevel,
mapheaderinfo_musname,
mapheaderinfo_mustrack,
mapheaderinfo_muspos,
mapheaderinfo_musinterfadeout,
mapheaderinfo_musintername,
mapheaderinfo_forcecharacter,
mapheaderinfo_weather,
mapheaderinfo_skynum,
mapheaderinfo_skybox_scalex,
mapheaderinfo_skybox_scaley,
mapheaderinfo_skybox_scalez,
mapheaderinfo_interscreen,
mapheaderinfo_runsoc,
mapheaderinfo_scriptname,
mapheaderinfo_precutscenenum,
mapheaderinfo_cutscenenum,
mapheaderinfo_countdown,
mapheaderinfo_palette,
mapheaderinfo_numlaps,
mapheaderinfo_unlockrequired,
mapheaderinfo_levelselect,
mapheaderinfo_bonustype,
mapheaderinfo_saveoverride,
mapheaderinfo_levelflags,
mapheaderinfo_menuflags,
//mapheaderinfo_automap,
mapheaderinfo_mobj_scale,
};
static const char *const mapheaderinfo_opt[] = {
"lvlttl",
"subttl",
"zonttl",
"actnum",
"typeoflevel",
"nextlevel",
"musname",
"mustrack",
"muspos",
"musinterfadeout",
"musintername",
"forcecharacter",
"weather",
"skynum",
"skybox_scalex",
"skybox_scaley",
"skybox_scalez",
"interscreen",
"runsoc",
"scriptname",
"precutscenenum",
"cutscenenum",
"countdown",
"palette",
"numlaps",
"unlockrequired",
"levelselect",
"bonustype",
"saveoverride",
"levelflags",
"menuflags",
//"automap",
"mobj_scale",
NULL,
};
static int mapheaderinfo_fields_ref = LUA_NOREF;
static int mapheaderinfo_get(lua_State *L)
{
mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));
const char *field = luaL_checkstring(L, 2);
enum mapheaderinfo_e field = Lua_optoption(L, 2, -1, mapheaderinfo_fields_ref);
INT16 i;
if (fastcmp(field,"lvlttl"))
switch (field)
{
case mapheaderinfo_lvlttl:
lua_pushstring(L, header->lvlttl);
else if (fastcmp(field,"subttl"))
break;
case mapheaderinfo_subttl:
lua_pushstring(L, header->subttl);
else if (fastcmp(field,"zonttl"))
break;
case mapheaderinfo_zonttl:
lua_pushstring(L, header->zonttl);
else if (fastcmp(field,"actnum"))
break;
case mapheaderinfo_actnum:
lua_pushstring(L, header->actnum);
else if (fastcmp(field,"typeoflevel"))
break;
case mapheaderinfo_typeoflevel:
lua_pushinteger(L, header->typeoflevel);
else if (fastcmp(field,"nextlevel"))
break;
case mapheaderinfo_nextlevel:
lua_pushinteger(L, header->nextlevel);
else if (fastcmp(field,"musname"))
break;
case mapheaderinfo_musname:
lua_pushstring(L, header->musname);
else if (fastcmp(field,"mustrack"))
break;
case mapheaderinfo_mustrack:
lua_pushinteger(L, header->mustrack);
else if (fastcmp(field,"muspos"))
break;
case mapheaderinfo_muspos:
lua_pushinteger(L, header->muspos);
else if (fastcmp(field,"musinterfadeout"))
break;
case mapheaderinfo_musinterfadeout:
lua_pushinteger(L, header->musinterfadeout);
else if (fastcmp(field,"musintername"))
break;
case mapheaderinfo_musintername:
lua_pushstring(L, header->musintername);
else if (fastcmp(field,"forcecharacter"))
break;
case mapheaderinfo_forcecharacter:
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))
break;
case mapheaderinfo_weather:
lua_pushinteger(L, header->weather);
else if (fastcmp(field,"skynum"))
break;
case mapheaderinfo_skynum:
lua_pushinteger(L, header->skynum);
else if (fastcmp(field,"skybox_scalex"))
break;
case mapheaderinfo_skybox_scalex:
lua_pushinteger(L, header->skybox_scalex);
else if (fastcmp(field,"skybox_scaley"))
break;
case mapheaderinfo_skybox_scaley:
lua_pushinteger(L, header->skybox_scaley);
else if (fastcmp(field,"skybox_scalez"))
break;
case mapheaderinfo_skybox_scalez:
lua_pushinteger(L, header->skybox_scalez);
else if (fastcmp(field,"interscreen")) {
break;
case mapheaderinfo_interscreen:
for (i = 0; i < 8; i++)
if (!header->interscreen[i])
break;
lua_pushlstring(L, header->interscreen, i);
} else if (fastcmp(field,"runsoc"))
break;
case mapheaderinfo_runsoc:
lua_pushstring(L, header->runsoc);
else if (fastcmp(field,"scriptname"))
break;
case mapheaderinfo_scriptname:
lua_pushstring(L, header->scriptname);
else if (fastcmp(field,"precutscenenum"))
break;
case mapheaderinfo_precutscenenum:
lua_pushinteger(L, header->precutscenenum);
else if (fastcmp(field,"cutscenenum"))
break;
case mapheaderinfo_cutscenenum:
lua_pushinteger(L, header->cutscenenum);
else if (fastcmp(field,"countdown"))
break;
case mapheaderinfo_countdown:
lua_pushinteger(L, header->countdown);
else if (fastcmp(field,"palette"))
break;
case mapheaderinfo_palette:
lua_pushinteger(L, header->palette);
else if (fastcmp(field,"numlaps"))
break;
case mapheaderinfo_numlaps:
lua_pushinteger(L, header->numlaps);
else if (fastcmp(field,"unlockrequired"))
break;
case mapheaderinfo_unlockrequired:
lua_pushinteger(L, header->unlockrequired);
else if (fastcmp(field,"levelselect"))
break;
case mapheaderinfo_levelselect:
lua_pushinteger(L, header->levelselect);
else if (fastcmp(field,"bonustype"))
break;
case mapheaderinfo_bonustype:
lua_pushinteger(L, header->bonustype);
else if (fastcmp(field,"saveoverride"))
break;
case mapheaderinfo_saveoverride:
lua_pushinteger(L, header->saveoverride);
else if (fastcmp(field,"levelflags"))
break;
case mapheaderinfo_levelflags:
lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags"))
break;
case mapheaderinfo_menuflags:
lua_pushinteger(L, header->menuflags);
/*else if (fastcmp(field,"automap"))
lua_pushboolean(L, header->automap);*/
else if (fastcmp(field,"mobj_scale"))
break;
/*case mapheaderinfo_automap:
lua_pushstring(L, header->selectheading);
break;*/
case mapheaderinfo_mobj_scale:
lua_pushfixed(L, header->mobj_scale);
break;
// TODO add support for reading numGradedMares and grades
else {
default:
{
// Read custom vars now
// (note: don't include the "LUA." in your lua scripts!)
UINT8 j = 0;
for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j);
for (;j < header->numCustomOptions && !fastcmp(lua_tostring(L, 2), header->customopts[j].option); ++j);
if(j < header->numCustomOptions)
lua_pushstring(L, header->customopts[j].value);
else
lua_pushnil(L);
}
}
return 1;
}
int LUA_MapLib(lua_State *L)
@@ -1556,6 +1684,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
sector_fields_ref = Lua_CreateFieldTable(L, sector_opt);
luaL_newmetatable(L, META_SUBSECTOR);
lua_pushcfunction(L, subsector_get);
lua_setfield(L, -2, "__index");
@@ -1564,6 +1694,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
subsector_fields_ref = Lua_CreateFieldTable(L, subsector_opt);
luaL_newmetatable(L, META_LINE);
lua_pushcfunction(L, line_get);
lua_setfield(L, -2, "__index");
@@ -1572,6 +1704,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
line_fields_ref = Lua_CreateFieldTable(L, line_opt);
luaL_newmetatable(L, META_SIDENUM);
lua_pushcfunction(L, sidenum_get);
lua_setfield(L, -2, "__index");
@@ -1588,6 +1722,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
side_fields_ref = Lua_CreateFieldTable(L, side_opt);
luaL_newmetatable(L, META_VERTEX);
lua_pushcfunction(L, vertex_get);
lua_setfield(L, -2, "__index");
@@ -1596,6 +1732,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
vertex_fields_ref = Lua_CreateFieldTable(L, vertex_opt);
luaL_newmetatable(L, META_FFLOOR);
lua_pushcfunction(L, ffloor_get);
lua_setfield(L, -2, "__index");
@@ -1604,6 +1742,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L, 1);
ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt);
luaL_newmetatable(L, META_SLOPE);
lua_pushcfunction(L, slope_get);
lua_setfield(L, -2, "__index");
@@ -1612,6 +1752,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L, 1);
slope_fields_ref = Lua_CreateFieldTable(L, slope_opt);
luaL_newmetatable(L, META_VECTOR2);
lua_pushcfunction(L, vector2_get);
lua_setfield(L, -2, "__index");
@@ -1630,6 +1772,8 @@ int LUA_MapLib(lua_State *L)
//lua_setfield(L, -2, "__len");
lua_pop(L, 1);
mapheaderinfo_fields_ref = Lua_CreateFieldTable(L, mapheaderinfo_opt);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSector);
@@ -1690,4 +1834,4 @@ int LUA_MapLib(lua_State *L)
lua_setmetatable(L, -2);
lua_setglobal(L, "mapheaderinfo");
return 0;
}
}
+105 -49
View File
@@ -147,7 +147,7 @@ static const udata_field_t mobj_fields[] = {
FIELD(mobj_t, colorized, udatalib_getter_boolean, udatalib_setter_boolean),
FIELD(mobj_t, mirrored, udatalib_getter_boolean, udatalib_setter_boolean),
FIELD(mobj_t, rollmodel, udatalib_getter_boolean, udatalib_setter_boolean),
{ NULL },
{ NULL, 0, NULL, NULL },
};
#undef FIELD
@@ -769,14 +769,41 @@ static int mobj_set(lua_State *L)
#undef NOSETPOS
#undef NOFIELD
enum mapthing_e {
mapthing_valid = 0,
mapthing_x,
mapthing_y,
mapthing_angle,
mapthing_type,
mapthing_options,
mapthing_z,
mapthing_extrainfo,
mapthing_mobj,
};
const char *const mapthing_opt[] = {
"valid",
"x",
"y",
"angle",
"type",
"options",
"z",
"extrainfo",
"mobj",
NULL,
};
static int mapthing_fields_ref = LUA_NOREF;
static int mapthing_get(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
const char *field = luaL_checkstring(L, 2);
lua_Integer number;
enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref);
lua_settop(L, 2);
if (!mt) {
if (fastcmp(field,"valid")) {
if (field == mapthing_valid) {
lua_pushboolean(L, false);
return 1;
}
@@ -785,39 +812,50 @@ static int mapthing_get(lua_State *L)
return 0;
}
if (fastcmp(field,"valid")) {
lua_pushboolean(L, true);
return 1;
} else if(fastcmp(field,"x"))
number = mt->x;
else if(fastcmp(field,"y"))
number = mt->y;
else if(fastcmp(field,"angle"))
number = mt->angle;
else if(fastcmp(field,"type"))
number = mt->type;
else if(fastcmp(field,"options"))
number = mt->options;
else if(fastcmp(field,"z"))
number = mt->z;
else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo;
else if(fastcmp(field,"mobj")) {
LUA_PushUserdata(L, mt->mobj, META_MOBJ);
return 1;
} else if (devparm)
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
else
return 0;
switch (field)
{
case mapthing_valid:
lua_pushboolean(L, true);
break;
case mapthing_x:
lua_pushinteger(L, mt->x);
break;
case mapthing_y:
lua_pushinteger(L, mt->y);
break;
case mapthing_angle:
lua_pushinteger(L, mt->angle);
break;
case mapthing_type:
lua_pushinteger(L, mt->type);
break;
case mapthing_options:
lua_pushinteger(L, mt->options);
break;
case mapthing_z:
lua_pushinteger(L, mt->z);
break;
case mapthing_extrainfo:
lua_pushinteger(L, mt->extrainfo);
break;
case mapthing_mobj:
LUA_PushUserdata(L, mt->mobj, META_MOBJ);
break;
default:
if (devparm)
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
else
return 0;
}
lua_pushinteger(L, number);
return 1;
}
static int mapthing_set(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
const char *field = luaL_checkstring(L, 2);
enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref);
lua_settop(L, 3);
if (!mt)
return luaL_error(L, "accessed mapthing_t doesn't exist anymore.");
@@ -827,24 +865,40 @@ static int mapthing_set(lua_State *L)
if (hook_cmd_running)
return luaL_error(L, "Do not alter mapthing_t in BuildCMD code!");
if(fastcmp(field,"x"))
mt->x = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"y"))
mt->y = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"angle"))
mt->angle = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"type"))
mt->type = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"options"))
mt->options = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"z"))
mt->z = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"extrainfo"))
mt->extrainfo = (UINT8)luaL_checkinteger(L, 3);
else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
switch (field)
{
case mapthing_x:
mt->x = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_y:
mt->y = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_angle:
mt->angle = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_type:
mt->type = (UINT16)luaL_checkinteger(L, 3);
break;
case mapthing_options:
mt->options = (UINT16)luaL_checkinteger(L, 3);
break;
case mapthing_z:
mt->z = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_extrainfo:
{
INT32 extrainfo = luaL_checkinteger(L, 3);
if (extrainfo & ~15)
return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15);
mt->extrainfo = (UINT8)extrainfo;
break;
}
case mapthing_mobj:
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
break;
default:
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
}
return 0;
}
@@ -915,6 +969,8 @@ int LUA_MobjLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getMapthing);
@@ -925,4 +981,4 @@ int LUA_MobjLib(lua_State *L)
lua_setmetatable(L, -2);
lua_setglobal(L, "mapthings");
return 0;
}
}
+81 -18
View File
@@ -51,6 +51,9 @@ int player_localskin_setter(lua_State *L);
int player_sliproll_getter(lua_State *L);
int player_sliproll_noset(lua_State *L);
int player_viewrollangle_getter(lua_State *L);
int player_viewrollangle_noset(lua_State *L);
#define FIELD(type, field_name, getter, setter) { #field_name, offsetof(type, field_name), getter, setter }
static const udata_field_t player_fields[] = {
// Player doesn't actually have field "name" so macro fails. Need to declare field manually.
@@ -159,8 +162,9 @@ static const udata_field_t player_fields[] = {
#endif
// Same as player.name
{ "sliproll", 0, player_sliproll_getter, player_sliproll_noset },
{ "viewrollangle", 0, player_viewrollangle_getter, player_viewrollangle_noset },
{ "ping", 0, player_ping_getter, player_ping_noset }, // Hmm originally setter doesn't exist so data is written as unreachable custom field...
{ NULL },
{ NULL, 0, NULL, NULL },
};
#undef FIELD
@@ -217,6 +221,7 @@ NOSET(bot)
NOSET(splitscreenindex)
NOSET(ping)
NOSET(sliproll)
NOSET(viewrollangle)
#undef NOSET
@@ -372,6 +377,15 @@ int player_sliproll_getter(lua_State *L)
return 1;
}
int player_viewrollangle_getter(lua_State *L)
{
player_t *plr = GETPLAYER();
lua_pushangle(L, R_ViewRollAngle(plr));
return 1;
}
static int lib_iteratePlayers(lua_State *L)
{
INT32 i = -1;
@@ -694,30 +708,65 @@ static int kartstuff_len(lua_State *L)
}
#define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field)
#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", field)
enum ticcmd_e
{
ticcmd_forwardmove,
ticcmd_sidemove,
ticcmd_angleturn,
ticcmd_aiming,
ticcmd_buttons,
ticcmd_driftturn,
ticcmd_latency,
};
static const char *const ticcmd_opt[] = {
"forwardmove",
"sidemove",
"angleturn",
"aiming",
"buttons",
"driftturn",
"latency",
NULL,
};
static int ticcmd_fields_ref = LUA_NOREF;
static int ticcmd_get(lua_State *L)
{
ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD));
const char *field = luaL_checkstring(L, 2);
enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref);
if (!cmd)
return LUA_ErrInvalid(L, "player_t");
if (fastcmp(field,"forwardmove"))
switch (field)
{
case ticcmd_forwardmove:
lua_pushinteger(L, cmd->forwardmove);
else if (fastcmp(field,"sidemove"))
break;
case ticcmd_sidemove:
lua_pushinteger(L, cmd->sidemove);
else if (fastcmp(field,"angleturn"))
break;
case ticcmd_angleturn:
lua_pushinteger(L, cmd->angleturn);
else if (fastcmp(field,"aiming"))
break;
case ticcmd_aiming:
lua_pushinteger(L, cmd->aiming);
else if (fastcmp(field,"buttons"))
break;
case ticcmd_buttons:
lua_pushinteger(L, cmd->buttons);
else if (fastcmp(field,"driftturn"))
break;
case ticcmd_driftturn:
lua_pushinteger(L, cmd->driftturn);
else if (fastcmp(field,"latency"))
break;
case ticcmd_latency:
lua_pushinteger(L, cmd->latency);
else
break;
default:
return NOFIELD;
}
return 1;
}
@@ -725,32 +774,44 @@ static int ticcmd_get(lua_State *L)
static int ticcmd_set(lua_State *L)
{
ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD));
const char *field = luaL_checkstring(L, 2);
enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref);
if (!cmd)
return LUA_ErrInvalid(L, "ticcmd_t");
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (fastcmp(field,"forwardmove"))
switch (field)
{
case ticcmd_forwardmove:
cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"sidemove"))
break;
case ticcmd_sidemove:
cmd->sidemove = (SINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"angleturn"))
break;
case ticcmd_angleturn:
cmd->angleturn = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"aiming"))
break;
case ticcmd_aiming:
cmd->aiming = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"buttons"))
break;
case ticcmd_buttons:
cmd->buttons = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"driftturn"))
break;
case ticcmd_driftturn:
cmd->driftturn = (INT16)luaL_checkinteger(L, 3);
else
break;
case ticcmd_latency:
return NOSET;
default:
return NOFIELD;
}
return 0;
}
#undef NOFIELD
#undef NOSET
int LUA_PlayerLib(lua_State *L)
{
@@ -797,6 +858,8 @@ int LUA_PlayerLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
ticcmd_fields_ref = Lua_CreateFieldTable(L, ticcmd_opt);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getPlayer);
+80 -21
View File
@@ -152,6 +152,7 @@ static int noglobals(lua_State *L)
{
const char *csname;
char *name;
enum actionnum actionnum;
lua_remove(L, 1); // we're not gonna be using _G
csname = lua_tostring(L, 1);
@@ -170,6 +171,10 @@ static int noglobals(lua_State *L)
lua_rawset(L, -3); // rawset doesn't trigger this metatable again.
// otherwise we would've used setfield, obviously.
actionnum = LUA_GetActionNumByName(name);
if (actionnum < NUMACTIONS)
actionsoverridden[actionnum] = true;
Z_Free(name);
return 0;
}
@@ -394,8 +399,14 @@ fixed_t LUA_EvalMath(const char *word)
if (luaL_dostring(mL, buf))
{
p = lua_tostring(mL, -1);
while (*p++ != ':' && *p) ;
p += 3; // "1: "
// If there is [string "..."]:1: text, skip it
if (strstr(p, ":") != NULL)
{
while (*p++ != ':' && *p);
p += 3; // "1: "
}
CONS_Alert(CONS_WARNING, "%s\n", p);
}
else
@@ -659,8 +670,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
lua_pop(gL, 1);
}
if (!found)
{
t++;
if (t == 0)
{
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
WRITEUINT8(save_p, ARCH_NULL);
return 0;
}
}
WRITEUINT8(save_p, ARCH_TABLE);
WRITEUINT16(save_p, t);
@@ -1427,7 +1447,12 @@ static void UnArchiveExtVars(void *pointer)
if (field_count == 0)
return;
I_Assert(gL != NULL);
// Technically possible new, since server may have local lua scripts but no "public" ones, so
// field_count would be non zero (there is no way to tell local field from non-local, so
// everything gets archived)
if (!gL)
return;
TABLESINDEX = lua_gettop(gL);
lua_createtable(gL, 0, field_count); // pointer's ext vars subtable
@@ -1587,12 +1612,14 @@ void LUA_Archive(void)
if (gamestate == GS_LEVEL)
{
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(th, "mobj");
}
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(th, "mobj");
}
}
WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
@@ -1620,11 +1647,15 @@ void LUA_UnArchive(void)
}
do {
mobjnum = READUINT32(save_p); // read a mobjnum
mobjnum = READUINT32(save_p); // read a mobjnum
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker
&& ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj
UnArchiveExtVars(th); // apply variables
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
continue;
UnArchiveExtVars(th); // apply variables
}
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode
@@ -1678,13 +1709,41 @@ void LUA_UnArchiveDemo(void)
}
// For mobj_t, player_t, etc. to take custom variables.
int Lua_optoption(lua_State *L, int narg,
const char *def, const char *const lst[])
int Lua_optoption(lua_State *L, int narg, int def, int list_ref)
{
int result = -1;
if (lua_isnoneornil(L, narg))
return def;
I_Assert(lua_checkstack(L, 2));
luaL_checkstring(L, narg);
lua_rawgeti(L, LUA_REGISTRYINDEX, list_ref);
I_Assert(lua_istable(L, -1));
lua_pushvalue(L, narg);
lua_rawget(L, -2);
if (lua_isnumber(L, -1))
result = lua_tointeger(L, -1);
lua_pop(L, 2); // Pop result and fields table
return result;
}
int Lua_CreateFieldTable(lua_State *L, const char *const lst[])
{
const char *name = (def) ? luaL_optstring(L, narg, def) : luaL_checkstring(L, narg);
int i;
for (i=0; lst[i]; i++)
if (fastcmp(lst[i], name))
return i;
return -1;
}
lua_newtable(L);
for (i = 0; lst[i] != NULL; i++)
{
lua_pushstring(L, lst[i]);
lua_pushinteger(L, i);
lua_settable(L, -3);
}
return luaL_ref(L, LUA_REGISTRYINDEX);
}
+2 -2
View File
@@ -63,8 +63,8 @@ void LUA_UnArchiveDemo(void);
void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
void LUA_CVarChanged(const char *name); // lua_consolelib.c
int Lua_optoption(lua_State *L, int narg,
const char *def, const char *const lst[]);
int Lua_optoption(lua_State *L, int narg, int def, int list_ref);
int Lua_CreateFieldTable(lua_State *L, const char *const lst[]);
void LUAh_NetArchiveHook(lua_CFunction archFunc);
// Console wrapper
+6 -1
View File
@@ -38,6 +38,7 @@ enum skin {
skin_highresscale,
skin_soundsid
};
static const char *const skin_opt[] = {
"valid",
"name",
@@ -61,10 +62,12 @@ static const char *const skin_opt[] = {
#define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field])
static int skin_fields_ref = LUA_NOREF;
static int skin_get(lua_State *L)
{
skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN));
enum skin field = luaL_checkoption(L, 2, NULL, skin_opt);
enum skin field = Lua_optoption(L, 2, -1, skin_fields_ref);
INT32 i;
// skins are always valid, only added, never removed
@@ -253,6 +256,8 @@ int LUA_SkinLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L,1);
skin_fields_ref = Lua_CreateFieldTable(L, skin_opt);
luaL_newmetatable(L, META_SOUNDSID);
lua_pushcfunction(L, soundsid_get);
lua_setfield(L, -2, "__index");
+3 -2
View File
@@ -909,8 +909,9 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mo = (mobj_t *)th;
// get offset from mt, which points to old mapthings, then add new location
if (mo->spawnpoint)
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
if (!mo->spawnpoint)
continue;
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
}
}
-7
View File
@@ -1011,13 +1011,6 @@ int main(int argc, char** argv)
exit(0);
}
static void *cpu_cpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
void *(*M_Memcpy)(void* dest, const void* src, size_t n) = cpu_cpy;
void I_Error(const char *error, ...)
{
(void)error;
+866 -780
View File
File diff suppressed because it is too large. Load diff
+24 -2
View File
@@ -21,6 +21,8 @@
#include "mserv.h"
#include "r_things.h" // for SKINNAMESIZE
extern boolean forceshowhud;
//
// MENUS
//
@@ -59,6 +61,9 @@ void M_SortServerList(void);
// Draws a box with a texture inside as background for messages
void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines);
// Same but with extra flags applied
void M_DrawTextBoxFlags(INT32 x, INT32 y, INT32 width, INT32 boxlines, INT32 flags);
// Used in d_netcmd to restart time attack
void M_ModeAttackRetry(INT32 choice);
@@ -74,6 +79,11 @@ typedef enum
} menumessagetype_t;
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
extern boolean DPADUPSCROLL;
extern boolean DPADDOWNSCROLL;
extern boolean DPADLEFTSCROLL;
extern boolean DPADRIGHTSCROLL;
typedef enum
{
M_NOT_WAITING,
@@ -250,6 +260,7 @@ extern INT32 mapwads[NUMMAPS];
extern description_t description[MAXSKINS];
extern consvar_t cv_replaysearchrate;
extern consvar_t cv_showfocuslost;
extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
extern consvar_t cv_showallmaps;
@@ -281,8 +292,8 @@ void PDistort_menu_Onchange(void);
// Bird menu updating
void Bird_menu_Onchange(void);
// Saturn menu updating
void Saturn_menu_Onchange(void);
// Saturn Hud menu updating
void SaturnHud_menu_Onchange(void);
void M_ReplayHut(INT32 choice);
void M_SetPlaybackMenuPointer(void);
@@ -392,4 +403,15 @@ void M_SlotCvarIntoModMenu(consvar_t* cvar, const char* category, const char* na
{NULL}\
}
#define DoToolTips(menu, tooltip)\
if (currentMenu == &menu)\
{\
if (!(tooltip[itemOn] == NULL))\
{\
M_DrawSplitText(BASEVIDWIDTH / 2, BASEVIDHEIGHT-50, V_ALLOWLOWERCASE|V_SNAPTOBOTTOM, tooltip[itemOn], coolalphatimer);\
if (coolalphatimer > 0 && interpTimerHackAllow)\
coolalphatimer--;\
}\
}
#endif //__X_MENU__
+50 -1
View File
@@ -334,6 +334,38 @@ boolean FIL_FileOK(char const *name)
return access(name,6)+1; //R_OK|W_OK
}
/** Copies contents of one file to another
*
* \param src File to copy from
* \param dst File to write into
* \return true if copy was succesful, false if it doesn't.
*/
boolean FIL_CopyFile(const char *src, const char *dst)
{
FILE *srcFile = fopen(src, "rb");
if (srcFile == NULL)
return false;
FILE *dstFile = fopen(dst, "wb");
if (dstFile == NULL)
{
fclose(srcFile);
return false;
}
char buffer[1024];
size_t n;
while ((n = fread(buffer, 1, sizeof(buffer), srcFile)) > 0)
fwrite(buffer, 1, n, dstFile);
fclose(srcFile);
fclose(dstFile);
return true;
}
/** Checks if a pathname has a file extension and adds the extension provided
* if not.
@@ -525,11 +557,28 @@ void M_SaveConfig(const char *filename)
{
FILE *f;
char *filepath;
char backupfile[MAX_WADPATH+4];
// make sure not to write back the config until it's been correctly loaded
if (!gameconfig_loaded)
return;
// Create backup of the config file
snprintf(backupfile, sizeof backupfile, "%s.bak", configfile);
backupfile[sizeof backupfile - 1] = '\0';
FILE *config = fopen(configfile, "r");
if (config != NULL)
{
fclose(config);
if (FIL_CopyFile(configfile, backupfile) == false)
{
CONS_Alert(CONS_WARNING,"Failed to create a backup of the configuration file. Will not attempt to write to file\n");
return;
}
}
// can change the file name
if (filename)
{
@@ -1938,7 +1987,7 @@ char *sizeu5(size_t num)
return sizeu5_buf;
}
void *M_Memcpy(void *dest, const void *src, size_t n)
FUNCINLINE ATTRINLINE void *M_Memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
+1
View File
@@ -54,6 +54,7 @@ boolean FIL_FileExists(const char *name);
boolean FIL_WriteFileOK(char const *name);
boolean FIL_ReadFileOK(char const *name);
boolean FIL_FileOK(char const *name);
boolean FIL_CopyFile(const char *src, const char *dst);
void FIL_DefaultExtension (char *path, const char *extension);
void FIL_ForceExtension(char *path, const char *extension);
-5
View File
@@ -58,7 +58,6 @@ static ps_metric_t ps_regularcount = {0};
static ps_metric_t ps_scenerycount = {0};
static ps_metric_t ps_nothinkcount = {0};
static ps_metric_t ps_otherthcount = {0};
static ps_metric_t ps_precipcount = {0};
static ps_metric_t ps_removecount = {0};
ps_metric_t ps_checkposition_calls = {0};
@@ -173,7 +172,6 @@ perfstatrow_t thinkercount_rows[] = {
{" scenery", " Scenery: ", &ps_scenerycount, PS_LEVEL},
{" nothink", " Nothink: ", &ps_nothinkcount, PS_HIDE_ZERO|PS_LEVEL},
{" other ", " Other: ", &ps_otherthcount, PS_LEVEL},
{" precip ", " Precipitation: ", &ps_precipcount, PS_LEVEL},
{" remove ", " Pending removal:", &ps_removecount, PS_LEVEL},
{0}
};
@@ -572,7 +570,6 @@ static void PS_CountThinkers(void)
ps_scenerycount.value.i = 0;
ps_nothinkcount.value.i = 0;
ps_otherthcount.value.i = 0;
ps_precipcount.value.i = 0;
ps_removecount.value.i = 0;
for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next)
{
@@ -590,8 +587,6 @@ static void PS_CountThinkers(void)
else
ps_regularcount.value.i++;
}
else if (thinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
ps_precipcount.value.i++;
else
ps_otherthcount.value.i++;
}
+73 -16
View File
@@ -17,6 +17,7 @@
#include "doomstat.h"
#include "doomdef.h"
#include "console.h" // con_startup
#include "command.h"
#include "i_threads.h"
#include "mserv.h"
@@ -212,20 +213,50 @@ static void Command_Listserv_f(void)
}
#endif
static boolean firstmsrules = false;
static void
Get_masterserver_rules (boolean checkfirst)
{
char rules[256];
if (checkfirst)
{
boolean MSRulesExist;
Lock_state();
MSRulesExist = (MSRules != NULL);
Unlock_state();
if (MSRulesExist)
return;
}
if (HMS_fetch_rules(rules, sizeof rules))
{
Lock_state();
Z_Free(MSRules);
MSRules = Z_StrDup(rules);
if (MSRegistered == true)
{
CONS_Printf("\n");
CONS_Alert(CONS_NOTICE, "%s\n", rules);
}
firstmsrules = true;
Unlock_state();
}
}
static void
Finish_registration (void)
{
int registered;
char *rules = GetMasterServerRules();
CONS_Printf("Registering this server on the master server...\n");
if (rules)
{
CONS_Printf("\n");
CONS_Alert(CONS_NOTICE, "%s\n", rules);
}
registered = HMS_register();
Lock_state();
@@ -237,6 +268,17 @@ Finish_registration (void)
}
Unlock_state();
char *rules = GetMasterServerRules();
if (rules == NULL)
{
Get_masterserver_rules(true);
}
else
{
CONS_Printf("\n");
CONS_Alert(CONS_NOTICE, "%s\n", rules);
}
if (registered)
CONS_Printf("Master server registration successful.\n");
}
@@ -322,17 +364,10 @@ Finish_unlist (void)
static void
Finish_masterserver_change (char *api)
{
char rules[256];
HMS_set_api(api);
if (HMS_fetch_rules(rules, sizeof rules))
{
Lock_state();
Z_Free(MSRules);
MSRules = Z_StrDup(rules);
Unlock_state();
}
if (!con_startup)
Get_masterserver_rules(false);
}
#ifdef HAVE_THREADS
@@ -430,6 +465,14 @@ Change_masterserver_thread (char *api)
Finish_masterserver_change(api);
}
static void
Get_masterserver_rules_thread (void)
{
// THIS FUNC has its own lock check in it
Get_masterserver_rules(true);
}
#endif/*HAVE_THREADS*/
void RegisterServer(void)
@@ -540,6 +583,20 @@ Set_api (const char *api)
#endif
}
void
Get_rules (void)
{
#ifdef HAVE_THREADS
I_spawn_thread(
"get-masterserver-rules",
(I_thread_fn)Get_masterserver_rules_thread,
NULL
);
#else
Get_masterserver_rules(true);
#endif
}
#endif/*MASTERSERVER*/
static void
+5 -1
View File
@@ -82,6 +82,8 @@ extern I_mutex ms_ServerList_mutex;
void RegisterServer(void);
void UnregisterServer(void);
void Get_rules(void);
void MasterClient_Ticker(void);
msg_server_t *GetShortServersList(int id);
@@ -90,9 +92,11 @@ char *GetMODVersion(int id);
#endif
char *GetMasterServerRules(void);
#endif
void AddMServCommands(void);
#ifdef MASTERSERVER
/* HTTP */
void HMS_set_api (char *api);
int HMS_register (void);
@@ -105,4 +109,4 @@ const char * HMS_fetch_rules (char *buffer, size_t size_of_buffer);
#endif
#endif
#endif
+203 -203
View File
File diff suppressed because it is too large. Load diff
-24
View File
@@ -1968,32 +1968,8 @@ void T_ThwompSector(levelspecthink_t *thwomp)
}
else // Not going anywhere, so look for players.
{
//thinker_t *th;
//mobj_t *mo;
thwomp->direction = -1;
/* // SRB2kart 170217 - Thwomps are automatic.
// scan the thinkers to find players!
if (!rover || (rover->flags & FF_EXISTS))
{
// scan the thinkers to find players!
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator
&& mo->z <= thwomp->sector->ceilingheight
&& P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT)
{
thwomp->direction = -1;
break;
}
}
}*/
thwomp->sector->ceilspeed = 0;
thwomp->sector->floorspeed = 0;
}
+65 -594
View File
@@ -17,6 +17,7 @@
#include "g_game.h"
#include "m_random.h"
#include "p_local.h"
#include "p_setup.h"
#include "s_sound.h"
#include "r_main.h"
#include "st_stuff.h"
@@ -253,26 +254,21 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (heightcheck)
{
/*if (special->type == MT_FLINGEMERALD) // little hack here...
{ // flingemerald sprites are low to the ground, so extend collision radius down some.
if (toucher->z > (special->z + special->height))
return;
if (special->z - special->height > (toucher->z + toucher->height))
return;
}
else*/
if (toucher->momz < 0)
{
if (toucher->momz < 0) {
if (toucher->z + toucher->momz > special->z + special->height)
return;
} else if (toucher->z > special->z + special->height)
return;
if (toucher->momz > 0) {
if (toucher->z + toucher->height + toucher->momz < special->z)
return;
} else if (toucher->z + toucher->height < special->z)
if (toucher->z + toucher->momz > special->z + special->height)
return;
}
else if (toucher->z > special->z + special->height)
return;
if (toucher->momz > 0)
{
if (toucher->z + toucher->height + toucher->momz < special->z)
return;
}
else if (toucher->z + toucher->height < special->z)
return;
}
if (special->health <= 0)
@@ -383,16 +379,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->kartstuff[k_roulettetype] = 2;
}
#if 0
// Eggbox snipe!
if (special->type == MT_EGGMANITEM && special->health > 1)
S_StartSound(toucher, sfx_bsnipe);
#endif
{
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
S_StartSound(poof, special->info->deathsound);
}
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
S_StartSound(poof, special->info->deathsound);
if (special->target && special->target->player)
{
@@ -475,8 +463,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
else if (special->target->player->kartstuff[k_comebackmode] == 1 && P_CanPickupItem(player, 1))
{
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
S_StartSound(poof, special->info->seesound);
mobj_t *poof2 = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
S_StartSound(poof2, special->info->seesound);
// Karma fireworks
for (i = 0; i < 5; i++)
@@ -502,10 +490,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
else if (special->target->player->kartstuff[k_comebackmode] == 2 && P_CanPickupItem(player, 2))
{
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
mobj_t *poof3 = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
UINT8 ptadd = 1; // No WANTED bonus for tricking
S_StartSound(poof, special->info->seesound);
S_StartSound(poof3, special->info->seesound);
if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1
{
@@ -583,10 +571,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else
K_SpinPlayer(player, special->target, 0, special, false);
return;
/*case MT_EERIEFOG:
special->frame &= ~FF_TRANS80;
special->frame |= FF_TRANS90;
return;*/
case MT_SMK_MOLE:
if (special->target && !P_MobjWasRemoved(special->target))
return;
@@ -935,12 +919,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->flyangle = special->threshold;
player->speed = FixedMul(special->info->speed, special->scale);
// Potentially causes axis transfer failures.
// Also rarely worked properly anyway.
//P_UnsetThingPosition(player->mo);
//player->mo->x = special->x;
//player->mo->y = special->y;
//P_SetThingPosition(player->mo);
toucher->z = special->z+(special->height/4);
}
else // More like a spring
@@ -985,140 +963,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
}
return;
/*case MT_NIGHTSSUPERLOOP:
if (player->bot || !(player->pflags & PF_NIGHTSMODE))
return;
if (!G_IsSpecialStage(gamemap))
player->powers[pw_nights_superloop] = (UINT16)special->info->speed;
else
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE)
players[i].powers[pw_nights_superloop] = (UINT16)special->info->speed;
if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound);
}
// CECHO showing you what this item is
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Super Paraloop"));
}
break;
case MT_NIGHTSDRILLREFILL:
if (player->bot || !(player->pflags & PF_NIGHTSMODE))
return;
if (!G_IsSpecialStage(gamemap))
player->drillmeter = special->info->speed;
else
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE)
players[i].drillmeter = special->info->speed;
if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound);
}
// CECHO showing you what this item is
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Drill Refill"));
}
break;
case MT_NIGHTSHELPER:
if (player->bot || !(player->pflags & PF_NIGHTSMODE))
return;
if (!G_IsSpecialStage(gamemap))
{
// A flicky orbits us now
mobj_t *flickyobj = P_SpawnMobj(toucher->x, toucher->y, toucher->z + toucher->info->height, MT_NIGHTOPIANHELPER);
P_SetTarget(&flickyobj->target, toucher);
player->powers[pw_nights_helper] = (UINT16)special->info->speed;
}
else
{
mobj_t *flickyobj;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && players[i].pflags & PF_NIGHTSMODE) {
players[i].powers[pw_nights_helper] = (UINT16)special->info->speed;
flickyobj = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_NIGHTOPIANHELPER);
P_SetTarget(&flickyobj->target, players[i].mo);
}
if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound);
}
// CECHO showing you what this item is
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Nightopian Helper"));
}
break;
case MT_NIGHTSEXTRATIME:
if (player->bot || !(player->pflags & PF_NIGHTSMODE))
return;
if (!G_IsSpecialStage(gamemap))
{
player->nightstime += special->info->speed;
player->startedtime += special->info->speed;
P_RestoreMusic(player);
}
else
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE)
{
players[i].nightstime += special->info->speed;
players[i].startedtime += special->info->speed;
P_RestoreMusic(&players[i]);
}
if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound);
}
// CECHO showing you what this item is
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Extra Time"));
}
break;
case MT_NIGHTSLINKFREEZE:
if (player->bot || !(player->pflags & PF_NIGHTSMODE))
return;
if (!G_IsSpecialStage(gamemap))
{
player->powers[pw_nights_linkfreeze] = (UINT16)special->info->speed;
player->linktimer = 2*TICRATE;
}
else
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE)
{
players[i].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed;
players[i].linktimer = 2*TICRATE;
}
if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound);
}
// CECHO showing you what this item is
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Link Freeze"));
}
break;*/
case MT_NIGHTSWING:
if (G_IsSpecialStage(gamemap) && useNightsSS)
{ // Pseudo-ring.
@@ -1132,7 +976,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
break;
case MT_HOOPCOLLIDE:
// This produces a kind of 'domino effect' with the hoop's pieces.
for (; special->hprev != NULL; special = special->hprev); // Move to the first sprite in the hoop
if (!midgamejoin)
for (; special->hprev != NULL; special = special->hprev); // Move to the first sprite in the hoop
i = 0;
for (; special->type == MT_HOOP; special = special->hnext)
{
@@ -1464,7 +1310,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
else
{
P_PlayRinglossSound(toucher);
P_PlayRinglossSound(toucher, NULL);
if (toucher->health > 10)
toucher->health -= 10;
else
@@ -1510,23 +1356,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|| special->z > toucher->z + (toucher->height*2/3))
return; // Only go in the mouth
/* // SRB2kart - Can't drown.
// Eaten by player!
if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)
P_RestoreMusic(player);
if (player->powers[pw_underwater] < underwatertics + 1)
player->powers[pw_underwater] = underwatertics + 1;
*/
/*
if (!player->climbing)
{
P_SetPlayerMobjState(toucher, S_PLAY_GASP);
P_ResetPlayer(player);
}
*/
toucher->momx = toucher->momy = toucher->momz = 0;
break;
@@ -1583,26 +1412,7 @@ void P_CheckTimeLimit(void)
if (gameaction == ga_completed)
return;
//Tagmode round end but only on the tic before the
//XD_EXITLEVEL packet is received by all players.
/*if (G_TagGametype())
{
if (leveltime == (timelimitintics + 1))
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator
|| (players[i].pflags & PF_TAGGED) || (players[i].pflags & PF_TAGIT))
continue;
CONS_Printf(M_GetText("%s received double points for surviving the round.\n"), player_names[i]);
P_AddPlayerScore(&players[i], players[i].score);
}
}
}
//Optional tie-breaker for Match/CTF
else*/ if (cv_overtime.value)
if (cv_overtime.value)
{
INT32 playerarray[MAXPLAYERS];
INT32 tempplayer = 0;
@@ -1675,9 +1485,6 @@ void P_CheckTimeLimit(void)
return;
P_DoPlayerExit(&players[i]);
}
/*if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);*/
}
/** Checks if a player's score is over the pointlimit and the round should end.
@@ -1699,127 +1506,27 @@ void P_CheckPointLimit(void)
if (G_RaceGametype())
return;
// pointlimit is nonzero, check if it's been reached by this player
/*if (G_GametypeHasTeams())
for (i = 0; i < MAXPLAYERS; i++)
{
// Just check both teams
if ((UINT32)cv_pointlimit.value <= redscore || (UINT32)cv_pointlimit.value <= bluescore)
{
if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
}
else*/
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!playeringame[i] || players[i].spectator)
continue;
if ((UINT32)cv_pointlimit.value <= players[i].marescore)
if ((UINT32)cv_pointlimit.value <= players[i].marescore)
{
for (i = 0; i < MAXPLAYERS; i++) // AAAAA nested loop using the same iteration variable ;;
{
for (i = 0; i < MAXPLAYERS; i++) // AAAAA nested loop using the same iteration variable ;;
{
if (!playeringame[i] || players[i].spectator)
continue;
if (players[i].exiting)
return;
P_DoPlayerExit(&players[i]);
}
/*if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);*/
return; // good thing we're leaving the function immediately instead of letting the loop get mangled!
if (!playeringame[i] || players[i].spectator)
continue;
if (players[i].exiting)
return;
P_DoPlayerExit(&players[i]);
}
return; // good thing we're leaving the function immediately instead of letting the loop get mangled!
}
}
}
/*Checks for untagged remaining players in both tag derivitave modes.
*If no untagged players remain, end the round.
*Also serves as error checking if the only IT player leaves.*/
/*void P_CheckSurvivors(void)
{
INT32 i;
INT32 survivors = 0;
INT32 taggers = 0;
INT32 spectators = 0;
INT32 survivorarray[MAXPLAYERS];
if (!D_NumPlayers()) //no players in the game, no check performed.
return;
for (i=0; i < MAXPLAYERS; i++) //figure out counts of taggers, survivors and spectators.
{
if (playeringame[i])
{
if (players[i].spectator)
spectators++;
else if (players[i].pflags & PF_TAGIT)
taggers++;
else if (!(players[i].pflags & PF_TAGGED))
{
survivorarray[survivors] = i;
survivors++;
}
}
}
if (!taggers) //If there are no taggers, pick a survivor at random to be it.
{
// Exception for hide and seek. If a round has started and the IT player leaves, end the round.
if (gametype == GT_HIDEANDSEEK && (leveltime >= (hidetime * TICRATE)))
{
CONS_Printf(M_GetText("The IT player has left the game.\n"));
if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
return;
}
if (survivors)
{
INT32 newtagger = survivorarray[P_RandomKey(survivors)];
CONS_Printf(M_GetText("%s is now IT!\n"), player_names[newtagger]); // Tell everyone who is it!
players[newtagger].pflags |= PF_TAGIT;
survivors--; //Get rid of the guy we just made IT.
//Yeah, we have an eligible tagger, but we may not have anybody for him to tag!
//If there is only one guy waiting on the game to fill or spectators to enter game, don't bother.
if (!survivors && (D_NumPlayers() - spectators) > 1)
{
CONS_Printf(M_GetText("All players have been tagged!\n"));
if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
return;
}
//If we reach this point, no player can replace the one that was IT.
//Unless it is one player waiting on a game, end the round.
if ((D_NumPlayers() - spectators) > 1)
{
CONS_Printf(M_GetText("There are no players able to become IT.\n"));
if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
return;
}
//If there are taggers, but no survivors, end the round.
//Except when the tagger is by himself and the rest of the game are spectators.
if (!survivors && (D_NumPlayers() - spectators) > 1)
{
CONS_Printf(M_GetText("All players have been tagged!\n"));
if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
}*/
// Checks whether or not to end a race netgame.
boolean P_CheckRacers(void)
{
@@ -1908,9 +1615,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
mobj_t *mo;
int ms;
//if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
// P_SetTarget(&target->tracer, inflictor);
if (!useNightsSS && G_IsSpecialStage(gamemap) && target->player && sstimer > 6)
sstimer = 6; // Just let P_Ticker take care of the rest.
@@ -1959,7 +1663,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
K_KillBananaChain(target->target->hnext, inflictor, source);
target->target->player->kartstuff[k_itemamount] = 0;
}
else
else if (target->target->player->kartstuff[k_itemamount])
target->target->player->kartstuff[k_itemamount]--;
}
else if ((target->type == MT_ORBINAUT_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_ORBINAUT) // orbit items
@@ -1991,14 +1695,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
{
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
G_StopMetalRecording();
/*if (gametype == GT_MATCH && cv_match_scoring.value == 0 // note, no team match suicide penalty
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
{ // Suicide penalty - Not in Kart
if (target->player->score >= 50)
target->player->score -= 50;
else
target->player->score = 0;
}*/
target->flags2 &= ~MF2_DONTDRAW;
}
@@ -2015,85 +1711,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
target->fuse = cv_itemrespawntime.value*TICRATE + 2; // Random box generation
}
}
// Award Score Tails
/*{ // Enemies shouldn't award points in Kart
INT32 score = 0;
if (maptol & TOL_NIGHTS) // Enemies always worth 200, bosses don't do anything.
{
if ((target->flags & MF_ENEMY) && !(target->flags & (MF_MISSILE|MF_BOSS)))
{
score = 200;
if (source->player->bonustime)
score *= 2;
// Also, add to the link.
// I don't know if NiGHTS did this, but
// Sonic Time Attacked did and it seems like a good enough incentive
// to make people want to actually dash towards/paraloop enemies
if (++source->player->linkcount > source->player->maxlink)
source->player->maxlink = source->player->linkcount;
source->player->linktimer = 2*TICRATE;
}
}
else
{
if (target->flags & MF_BOSS)
score = 1000;
else if ((target->flags & MF_ENEMY) && !(target->flags & MF_MISSILE))
{
mobj_t *scoremobj;
UINT32 scorestate = mobjinfo[MT_SCORE].spawnstate;
scoremobj = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2), MT_SCORE);
// On ground? No chain starts.
if (!source->player->powers[pw_invulnerability] && P_IsObjectOnGround(source))
{
source->player->scoreadd = 0;
score = 100;
}
// Mario Mode has Mario-like chain point values
else if (mariomode) switch (++source->player->scoreadd)
{
case 1: score = 100; break;
case 2: score = 200; scorestate += 1; break;
case 3: score = 400; scorestate += 5; break;
case 4: score = 800; scorestate += 6; break;
case 5: score = 1000; scorestate += 3; break;
case 6: score = 2000; scorestate += 7; break;
case 7: score = 4000; scorestate += 8; break;
case 8: score = 8000; scorestate += 9; break;
default: // 1up for a chain this long
if (modeattacking) // but 1ups don't exist in record attack!
{ // So we just go back to 10k points.
score = 10000; scorestate += 4; break;
}
P_GivePlayerLives(source->player, 1);
P_PlayLivesJingle(source->player);
scorestate += 10;
break;
}
// More Sonic-like point system
else switch (++source->player->scoreadd)
{
case 1: score = 100; break;
case 2: score = 200; scorestate += 1; break;
case 3: score = 500; scorestate += 2; break;
case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14:
score = 1000; scorestate += 3; break;
default: score = 10000; scorestate += 4; break;
}
P_SetMobjState(scoremobj, scorestate);
}
}
P_AddPlayerScore(source->player, score);
}*/
}
// if a player avatar dies...
@@ -2120,7 +1737,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
}
target->player->playerstate = PST_DEAD;
if (cv_fading.value && cv_birdmusic.value && P_IsLocalPlayer(target->player))
if (cv_birdmusic.value && cv_fading.value && P_IsLocalPlayer(target->player))
{
if (netgame || multiplayer)
ms = cv_respawntime.value * 1000;
@@ -2131,7 +1748,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
If the time spent with the music paused is less than half
a second, continue playing the song (just mute it).
*/
if (( ms - cv_respawnfademusicout.value ) < 500)
if ((ms - cv_respawnfademusicout.value) < 500)
S_FadeMusic(0, cv_respawnfademusicout.value);
else
S_FadeOutStopMusic(cv_respawnfademusicout.value);
@@ -2157,42 +1774,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
if (target->player == &players[displayplayers[3]])
localaiming[3] = 0;
//tag deaths handled differently in suicide cases. Don't count spectators!
/*if (G_TagGametype()
&& !(target->player->pflags & PF_TAGIT) && (!source || !source->player) && !(target->player->spectator))
{
// if you accidentally die before you run out of time to hide, ignore it.
// allow them to try again, rather than sitting the whole thing out.
if (leveltime >= hidetime * TICRATE)
{
if (gametype == GT_TAG)//suiciding in survivor makes you IT.
{
target->player->pflags |= PF_TAGIT;
CONS_Printf(M_GetText("%s is now IT!\n"), player_names[target->player-players]); // Tell everyone who is it!
P_CheckSurvivors();
}
else
{
if (!(target->player->pflags & PF_TAGGED))
{
//otherwise, increment the tagger's score.
//in hide and seek, suiciding players are counted as found.
INT32 w;
for (w=0; w < MAXPLAYERS; w++)
{
if (players[w].pflags & PF_TAGIT)
P_AddPlayerScore(&players[w], 1);
}
target->player->pflags |= PF_TAGGED;
CONS_Printf(M_GetText("%s was found!\n"), player_names[target->player-players]);
P_CheckSurvivors();
}
}
}
}
else*/ if (G_BattleGametype())
if (G_BattleGametype())
K_CheckBumpers();
target->player->kartstuff[k_pogospring] = 0;
@@ -2607,26 +2189,6 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return false;
}
// The tag occurs so long as you aren't shooting another tagger with friendlyfire on.
/*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
{
P_AddPlayerScore(source->player, 1); //award points to tagger.
if (gametype == GT_TAG) //survivor
{
player->pflags |= PF_TAGIT; //in survivor, the player becomes IT and helps hunt down the survivors.
CONS_Printf(M_GetText("%s is now IT!\n"), player_names[player-players]); // Tell everyone who is it!
}
else
{
player->pflags |= PF_TAGGED; //in hide and seek, the player is tagged and stays stationary.
CONS_Printf(M_GetText("%s was found!\n"), player_names[player-players]); // Tell everyone who is it!
}
//checks if tagger has tagged all players, if so, end round early.
P_CheckSurvivors();
}*/
P_DoPlayerPain(player, source, inflictor);
// Check for a shield
@@ -2644,7 +2206,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
}
else if (target->health > 1) // Ring loss
{
P_PlayRinglossSound(target);
P_PlayRinglossSound(target, source);
P_PlayerRingBurst(player, player->mo->health - 1);
}
@@ -2665,15 +2227,6 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
{
player_t *player = target->player;
// You can't kill yourself, idiot... // Unless it's Mario kart. Which it is. In this mod. All the time.
//if (source == target)
// return false;
// In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on
// ...But in SRB2kart, you can!
//if (!cv_friendlyfire.value && (G_RaceGametype()))
// return false;
// Tag handling
if (G_TagGametype())
return P_TagDamage(target, inflictor, source, damage);
@@ -2725,32 +2278,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
/*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 1);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 1);
}
// If the player was super, tell them he/she ain't so super nomore.
if (gametype != GT_COOP && player->powers[pw_super])
{
S_StartSound(NULL, sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
}*/
if (player->pflags & PF_TIMEOVER)
{
mobj_t *boom;
@@ -2811,44 +2338,8 @@ void P_RemoveShield(player_t *player)
player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK;
}
/*
static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused.
{
// Must do pain first to set flashing -- P_RemoveShield can cause damage
P_DoPlayerPain(player, source, inflictor);
P_RemoveShield(player);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes
S_StartSound(player->mo, sfx_spkdth);
else
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss.
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, cv_match_scoring.value == 1 ? 25 : 50);
}
}
*/
static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
//const UINT8 scoremultiply = ((K_IsWantedPlayer(player) && !trapitem) : 2 ? 1);
if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoPlayerPain(player, source, inflictor);
@@ -2859,26 +2350,8 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
S_StartSound(player->mo, sfx_spkdth);
}
/*if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, scoremultiply);
}
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, scoremultiply);
}
}*/
// Ring loss sound plays despite hitting spikes
P_PlayRinglossSound(player->mo); // Ringledingle!
P_PlayRinglossSound(player->mo, source); // Ringledingle!
}
/** Damages an object, which may or may not be a player.
@@ -3676,32 +3149,30 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
P_SetTarget(&flag->target, player->mo);
// Flag text
char plname[MAXPLAYERNAME+4];
const char *flagtext;
char flagcolor;
snprintf(plname, sizeof(plname), "%s%s%s",
CTFTEAMCODE(player),
player_names[player - players],
CTFTEAMENDCODE(player));
if (type == MT_REDFLAG)
{
char plname[MAXPLAYERNAME+4];
const char *flagtext;
char flagcolor;
snprintf(plname, sizeof(plname), "%s%s%s",
CTFTEAMCODE(player),
player_names[player - players],
CTFTEAMENDCODE(player));
if (type == MT_REDFLAG)
{
flagtext = M_GetText("Red flag");
flagcolor = '\x85';
}
else
{
flagtext = M_GetText("Blue flag");
flagcolor = '\x84';
}
if (toss)
CONS_Printf(M_GetText("%s tossed the %c%s%c.\n"), plname, flagcolor, flagtext, 0x80);
else
CONS_Printf(M_GetText("%s dropped the %c%s%c.\n"), plname, flagcolor, flagtext, 0x80);
flagtext = M_GetText("Red flag");
flagcolor = '\x85';
}
else
{
flagtext = M_GetText("Blue flag");
flagcolor = '\x84';
}
if (toss)
CONS_Printf(M_GetText("%s tossed the %c%s%c.\n"), plname, flagcolor, flagtext, 0x80);
else
CONS_Printf(M_GetText("%s dropped the %c%s%c.\n"), plname, flagcolor, flagtext, 0x80);
player->gotflag = 0;
+6 -3
View File
@@ -70,6 +70,7 @@ extern thinker_t thinkercap;
void P_InitThinkers(void);
void P_AddThinker(thinker_t *thinker);
void P_RemoveThinker(thinker_t *thinker);
void P_UnlinkThinker(thinker_t *thinker);
//
// P_USER
@@ -143,6 +144,8 @@ extern consvar_t cv_tiltsmoothing;
extern consvar_t cv_actionmovie;
extern consvar_t cv_lookbackmom;
extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate;
extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate;
extern fixed_t t_cam3_dist, t_cam3_height, t_cam3_rotate;
@@ -215,7 +218,7 @@ boolean P_PlayerMoving(INT32 pnum);
void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range);
void P_PlayLivesJingle(player_t *player);
void P_PlayRinglossSound(mobj_t *source);
void P_PlayRinglossSound(mobj_t *source, mobj_t *damager);
void P_PlayDeathSound(mobj_t *source);
void P_PlayVictorySound(mobj_t *source);
@@ -245,7 +248,7 @@ void P_RecalcPrecipInSector(sector_t *sector);
void P_PrecipitationEffects(void);
void P_RemoveMobj(mobj_t *th);
boolean P_MobjWasRemoved(mobj_t *th);
boolean P_MobjWasRemoved(const mobj_t *th);
void P_RemoveSavegameMobj(mobj_t *th);
boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
@@ -288,7 +291,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype
#define P_SpawnNameFinder(s,t) P_SPMAngle(s,t,s->angle,true,0)
#endif
void P_ColorTeamMissile(mobj_t *missile, player_t *source);
SINT8 P_MobjFlip(mobj_t *mobj);
SINT8 P_MobjFlip(const mobj_t *mobj);
fixed_t P_GetMobjGravity(mobj_t *mo);
FUNCMATH boolean P_WeaponOrPanel(mobjtype_t type);
+6 -86
View File
@@ -319,78 +319,6 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
}
#if 0
static void P_DoTailsCarry(player_t *sonic, player_t *tails)
{
INT32 p;
fixed_t zdist; // z distance between the two players' bottoms
if ((tails->pflags & PF_CARRIED) && tails->mo->tracer == sonic->mo)
return;
if ((sonic->pflags & PF_CARRIED) && sonic->mo->tracer == tails->mo)
return;
if (tails->bot == 1)
return;
if (sonic->pflags & PF_NIGHTSMODE)
return;
if (sonic->mo->tracer && sonic->mo->tracer->type == MT_TUBEWAYPOINT
&& !(sonic->pflags & PF_ROPEHANG))
return; // don't steal players from zoomtubes!
if ((sonic->mo->eflags & MFE_VERTICALFLIP) != (tails->mo->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity
if (tails->mo->eflags & MFE_VERTICALFLIP)
{
if (tails->mo->ceilingz - (tails->mo->z + tails->mo->height) < sonic->mo->height-FixedMul(2*FRACUNIT, sonic->mo->scale))
return;
}
else if (tails->mo->z - tails->mo->floorz < sonic->mo->height-FixedMul(2*FRACUNIT, sonic->mo->scale))
return; // No room to pick up this guy!
// Search in case another player is already being carried by this fox.
for (p = 0; p < MAXPLAYERS; p++)
if (playeringame[p] && players[p].mo
&& players[p].pflags & PF_CARRIED && players[p].mo->tracer == tails->mo)
return;
if (tails->mo->eflags & MFE_VERTICALFLIP)
zdist = (sonic->mo->z + sonic->mo->height) - (tails->mo->z + tails->mo->height);
else
zdist = tails->mo->z - sonic->mo->z;
if (zdist <= sonic->mo->height + FixedMul(FRACUNIT, sonic->mo->scale)
&& zdist > sonic->mo->height*2/3
&& P_MobjFlip(tails->mo)*sonic->mo->momz <= 0)
{
// Why block opposing teams from tailsflying each other?
// Sneaking into the hands of a flying tails player in Race might be a viable strategy, who knows.
if (tails->spectator || sonic->spectator || G_RaceGametype()) // SRB2kart
sonic->pflags &= ~PF_CARRIED;
else
{
if (sonic-players == consoleplayer && botingame)
//CV_SetValue(&cv_analog2, false);
P_ResetPlayer(sonic);
P_SetTarget(&sonic->mo->tracer, tails->mo);
sonic->pflags |= PF_CARRIED;
S_StartSound(sonic->mo, sfx_s3k4a);
P_UnsetThingPosition(sonic->mo);
sonic->mo->x = tails->mo->x;
sonic->mo->y = tails->mo->y;
P_SetThingPosition(sonic->mo);
}
}
else {
if (sonic-players == consoleplayer && botingame)
//CV_SetValue(&cv_analog2, true);
sonic->pflags &= ~PF_CARRIED;
}
}
#endif
//
// PIT_CheckThing
//
@@ -588,9 +516,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
// check for skulls slamming into things
if (tmthing->flags2 & MF2_SKULLFLY)
{
/*if (tmthing->type == MT_EGGMOBILE) // Don't make Eggman stop!
return true; // Let him RUN YOU RIGHT OVER. >:3
else*/
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
@@ -1676,7 +1601,7 @@ static boolean PIT_CheckLine(line_t *ld)
if (P_BoxOnLineSide(tmbbox, ld) != -1)
return true;
if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag.
if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag.
{
fixed_t cosradius, sinradius;
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
@@ -2245,6 +2170,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
floatok = false;
if (dedicated) // this crashes so don't even try it
return false;
if (twodlevel)
itsatwodlevel = true;
else
@@ -2474,14 +2402,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 12)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 12)
maxstep = 0;
// Don't 'step up' while springing,
// Only step up "if needed".
/* // SRB2kart - don't need
if (thing->state == &states[S_PLAY_SPRING]
&& P_MobjFlip(thing)*thing->momz > FixedMul(FRACUNIT, thing->scale))
maxstep = 0;
*/
}
if (thing->type == MT_SKIM)
@@ -4143,7 +4063,7 @@ static inline boolean PIT_GetSectors(line_t *ld)
tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
return true;
return true;
if (P_BoxOnLineSide(tmbbox, ld) != -1)
return true;
@@ -4178,7 +4098,7 @@ static inline boolean PIT_GetPrecipSectors(line_t *ld)
preciptmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
preciptmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
preciptmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
return true;
return true;
if (P_BoxOnLineSide(preciptmbbox, ld) != -1)
return true;
+610 -523
View File
File diff suppressed because it is too large. Load diff
+15 -18
View File
@@ -254,24 +254,21 @@ typedef enum
// PRECIPITATION flags ?! ?! ?!
//
typedef enum {
// Don't draw.
PCF_INVISIBLE = 1,
// Above pit.
PCF_PIT = 2,
// Above FOF.
PCF_FOF = 4,
// Above MOVING FOF (this means we need to keep floorz up to date...)
PCF_MOVINGFOF = 8,
// Is rain.
PCF_RAIN = 16,
// Ran the thinker this tic.
PCF_THUNK = 32,
PCF_INVISIBLE = 1, // Don't draw.
PCF_PIT = 1<<1, // Above pit.
PCF_FOF = 1<<2, // Above FOF.
PCF_MOVINGFOF = 1<<3, // Above MOVING FOF (this means we need to keep floorz up to date...)
PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over
PCF_THUNK = 1<<5, // Ran the thinker this tic.
} precipflag_t;
// Map Object definition.
typedef struct mobj_s
{
// List: thinker links.
thinker_t thinker;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// Info for drawing: position.
fixed_t x, y, z;
@@ -345,9 +342,6 @@ typedef struct mobj_s
struct mobj_s *hnext;
struct mobj_s *hprev;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
INT32 health; // for player this is rings + 1
// Movement direction, movement generation (zig-zagging).
@@ -426,6 +420,9 @@ typedef struct precipmobj_s
// List: thinker links.
thinker_t thinker;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// Info for drawing: position.
fixed_t x, y, z;
fixed_t old_x, old_y, old_z; // position interpolation
@@ -479,6 +476,7 @@ typedef struct precipmobj_s
INT32 tics; // state tic counter
state_t *state;
INT32 flags; // flags from mobjinfo tables
tic_t lastThink;
} precipmobj_t;
typedef struct actioncache_s
@@ -518,10 +516,9 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb
boolean P_BossTargetPlayer(mobj_t *actor, boolean closest);
boolean P_SupermanLook4Players(mobj_t *actor);
void P_DestroyRobots(void);
void P_SnowThinker(precipmobj_t *mobj);
void P_RainThinker(precipmobj_t *mobj);
boolean P_PrecipThinker(precipmobj_t *mobj);
void P_NullPrecipThinker(precipmobj_t *mobj);
void P_RemovePrecipMobj(precipmobj_t *mobj);
void P_FreePrecipMobj(precipmobj_t *mobj);
void P_SetScale(mobj_t *mobj, fixed_t newscale);
void P_XYMovement(mobj_t *mo);
void P_EmeraldManager(void);
+84 -229
View File
@@ -95,6 +95,8 @@ INT32 numPolyObjects;
// Polyobject Blockmap -- initialized in P_LoadBlockMap
polymaplink_t **polyblocklinks;
static size_t *KnownPolySides;
static size_t KnownPolySidesCount;
//
// Static Data
@@ -152,6 +154,36 @@ FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th)
thinkercap.next = th;
}
static void FreeSideLists(void)
{
free(KnownPolySides);
KnownPolySides = NULL;
KnownPolySidesCount = 0;
}
//==========================================================================
//
// InitSideLists [RH]
//
// Group sides by vertex and collect side that are known to belong to a
// polyobject so that they can be initialized fast.
//==========================================================================
static void InitSideLists(void)
{
size_t i;
FreeSideLists();
KnownPolySides = malloc(numsegs * sizeof(KnownPolySides[0]));
for (i = 0; i < numsegs; i++)
{
if (segs[i].linedef &&
(segs[i].linedef->special == POLYOBJ_START_LINE ||
segs[i].linedef->special == POLYOBJ_EXPLICIT_LINE))
{
KnownPolySides[KnownPolySidesCount++] = i;
}
}
}
//
// P_PointInsidePolyobj
//
@@ -512,11 +544,12 @@ static void Polyobj_findExplicit(polyobj_t *po)
size_t numSegItems = 0;
size_t numSegItemsAlloc = 0;
size_t i;
size_t i, ii;
// first loop: save off all segs with polyobject's id number
for (i = 0; i < numsegs; ++i)
for (ii = 0; ii < KnownPolySidesCount; ii++)
{
i = KnownPolySides[ii];
INT32 polyID, parentID;
if (segs[i].linedef->special != POLYOBJ_EXPLICIT_LINE)
@@ -566,7 +599,7 @@ static void Polyobj_findExplicit(polyobj_t *po)
//
static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
{
size_t i;
size_t i, ii;
polyobj_t *po = &PolyObjects[num];
// don't spawn a polyobject more than once
@@ -590,8 +623,9 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
// 1. Search segs for "line start" special with tag matching this
// polyobject's id number. If found, iterate through segs which
// share common vertices and record them into the polyobject.
for (i = 0; i < numsegs; ++i)
for (ii = 0; ii < KnownPolySidesCount; ii++)
{
i = KnownPolySides[ii];
seg_t *seg = &segs[i];
INT32 polyID, parentID;
@@ -1415,7 +1449,10 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings)
{
// update seg angles (used only by renderer)
for (i = 0; i < po->segCount; ++i)
{
po->segs[i]->angle += delta;
P_UpdateSegLightOffset(po->segs[i]);
}
// update polyobject's angle
po->angle += delta;
@@ -1514,29 +1551,29 @@ void Polyobj_InitLevel(void)
// the mobj_t pointers on a queue for use below.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj_t *mo = (mobj_t *)th;
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
{
mobj_t *mo = (mobj_t *)th;
++numPolyObjects;
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
{
++numPolyObjects;
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
}
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
{
++numAnchors;
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
}
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
{
++numAnchors;
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
}
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
}
}
@@ -1550,6 +1587,9 @@ void Polyobj_InitLevel(void)
for (i = 0; i < numPolyObjects; ++i)
PolyObjects[i].first = PolyObjects[i].next = numPolyObjects;
// [RH] Make this faster
InitSideLists();
// setup polyobjects
for (i = 0; i < numPolyObjects; ++i)
{
@@ -1558,6 +1598,9 @@ void Polyobj_InitLevel(void)
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->angle);
}
// [RH] Don't need the side lists anymore
FreeSideLists();
// move polyobjects to spawn points
for (i = 0; i < numAnchors; ++i)
{
@@ -1571,39 +1614,6 @@ void Polyobj_InitLevel(void)
Polyobj_linkToBlockmap(&PolyObjects[i]);
}
#if 0
// haleyjd 02/22/06: temporary debug
printf("DEBUG: numPolyObjects = %d\n", numPolyObjects);
for (i = 0; i < numPolyObjects; ++i)
{
INT32 j;
polyobj_t *po = &PolyObjects[i];
printf("polyobj %d:\n", i);
printf("id = %d, first = %d, next = %d\n", po->id, po->first, po->next);
printf("segCount = %d, numSegsAlloc = %d\n", po->segCount, po->numSegsAlloc);
for (j = 0; j < po->segCount; ++j)
printf("\tseg %d: %p\n", j, po->segs[j]);
printf("numVertices = %d, numVerticesAlloc = %d\n", po->numVertices, po->numVerticesAlloc);
for (j = 0; j < po->numVertices; ++j)
{
printf("\tvtx %d: (%d, %d) / orig: (%d, %d)\n",
j, po->vertices[j]->x>>FRACBITS, po->vertices[j]->y>>FRACBITS,
po->origVerts[j].x>>FRACBITS, po->origVerts[j].y>>FRACBITS);
}
printf("numLines = %d, numLinesAlloc = %d\n", po->numLines, po->numLinesAlloc);
for (j = 0; j < po->numLines; ++j)
printf("\tline %d: %p\n", j, po->lines[j]);
printf("spawnSpot = (%d, %d)\n", po->spawnSpot.x >> FRACBITS, po->spawnSpot.y >> FRACBITS);
printf("centerPt = (%d, %d)\n", po->centerPt.x >> FRACBITS, po->centerPt.y >> FRACBITS);
printf("attached = %d, linked = %d, validcount = %d, isBad = %d\n",
po->attached, po->linked, po->validcount, po->isBad);
printf("blockbox: [%d, %d, %d, %d]\n",
po->blockbox[BOXLEFT], po->blockbox[BOXRIGHT], po->blockbox[BOXBOTTOM],
po->blockbox[BOXTOP]);
}
#endif
// done with mobj queues
M_QueueFree(&spawnqueue);
M_QueueFree(&anchorqueue);
@@ -1789,12 +1799,12 @@ void T_PolyObjMove(polymove_t *th)
//
void T_PolyObjWaypoint(polywaypoint_t *th)
{
mobj_t *mo2;
mobj_t *target = NULL;
mobj_t *waypoint = NULL;
thinker_t *wp;
mobj_t *mo2;
fixed_t adjustx, adjusty, adjustz;
fixed_t momx, momy, momz, dist;
thinker_t *wp;
INT32 start;
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
polyobj_t *oldpo = po;
@@ -1811,7 +1821,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
if (!po->thinker)
po->thinker = &th->thinker;
// Find out target first.
@@ -1826,11 +1836,14 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence && mo2->health == th->pointnum)
{
target = mo2;
break;
}
if (mo2->threshold != th->sequence)
continue;
if (mo2->health != th->pointnum)
continue;
target = mo2;
break;
}
if (!target)
@@ -1896,37 +1909,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
{
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
// Find next waypoint
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence)
{
if (th->direction == -1)
{
if (mo2->health == target->health - 1)
{
waypoint = mo2;
break;
}
}
else
{
if (mo2->health == target->health + 1)
{
waypoint = mo2;
break;
}
}
}
}
waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false);
if (!waypoint && th->wrap) // If specified, wrap waypoints
{
@@ -1936,35 +1919,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
th->stophere = true;
}
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence)
{
if (th->direction == -1)
{
if (waypoint == NULL)
waypoint = mo2;
else if (mo2->health > waypoint->health)
waypoint = mo2;
}
else
{
if (mo2->health == 0)
{
waypoint = mo2;
break;
}
}
}
}
waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence);
}
else if (!waypoint && th->comeback) // Come back to the start
{
@@ -1973,36 +1928,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
if (!th->continuous)
th->comeback = false;
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence)
{
if (th->direction == -1)
{
if (mo2->health == target->health - 1)
{
waypoint = mo2;
break;
}
}
else
{
if (mo2->health == target->health + 1)
{
waypoint = mo2;
break;
}
}
}
}
waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false);
}
}
@@ -2452,11 +2378,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
polyobj_t *po;
polyobj_t *oldpo;
polywaypoint_t *th;
mobj_t *mo2;
mobj_t *first = NULL;
mobj_t *last = NULL;
mobj_t *target = NULL;
thinker_t *wp;
INT32 start;
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
@@ -2482,10 +2406,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
th->polyObjNum = pwdata->polyObjNum;
th->speed = pwdata->speed;
th->sequence = pwdata->sequence; // Used to specify sequence #
if (pwdata->reverse)
th->direction = -1;
else
th->direction = 1;
th->direction = pwdata->reverse ? -1 : 1;
th->comeback = pwdata->comeback;
th->continuous = pwdata->continuous;
@@ -2493,44 +2414,8 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
th->stophere = false;
// Find the first waypoint we need to use
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence)
{
if (th->direction == -1) // highest waypoint #
{
if (mo2->health == 0)
last = mo2;
else
{
if (first == NULL)
first = mo2;
else if (mo2->health > first->health)
first = mo2;
}
}
else // waypoint 0
{
if (mo2->health == 0)
first = mo2;
else
{
if (last == NULL)
last = mo2;
else if (mo2->health > last->health)
last = mo2;
}
}
}
}
first = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence);
last = (th->direction == -1) ? P_GetFirstWaypoint(th->sequence) : P_GetLastWaypoint(th->sequence);
if (!first)
{
@@ -2564,36 +2449,6 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// Find the actual target movement waypoint
target = first;
/*for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence)
{
if (th->direction == -1) // highest waypoint #
{
if (mo2->health == first->health - 1)
{
target = mo2;
break;
}
}
else // waypoint 0
{
if (mo2->health == first->health + 1)
{
target = mo2;
break;
}
}
}
}*/
if (!target)
{
+152 -118
View File
@@ -107,7 +107,7 @@ static inline void P_UnArchivePlayer(void)
//
// P_NetArchivePlayers
//
static void P_NetArchivePlayers(void)
static void P_NetArchivePlayers(boolean resending)
{
INT32 i, j;
UINT16 flags;
@@ -117,6 +117,9 @@ static void P_NetArchivePlayers(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (resending)
WRITESINT8(save_p, (SINT8)adminplayers[i]);
if (!playeringame[i])
continue;
@@ -124,6 +127,9 @@ static void P_NetArchivePlayers(void)
// no longer send ticcmds, player name, skin, or color
if (resending)
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
WRITEANGLE(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
@@ -148,6 +154,13 @@ static void P_NetArchivePlayers(void)
WRITEUINT16(save_p, players[i].flashpal);
WRITEUINT16(save_p, players[i].flashcount);
if (resending)
{
WRITEUINT8(save_p, players[i].skincolor);
WRITEINT32(save_p, players[i].skin);
}
WRITEUINT32(save_p, players[i].score);
WRITEFIXED(save_p, players[i].dashspeed);
WRITEINT32(save_p, players[i].dashtime);
@@ -285,7 +298,7 @@ static void P_NetArchivePlayers(void)
//
// P_NetUnArchivePlayers
//
static void P_NetUnArchivePlayers(void)
static void P_NetUnArchivePlayers(boolean resending)
{
INT32 i, j;
UINT16 flags;
@@ -295,6 +308,8 @@ static void P_NetUnArchivePlayers(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (resending)
adminplayers[i] = (INT32)READSINT8(save_p);
// Do NOT memset player struct to 0
// other areas may initialize data elsewhere
//memset(&players[i], 0, sizeof (player_t));
@@ -305,6 +320,9 @@ static void P_NetUnArchivePlayers(void)
// sending player names, skin and color should not be necessary at all!
// (that data is handled in the server config now)
if (resending)
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
players[i].aiming = READANGLE(save_p);
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
@@ -329,6 +347,12 @@ static void P_NetUnArchivePlayers(void)
players[i].flashpal = READUINT16(save_p);
players[i].flashcount = READUINT16(save_p);
if (resending)
{
players[i].skincolor = READUINT8(save_p);
players[i].skin = READINT32(save_p);
}
players[i].score = READUINT32(save_p);
players[i].dashspeed = READFIXED(save_p); // dashing speed
players[i].dashtime = READINT32(save_p); // dashing speed
@@ -499,35 +523,16 @@ static void P_NetArchiveWorld(void)
UINT8 *put;
// reload the map just to see difference
mapsector_t *ms;
mapsidedef_t *msd;
maplinedef_t *mld;
virtres_t* virt = vres_GetMap(lastloadedmaplumpnum);
mapsector_t *ms = (mapsector_t*) vres_Find(virt, "SECTORS")->data;
mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data;
maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data;
const sector_t *ss = sectors;
UINT8 diff, diff2;
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
put = save_p;
if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3
{ // HACK: Open wad file rather quickly so we can get the data from the relevant lumps
UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
#define retrieve_mapdata(d, f)\
d = Z_Malloc((f)->size, PU_CACHE, NULL); \
M_Memcpy(d, wadData + (f)->filepos, (f)->size)
retrieve_mapdata(ms, fileinfo + ML_SECTORS);
retrieve_mapdata(mld, fileinfo + ML_LINEDEFS);
retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS);
#undef retrieve_mapdata
Z_Free(wadData); // we're done with this now
}
else // phew it's just a WAD
{
ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE);
mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE);
msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE);
}
for (i = 0; i < numsectors; i++, ss++, ms++)
{
diff = diff2 = 0;
@@ -737,6 +742,7 @@ static void P_NetArchiveWorld(void)
WRITEUINT16(put, 0xffff);
R_ClearTextureNumCache(false);
vres_Free(virt);
save_p = put;
}
@@ -1874,7 +1880,7 @@ static void P_NetArchiveThinkers(void)
continue;
}
#ifdef PARANOIA
else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection
else if (th->function.acp1 != P_RemoveThinkerDelayed) // wait garbage collection
I_Error("unknown thinker type %p", th->function.acp1);
#endif
}
@@ -1899,8 +1905,11 @@ mobj_t *P_FindNewPosition(UINT32 oldposition)
continue;
mobj = (mobj_t *)th;
if (mobj->mobjnum == oldposition)
return mobj;
if (mobj->mobjnum != oldposition)
continue;
return mobj;
}
CONS_Debug(DBG_GAMELOGIC, "mobj not found\n");
return NULL;
@@ -2899,12 +2908,13 @@ static void P_NetUnArchiveThinkers(void)
for (currentthinker = thinkercap.next; currentthinker != &thinkercap;
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay)
{
delay = (void *)currentthinker;
if ((mobjnum = (UINT32)(size_t)delay->caller))
delay->caller = P_FindNewPosition(mobjnum);
}
if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
continue;
delay = (void *)currentthinker;
if ((mobjnum = (UINT32)(size_t)delay->caller))
delay->caller = P_FindNewPosition(mobjnum);
}
}
}
@@ -3013,11 +3023,11 @@ static inline void P_FinishMobjs(void)
for (currentthinker = thinkercap.next; currentthinker != &thinkercap;
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
{
mobj = (mobj_t *)currentthinker;
mobj->info = &mobjinfo[mobj->type];
}
if (currentthinker->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj = (mobj_t *)currentthinker;
mobj->info = &mobjinfo[mobj->type];
}
}
@@ -3031,69 +3041,69 @@ static void P_RelinkPointers(void)
for (currentthinker = thinkercap.next; currentthinker != &thinkercap;
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
if (currentthinker->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj = (mobj_t *)currentthinker;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
continue;
if (mobj->tracer)
{
mobj = (mobj_t *)currentthinker;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
continue;
if (mobj->tracer)
{
temp = (UINT32)(size_t)mobj->tracer;
mobj->tracer = NULL;
if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type);
}
if (mobj->target)
{
temp = (UINT32)(size_t)mobj->target;
mobj->target = NULL;
if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type);
}
if (mobj->hnext)
{
temp = (UINT32)(size_t)mobj->hnext;
mobj->hnext = NULL;
if (!P_SetTarget(&mobj->hnext, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type);
}
if (mobj->hprev)
{
temp = (UINT32)(size_t)mobj->hprev;
mobj->hprev = NULL;
if (!P_SetTarget(&mobj->hprev, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->capsule)
{
temp = (UINT32)(size_t)mobj->player->capsule;
mobj->player->capsule = NULL;
if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis1)
{
temp = (UINT32)(size_t)mobj->player->axis1;
mobj->player->axis1 = NULL;
if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis2)
{
temp = (UINT32)(size_t)mobj->player->axis2;
mobj->player->axis2 = NULL;
if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->awayviewmobj)
{
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
mobj->player->awayviewmobj = NULL;
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
}
temp = (UINT32)(size_t)mobj->tracer;
mobj->tracer = NULL;
if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type);
}
if (mobj->target)
{
temp = (UINT32)(size_t)mobj->target;
mobj->target = NULL;
if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type);
}
if (mobj->hnext)
{
temp = (UINT32)(size_t)mobj->hnext;
mobj->hnext = NULL;
if (!P_SetTarget(&mobj->hnext, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type);
}
if (mobj->hprev)
{
temp = (UINT32)(size_t)mobj->hprev;
mobj->hprev = NULL;
if (!P_SetTarget(&mobj->hprev, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->capsule)
{
temp = (UINT32)(size_t)mobj->player->capsule;
mobj->player->capsule = NULL;
if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis1)
{
temp = (UINT32)(size_t)mobj->player->axis1;
mobj->player->axis1 = NULL;
if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis2)
{
temp = (UINT32)(size_t)mobj->player->axis2;
mobj->player->axis2 = NULL;
if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->awayviewmobj)
{
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
mobj->player->awayviewmobj = NULL;
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
}
}
}
@@ -3242,19 +3252,25 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
playeringame[consoleplayer] = true;
}
static void P_NetArchiveMisc(void)
static void P_NetArchiveMisc(boolean resending)
{
UINT32 pig = 0;
INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
if (resending)
WRITEUINT32(save_p, gametic);
WRITEINT16(save_p, gamemap);
if (gamestate != GS_LEVEL)
WRITEINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers
else
WRITEINT16(save_p, gamestate);
if (resending)
WRITEINT16(save_p, gametype);
for (i = 0; i < MAXPLAYERS; i++)
pig |= (playeringame[i] != 0)<<i;
WRITEUINT32(save_p, pig);
@@ -3337,14 +3353,18 @@ static void P_NetArchiveMisc(void)
WRITEUINT8(save_p, 0x2e);
}
FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(void)
FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(boolean reloading)
{
UINT32 pig;
INT32 i;
UINT8 *old_save_p;
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
I_Error("Bad $$$.sav at archive block Misc");
if (reloading)
gametic = READUINT32(save_p);
gamemap = READINT16(save_p);
// gamemap changed; we assume that its map header is always valid,
@@ -3354,10 +3374,14 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(void)
// tell the sound code to reset the music since we're skipping what
// normally sets this flag
mapmusflags |= MUSIC_RELOADRESET;
if (!reloading)
mapmusflags |= MUSIC_RELOADRESET;
G_SetGamestate(READINT16(save_p));
if (reloading)
gametype = READINT16(save_p);
pig = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++)
{
@@ -3371,8 +3395,16 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(void)
encoremode = (boolean)READUINT8(save_p);
if (!P_SetupLevel(true))
// FIXME: save_p should not be global!!!
old_save_p = save_p;
if (!P_SetupLevel(true, reloading))
{
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
return false;
}
save_p = old_save_p;
// get the time
leveltime = READUINT32(save_p);
@@ -3455,31 +3487,33 @@ void P_SaveGame(void)
WRITEUINT8(save_p, 0x1d); // consistency marker
}
void P_SaveNetGame(void)
void P_SaveNetGame(boolean resending)
{
thinker_t *th;
mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p, false);
P_NetArchiveMisc();
P_NetArchiveMisc(resending);
// Assign the mobjnumber for pointer tracking
if (gamestate == GS_LEVEL)
{
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{
mobj = (mobj_t *)th;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
continue;
mobj->mobjnum = i++;
}
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj = (mobj_t *)th;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
continue;
mobj->mobjnum = i++;
}
}
P_NetArchivePlayers();
P_NetArchivePlayers(resending);
if (gamestate == GS_LEVEL)
{
P_NetArchiveWorld();
@@ -3514,12 +3548,12 @@ boolean P_LoadGame(INT16 mapoverride)
return true;
}
boolean P_LoadNetGame(void)
boolean P_LoadNetGame(boolean resending)
{
CV_LoadNetVars(&save_p);
if (!P_NetUnArchiveMisc())
if (!P_NetUnArchiveMisc(resending))
return false;
P_NetUnArchivePlayers();
P_NetUnArchivePlayers(resending);
if (gamestate == GS_LEVEL)
{
P_NetUnArchiveWorld();
+2 -2
View File
@@ -22,9 +22,9 @@
// These are the load / save game routines.
void P_SaveGame(void);
void P_SaveNetGame(void);
void P_SaveNetGame(boolean resending);
boolean P_LoadGame(INT16 mapoverride);
boolean P_LoadNetGame(void);
boolean P_LoadNetGame(boolean resending);
mobj_t *P_FindNewPosition(UINT32 oldposition);
+382 -733
View File
File diff suppressed because it is too large. Load diff
+6 -5
View File
@@ -17,6 +17,9 @@
#include "doomdata.h"
#include "doomstat.h"
#include "r_defs.h"
#include "w_wad.h"
extern SINT8 midgamejoin;
// map md5, sent to players via PT_SERVERINFO
extern unsigned char mapmd5[16];
@@ -30,6 +33,7 @@ extern boolean levelloading;
extern UINT8 levelfadecol;
extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame
extern virtres_t *curmapvirt;
//
// MAP used flats lookup table
//
@@ -55,11 +59,8 @@ extern size_t nummapthings;
extern mapthing_t *mapthings;
void P_SetupLevelSky(INT32 skynum, boolean global);
#ifdef SCANTHINGS
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif
void P_LoadThingsOnly(void);
boolean P_SetupLevel(boolean skipprecip);
boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate);
#ifdef HWRENDER
void HWR_LoadLevel(void);
#endif
@@ -87,11 +88,11 @@ SINT8 P_PartialAddGetStage(void);
boolean P_RunSOC(const char *socfilename);
void P_WriteThings(lumpnum_t lump);
void P_UpdateSegLightOffset(seg_t *li);
size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i);
// Needed for NiGHTS
void P_ReloadRings(void);
void P_DeleteGrades(INT16 i);
void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext);
UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
+60 -12
View File
@@ -27,11 +27,51 @@
static pslope_t *slopelist = NULL;
static UINT16 slopecount = 0;
// Calculate light
static void P_UpdateSlopeLightOffset(pslope_t *slope)
{
const boolean ceiling = (slope->normal.z < 0);
const UINT8 contrast = 8;
fixed_t contrastFixed = ((fixed_t)contrast) * FRACUNIT;
fixed_t zMul = FRACUNIT;
angle_t slopeDir = ANGLE_MAX;
fixed_t extralight = 0;
if (slope->normal.z == 0)
{
slope->lightOffset = 0;
#ifdef HWRENDER
slope->hwLightOffset = 0;
#endif
return;
}
slopeDir = R_PointToAngle2(0, 0, abs(slope->normal.y), abs(slope->normal.x));
if (ceiling == true)
{
slopeDir ^= ANGLE_180;
}
zMul = min(FRACUNIT, abs(slope->zdelta)*3/2); // *3/2, to make 60 degree slopes match walls.
contrastFixed = FixedMul(contrastFixed, zMul);
extralight = -contrastFixed + FixedMul(FixedDiv(AngleFixed(slopeDir), ANGLE_90), (contrastFixed * 2));
// Between -2 and 2 for software, -8 and 8 for hardware
slope->lightOffset = FixedFloor((extralight / 8) + (FRACUNIT / 2)) / FRACUNIT;
#ifdef HWRENDER
slope->hwLightOffset = FixedFloor(extralight + (FRACUNIT / 2)) / FRACUNIT;
#endif
}
// Calculate line normal
void P_CalculateSlopeNormal(pslope_t *slope) {
void P_CalculateSlopeNormal(pslope_t *slope)
{
slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT);
slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), -slope->d.x);
slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), -slope->d.y);
P_UpdateSlopeLightOffset(slope);
}
// With a vertex slope that has its vertices set, configure relevant slope info
@@ -89,18 +129,24 @@ static void P_ReconfigureVertexSlope(pslope_t *slope)
slope->real_xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
slope->real_zangle = InvAngle(R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta));
if (slope->normal.x == 0 && slope->normal.y == 0) { // Set some defaults for a non-sloped "slope"
if (slope->normal.x == 0 && slope->normal.y == 0) // Set some defaults for a non-sloped "slope"
{
slope->zangle = slope->xydirection = 0;
slope->zdelta = slope->d.x = slope->d.y = 0;
} else {
}
else
{
slope->extent = extent;
slope->xydirection = slope->real_xydirection;
slope->zangle = slope->real_zangle;
}
P_UpdateSlopeLightOffset(slope);
}
// Recalculate dynamic slopes
void P_RunDynamicSlopes(void) {
void P_RunDynamicSlopes(void)
{
pslope_t *slope;
for (slope = slopelist; slope; slope = slope->next) {
@@ -284,7 +330,7 @@ void P_SpawnSlope_Line(int linenum)
origin.y = line->v1->y + (line->v2->y - line->v1->y)/2;
// For FOF slopes, make a special function to copy to the xy origin & direction relative to the position of the FOF on the map!
if(frontfloor || frontceil)
if (frontfloor || frontceil)
{
line->frontsector->hasslope = true; // Tell the software renderer that we're sloped
@@ -308,7 +354,7 @@ void P_SpawnSlope_Line(int linenum)
// TODO: We take origin and point 's xy values and translate them to the center of an FOF!
if(frontfloor)
if (frontfloor)
{
fixed_t highest, lowest;
size_t l;
@@ -369,7 +415,8 @@ void P_SpawnSlope_Line(int linenum)
P_CalculateSlopeNormal(fslope);
}
if(frontceil)
if (frontceil)
{
fixed_t highest, lowest;
size_t l;
@@ -416,7 +463,7 @@ void P_SpawnSlope_Line(int linenum)
P_CalculateSlopeNormal(cslope);
}
}
if(backfloor || backceil)
if (backfloor || backceil)
{
line->backsector->hasslope = true; // Tell the software renderer that we're sloped
@@ -439,7 +486,7 @@ void P_SpawnSlope_Line(int linenum)
direction.x = -direction.x;
direction.y = -direction.y;
if(backfloor)
if (backfloor)
{
fixed_t highest, lowest;
size_t l;
@@ -484,7 +531,7 @@ void P_SpawnSlope_Line(int linenum)
P_CalculateSlopeNormal(fslope);
}
if(backceil)
if (backceil)
{
fixed_t highest, lowest;
size_t l;
@@ -634,7 +681,8 @@ pslope_t *P_SlopeById(UINT16 id)
}
// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes
void P_ResetDynamicSlopes(void) {
void P_ResetDynamicSlopes(void)
{
size_t i;
slopelist = NULL;
@@ -934,4 +982,4 @@ void P_ButteredSlope(mobj_t *mo)
P_Thrust(mo, mo->standingslope->xydirection, thrust);
}
// EOF
// EOF
+75 -577
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -32,7 +32,7 @@ void P_InitPicAnims(void);
void P_SetupLevelFlatAnims(void);
// at map load
void P_SpawnSpecials(INT32 fromnetsave);
void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate);
// every tic
void P_UpdateSpecials(void);
+10 -9
View File
@@ -84,10 +84,11 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
{
if (thing->player != &players[displayplayers[i]])
continue;
if (camera[i].chase)
P_ResetCamera(thing->player, &camera[i]);
R_ResetViewInterpolation(i + 1);
break;
}
// don't run in place after a teleport
@@ -157,14 +158,14 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
// move chasecam at new player location
for (i = 0; i <= splitscreen; i++)
{
if (thing->player == &players[displayplayers[i]])
{
localangle[i] = angle;
if (camera[i].chase)
P_ResetCamera(thing->player, &camera[i]);
R_ResetViewInterpolation(i + 1);
break;
}
if (thing->player != &players[displayplayers[i]])
continue;
localangle[i] = angle;
if (camera[i].chase)
P_ResetCamera(thing->player, &camera[i]);
R_ResetViewInterpolation(i + 1);
}
// don't run in place after a teleport
+102 -278
View File
@@ -18,10 +18,12 @@
#include "z_zone.h"
#include "s_sound.h"
#include "st_stuff.h"
#include "p_setup.h"
#include "p_polyobj.h"
#include "m_random.h"
#include "lua_script.h"
#include "lua_hook.h"
#include "k_director.h"
#include "k_kart.h"
#include "i_system.h"
#include "r_main.h"
@@ -32,6 +34,9 @@
// Object place
#include "m_cheat.h"
// Dynamic slopes
#include "p_slopes.h"
tic_t leveltime;
//
@@ -63,8 +68,6 @@ void Command_Numthinkers_f(void)
CONS_Printf(M_GetText("numthinkers <#>: Count number of thinkers\n"));
CONS_Printf(
"\t1: P_MobjThinker\n"
/*"\t2: P_RainThinker\n"
"\t3: P_SnowThinker\n"*/
"\t2: P_NullPrecipThinker\n"
"\t3: T_Friction\n"
"\t4: T_Pusher\n"
@@ -80,14 +83,6 @@ void Command_Numthinkers_f(void)
action = (actionf_p1)P_MobjThinker;
CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker");
break;
/*case 2:
action = (actionf_p1)P_RainThinker;
CONS_Printf(M_GetText("Number of %s: "), "P_RainThinker");
break;
case 3:
action = (actionf_p1)P_SnowThinker;
CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker");
break;*/
case 2:
action = (actionf_p1)P_NullPrecipThinker;
CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker");
@@ -221,23 +216,41 @@ static thinker_t *currentthinker;
// remove it, and set currentthinker to one node preceeding it, so
// that the next step in P_RunThinkers() will get its successor.
//
void P_RemoveThinkerDelayed(void *pthinker)
void P_RemoveThinkerDelayed(thinker_t *thinker)
{
thinker_t *thinker = pthinker;
if (!thinker->references)
{
{
/* Remove from main thinker list */
thinker_t *next = thinker->next;
/* Note that currentthinker is guaranteed to point to us,
* and since we're freeing our memory, we had better change that. So
* point it to thinker->prev, so the iterator will correctly move on to
* thinker->prev->next = thinker->next */
(next->prev = currentthinker = thinker->prev)->next = next;
}
R_DestroyLevelInterpolators(thinker);
Z_Free(thinker);
}
#ifdef PARANOIA
if (thinker->next)
thinker->next = NULL;
else if (thinker->references) // Usually gets cleared up in one frame; what's going on here, then?
CONS_Printf("Number of potentially faulty references: %d\n", thinker->references);
#endif
if (thinker->references)
return;
/* Remove from main thinker list */
thinker_t *next = thinker->next;
/* Note that currentthinker is guaranteed to point to us,
* and since we're freeing our memory, we had better change that. So
* point it to thinker->prev, so the iterator will correctly move on to
* thinker->prev->next = thinker->next */
(next->prev = currentthinker = thinker->prev)->next = next;
R_DestroyLevelInterpolators(thinker);
Z_Free(thinker);
}
//
// P_UnlinkThinker()
//
// Actually removes thinker from the list and frees its memory.
//
void P_UnlinkThinker(thinker_t *thinker)
{
thinker_t *next = thinker->next;
I_Assert(thinker->references == 0);
(next->prev = thinker->prev)->next = next;
Z_Free(thinker);
}
//
@@ -255,7 +268,7 @@ void P_RemoveThinkerDelayed(void *pthinker)
void P_RemoveThinker(thinker_t *thinker)
{
LUA_InvalidateUserdata(thinker);
thinker->function.acp1 = P_RemoveThinkerDelayed;
thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
}
/*
@@ -310,265 +323,76 @@ static inline void P_RunThinkers(void)
}
}
//
// P_DoAutobalanceTeams()
//
// Determine if the teams are unbalanced, and if so, move a player to the other team.
//
/*static void P_DoAutobalanceTeams(void)
static inline void P_DeviceRumbleTick(void)
{
changeteam_union NetPacket;
UINT16 usvalue;
INT32 i=0;
INT32 red=0, blue=0;
INT32 redarray[MAXPLAYERS], bluearray[MAXPLAYERS];
INT32 redflagcarrier = 0, blueflagcarrier = 0;
INT32 totalred = 0, totalblue = 0;
UINT8 i;
NetPacket.value.l = NetPacket.value.b = 0;
memset(redarray, 0, sizeof(redarray));
memset(bluearray, 0, sizeof(bluearray));
// Only do it if we have enough room in the net buffer to send it.
// Otherwise, come back next time and try again.
if (sizeof(usvalue) > GetFreeXCmdSize())
if (I_NumJoys() == 0 || (cv_rumble[0].value == 0 && cv_rumble[1].value == 0 && cv_rumble[2].value == 0 && cv_rumble[3].value == 0))
{
return;
//We have to store the players in an array with the rest of their team.
//We can then pick a random player to be forced to change teams.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].ctfteam)
{
if (players[i].ctfteam == 1)
{
if (!players[i].gotflag)
{
redarray[red] = i; //store the player's node.
red++;
}
else
redflagcarrier++;
}
else
{
if (!players[i].gotflag)
{
bluearray[blue] = i; //store the player's node.
blue++;
}
else
blueflagcarrier++;
}
}
}
totalred = red + redflagcarrier;
totalblue = blue + blueflagcarrier;
if ((abs(totalred - totalblue) > cv_autobalance.value))
for (i = 0; i <= splitscreen; i++)
{
if (totalred > totalblue)
{
i = M_RandomKey(red);
NetPacket.packet.newteam = 2;
NetPacket.packet.playernum = redarray[i];
NetPacket.packet.verification = true;
NetPacket.packet.autobalance = true;
player_t *player = &players[displayplayers[i]];
UINT16 low = 0;
UINT16 high = 0;
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
}
if (totalblue > totalred)
{
i = M_RandomKey(blue);
NetPacket.packet.newteam = 1;
NetPacket.packet.playernum = bluearray[i];
NetPacket.packet.verification = true;
NetPacket.packet.autobalance = true;
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
}
}
}
//
// P_DoTeamscrambling()
//
// If a team scramble has been started, scramble one person from the
// pre-made scramble array. Said array is created in TeamScramble_OnChange()
//
void P_DoTeamscrambling(void)
{
changeteam_union NetPacket;
UINT16 usvalue;
NetPacket.value.l = NetPacket.value.b = 0;
// Only do it if we have enough room in the net buffer to send it.
// Otherwise, come back next time and try again.
if (sizeof(usvalue) > GetFreeXCmdSize())
return;
if (scramblecount < scrambletotal)
{
if (players[scrambleplayers[scramblecount]].ctfteam != scrambleteams[scramblecount])
{
NetPacket.packet.newteam = scrambleteams[scramblecount];
NetPacket.packet.playernum = scrambleplayers[scramblecount];
NetPacket.packet.verification = true;
NetPacket.packet.scrambled = true;
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
}
scramblecount++; //Increment, and get to the next player when we come back here next time.
}
else
CV_SetValue(&cv_teamscramble, 0);
}
static inline void P_DoSpecialStageStuff(void)
{
boolean inwater = false;
INT32 i;
// Can't drown in a special stage
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
if (!P_IsLocalPlayer(player))
continue;
players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0;
}
if (G_GetDeviceForPlayer(i) == 0)
continue;
if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC))
S_SpeedMusic(1.4f);
if (!playeringame[displayplayers[i]] || player->spectator)
continue;
if (sstimer < 7 && sstimer > 0) // The special stage time is up!
{
sstimer = 0;
for (i = 0; i < MAXPLAYERS; i++)
if (player->mo == NULL)
continue;
if (player->exiting)
{
if (playeringame[i])
{
players[i].exiting = raceexittime+1;
players[i].pflags &= ~PF_GLIDING;
}
if (i == consoleplayer)
S_StartSound(NULL, sfx_lose);
G_PlayerDeviceRumble(i, low, high, 0);
continue;
}
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
S_SpeedMusic(1.0f);
stagefailed = true;
}
if (sstimer > 1) // As long as time isn't up...
{
UINT32 ssrings = 0;
// Count up the rings of all the players and see if
// they've collected the required amount.
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
ssrings += (players[i].mo->health-1);
// If in water, deplete timer 6x as fast.
if ((players[i].mo->eflags & MFE_TOUCHWATER)
|| (players[i].mo->eflags & MFE_UNDERWATER))
inwater = true;
}
if (ssrings >= totalrings && totalrings > 0)
if (player->kartstuff[k_spinouttimer])
{
// Halt all the players
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
players[i].mo->momx = players[i].mo->momy = 0;
players[i].exiting = raceexittime+1;
}
sstimer = 0;
P_GiveEmerald(true);
low = high = 65536 / 4;
}
else if (player->kartstuff[k_sneakertimer] > (sneakertime-(TICRATE/2)))
{
low = high = 65536 / 8;
}
else if ((player->kartstuff[k_offroad] && !player->kartstuff[k_hyudorotimer])
&& P_IsObjectOnGround(player->mo) && player->speed != 0)
{
low = high = 65536 / 64;
}
else if (player->kartstuff[k_brakedrift])
{
low = 0;
high = 65536 / 256;
}
// Decrement the timer
if (!objectplacing)
{
if (inwater)
sstimer -= 6;
else
sstimer--;
}
if (low == 0 && high == 0)
continue;
G_PlayerDeviceRumble(i, low, high, 57); // hack alert! i just dont want this think constantly resetting the rumble lol
}
}
static inline void P_DoTagStuff(void)
void P_RunChaseCameras(void)
{
INT32 i;
UINT8 i;
// tell the netgame who the initial IT person is.
if (leveltime == TICRATE)
for (i = 0; i <= splitscreen; i++)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (players[i].pflags & PF_TAGIT)
{
CONS_Printf(M_GetText("%s is now IT!\n"), player_names[i]); // Tell everyone who is it!
break;
}
}
}
//increment survivor scores
if (leveltime % TICRATE == 0 && leveltime > (hidetime * TICRATE))
{
INT32 participants = 0;
for (i=0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
participants++;
}
for (i=0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator && players[i].playerstate == PST_LIVE
&& !(players[i].pflags & (PF_TAGIT|PF_TAGGED)))
//points given is the number of participating players divided by two.
P_AddPlayerScore(&players[i], participants/2);
}
if (camera[i].chase)
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
}
}
static inline void P_DoCTFStuff(void)
{
// Automatic team balance for CTF and team match
if (leveltime % (TICRATE * 5) == 0) //only check once per five seconds for the sake of CPU conservation.
{
// Do not attempt to autobalance and scramble teams at the same time.
// Only the server should execute this. No verified admins, please.
if ((cv_autobalance.value && !cv_teamscramble.value) && cv_allowteamchange.value && server)
P_DoAutobalanceTeams();
}
// Team scramble code for team match and CTF.
if ((leveltime % (TICRATE/7)) == 0)
{
// If we run out of time in the level, the beauty is that
// the Y_Ticker() team scramble code will pick it up.
if (cv_teamscramble.value && server)
P_DoTeamscrambling();
}
}*/
//
// P_Ticker
//
@@ -581,13 +405,6 @@ void P_Ticker(boolean run)
if (playeringame[i])
++players[i].jointime;
if (run)
{
// Update old view state BEFORE ticking so resetting
// the old interpolation state from game logic works.
R_UpdateViewInterpolation();
}
if (objectplacing)
{
if (OP_FreezeObjectplace())
@@ -683,6 +500,10 @@ void P_Ticker(boolean run)
if (run)
{
// Dynamic slopeness
if (midgamejoin) // only run here if we joined midgame to fix some desynchs
P_RunDynamicSlopes();
PS_START_TIMING(ps_thinkertime);
P_RunThinkers();
PS_STOP_TIMING(ps_thinkertime);
@@ -692,6 +513,12 @@ void P_Ticker(boolean run)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
// Apply rumble to local players
if (!demo.playback)
{
P_DeviceRumbleTick();
}
PS_START_TIMING(ps_lua_thinkframe_time);
LUAh_ThinkFrame();
PS_STOP_TIMING(ps_lua_thinkframe_time);
@@ -716,12 +543,6 @@ void P_Ticker(boolean run)
if (!(modeattacking && !demo.playback) || leveltime >= starttime - TICRATE*4)
timeinmap++;
/*if (G_TagGametype())
P_DoTagStuff();
if (G_GametypeHasTeams())
P_DoCTFStuff();*/
if (run)
{
if (countdowntimer && --countdowntimer <= 0)
@@ -824,16 +645,15 @@ void P_Ticker(boolean run)
PS_STOP_TIMING(ps_lua_postthinkframe_time);
}
K_UpdateDirector();
// Always move the camera.
for (i = 0; i <= splitscreen; i++)
{
if (camera[i].chase)
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
}
P_RunChaseCameras();
if (run)
{
R_UpdateLevelInterpolators();
R_UpdateViewInterpolation();
// Hack: ensure newview is assigned every tic.
// Ensures view interpolation is T-1 to T in poor network conditions
@@ -898,6 +718,10 @@ void P_PreTicker(INT32 frames)
memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t));
}
// Dynamic slopeness
if (midgamejoin)
P_RunDynamicSlopes();
P_RunThinkers();
// Run any "after all the other thinkers" stuff
+2 -1
View File
@@ -24,10 +24,11 @@ extern tic_t leveltime;
void Command_Numthinkers_f(void);
void Command_CountMobjs_f(void);
void P_RunChaseCameras(void);
void P_Ticker(boolean run);
void P_PreTicker(INT32 frames);
void P_DoTeamscrambling(void);
void P_RemoveThinkerDelayed(void *pthinker); //killed
void P_RemoveThinkerDelayed(thinker_t *thinker);
mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
#endif
Loaded 100 of 136 files, more files were not shown because too many files have changed in this diff. Show more