mirror of
https://github.com/yquake2/ctf.git
synced 2025-04-20 17:43:18 +00:00
Compare commits
63 commits
Author | SHA1 | Date | |
---|---|---|---|
|
3a1863f625 | ||
|
c7a4b27bf6 | ||
|
8878216828 | ||
|
dcc5a1f616 | ||
|
869b18c329 | ||
|
0a7e3c9c78 | ||
|
693e82ffa4 | ||
|
b9cac9410e | ||
|
787de54da5 | ||
|
6a2d5125f6 | ||
|
b8a45290a2 | ||
|
38cc7813dd | ||
|
a5f933ba03 | ||
|
95852c466c | ||
|
4bbda4cd98 | ||
|
48c30c68a3 | ||
|
c99c53d4b6 | ||
|
554590fca9 | ||
|
ab58bc5a37 | ||
|
606a52ddf4 | ||
|
7932c76d16 | ||
|
55b80715ac | ||
|
2e2e1945e8 | ||
|
5e4fc5a0ed | ||
|
72b78e39ca | ||
|
ff3a920d20 | ||
|
5f7038c407 | ||
|
928066d37d | ||
|
f31b3264d5 | ||
|
23d0f705c6 | ||
|
26019096ee | ||
|
1531bcebb7 | ||
|
fad0152c6b | ||
|
8e92749a8b | ||
|
16198d78be | ||
|
befa16b12f | ||
|
71574de589 | ||
|
2ffb440a66 | ||
|
d209850ef7 | ||
|
cf0471a367 | ||
|
8c58273867 | ||
|
4f8b49daf3 | ||
|
821872c798 | ||
|
15a25d8daa | ||
|
0e35097cd0 | ||
|
d7457925db | ||
|
c13036df55 | ||
|
08a9c4fdc1 | ||
|
1e37bf132d | ||
|
2d6dd4117d | ||
|
b67a392cb6 | ||
|
f5449a9185 | ||
|
3e82fe1ef2 | ||
|
097dd56e35 | ||
|
ca0e44b2a4 | ||
|
5447354a76 | ||
|
6f1b2f101f | ||
|
327cea19f5 | ||
|
df29a29633 | ||
|
b475a527c9 | ||
|
eadb063611 | ||
|
d8d33d4353 | ||
|
b71b80d790 |
26 changed files with 707 additions and 170 deletions
45
.github/workflows/linux_aarch64.yml
vendored
Normal file
45
.github/workflows/linux_aarch64.yml
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
name: Testbuild for Linux (aarch64)
|
||||
run-name: testbuild_linux_aarch64
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_ubuntu_aarch64:
|
||||
runs-on: ubuntu-22.04-arm
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- env: ubuntu
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
- name: Create testbuild package
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-ctf-linux_aarch64-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-ctf-linux_aarch64-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp LICENSE publish/quake2-ctf-linux_aarch64-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-ctf-linux_aarch64-${{github.sha}}/misc/docs/README.txt
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-ctf-linux_aarch64-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
45
.github/workflows/linux_x86_64.yml
vendored
Normal file
45
.github/workflows/linux_x86_64.yml
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
name: Testbuild for Linux (x86_64)
|
||||
run-name: testbuild_linux_x86_64
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_ubuntu_x86_64:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- env: ubuntu
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
- name: Create testbuild package
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-ctf-linux_x86_64-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-ctf-linux_x86_64-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp LICENSE publish/quake2-ctf-linux_x86_64-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-ctf-linux_x86_64-${{github.sha}}/misc/docs/README.txt
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-ctf-linux_x86_64-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
49
.github/workflows/macos.yml
vendored
Normal file
49
.github/workflows/macos.yml
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
name: Testbuild for MacOS
|
||||
run-name: testbuild_macos
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_macos_aarch64:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- env: macos
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
brew update
|
||||
brew install make
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
# Public runners come with 3 CPUs.
|
||||
gmake -j3
|
||||
- name: Create testbuild package
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-ctf-macos-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-ctf-macos-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp LICENSE publish/quake2-ctf-macos-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-ctf-macos-${{github.sha}}/misc/docs/README.txt
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-ctf-macos-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
56
.github/workflows/win32.yml
vendored
Normal file
56
.github/workflows/win32.yml
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
name: Testbuild for Win32
|
||||
run-name: testbuild_win32
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_mingw_x86_32:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { sys: mingw32, env: i686 }
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{matrix.sys}}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
make
|
||||
mingw-w64-${{matrix.env}}-gcc
|
||||
mingw-w64-${{matrix.env}}-make
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
- name: Create testbuild package
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-ctf-win32-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-ctf-win32-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp LICENSE publish/quake2-ctf-win32-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-ctf-win32-${{github.sha}}/misc/docs/README.txt
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-ctf-win32-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
56
.github/workflows/win64.yml
vendored
Normal file
56
.github/workflows/win64.yml
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
name: Testbuild for Win64
|
||||
run-name: testbuild_win64
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_mingw_x86_64:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { sys: mingw64, env: x86_64 }
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{matrix.sys}}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
make
|
||||
mingw-w64-${{matrix.env}}-gcc
|
||||
mingw-w64-${{matrix.env}}-make
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
- name: Create testbuild package
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-ctf-win64-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-ctf-win64-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp LICENSE publish/quake2-ctf-win64-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-ctf-win64-${{github.sha}}/misc/docs/README.txt
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-ctf-win64-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
build/
|
||||
release/
|
23
CHANGELOG
23
CHANGELOG
|
@ -1,3 +1,26 @@
|
|||
Three Wave Capture The Flag 1.10 to 1.11
|
||||
- Fix build in C23 mode.
|
||||
|
||||
Three Wave Capture The Flag 1.09 to 1.10
|
||||
- Fix build on ARM Macs.
|
||||
|
||||
Three Wave Capture The Flag 1.08 to 1.09
|
||||
- Several small bugfixes.
|
||||
|
||||
Three Wave Capture The Flag 1.07 to 1.08
|
||||
- Several small bugfixes.
|
||||
|
||||
Three Wave Capture The Flag 1.06 to 1.07
|
||||
- Several small bugfixes.
|
||||
|
||||
Three Wave Capture The Flag 1.05 to 1.06
|
||||
- Small bugfixes.
|
||||
- Better compatibility with the current Windows build environment.
|
||||
|
||||
Three Wave Capture The Flag 1.04 to 1.05
|
||||
- Some bugfixes to monster AI, mostly to keep the source
|
||||
in sync with baseq2 and the other addons.
|
||||
|
||||
Three Wave Capture The Flag 1.03 to 1.04
|
||||
- Fix CMake support
|
||||
- Make gibs and debris SOLID_BBOX so they move on entities.
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
# Print a message that using the Makefiles is recommended.
|
||||
message(NOTICE: " The CMakeLists.txt is unmaintained. Use the Makefile if possible.")
|
||||
|
||||
# Enforce "Debug" as standard build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||
|
|
203
Makefile
Normal file → Executable file
203
Makefile
Normal file → Executable file
|
@ -6,64 +6,161 @@
|
|||
# #
|
||||
# Dependencies: #
|
||||
# - None, but you need a Quake II to play. #
|
||||
# While in theorie every one should work #
|
||||
# Yamagi Quake II ist recommended. #
|
||||
# While in theory every one should work #
|
||||
# Yamagi Quake II is recommended. #
|
||||
# #
|
||||
# Platforms: #
|
||||
# - FreeBSD #
|
||||
# - Linux #
|
||||
# - Mac OS X #
|
||||
# - OpenBSD #
|
||||
# - Windows #
|
||||
# - Windows #
|
||||
# ----------------------------------------------------- #
|
||||
|
||||
# Detect the OS
|
||||
ifdef SystemRoot
|
||||
OSTYPE := Windows
|
||||
YQ2_OSTYPE ?= Windows
|
||||
else
|
||||
OSTYPE := $(shell uname -s)
|
||||
YQ2_OSTYPE ?= $(shell uname -s)
|
||||
endif
|
||||
|
||||
|
||||
# Special case for MinGW
|
||||
ifneq (,$(findstring MINGW,$(OSTYPE)))
|
||||
OSTYPE := Windows
|
||||
ifneq (,$(findstring MINGW,$(YQ2_OSTYPE)))
|
||||
YQ2_OSTYPE := Windows
|
||||
endif
|
||||
|
||||
# Detect the architecture
|
||||
ifeq ($(YQ2_OSTYPE), Windows)
|
||||
ifdef MINGW_CHOST
|
||||
ifeq ($(MINGW_CHOST), x86_64-w64-mingw32)
|
||||
YQ2_ARCH ?= x86_64
|
||||
else # i686-w64-mingw32
|
||||
YQ2_ARCH ?= i386
|
||||
endif
|
||||
else # windows, but MINGW_CHOST not defined
|
||||
ifdef PROCESSOR_ARCHITEW6432
|
||||
# 64 bit Windows
|
||||
YQ2_ARCH ?= $(PROCESSOR_ARCHITEW6432)
|
||||
else
|
||||
# 32 bit Windows
|
||||
YQ2_ARCH ?= $(PROCESSOR_ARCHITECTURE)
|
||||
endif
|
||||
endif # windows but MINGW_CHOST not defined
|
||||
else
|
||||
ifneq ($(YQ2_OSTYPE), Darwin)
|
||||
# Normalize some abiguous YQ2_ARCH strings
|
||||
YQ2_ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' -e 's/amd64/x86_64/' -e 's/arm64/aarch64/' -e 's/^arm.*/arm/')
|
||||
else
|
||||
YQ2_ARCH ?= $(shell uname -m)
|
||||
endif
|
||||
endif
|
||||
|
||||
# On Windows / MinGW $(CC) is undefined by default.
|
||||
ifeq ($(YQ2_OSTYPE),Windows)
|
||||
CC ?= gcc
|
||||
endif
|
||||
|
||||
# Detect the compiler
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||
COMPILER := clang
|
||||
COMPILERVER := $(shell $(CC) -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
|
||||
else ifeq ($(shell $(CC) -v 2>&1 | grep -c -E "(gcc version|gcc-Version)"), 1)
|
||||
COMPILER := gcc
|
||||
COMPILERVER := $(shell $(CC) -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
|
||||
else
|
||||
COMPILER := unknown
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
# Base CFLAGS.
|
||||
#
|
||||
# -O2 are enough optimizations.
|
||||
#
|
||||
# -fno-strict-aliasing since the source doesn't comply
|
||||
# with strict aliasing rules and it's next to impossible
|
||||
# to get it there...
|
||||
#
|
||||
# -fomit-frame-pointer since the framepointer is mostly
|
||||
# useless for debugging Quake II and slows things down.
|
||||
#
|
||||
# -g to build allways with debug symbols. Please do not
|
||||
# change this, since it's our only chance to debug this
|
||||
# crap when random crashes happen!
|
||||
#
|
||||
# -fPIC for position independend code.
|
||||
#
|
||||
# -MMD to generate header dependencies.
|
||||
ifeq ($(OSTYPE), Darwin)
|
||||
CFLAGS := -O2 -fno-strict-aliasing -fomit-frame-pointer \
|
||||
-Wall -pipe -g -fwrapv -arch i386 -arch x86_64
|
||||
# Base CFLAGS. These may be overridden by the environment.
|
||||
# Highest supported optimizations are -O2, higher levels
|
||||
# will likely break this crappy code.
|
||||
ifdef DEBUG
|
||||
CFLAGS ?= -O0 -g -Wall -pipe
|
||||
else
|
||||
CFLAGS := -O2 -fno-strict-aliasing -fomit-frame-pointer \
|
||||
-Wall -pipe -g -MMD -fwrapv
|
||||
CFLAGS ?= -O2 -Wall -pipe -fomit-frame-pointer
|
||||
endif
|
||||
|
||||
# Always needed are:
|
||||
# -fno-strict-aliasing since the source doesn't comply
|
||||
# with strict aliasing rules and it's next to impossible
|
||||
# to get it there...
|
||||
# -fwrapv for defined integer wrapping. MSVC6 did this
|
||||
# and the game code requires it.
|
||||
override CFLAGS += -fno-strict-aliasing -fwrapv
|
||||
|
||||
# -MMD to generate header dependencies. Unsupported by
|
||||
# the Clang shipped with OS X.
|
||||
ifneq ($(YQ2_OSTYPE), Darwin)
|
||||
override CFLAGS += -MMD
|
||||
endif
|
||||
|
||||
# OS X architecture.
|
||||
ifeq ($(YQ2_OSTYPE), Darwin)
|
||||
override CFLAGS += -arch $(YQ2_ARCH)
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
# Switch off some annoying warnings.
|
||||
ifeq ($(COMPILER), clang)
|
||||
# -Wno-missing-braces because otherwise clang complains
|
||||
# about totally valid 'vec3_t bla = {0}' constructs.
|
||||
CFLAGS += -Wno-missing-braces
|
||||
else ifeq ($(COMPILER), gcc)
|
||||
# GCC 8.0 or higher.
|
||||
ifeq ($(shell test $(COMPILERVER) -ge 80000; echo $$?),0)
|
||||
# -Wno-format-truncation and -Wno-format-overflow
|
||||
# because GCC spams about 50 false positives.
|
||||
CFLAGS += -Wno-format-truncation -Wno-format-overflow
|
||||
endif
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
# Defines the operating system and architecture
|
||||
override CFLAGS += -DYQ2OSTYPE=\"$(YQ2_OSTYPE)\" -DYQ2ARCH=\"$(YQ2_ARCH)\"
|
||||
|
||||
# ----------
|
||||
|
||||
# For reproducible builds, look here for details:
|
||||
# https://reproducible-builds.org/specs/source-date-epoch/
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
CFLAGS += -DBUILD_DATE=\"$(shell date --utc --date="@${SOURCE_DATE_EPOCH}" +"%b %_d %Y" | sed -e 's/ /\\ /g')\"
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
# Using the default x87 float math on 32bit x86 causes rounding trouble
|
||||
# -ffloat-store could work around that, but the better solution is to
|
||||
# just enforce SSE - every x86 CPU since Pentium3 supports that
|
||||
# and this should even improve the performance on old CPUs
|
||||
ifeq ($(YQ2_ARCH), i386)
|
||||
override CFLAGS += -msse -mfpmath=sse
|
||||
endif
|
||||
|
||||
# Force SSE math on x86_64. All sane compilers should do this
|
||||
# anyway, just to protect us from broken Linux distros.
|
||||
ifeq ($(YQ2_ARCH), x86_64)
|
||||
override CFLAGS += -mfpmath=sse
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
# Base LDFLAGS.
|
||||
ifeq ($(OSTYPE), Darwin)
|
||||
LDFLAGS := -shared -arch i386 -arch x86_64
|
||||
LDFLAGS ?=
|
||||
|
||||
# It's a shared library.
|
||||
override LDFLAGS += -shared
|
||||
|
||||
# Required libraries
|
||||
ifeq ($(YQ2_OSTYPE), Darwin)
|
||||
override LDFLAGS += -arch $(YQ2_ARCH)
|
||||
else ifeq ($(YQ2_OSTYPE), Windows)
|
||||
override LDFLAGS += -static-libgcc
|
||||
else
|
||||
LDFLAGS := -shared
|
||||
override LDFLAGS += -lm
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
@ -72,7 +169,7 @@ endif
|
|||
all: ctf
|
||||
|
||||
# ----------
|
||||
|
||||
|
||||
# When make is invoked by "make VERBOSE=1" print
|
||||
# the compiler and linker commands.
|
||||
|
||||
|
@ -88,39 +185,39 @@ endif
|
|||
.PHONY : all clean ctf
|
||||
|
||||
# ----------
|
||||
|
||||
|
||||
# Cleanup
|
||||
clean:
|
||||
@echo "===> CLEAN"
|
||||
${Q}rm -Rf build release
|
||||
|
||||
|
||||
# ----------
|
||||
|
||||
# The ctf game
|
||||
ifeq ($(OSTYPE), Windows)
|
||||
ifeq ($(YQ2_OSTYPE), Windows)
|
||||
ctf:
|
||||
@echo "===> Building game.dll"
|
||||
$(Q)mkdir -p release
|
||||
$(MAKE) release/game.dll
|
||||
|
||||
build/%.o: %.c
|
||||
@echo "===> CC $<"
|
||||
$(Q)mkdir -p $(@D)
|
||||
$(Q)$(CC) -c $(CFLAGS) -o $@ $<
|
||||
else ifeq ($(YQ2_OSTYPE), Darwin)
|
||||
ctf:
|
||||
@echo "===> Building game.dylib"
|
||||
${Q}mkdir -p release
|
||||
$(MAKE) release/game.dylib
|
||||
else
|
||||
ctf:
|
||||
@echo "===> Building game.so"
|
||||
$(Q)mkdir -p release
|
||||
$(MAKE) release/game.so
|
||||
|
||||
release/game.so : CFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
build/%.o: %.c
|
||||
@echo "===> CC $<"
|
||||
$(Q)mkdir -p $(@D)
|
||||
$(Q)$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
release/game.so : CFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
CTF_OBJS_ = \
|
||||
|
@ -149,7 +246,7 @@ CTF_OBJS_ = \
|
|||
src/player/trail.o \
|
||||
src/player/view.o \
|
||||
src/player/weapon.o \
|
||||
src/shared/shared.o
|
||||
src/shared/shared.o
|
||||
|
||||
# ----------
|
||||
|
||||
|
@ -168,14 +265,18 @@ CTF_DEPS= $(CTF_OBJS:.o=.d)
|
|||
|
||||
# ----------
|
||||
|
||||
ifeq ($(OSTYPE), Windows)
|
||||
ifeq ($(YQ2_OSTYPE), Windows)
|
||||
release/game.dll : $(CTF_OBJS)
|
||||
@echo "===> LD $@"
|
||||
$(Q)$(CC) $(LDFLAGS) -o $@ $(CTF_OBJS)
|
||||
$(Q)$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS)
|
||||
else ifeq ($(YQ2_OSTYPE), Darwin)
|
||||
release/game.dylib : $(CTF_OBJS)
|
||||
@echo "===> LD $@"
|
||||
${Q}$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS)
|
||||
else
|
||||
release/game.so : $(CTF_OBJS)
|
||||
@echo "===> LD $@"
|
||||
$(Q)$(CC) $(LDFLAGS) -o $@ $(CTF_OBJS)
|
||||
$(Q)$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
|
||||
# ----------
|
||||
|
|
32
README
32
README
|
@ -1,32 +0,0 @@
|
|||
This is a 64 bit clean and bugfixed version of id Software's Quake II
|
||||
addon pack "Capture The Flag", developed by David 'Zoid' Kirsch. Hundred
|
||||
of type errors and strange constructs were fixed, thus this version
|
||||
should run much more stable than the old SDK version. While it may work
|
||||
with every Quake II client, the "Yamagi Quake II" client is highly
|
||||
recommended. For more Information visit http://www.yamagi.org/quake2.
|
||||
|
||||
Installation for FreeBSD, Linux and OpenBSD:
|
||||
--------------------------------------------
|
||||
1. Type "make" or "gmake" to compile the game.so.
|
||||
2. Copy release/game.so to the ctf/ subfolder of your Quake II
|
||||
installation. The CTF gamedata is part of the 3.20 point release.
|
||||
3. Start the game with "./quake2 +set game ctf".
|
||||
|
||||
Installation for OS X:
|
||||
----------------------
|
||||
1. Copy game.dll from the zip-archive to ctf/.
|
||||
2. Start the game with "quake2 +set game ctf"
|
||||
|
||||
If you want to compile 'ctf' for OS X from source, please take a look at
|
||||
the "Installation" section of the README of the Yamagi Quake II client.
|
||||
In the same file the integration into an app-bundle is explained.
|
||||
|
||||
Installation for Windows:
|
||||
-------------------------
|
||||
1. Copy the game.dll to the ctf\ subfolder of your Quake II
|
||||
installation. The CTF gamedata is part of the 3.20 point release.
|
||||
2. Start the game with "quake2.exe +set game ctf".
|
||||
|
||||
If you want to compile 'ctf' for Windows from source, please take a
|
||||
look at the "Installation" section of the README of the Yamagi Quake
|
||||
II client. There's descripted how to setup the build environment.
|
66
README.md
Normal file
66
README.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Three Wave Capture The Flag for Yamagi Quake II
|
||||
|
||||
Three Wave Capture The Flag for Yamagi Quake II is a bugfixed version of
|
||||
the official CTF addon for Quake II. It's based upon the Quake II source
|
||||
code release and and is licensed under GPL version 2:
|
||||
|
||||
* [LICENSE](https://github.com/yquake2/ctf/blob/master/LICENSE)
|
||||
|
||||
Several bugs were fixed. The addon is intended to be used with Yamagi
|
||||
Quake II, but it's also fully backward compatible with the last Quake II
|
||||
pointrelease 3.20 and may work with other source ports.
|
||||
|
||||
Officially supported operating systems are:
|
||||
|
||||
* FreeBSD
|
||||
* Linux
|
||||
* Windows
|
||||
|
||||
Beside theses Three Wave Capture The Flag for Yamagi Quake II has
|
||||
community support for MacOS and most other unixoid operating systems,
|
||||
including NetBSD, OpenBSD and Solaris.
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
Three Wave Capture The Flag for Yamagi Quake II is a community driven
|
||||
project and lives from community involvement. Please report bugs in our
|
||||
issue tracker:
|
||||
|
||||
* [Issue Tracker](https://github.com/yquake2/ctf/issues)
|
||||
|
||||
We are always open to code contributions, no matter if they are small
|
||||
bugfixes or bigger features. However, Yamagi Quake II is a conservative
|
||||
project with big focus on stability and backward compatibility. We don't
|
||||
accept breaking changes. When in doubt please open an issue and ask if a
|
||||
contribution in welcome before putting too much work into it. Open a
|
||||
pull request to submit code:
|
||||
|
||||
* [Pull Requests](https://github.com/yquake2/ctf/pulls)
|
||||
|
||||
Also have a look at our contributors guide:
|
||||
|
||||
* [Contributors Guide](https://github.com/yquake2/yquake2/blob/master/doc/080_contributing.md)
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
Yamagi Quake II has rather extensive documentation covering all relevant
|
||||
areas from installation and configuration to package building. Have a
|
||||
look at the documentation index:
|
||||
|
||||
* [Documentation Index](https://github.com/yquake2/yquake2/blob/master/doc/010_index.md)
|
||||
|
||||
|
||||
## Releases
|
||||
|
||||
Three Wave Capture The Flag for Yamagi Quake II releases at an irregular
|
||||
schedule. The official releases with source code tarballs and prebuild
|
||||
Windows binaries can be found at the homepage:
|
||||
|
||||
* [Homepage](https://www.yamagi.org/quake2/)
|
||||
|
||||
Our CI builds **unsupported** Linux, MacOS and Windows binaries at every
|
||||
commit. The artifacts can be found here:
|
||||
|
||||
* [Github Actions](https://github.com/yquake2/ctf/actions)
|
26
src/g_ai.c
26
src/g_ai.c
|
@ -404,7 +404,7 @@ FoundTarget(edict_t *self)
|
|||
level.sight_entity->light_level = 128;
|
||||
}
|
||||
|
||||
self->show_hostile = level.time + 1; /* wake up other monsters */
|
||||
self->show_hostile = (int)level.time + 1; /* wake up other monsters */
|
||||
|
||||
VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting);
|
||||
self->monsterinfo.trail_time = level.time;
|
||||
|
@ -577,7 +577,7 @@ FindTarget(edict_t *self)
|
|||
|
||||
if (r == RANGE_NEAR)
|
||||
{
|
||||
if ((client->show_hostile < level.time) && !infront(self, client))
|
||||
if ((client->show_hostile < (int)level.time) && !infront(self, client))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -810,8 +810,11 @@ ai_run_melee(edict_t *self)
|
|||
|
||||
if (FacingIdeal(self))
|
||||
{
|
||||
self->monsterinfo.melee(self);
|
||||
self->monsterinfo.attack_state = AS_STRAIGHT;
|
||||
if (self->monsterinfo.melee)
|
||||
{
|
||||
self->monsterinfo.melee(self);
|
||||
self->monsterinfo.attack_state = AS_STRAIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -827,8 +830,11 @@ ai_run_missile(edict_t *self)
|
|||
|
||||
if (FacingIdeal(self))
|
||||
{
|
||||
self->monsterinfo.attack(self);
|
||||
self->monsterinfo.attack_state = AS_STRAIGHT;
|
||||
if (self->monsterinfo.attack)
|
||||
{
|
||||
self->monsterinfo.attack(self);
|
||||
self->monsterinfo.attack_state = AS_STRAIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -882,9 +888,9 @@ ai_checkattack(edict_t *self, float dist)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (self->monsterinfo.aiflags & AI_SOUND_TARGET)
|
||||
if ((self->monsterinfo.aiflags & AI_SOUND_TARGET) && !visible(self, self->goalentity))
|
||||
{
|
||||
if ((level.time - self->enemy->teleport_time) > 5.0)
|
||||
if ((level.time - self->enemy->last_sound_time) > 5.0)
|
||||
{
|
||||
if (self->goalentity == self->enemy)
|
||||
{
|
||||
|
@ -908,7 +914,7 @@ ai_checkattack(edict_t *self, float dist)
|
|||
}
|
||||
else
|
||||
{
|
||||
self->show_hostile = level.time + 1;
|
||||
self->show_hostile = (int)level.time + 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -980,7 +986,7 @@ ai_checkattack(edict_t *self, float dist)
|
|||
}
|
||||
}
|
||||
|
||||
self->show_hostile = level.time + 1; /* wake up other monsters */
|
||||
self->show_hostile = (int)level.time + 1; /* wake up other monsters */
|
||||
|
||||
/* check knowledge of enemy */
|
||||
enemy_vis = visible(self, self->enemy);
|
||||
|
|
|
@ -229,6 +229,7 @@ Cmd_Give_f(edict_t *ent)
|
|||
if (gi.argc() == 3)
|
||||
{
|
||||
ent->health = atoi(gi.argv(2));
|
||||
ent->health = ent->health < 1 ? 1 : ent->health;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
21
src/g_ctf.c
21
src/g_ctf.c
|
@ -731,7 +731,7 @@ CTFFragBonuses(edict_t *targ, edict_t *inflictor, edict_t *attacker)
|
|||
flag carrier */
|
||||
attacker->client->resp.score += CTF_CARRIER_DANGER_PROTECT_BONUS;
|
||||
gi.bprintf(PRINT_MEDIUM,
|
||||
"%s defends %s's flag carrier against an agressive enemy\n",
|
||||
"%s defends %s's flag carrier against an aggressive enemy\n",
|
||||
attacker->client->pers.netname,
|
||||
CTFTeamName(attacker->client->resp.ctf_team));
|
||||
|
||||
|
@ -1718,8 +1718,7 @@ CTFGrappleDrawCable(edict_t *self)
|
|||
|
||||
AngleVectors(self->owner->client->v_angle, f, r, NULL);
|
||||
VectorSet(offset, 16, 16, self->owner->viewheight - 8);
|
||||
P_ProjectSource(self->owner->client, self->owner->s.origin,
|
||||
offset, f, r, start);
|
||||
P_ProjectSource(self->owner, offset, f, r, start);
|
||||
|
||||
VectorSubtract(start, self->owner->s.origin, offset);
|
||||
|
||||
|
@ -1903,7 +1902,7 @@ CTFGrappleFire(edict_t *ent, vec3_t g_offset, int damage, int effect)
|
|||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
VectorSet(offset, 24, 8, ent->viewheight - 8 + 2);
|
||||
VectorAdd(offset, g_offset, offset);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -1;
|
||||
|
@ -3621,7 +3620,7 @@ CTFWinElection(void)
|
|||
gi.bprintf(PRINT_HIGH, "%s has become an admin.\n",
|
||||
ctfgame.etarget->client->pers.netname);
|
||||
gi.cprintf(ctfgame.etarget, PRINT_HIGH,
|
||||
"Type 'admin' to access the adminstration menu.\n");
|
||||
"Type 'admin' to access the administration menu.\n");
|
||||
break;
|
||||
|
||||
case ELECT_MAP:
|
||||
|
@ -3723,7 +3722,7 @@ CTFReady(edict_t *ent)
|
|||
|
||||
if (ent->client->resp.ready)
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You have already commited.\n");
|
||||
gi.cprintf(ent, PRINT_HIGH, "You have already committed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3758,8 +3757,8 @@ CTFReady(edict_t *ent)
|
|||
|
||||
if (!j && t1 && t2)
|
||||
{
|
||||
/* everyone has commited */
|
||||
gi.bprintf(PRINT_CHAT, "All players have commited. Match starting\n");
|
||||
/* everyone has committed */
|
||||
gi.bprintf(PRINT_CHAT, "All players have committed. Match starting\n");
|
||||
ctfgame.match = MATCH_PREGAME;
|
||||
ctfgame.matchtime = level.time + matchstarttime->value;
|
||||
ctfgame.countdown = false;
|
||||
|
@ -3785,7 +3784,7 @@ CTFNotReady(edict_t *ent)
|
|||
|
||||
if (!ent->client->resp.ready)
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You haven't commited.\n");
|
||||
gi.cprintf(ent, PRINT_HIGH, "You haven't committed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5013,7 +5012,7 @@ CTFAdmin_Reset(edict_t *ent, pmenuhnd_t *p)
|
|||
PMenu_Close(ent);
|
||||
|
||||
/* go back to normal mode */
|
||||
gi.bprintf(PRINT_CHAT, "Match mode has been terminated, reseting to normal game.\n");
|
||||
gi.bprintf(PRINT_CHAT, "Match mode has been terminated, resetting to normal game.\n");
|
||||
ctfgame.match = MATCH_NONE;
|
||||
gi.cvar_set("competition", "1");
|
||||
CTFResetAllPlayers();
|
||||
|
@ -5082,7 +5081,7 @@ CTFAdmin(edict_t *ent)
|
|||
ent->client->resp.admin = true;
|
||||
gi.bprintf(PRINT_HIGH, "%s has become an admin.\n",
|
||||
ent->client->pers.netname);
|
||||
gi.cprintf(ent, PRINT_HIGH, "Type 'admin' to access the adminstration menu.\n");
|
||||
gi.cprintf(ent, PRINT_HIGH, "Type 'admin' to access the administration menu.\n");
|
||||
}
|
||||
|
||||
if (!ent->client->resp.admin)
|
||||
|
|
|
@ -77,6 +77,8 @@ cvar_t *flood_waitdelay;
|
|||
|
||||
cvar_t *sv_maplist;
|
||||
|
||||
cvar_t *aimfix;
|
||||
|
||||
void SpawnEntities(char *mapname, char *entities, char *spawnpoint);
|
||||
void ClientThink(edict_t *ent, usercmd_t *cmd);
|
||||
qboolean ClientConnect(edict_t *ent, char *userinfo);
|
||||
|
@ -386,7 +388,7 @@ ExitLevel(void)
|
|||
}
|
||||
|
||||
gibsthisframe = 0;
|
||||
lastgibframe = 0;
|
||||
debristhisframe = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -401,6 +403,9 @@ G_RunFrame(void)
|
|||
level.framenum++;
|
||||
level.time = level.framenum * FRAMETIME;
|
||||
|
||||
gibsthisframe = 0;
|
||||
debristhisframe = 0;
|
||||
|
||||
/* choose a client for monsters to target this frame */
|
||||
AI_SetSightClient();
|
||||
|
||||
|
|
24
src/g_misc.c
24
src/g_misc.c
|
@ -1,7 +1,7 @@
|
|||
#include "header/local.h"
|
||||
|
||||
int debristhisframe;
|
||||
int gibsthisframe;
|
||||
int lastgibframe;
|
||||
|
||||
/*
|
||||
* QUAKED func_group (0 0 0) ?
|
||||
|
@ -139,15 +139,9 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type)
|
|||
vec3_t size;
|
||||
float vscale;
|
||||
|
||||
if (level.framenum > lastgibframe)
|
||||
{
|
||||
gibsthisframe = 0;
|
||||
lastgibframe = level.framenum;
|
||||
}
|
||||
|
||||
gibsthisframe++;
|
||||
|
||||
if (gibsthisframe > 20)
|
||||
if (gibsthisframe > MAX_GIBS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -166,6 +160,7 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type)
|
|||
gib->flags |= FL_NO_KNOCKBACK;
|
||||
gib->takedamage = DAMAGE_YES;
|
||||
gib->die = gib_die;
|
||||
gib->health = 250;
|
||||
|
||||
if (type == GIB_ORGANIC)
|
||||
{
|
||||
|
@ -293,15 +288,9 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin)
|
|||
edict_t *chunk;
|
||||
vec3_t v;
|
||||
|
||||
if (level.framenum > lastgibframe)
|
||||
{
|
||||
gibsthisframe = 0;
|
||||
lastgibframe = level.framenum;
|
||||
}
|
||||
debristhisframe++;
|
||||
|
||||
gibsthisframe++;
|
||||
|
||||
if (gibsthisframe > 20)
|
||||
if (debristhisframe > MAX_DEBRIS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -325,6 +314,7 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin)
|
|||
chunk->classname = "debris";
|
||||
chunk->takedamage = DAMAGE_YES;
|
||||
chunk->die = debris_die;
|
||||
chunk->health = 250;
|
||||
gi.linkentity(chunk);
|
||||
}
|
||||
|
||||
|
@ -344,7 +334,7 @@ BecomeExplosion1(edict_t *self)
|
|||
{
|
||||
CTFResetFlag(CTF_TEAM2); /* this will free self! */
|
||||
gi.bprintf(PRINT_HIGH, "The %s flag has returned!\n",
|
||||
CTFTeamName(CTF_TEAM1));
|
||||
CTFTeamName(CTF_TEAM2));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
16
src/g_phys.c
16
src/g_phys.c
|
@ -497,6 +497,22 @@ retry:
|
|||
VectorCopy(trace.endpos, ent->s.origin);
|
||||
gi.linkentity(ent);
|
||||
|
||||
/* Push slightly away from non-horizontal surfaces,
|
||||
prevent origin stuck in the plane which causes
|
||||
the entity to be rendered in full black. */
|
||||
if (trace.plane.type != 2)
|
||||
{
|
||||
/* Limit the fix to gibs, debris and dead monsters.
|
||||
Everything else may break existing maps. Items
|
||||
may slide to unreachable locations, monsters may
|
||||
get stuck, etc. */
|
||||
if (((strncmp(ent->classname, "monster_", 8) == 0) && ent->health < 1) ||
|
||||
(strcmp(ent->classname, "debris") == 0) || (ent->s.effects & EF_GIB))
|
||||
{
|
||||
VectorAdd(ent->s.origin, trace.plane.normal, ent->s.origin);
|
||||
}
|
||||
}
|
||||
|
||||
if (trace.fraction != 1.0)
|
||||
{
|
||||
SV_Impact(ent, &trace);
|
||||
|
|
15
src/g_save.c
15
src/g_save.c
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include "header/local.h"
|
||||
|
||||
#ifndef BUILD_DATE
|
||||
#define BUILD_DATE __DATE__
|
||||
#endif
|
||||
|
||||
field_t fields[] = {
|
||||
{"classname", FOFS(classname), F_LSTRING},
|
||||
{"origin", FOFS(s.origin), F_VECTOR},
|
||||
|
@ -141,7 +145,7 @@ void
|
|||
InitGame(void)
|
||||
{
|
||||
gi.dprintf("Game is starting up.\n");
|
||||
gi.dprintf("Game is ctf built on %s.\n", GAMEVERSION, __DATE__);
|
||||
gi.dprintf("Game is ctf built on %s.\n", GAMEVERSION, BUILD_DATE);
|
||||
|
||||
gun_x = gi.cvar("gun_x", "0", 0);
|
||||
gun_y = gi.cvar("gun_y", "0", 0);
|
||||
|
@ -157,7 +161,7 @@ InitGame(void)
|
|||
/* latched vars */
|
||||
sv_cheats = gi.cvar("cheats", "0", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
gi.cvar("gamename", GAMEVERSION, CVAR_SERVERINFO | CVAR_LATCH);
|
||||
gi.cvar("gamedate", __DATE__, CVAR_SERVERINFO | CVAR_LATCH);
|
||||
gi.cvar("gamedate", BUILD_DATE, CVAR_SERVERINFO | CVAR_LATCH);
|
||||
maxclients = gi.cvar("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
deathmatch = gi.cvar("deathmatch", "0", CVAR_LATCH);
|
||||
coop = gi.cvar("coop", "0", CVAR_LATCH);
|
||||
|
@ -200,6 +204,9 @@ InitGame(void)
|
|||
/* dm map list */
|
||||
sv_maplist = gi.cvar("sv_maplist", "", 0);
|
||||
|
||||
/* others */
|
||||
aimfix = gi.cvar("aimfix", "0", CVAR_ARCHIVE);
|
||||
|
||||
/* items */
|
||||
InitItems();
|
||||
|
||||
|
@ -493,7 +500,7 @@ WriteGame(char *filename, qboolean autosave)
|
|||
}
|
||||
|
||||
memset(str, 0, sizeof(str));
|
||||
strcpy(str, __DATE__);
|
||||
strcpy(str, BUILD_DATE);
|
||||
fwrite(str, sizeof(str), 1, f);
|
||||
|
||||
game.autosaved = autosave;
|
||||
|
@ -526,7 +533,7 @@ ReadGame(char *filename)
|
|||
|
||||
fread(str, sizeof(str), 1, f);
|
||||
|
||||
if (strcmp(str, __DATE__))
|
||||
if (strcmp(str, BUILD_DATE))
|
||||
{
|
||||
fclose(f);
|
||||
gi.error("Savegame from an older version.\n");
|
||||
|
|
|
@ -813,11 +813,11 @@ SP_worldspawn(edict_t *ent)
|
|||
if (ent->message && ent->message[0])
|
||||
{
|
||||
gi.configstring(CS_NAME, ent->message);
|
||||
strncpy(level.level_name, ent->message, sizeof(level.level_name));
|
||||
Q_strlcpy(level.level_name, ent->message, sizeof(level.level_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(level.level_name, level.mapname, sizeof(level.level_name));
|
||||
Q_strlcpy(level.level_name, level.mapname, sizeof(level.level_name));
|
||||
}
|
||||
|
||||
if (st.sky && st.sky[0])
|
||||
|
|
|
@ -168,11 +168,11 @@ SV_FilterPacket(char *from)
|
|||
{
|
||||
if ((in & ipfilters[i].mask) == ipfilters[i].compare)
|
||||
{
|
||||
return (int)filterban->value;
|
||||
return (filterban->value != 0);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)!filterban->value;
|
||||
return (filterban->value == 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -121,7 +121,7 @@ SP_target_speaker(edict_t *ent)
|
|||
}
|
||||
else
|
||||
{
|
||||
strncpy(buffer, st.noise, sizeof(buffer));
|
||||
Q_strlcpy(buffer, st.noise, sizeof(buffer));
|
||||
}
|
||||
|
||||
ent->noise_index = gi.soundindex(buffer);
|
||||
|
|
|
@ -110,6 +110,10 @@ typedef enum
|
|||
AMMO_SLUGS
|
||||
} ammo_t;
|
||||
|
||||
/* Maximum debris / gibs per frame */
|
||||
#define MAX_GIBS 20
|
||||
#define MAX_DEBRIS 20
|
||||
|
||||
/* deadflag */
|
||||
#define DEAD_NO 0
|
||||
#define DEAD_DYING 1
|
||||
|
@ -446,8 +450,8 @@ extern spawn_temp_t st;
|
|||
extern int sm_meat_index;
|
||||
extern int snd_fry;
|
||||
|
||||
extern int debristhisframe;
|
||||
extern int gibsthisframe;
|
||||
extern int lastgibframe;
|
||||
|
||||
|
||||
/* means of death */
|
||||
|
@ -537,6 +541,8 @@ extern cvar_t *flood_waitdelay;
|
|||
|
||||
extern cvar_t *sv_maplist;
|
||||
|
||||
extern cvar_t *aimfix;
|
||||
|
||||
#define world (&g_edicts[0])
|
||||
|
||||
/* item spawnflags */
|
||||
|
@ -756,7 +762,7 @@ void DeathmatchScoreboardMessage(edict_t *client, edict_t *killer);
|
|||
|
||||
/* g_pweapon.c */
|
||||
void PlayerNoise(edict_t *who, vec3_t where, int type);
|
||||
void P_ProjectSource(gclient_t *client, vec3_t point, vec3_t distance,
|
||||
void P_ProjectSource(edict_t *ent, vec3_t distance,
|
||||
vec3_t forward, vec3_t right, vec3_t result);
|
||||
void Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST,
|
||||
int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames,
|
||||
|
@ -1033,7 +1039,7 @@ struct edict_s
|
|||
int max_health;
|
||||
int gib_health;
|
||||
int deadflag;
|
||||
qboolean show_hostile;
|
||||
int show_hostile;
|
||||
|
||||
float powerarmor_time;
|
||||
|
||||
|
@ -1069,7 +1075,7 @@ struct edict_s
|
|||
float delay; /* before firing targets */
|
||||
float random;
|
||||
|
||||
float teleport_time;
|
||||
float last_sound_time;
|
||||
|
||||
int watertype;
|
||||
int waterlevel;
|
||||
|
|
|
@ -36,8 +36,21 @@
|
|||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L // C23 or newer
|
||||
typedef bool qboolean;
|
||||
#else
|
||||
#ifdef true
|
||||
#undef true
|
||||
#endif
|
||||
|
||||
#ifdef false
|
||||
#undef false
|
||||
#endif
|
||||
|
||||
typedef enum {false, true} qboolean;
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
|
@ -202,6 +215,8 @@ void Com_PageInMemory(byte *buffer, int size);
|
|||
int Q_stricmp(const char *s1, const char *s2);
|
||||
int Q_strcasecmp(char *s1, char *s2);
|
||||
int Q_strncasecmp(char *s1, char *s2, int n);
|
||||
int Q_strlcpy(char *dst, const char *src, int size);
|
||||
int Q_strlcat(char *dst, const char *src, int size);
|
||||
|
||||
/* ============================================= */
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* Interface between client <-> game and client calculations.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "../header/local.h"
|
||||
#include "../monster/player.h"
|
||||
|
@ -76,11 +76,11 @@ SP_info_player_coop(edict_t *self)
|
|||
/*
|
||||
* QUAKED info_player_intermission (1 0 1) (-16 -16 -24) (16 16 32)
|
||||
* The deathmatch intermission point will be at one of these
|
||||
* Use 'angles' instead of 'angle', so you can set pitch or
|
||||
* Use 'angles' instead of 'angle', so you can set pitch or
|
||||
* roll as well as yaw. 'pitch yaw roll'
|
||||
*/
|
||||
void
|
||||
SP_info_player_intermission(void)
|
||||
SP_info_player_intermission(edict_t *ent)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ SP_info_player_intermission(void)
|
|||
void
|
||||
player_pain(edict_t *self, edict_t *other, float kick, int damage)
|
||||
{
|
||||
/* player pain is handled at the
|
||||
/* player pain is handled at the
|
||||
end of the frame in P_DamageFeedback */
|
||||
}
|
||||
|
||||
|
@ -521,7 +521,7 @@ player_die(edict_t *self, edict_t *inflictor, edict_t *attacker,
|
|||
memset(self->client->pers.inventory, 0, sizeof(self->client->pers.inventory));
|
||||
|
||||
if (self->health < -40)
|
||||
{
|
||||
{
|
||||
/* gib */
|
||||
gi.sound(self, CHAN_BODY, gi.soundindex(
|
||||
"misc/udeath.wav"), 1, ATTN_NORM, 0);
|
||||
|
@ -586,7 +586,7 @@ player_die(edict_t *self, edict_t *inflictor, edict_t *attacker,
|
|||
/* ======================================================================= */
|
||||
|
||||
/*
|
||||
* This is only called when the game
|
||||
* This is only called when the game
|
||||
* first initializes in single player,
|
||||
* but is called after each death and
|
||||
* level change in deathmatch
|
||||
|
@ -731,7 +731,7 @@ PlayersRangeFromSpot(edict_t *spot)
|
|||
}
|
||||
|
||||
/*
|
||||
* go to a random point, but NOT the two
|
||||
* go to a random point, but NOT the two
|
||||
* points closest to other players
|
||||
*/
|
||||
edict_t *
|
||||
|
@ -824,7 +824,7 @@ SelectFarthestDeathmatchSpawnPoint(void)
|
|||
return bestspot;
|
||||
}
|
||||
|
||||
/* if there is a player just spawned on
|
||||
/* if there is a player just spawned on
|
||||
each and every start spot we have no
|
||||
choice to turn one into a telefrag meltdown */
|
||||
spot = G_Find(NULL, FOFS(classname), "info_player_deathmatch");
|
||||
|
@ -880,7 +880,7 @@ SelectCoopSpawnPoint(edict_t *ent)
|
|||
}
|
||||
|
||||
if (Q_stricmp(game.spawnpoint, target) == 0)
|
||||
{
|
||||
{
|
||||
/* this is a coop spawn point for one of the clients here */
|
||||
index--;
|
||||
|
||||
|
@ -942,7 +942,7 @@ SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles)
|
|||
if (!spot)
|
||||
{
|
||||
if (!game.spawnpoint[0])
|
||||
{
|
||||
{
|
||||
/* there wasn't a spawnpoint without a target, so use any */
|
||||
spot = G_Find(spot, FOFS(classname), "info_player_start");
|
||||
}
|
||||
|
@ -1062,7 +1062,7 @@ respawn(edict_t *self)
|
|||
/* ============================================================== */
|
||||
|
||||
/*
|
||||
* Called when a player connects
|
||||
* Called when a player connects
|
||||
* to a server or respawns in
|
||||
* a deathmatch.
|
||||
*/
|
||||
|
@ -1225,7 +1225,7 @@ PutClientInServer(edict_t *ent)
|
|||
}
|
||||
|
||||
if (!KillBox(ent))
|
||||
{
|
||||
{
|
||||
/* could't spawn in? */
|
||||
}
|
||||
|
||||
|
@ -1237,7 +1237,7 @@ PutClientInServer(edict_t *ent)
|
|||
}
|
||||
|
||||
/*
|
||||
* A client has just connected to
|
||||
* A client has just connected to
|
||||
* the server in deathmatch mode,
|
||||
* so clear everything out before
|
||||
* starting them.
|
||||
|
@ -1288,13 +1288,13 @@ ClientBegin(edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
/* if there is already a body waiting for
|
||||
/* if there is already a body waiting for
|
||||
us (a loadgame), just take it, otherwise
|
||||
spawn one from scratch */
|
||||
if (ent->inuse == true)
|
||||
{
|
||||
/* the client has cleared the client side viewangles upon
|
||||
connecting to the server, which is different than the
|
||||
/* the client has cleared the client side viewangles upon
|
||||
connecting to the server, which is different than the
|
||||
state when the game is saved, so we need to compensate
|
||||
with deltaangles */
|
||||
for (i = 0; i < 3; i++)
|
||||
|
@ -1305,7 +1305,7 @@ ClientBegin(edict_t *ent)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* a spawn point will completely reinitialize the entity
|
||||
/* a spawn point will completely reinitialize the entity
|
||||
except for the persistant data that was initialized at
|
||||
ClientConnect() time */
|
||||
G_InitEdict(ent);
|
||||
|
@ -1513,9 +1513,9 @@ ClientDisconnect(edict_t *ent)
|
|||
|
||||
edict_t *pm_passent;
|
||||
|
||||
/*
|
||||
/*
|
||||
* pmove doesn't need to know about
|
||||
* passent and contentmask
|
||||
* passent and contentmask
|
||||
*/
|
||||
trace_t
|
||||
PM_trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
|
||||
|
@ -1727,7 +1727,7 @@ ClientThink(edict_t *ent, usercmd_t *ucmd)
|
|||
client->buttons = ucmd->buttons;
|
||||
client->latched_buttons |= client->buttons & ~client->oldbuttons;
|
||||
|
||||
/* save light level the player is
|
||||
/* save light level the player is
|
||||
standing on for monster sighting AI */
|
||||
ent->light_level = ucmd->lightlevel;
|
||||
|
||||
|
|
|
@ -33,10 +33,12 @@ static byte is_silenced;
|
|||
void weapon_grenade_fire(edict_t *ent, qboolean held);
|
||||
|
||||
void
|
||||
P_ProjectSource(gclient_t *client, vec3_t point, vec3_t distance,
|
||||
P_ProjectSource(edict_t *ent, vec3_t distance,
|
||||
vec3_t forward, vec3_t right, vec3_t result)
|
||||
{
|
||||
vec3_t _distance;
|
||||
gclient_t *client = ent->client;
|
||||
float *point = ent->s.origin;
|
||||
vec3_t _distance;
|
||||
|
||||
VectorCopy(distance, _distance);
|
||||
|
||||
|
@ -50,6 +52,21 @@ P_ProjectSource(gclient_t *client, vec3_t point, vec3_t distance,
|
|||
}
|
||||
|
||||
G_ProjectSource(point, _distance, forward, right, result);
|
||||
|
||||
// Berserker: fix - now the projectile hits exactly where the scope is pointing.
|
||||
if (aimfix->value)
|
||||
{
|
||||
vec3_t start, end;
|
||||
VectorSet(start, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] + ent->viewheight);
|
||||
VectorMA(start, 8192, forward, end);
|
||||
|
||||
trace_t tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT);
|
||||
if (tr.fraction < 1)
|
||||
{
|
||||
VectorSubtract(tr.endpos, result, forward);
|
||||
VectorNormalize(forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -119,7 +136,7 @@ PlayerNoise(edict_t *who, vec3_t where, int type)
|
|||
VectorCopy(where, noise->s.origin);
|
||||
VectorSubtract(where, noise->maxs, noise->absmin);
|
||||
VectorAdd(where, noise->maxs, noise->absmax);
|
||||
noise->teleport_time = level.time;
|
||||
noise->last_sound_time = level.time;
|
||||
gi.linkentity(noise);
|
||||
}
|
||||
|
||||
|
@ -659,7 +676,7 @@ weapon_grenade_fire(edict_t *ent, qboolean held)
|
|||
|
||||
VectorSet(offset, 8, 8, ent->viewheight - 8);
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
timer = ent->client->grenade_time - level.time;
|
||||
speed = GRENADE_MINSPEED + (GRENADE_TIMER -
|
||||
|
@ -848,7 +865,7 @@ weapon_grenadelauncher_fire(edict_t *ent)
|
|||
|
||||
VectorSet(offset, 8, 8, ent->viewheight - 8);
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -1;
|
||||
|
@ -913,7 +930,7 @@ Weapon_RocketLauncher_Fire(edict_t *ent)
|
|||
ent->client->kick_angles[0] = -1;
|
||||
|
||||
VectorSet(offset, 8, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
fire_rocket(ent, start, forward, damage, 650, damage_radius, radius_damage);
|
||||
|
||||
/* send muzzle flash */
|
||||
|
@ -966,7 +983,7 @@ Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage,
|
|||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
VectorSet(offset, 24, 8, ent->viewheight - 8);
|
||||
VectorAdd(offset, g_offset, offset);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -1;
|
||||
|
@ -1200,7 +1217,7 @@ Machinegun_Fire(edict_t *ent)
|
|||
VectorAdd(ent->client->v_angle, ent->client->kick_angles, angles);
|
||||
AngleVectors(angles, forward, right, NULL);
|
||||
VectorSet(offset, 0, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
fire_bullet(ent, start, forward, damage, kick,
|
||||
DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD,
|
||||
MOD_MACHINEGUN);
|
||||
|
@ -1367,8 +1384,7 @@ Chaingun_Fire(edict_t *ent)
|
|||
r = 7 + crandom() * 4;
|
||||
u = crandom() * 4;
|
||||
VectorSet(offset, 0, r, u + ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset,
|
||||
forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
fire_bullet(ent, start, forward, damage, kick,
|
||||
DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD,
|
||||
|
@ -1427,7 +1443,7 @@ weapon_shotgun_fire(edict_t *ent)
|
|||
ent->client->kick_angles[0] = -2;
|
||||
|
||||
VectorSet(offset, 0, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
if (is_quad)
|
||||
{
|
||||
|
@ -1487,7 +1503,7 @@ weapon_supershotgun_fire(edict_t *ent)
|
|||
ent->client->kick_angles[0] = -2;
|
||||
|
||||
VectorSet(offset, 0, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
if (is_quad)
|
||||
{
|
||||
|
@ -1499,10 +1515,35 @@ weapon_supershotgun_fire(edict_t *ent)
|
|||
v[YAW] = ent->client->v_angle[YAW] - 5;
|
||||
v[ROLL] = ent->client->v_angle[ROLL];
|
||||
AngleVectors(v, forward, NULL, NULL);
|
||||
|
||||
if (aimfix->value)
|
||||
{
|
||||
AngleVectors(v, forward, right, NULL);
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -2;
|
||||
|
||||
VectorSet(offset, 0, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
}
|
||||
|
||||
fire_shotgun(ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD,
|
||||
DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN);
|
||||
|
||||
v[YAW] = ent->client->v_angle[YAW] + 5;
|
||||
AngleVectors(v, forward, NULL, NULL);
|
||||
|
||||
if (aimfix->value)
|
||||
{
|
||||
AngleVectors(v, forward, right, NULL);
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -2;
|
||||
|
||||
VectorSet(offset, 0, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
}
|
||||
|
||||
fire_shotgun(ent, start, forward, damage, kick,
|
||||
DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD,
|
||||
DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN);
|
||||
|
@ -1573,7 +1614,7 @@ weapon_railgun_fire(edict_t *ent)
|
|||
ent->client->kick_angles[0] = -3;
|
||||
|
||||
VectorSet(offset, 0, 7, ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
fire_rail(ent, start, forward, damage, kick);
|
||||
|
||||
/* send muzzle flash */
|
||||
|
@ -1663,7 +1704,7 @@ weapon_bfg_fire(edict_t *ent)
|
|||
ent->client->v_dmg_time = level.time + DAMAGE_TIME;
|
||||
|
||||
VectorSet(offset, 8, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
fire_bfg(ent, start, forward, damage, 400, damage_radius);
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
|
|
|
@ -1072,6 +1072,43 @@ Q_strcasecmp(char *s1, char *s2)
|
|||
return Q_strncasecmp(s1, s2, 99999);
|
||||
}
|
||||
|
||||
int
|
||||
Q_strlcpy(char *dst, const char *src, int size)
|
||||
{
|
||||
const char *s = src;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (size > 1)
|
||||
{
|
||||
*dst++ = *s;
|
||||
size--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
if (size > 0)
|
||||
{
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
return s - src;
|
||||
}
|
||||
|
||||
int
|
||||
Q_strlcat(char *dst, const char *src, int size)
|
||||
{
|
||||
char *d = dst;
|
||||
|
||||
while (size > 0 && *d)
|
||||
{
|
||||
size--;
|
||||
d++;
|
||||
}
|
||||
|
||||
return (d - dst) + Q_strlcpy(d, src, size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Com_sprintf(char *dest, int size, char *fmt, ...)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue