Compare commits

..

No commits in common. "master" and "CTF_1_04" have entirely different histories.

26 changed files with 170 additions and 707 deletions

View file

@ -1,45 +0,0 @@
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

View file

@ -1,45 +0,0 @@
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

View file

@ -1,49 +0,0 @@
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

View file

@ -1,56 +0,0 @@
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

View file

@ -1,56 +0,0 @@
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
View file

@ -1,2 +0,0 @@
build/
release/

View file

@ -1,26 +1,3 @@
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.

View file

@ -1,8 +1,5 @@
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 Executable file → Normal file
View file

@ -6,161 +6,64 @@
# #
# Dependencies: #
# - None, but you need a Quake II to play. #
# While in theory every one should work #
# Yamagi Quake II is recommended. #
# While in theorie every one should work #
# Yamagi Quake II ist recommended. #
# #
# Platforms: #
# - FreeBSD #
# - Linux #
# - Mac OS X #
# - OpenBSD #
# - Windows #
# - Windows #
# ----------------------------------------------------- #
# Detect the OS
ifdef SystemRoot
YQ2_OSTYPE ?= Windows
OSTYPE := Windows
else
YQ2_OSTYPE ?= $(shell uname -s)
OSTYPE := $(shell uname -s)
endif
# Special case for MinGW
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
ifneq (,$(findstring MINGW,$(OSTYPE)))
OSTYPE := Windows
endif
# ----------
# 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
# 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
else
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
CFLAGS := -O2 -fno-strict-aliasing -fomit-frame-pointer \
-Wall -pipe -g -MMD -fwrapv
endif
# ----------
# Base LDFLAGS.
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
ifeq ($(OSTYPE), Darwin)
LDFLAGS := -shared -arch i386 -arch x86_64
else
override LDFLAGS += -lm
LDFLAGS := -shared
endif
# ----------
@ -169,7 +72,7 @@ endif
all: ctf
# ----------
# When make is invoked by "make VERBOSE=1" print
# the compiler and linker commands.
@ -185,39 +88,39 @@ endif
.PHONY : all clean ctf
# ----------
# Cleanup
clean:
@echo "===> CLEAN"
${Q}rm -Rf build release
# ----------
# The ctf game
ifeq ($(YQ2_OSTYPE), Windows)
ifeq ($(OSTYPE), Windows)
ctf:
@echo "===> Building game.dll"
$(Q)mkdir -p release
$(MAKE) release/game.dll
else ifeq ($(YQ2_OSTYPE), Darwin)
ctf:
@echo "===> Building game.dylib"
${Q}mkdir -p release
$(MAKE) release/game.dylib
build/%.o: %.c
@echo "===> CC $<"
$(Q)mkdir -p $(@D)
$(Q)$(CC) -c $(CFLAGS) -o $@ $<
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_ = \
@ -246,7 +149,7 @@ CTF_OBJS_ = \
src/player/trail.o \
src/player/view.o \
src/player/weapon.o \
src/shared/shared.o
src/shared/shared.o
# ----------
@ -265,18 +168,14 @@ CTF_DEPS= $(CTF_OBJS:.o=.d)
# ----------
ifeq ($(YQ2_OSTYPE), Windows)
ifeq ($(OSTYPE), Windows)
release/game.dll : $(CTF_OBJS)
@echo "===> LD $@"
$(Q)$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS)
else ifeq ($(YQ2_OSTYPE), Darwin)
release/game.dylib : $(CTF_OBJS)
@echo "===> LD $@"
${Q}$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS)
$(Q)$(CC) $(LDFLAGS) -o $@ $(CTF_OBJS)
else
release/game.so : $(CTF_OBJS)
@echo "===> LD $@"
$(Q)$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS)
$(Q)$(CC) $(LDFLAGS) -o $@ $(CTF_OBJS)
endif
# ----------

32
README Normal file
View file

@ -0,0 +1,32 @@
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.

View file

@ -1,66 +0,0 @@
# 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)

View file

@ -404,7 +404,7 @@ FoundTarget(edict_t *self)
level.sight_entity->light_level = 128;
}
self->show_hostile = (int)level.time + 1; /* wake up other monsters */
self->show_hostile = 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 < (int)level.time) && !infront(self, client))
if ((client->show_hostile < level.time) && !infront(self, client))
{
return false;
}
@ -810,11 +810,8 @@ ai_run_melee(edict_t *self)
if (FacingIdeal(self))
{
if (self->monsterinfo.melee)
{
self->monsterinfo.melee(self);
self->monsterinfo.attack_state = AS_STRAIGHT;
}
self->monsterinfo.melee(self);
self->monsterinfo.attack_state = AS_STRAIGHT;
}
}
@ -830,11 +827,8 @@ ai_run_missile(edict_t *self)
if (FacingIdeal(self))
{
if (self->monsterinfo.attack)
{
self->monsterinfo.attack(self);
self->monsterinfo.attack_state = AS_STRAIGHT;
}
self->monsterinfo.attack(self);
self->monsterinfo.attack_state = AS_STRAIGHT;
}
}
@ -888,9 +882,9 @@ ai_checkattack(edict_t *self, float dist)
return false;
}
if ((self->monsterinfo.aiflags & AI_SOUND_TARGET) && !visible(self, self->goalentity))
if (self->monsterinfo.aiflags & AI_SOUND_TARGET)
{
if ((level.time - self->enemy->last_sound_time) > 5.0)
if ((level.time - self->enemy->teleport_time) > 5.0)
{
if (self->goalentity == self->enemy)
{
@ -914,7 +908,7 @@ ai_checkattack(edict_t *self, float dist)
}
else
{
self->show_hostile = (int)level.time + 1;
self->show_hostile = level.time + 1;
return false;
}
}
@ -986,7 +980,7 @@ ai_checkattack(edict_t *self, float dist)
}
}
self->show_hostile = (int)level.time + 1; /* wake up other monsters */
self->show_hostile = level.time + 1; /* wake up other monsters */
/* check knowledge of enemy */
enemy_vis = visible(self, self->enemy);

View file

@ -229,7 +229,6 @@ 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
{

View file

@ -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 aggressive enemy\n",
"%s defends %s's flag carrier against an agressive enemy\n",
attacker->client->pers.netname,
CTFTeamName(attacker->client->resp.ctf_team));
@ -1718,7 +1718,8 @@ 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, offset, f, r, start);
P_ProjectSource(self->owner->client, self->owner->s.origin,
offset, f, r, start);
VectorSubtract(start, self->owner->s.origin, offset);
@ -1902,7 +1903,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, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
VectorScale(forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
@ -3620,7 +3621,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 administration menu.\n");
"Type 'admin' to access the adminstration menu.\n");
break;
case ELECT_MAP:
@ -3722,7 +3723,7 @@ CTFReady(edict_t *ent)
if (ent->client->resp.ready)
{
gi.cprintf(ent, PRINT_HIGH, "You have already committed.\n");
gi.cprintf(ent, PRINT_HIGH, "You have already commited.\n");
return;
}
@ -3757,8 +3758,8 @@ CTFReady(edict_t *ent)
if (!j && t1 && t2)
{
/* everyone has committed */
gi.bprintf(PRINT_CHAT, "All players have committed. Match starting\n");
/* everyone has commited */
gi.bprintf(PRINT_CHAT, "All players have commited. Match starting\n");
ctfgame.match = MATCH_PREGAME;
ctfgame.matchtime = level.time + matchstarttime->value;
ctfgame.countdown = false;
@ -3784,7 +3785,7 @@ CTFNotReady(edict_t *ent)
if (!ent->client->resp.ready)
{
gi.cprintf(ent, PRINT_HIGH, "You haven't committed.\n");
gi.cprintf(ent, PRINT_HIGH, "You haven't commited.\n");
return;
}
@ -5012,7 +5013,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, resetting to normal game.\n");
gi.bprintf(PRINT_CHAT, "Match mode has been terminated, reseting to normal game.\n");
ctfgame.match = MATCH_NONE;
gi.cvar_set("competition", "1");
CTFResetAllPlayers();
@ -5081,7 +5082,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 administration menu.\n");
gi.cprintf(ent, PRINT_HIGH, "Type 'admin' to access the adminstration menu.\n");
}
if (!ent->client->resp.admin)

View file

@ -77,8 +77,6 @@ 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);
@ -388,7 +386,7 @@ ExitLevel(void)
}
gibsthisframe = 0;
debristhisframe = 0;
lastgibframe = 0;
}
/*
@ -403,9 +401,6 @@ 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();

View file

@ -1,7 +1,7 @@
#include "header/local.h"
int debristhisframe;
int gibsthisframe;
int lastgibframe;
/*
* QUAKED func_group (0 0 0) ?
@ -139,9 +139,15 @@ 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 > MAX_GIBS)
if (gibsthisframe > 20)
{
return;
}
@ -160,7 +166,6 @@ 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)
{
@ -288,9 +293,15 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin)
edict_t *chunk;
vec3_t v;
debristhisframe++;
if (level.framenum > lastgibframe)
{
gibsthisframe = 0;
lastgibframe = level.framenum;
}
if (debristhisframe > MAX_DEBRIS)
gibsthisframe++;
if (gibsthisframe > 20)
{
return;
}
@ -314,7 +325,6 @@ 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);
}
@ -334,7 +344,7 @@ BecomeExplosion1(edict_t *self)
{
CTFResetFlag(CTF_TEAM2); /* this will free self! */
gi.bprintf(PRINT_HIGH, "The %s flag has returned!\n",
CTFTeamName(CTF_TEAM2));
CTFTeamName(CTF_TEAM1));
return;
}

View file

@ -497,22 +497,6 @@ 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);

View file

@ -28,10 +28,6 @@
#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},
@ -145,7 +141,7 @@ void
InitGame(void)
{
gi.dprintf("Game is starting up.\n");
gi.dprintf("Game is ctf built on %s.\n", GAMEVERSION, BUILD_DATE);
gi.dprintf("Game is ctf built on %s.\n", GAMEVERSION, __DATE__);
gun_x = gi.cvar("gun_x", "0", 0);
gun_y = gi.cvar("gun_y", "0", 0);
@ -161,7 +157,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", BUILD_DATE, CVAR_SERVERINFO | CVAR_LATCH);
gi.cvar("gamedate", __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);
@ -204,9 +200,6 @@ InitGame(void)
/* dm map list */
sv_maplist = gi.cvar("sv_maplist", "", 0);
/* others */
aimfix = gi.cvar("aimfix", "0", CVAR_ARCHIVE);
/* items */
InitItems();
@ -500,7 +493,7 @@ WriteGame(char *filename, qboolean autosave)
}
memset(str, 0, sizeof(str));
strcpy(str, BUILD_DATE);
strcpy(str, __DATE__);
fwrite(str, sizeof(str), 1, f);
game.autosaved = autosave;
@ -533,7 +526,7 @@ ReadGame(char *filename)
fread(str, sizeof(str), 1, f);
if (strcmp(str, BUILD_DATE))
if (strcmp(str, __DATE__))
{
fclose(f);
gi.error("Savegame from an older version.\n");

View file

@ -813,11 +813,11 @@ SP_worldspawn(edict_t *ent)
if (ent->message && ent->message[0])
{
gi.configstring(CS_NAME, ent->message);
Q_strlcpy(level.level_name, ent->message, sizeof(level.level_name));
strncpy(level.level_name, ent->message, sizeof(level.level_name));
}
else
{
Q_strlcpy(level.level_name, level.mapname, sizeof(level.level_name));
strncpy(level.level_name, level.mapname, sizeof(level.level_name));
}
if (st.sky && st.sky[0])

View file

@ -168,11 +168,11 @@ SV_FilterPacket(char *from)
{
if ((in & ipfilters[i].mask) == ipfilters[i].compare)
{
return (filterban->value != 0);
return (int)filterban->value;
}
}
return (filterban->value == 0);
return (int)!filterban->value;
}
void

View file

@ -121,7 +121,7 @@ SP_target_speaker(edict_t *ent)
}
else
{
Q_strlcpy(buffer, st.noise, sizeof(buffer));
strncpy(buffer, st.noise, sizeof(buffer));
}
ent->noise_index = gi.soundindex(buffer);

View file

@ -110,10 +110,6 @@ 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
@ -450,8 +446,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 */
@ -541,8 +537,6 @@ extern cvar_t *flood_waitdelay;
extern cvar_t *sv_maplist;
extern cvar_t *aimfix;
#define world (&g_edicts[0])
/* item spawnflags */
@ -762,7 +756,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(edict_t *ent, vec3_t distance,
void P_ProjectSource(gclient_t *client, vec3_t point, 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,
@ -1039,7 +1033,7 @@ struct edict_s
int max_health;
int gib_health;
int deadflag;
int show_hostile;
qboolean show_hostile;
float powerarmor_time;
@ -1075,7 +1069,7 @@ struct edict_s
float delay; /* before firing targets */
float random;
float last_sound_time;
float teleport_time;
int watertype;
int waterlevel;

View file

@ -36,21 +36,8 @@
#include <stdlib.h>
#include <time.h>
#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;
typedef enum {false, true} qboolean;
#ifndef NULL
#define NULL ((void *)0)
@ -215,8 +202,6 @@ 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);
/* ============================================= */

View file

@ -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(edict_t *ent)
SP_info_player_intermission(void)
{
}
@ -89,7 +89,7 @@ SP_info_player_intermission(edict_t *ent)
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;

View file

@ -33,12 +33,10 @@ static byte is_silenced;
void weapon_grenade_fire(edict_t *ent, qboolean held);
void
P_ProjectSource(edict_t *ent, vec3_t distance,
P_ProjectSource(gclient_t *client, vec3_t point, vec3_t distance,
vec3_t forward, vec3_t right, vec3_t result)
{
gclient_t *client = ent->client;
float *point = ent->s.origin;
vec3_t _distance;
vec3_t _distance;
VectorCopy(distance, _distance);
@ -52,21 +50,6 @@ P_ProjectSource(edict_t *ent, 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);
}
}
}
/*
@ -136,7 +119,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->last_sound_time = level.time;
noise->teleport_time = level.time;
gi.linkentity(noise);
}
@ -676,7 +659,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, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
timer = ent->client->grenade_time - level.time;
speed = GRENADE_MINSPEED + (GRENADE_TIMER -
@ -865,7 +848,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, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
VectorScale(forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
@ -930,7 +913,7 @@ Weapon_RocketLauncher_Fire(edict_t *ent)
ent->client->kick_angles[0] = -1;
VectorSet(offset, 8, 8, ent->viewheight - 8);
P_ProjectSource(ent, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
fire_rocket(ent, start, forward, damage, 650, damage_radius, radius_damage);
/* send muzzle flash */
@ -983,7 +966,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, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
VectorScale(forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
@ -1217,7 +1200,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, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
fire_bullet(ent, start, forward, damage, kick,
DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD,
MOD_MACHINEGUN);
@ -1384,7 +1367,8 @@ Chaingun_Fire(edict_t *ent)
r = 7 + crandom() * 4;
u = crandom() * 4;
VectorSet(offset, 0, r, u + ent->viewheight - 8);
P_ProjectSource(ent, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset,
forward, right, start);
fire_bullet(ent, start, forward, damage, kick,
DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD,
@ -1443,7 +1427,7 @@ weapon_shotgun_fire(edict_t *ent)
ent->client->kick_angles[0] = -2;
VectorSet(offset, 0, 8, ent->viewheight - 8);
P_ProjectSource(ent, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
if (is_quad)
{
@ -1503,7 +1487,7 @@ weapon_supershotgun_fire(edict_t *ent)
ent->client->kick_angles[0] = -2;
VectorSet(offset, 0, 8, ent->viewheight - 8);
P_ProjectSource(ent, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
if (is_quad)
{
@ -1515,35 +1499,10 @@ 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);
@ -1614,7 +1573,7 @@ weapon_railgun_fire(edict_t *ent)
ent->client->kick_angles[0] = -3;
VectorSet(offset, 0, 7, ent->viewheight - 8);
P_ProjectSource(ent, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
fire_rail(ent, start, forward, damage, kick);
/* send muzzle flash */
@ -1704,7 +1663,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, offset, forward, right, start);
P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
fire_bfg(ent, start, forward, damage, 400, damage_radius);
ent->client->ps.gunframe++;

View file

@ -1072,43 +1072,6 @@ 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, ...)
{