Compare commits

...

102 commits

Author SHA1 Message Date
Yamagi
b315ef2993 Update the CHANGELOG. 2025-04-02 11:20:03 +02:00
Yamagi
868978ad84 Fix (potential) problematic use cases of qboolean.
xatrix had only one potential problematic use case, putting an int into
qboolean. It would have worked if qboolean is a bool, but better do it
right. No functional change intended.
2025-03-15 17:21:47 +01:00
Yamagi
2e95d187b5
Merge pull request #103 from BjossiAlfreds/door-use-fix
Fixed doors being unusable with NULL activator
2025-03-01 16:49:11 +01:00
Yamagi
f75a0e16f1 Fix build with C23 by reusing the predefined bool type. 2025-03-01 12:42:21 +01:00
Yamagi
26d8292829 Follow yquake2 and don't force a C standard in Makefile and CMakeLists.
This reverts 6482460.
2025-03-01 12:41:17 +01:00
BjossiAlfreds
026be478dd Fixed doors being unusable with NULL activator 2025-02-24 15:43:07 +00:00
Yamagi
64824600d1 Force C standard to gnu99 in cmake builds.
The Makefiles forces gnu99 since ages. Additionally gcc15 started to
default to C23 and our code doesn't (yet) build with it.
2025-02-22 11:43:01 +01:00
Yamagi
6ca882da1f Fix a typo. 2025-02-09 11:30:54 +01:00
Yamagi
28d4e362ed Add a Win64 workflow file. 2025-02-09 11:24:43 +01:00
Yamagi
a24ceb45b4 Add a Linux/aarch64 workflow file. 2025-02-09 11:23:10 +01:00
Yamagi
a6a7521ded Rename the Linux/x86_64 workflow file.
This is a preparation of an upcoming Linux/aarch64 build. While here
switch back to Ubuntu 22.04 as builder, we should use the same Ubuntu
version everywhere.
2025-02-09 11:22:47 +01:00
Yamagi
7b6b787c35 Update CI to use 4 CPUs on Linux and Windows. 2025-02-09 10:58:06 +01:00
Yamagi
d215802d16
Merge pull request #102 from protocultor/wpn_preview
Weapon preview for cycleweap
2024-12-21 09:52:30 +01:00
Jaime Moreira
6767664988 Weapon preview for cycleweap
'Pickup style' just like weapprev/weapnext, only works when cycleweap
is called with 3 or more parameters.
2024-12-04 19:00:43 -03:00
Yamagi
1957253b25 Mark g_swap_speed as CVAR_ARCHIVE. 2024-09-21 09:53:42 +02:00
Yamagi
16db9eab3f
Merge pull request #101 from BjossiAlfreds/spawntemp-leak-fix
Fixed spawntemp data leaking into mid-level spawned entities
2024-08-21 21:02:51 +02:00
Yamagi
de69b2a37d
Merge pull request #100 from devnexen/hunt_target_fix
backport yquake2 fix for HuntTarget unitialised vector
2024-08-18 17:05:34 +02:00
David Carlier
9fc912dc01
backport yquake2 fix for HuntTarget unitialised vector 2024-08-18 14:40:53 +01:00
BjossiAlfreds
6cfda5732d Fixed spawntemp data leaking into mid-level spawned entities 2024-08-12 16:31:04 +00:00
Yamagi
6fba354e60 There's no need to run brew upgrade. 2024-08-12 18:23:10 +02:00
Yamagi
68f407f16f Add CI workflows for Linux, MacOS and Windows.
This is equivalent to the CI workflows added to the yquake2 main
repository. The workflows are triggered on commit, for new pull
requests and when the pull request branch is updated. The CI is
mostly for providing users with up to date test builds.
2024-08-12 15:40:29 +02:00
Yamagi
69faeb6777 Modernize the README.
Convert to markdown and follow the same style as the yquake2 main
repository. Use it's resources were appropriate.
2024-08-12 15:31:59 +02:00
Yamagi
31b1c2d92b Add g_monsterfootsteps to the CHANGELOG. 2024-07-22 18:01:40 +02:00
Yamagi
33cb7a911f
Merge pull request #99 from 0lvin/master
Add Monster footsteps support #91
2024-07-22 18:00:58 +02:00
Denis Pauk
4faedcf71e Add Monster footsteps support #91 2024-07-21 13:23:02 +03:00
Yamagi
b2e6790c8f Update CHANGELOG for 'Work around naggy help icons'. 2024-07-20 09:21:07 +02:00
Yamagi
2d6c12b423
Merge pull request #98 from BjossiAlfreds/helpmsg-always
Workarounds for naggy help icons
2024-07-20 09:18:39 +02:00
BjossiAlfreds
df596a7b44 Workarounds for naggy help icons 2024-07-15 22:46:01 +00:00
Yamagi
36e9e03144 Switch g_quick_weap to 1 by default.
It's a nice to have convenience feature that most players will never
notice. Die hard traditionalists can switch it off.
2024-07-15 21:44:18 +02:00
Yamagi
7a173ac7c1 Fix description of g_quick_weap. 2024-07-15 21:43:46 +02:00
Yamagi
0da2327185 Update CHANGELOG for 2.13. 2024-07-13 16:26:16 +02:00
Yamagi
b837ee59e6
Merge pull request #97 from protocultor/quick_weap
Faster "weapprev" and "weapnext" behavior
2023-12-17 11:50:44 +01:00
Jaime Moreira
e8065c8b5a Preview of the coming weapon for weapprev/weapnext
The weapon you are changing to appears in the HUD, in "pickup" format.
Requires g_quick_weap == 1.
2023-12-16 17:51:10 -03:00
Jaime Moreira
091dff9b59 Faster "weapprev" and "weapnext" behavior
Allows to skip the "previous" or "next" weapon, by constantly tapping
the bound key (or scrolling the mouse wheel).
2023-12-07 23:42:40 -03:00
Yamagi
d6f7384c74 s/Jaime Moreira/protocultor/g 2023-11-08 18:48:29 +01:00
Yamagi
05c915ca54 Update the CHANGELOG for version 2.12. 2023-11-04 11:01:20 +01:00
Yamagi
80016e7f7b Port aimfix support for the super shotgun from yquake2.
This enables the `aimfix` cvar for the super shotgun. While here add the
same fix to the phalanx, which is just a super shotgun with plasma
instead of shells.
2023-11-04 10:28:09 +01:00
Yamagi
0ee9b324a1 Relicense xatrix aka The Reckoning to GPL2.
This was made possible by id Software rereleasing the unaltered addon
sources codes under GPL2:

  https://github.com/id-Software/quake2-rerelease-dll/

All past contributors but one agreed with the relicensing:

* Andrey Nazarov - @skullernet
* Angus Freudenberg - @afreuden
* @BjossiAlfreds
* @DanielGibson
* David Carlier - @devnexen
* Denis Pauk - @0lvin
* @De-Seppe
* Jaime Moreira - @protocultor
* Joshua Scoggins - @DrItanium
* Mitchell Richters - @mjr4077au
* @NeonKnightOA
* Scott - @Pickle
* svdijk - @svdijk
* Yamagi

@Dremor8484 didn't give their permission, their commits were reverted:

* 368df08
* 44e50a1
* 04868b7

Many thanks to all involved with this project!
2023-11-04 10:14:22 +01:00
Yamagi
420413d169 Revert "Update weapon.c"
This reverts commit 04868b72ee.

The author didn't give us permission to relicense the code to GPL2.
2023-11-04 10:13:15 +01:00
Yamagi
b2fe34a575 Revert "Update weapon.c"
This reverts commit 44e50a12ca.

The author didn't give us permission to relicense the code to GPL2.
2023-11-04 10:13:06 +01:00
Yamagi
6fb31423e5 Revert "Update weapon.c"
This reverts commit 368df08757.

The author didn't give us permission to relicense the code to GPL2.
2023-11-04 10:12:47 +01:00
Yamagi
8123986f86
Merge pull request #95 from protocultor/limits
Added missing include, fixing compilation in Linux and MacOS
2023-09-15 20:21:19 +02:00
Jaime Moreira
0a34834dc5 Added missing include for USHRT_MAX 2023-09-15 11:52:42 -03:00
Yamagi
381b0ca57c
Merge pull request #94 from protocultor/g_swap_speed_fix
Fix for g_swap_speed behaviour with extreme values
2023-09-14 21:12:42 +02:00
Jaime Moreira
b86d7e954c Just typos 2023-08-26 22:49:41 -04:00
Jaime Moreira
1e63034859 Fixed g_swap_speed behaviour with extreme values
When its value was between 0 and 1, rounded down to 0; did the same
when bigger than 65535. Both cases locked up the weapon animation.
2023-08-26 22:48:23 -04:00
Yamagi
751f3f56fa
Merge pull request #90 from BjossiAlfreds/tdam-dir
T_Damage no longer modifies dir parameter
2023-07-16 09:49:44 +02:00
BjossiAlfreds
e1aaa64b67 T_Damage no longer modifies dir parameter 2023-07-07 23:47:15 +00:00
Yamagi
ae8a86dd71
Merge pull request #89 from protocultor/g_swap_speed
Cheat to speed up "weapon change" animations
2023-07-01 16:21:47 +02:00
Jaime Moreira
8e46e411bc Snappier "g_swap_speed" behaviour
Player is no longer forced to go through the last frame of activation
or deactivation of a weapon before changing its state.
2023-06-29 11:37:36 -04:00
Jaime Moreira
a43de22013 Cheat cvar "g_swap_speed" implemented
Allows to skip frames of "putting down weapon" and
"raising weapon" animations, speeding them up.
2023-06-28 15:57:43 -04:00
Yamagi
4a04cf8afd
Merge pull request #87 from BjossiAlfreds/makronjmp
Fixes to makron jump sequence
2023-06-17 16:36:14 +02:00
BjossiAlfreds
951fdb4f97 Fixes to makron jump sequence 2023-06-07 13:42:23 +00:00
Yamagi
94284938f4
Merge pull request #86 from BjossiAlfreds/makrondeath
Fixed ungibbable makron parts
2023-05-13 15:22:04 +02:00
BjossiAlfreds
15567f94a3 Fixed ungibbable makron parts 2023-05-09 18:32:27 +00:00
Yamagi
1010b2c694
Merge pull request #85 from BjossiAlfreds/intersight
Fixed monsters seeing players during intermissions
2023-05-08 18:08:56 +02:00
Yamagi
9626e71c86
Merge pull request #84 from BjossiAlfreds/gladrange
Fixed stand-ground gladiators not attacking at certain range
2023-05-08 18:07:38 +02:00
BjossiAlfreds
e0fb272e65 Fixed monsters seeing players during intermissions 2023-04-26 01:30:21 +00:00
BjossiAlfreds
04c9248961 Fixed stand-ground gladiators not attacking at certain range 2023-04-22 18:51:05 +00:00
Yamagi
1a3e721d51
Merge pull request #83 from Dremor8484/master
Update weapon.c
2023-03-25 17:15:31 +01:00
Dremor8484
04868b72ee
Update weapon.c
phalanx aimfix (like the supershotgun)
the first shot (in the if statement) is to the right, the second shot (in the else statement) shoots left

without the change to the code 1 shot is centered on the aim cross, the other is on the right
with the change to the code the left shot is on the left of the crossair and it touches the left -- of the crossair, while the right shot is on the right and touches the right -- of the crossair
2022-12-16 04:27:38 +01:00
Yamagi
92d83faff4 Update the CHANGELOG for 2.11. 2022-12-03 17:03:51 +01:00
Yamagi
b4c4a15c7d
Merge pull request #82 from Dremor8484/Dremor8484-xatrix-doublebarrelshotgun-aimfix
Update weapon.c
2022-12-03 16:56:28 +01:00
Dremor8484
44e50a12ca
Update weapon.c
the aimfix was working only on half of the attack, since the supershotgun shoots 2 times (half bullets left, half bullets right)

to carefully test it i tried to comment out 1 of the 2 shots while also keep yaw change to 0
in 1 case the bullets hit around the crossair, in the other case the bullets were not centered around the crossair.

i added the same fix to the shot that did not have it, and it worked.

i tested it out with yaw-5 and yaw+5 with both shots shooting at the same time and the bullets appeared to gather into 2 distinct clusters one left side of crossair, one right side of crossair like 2 eyes on the wall
2022-12-03 15:42:44 +01:00
Yamagi
731af54f2c
Merge pull request #80 from devnexen/va_fmt_chg
va little signature change
2022-11-06 17:20:48 +01:00
David CARLIER
0dc3c87742 va little signature change 2022-11-05 10:26:14 +00:00
Yamagi
f0059cecce
Merge pull request #81 from protocultor/underwater_phalanx
Underwater impacts of the Phalanx cannon sound muffled
2022-11-05 10:05:05 +01:00
Jaime Moreira
ed8c40349d Underwater impacts of the Phalanx sound muffled 2022-10-25 22:08:34 -03:00
Yamagi
c151fffd3a
Merge pull request #75 from skullernet/master
Remove broken pusher delta yaw manipulation.
2022-10-08 15:39:05 +02:00
Yamagi
b5149f927c
Merge pull request #79 from BjossiAlfreds/collision
Prevent dead bodies from obstructing elevators and falling through them
2022-10-08 15:35:52 +02:00
Yamagi
8c890f4347
Merge pull request #78 from BjossiAlfreds/powercubes
Fix coop power cube related bugs
2022-10-08 15:35:09 +02:00
Yamagi
dcc7860ffd
Merge pull request #77 from BjossiAlfreds/splashes
Fix items already in water at level start playing splash sound
2022-10-08 15:33:36 +02:00
Yamagi
eb55860150
Merge pull request #76 from BjossiAlfreds/flood
Prevent crash or memory corruption when flood_msgs is too high or too low
2022-10-08 15:33:23 +02:00
BjossiAlfreds
1a197b09a6 Prevent dead bodies from obstructing elevators and falling through them 2022-09-30 15:15:05 +00:00
BjossiAlfreds
d3d4e5357d Fix coop power cube related bugs 2022-09-24 14:32:43 +00:00
BjossiAlfreds
1d04967d88 Fix items already in water at level start playing splash sound 2022-09-24 12:22:40 +00:00
BjossiAlfreds
8431e0f15d Prevent crash or memory corruption when flood_msgs is too high or too low 2022-09-24 01:50:15 +00:00
Andrey Nazarov
e4c26a187d Remove broken pusher delta yaw manipulation.
This didn't work correctly for multiple reasons:

1. `deltayaw` was wrongly initialized for the pusher itself, rather than
for pushed client.

2. `delta_angles[YAW]` is a short, adding plain `amove[YAW]` to it is
wrong.

To support yaw angle rotation properly, delta_angles must be
interpolated on the client. But this is hardly practical as it would
introduce other bugs. Thus, simply remove delta yaw manipulation code
altogether.

Fixes infamous Q2 bug when player standing on a blocked lift gets turned
to wrong direction.
2022-09-09 21:56:09 +03:00
Yamagi
8fb33ee9fd
Merge pull request #74 from protocultor/cycleweap_quick
Faster weapon switching with 'cycleweap'
2022-08-07 18:21:53 +02:00
Jaime Moreira
5e31017f49 Faster weapon switching with 'cycleweap'
Allows to skip elements on the weapon list by tapping the same bound key
2022-08-01 14:34:49 -04:00
Yamagi
f4643f174f
Merge pull request #73 from Dremor8484/Dremor8484-xatrix-doublebarrelshotgun-aimfix
Update weapon.c
2022-06-11 17:03:03 +02:00
Dremor8484
368df08757
Update weapon.c
xatrix-doublebarrelshotgun-aimfix
2022-06-10 19:10:19 +02:00
Yamagi
8d6a6188c3 Fix off by one in Info_SetValueForKey(). Found by ASAN. 2022-05-28 11:40:09 +02:00
Yamagi
141458257f Update CHANGELOG for 2.10. 2022-05-28 11:40:09 +02:00
Yamagi
39e4828a65
Merge pull request #71 from devnexen/build_macos_arm_fix
Forcing proper native arch build on darwin mainly due to arm64
2022-05-20 12:48:53 +02:00
David CARLIER
67f45e6a33 Forcing proper native arch build on darwin mainly due to arm64 2022-05-14 16:29:14 +01:00
Yamagi
fdf95542f2
Merge pull request #70 from protocultor/prefweap
Added prefweap command to select weapon by priority
2022-04-13 11:51:11 +02:00
Jaime Moreira
d0ec2a5c72 Added prefweap command to select weapon by priority 2022-04-11 09:39:52 -04:00
Yamagi
4c65436342 Fix door_go_up() exiting early.
The problem in door_go_up() may prevent doors from crushing something
blocking them. While add it sanity check `activator` in
`G_UseTargets()`.
2022-02-05 17:18:27 +01:00
Yamagi
f97f46f91d Force an MASK_SHOT clip mask for thrown heads.
The ThrowHead() and ThrowClientHead() functions are special. They
transform the entity given in `self` (mostly the caller itself) into a
ripped off head. They don't reset the entities clip mask, which may
cause problems in interactions with other entities. Fix that by reseting
the clip mask to `MASK_SHOT`.

Suggested by @BjossiAlfreds.
2022-02-05 17:14:48 +01:00
Yamagi
dfd2224bbf Fix laser guard trying to fire two shots when dying.
The laser guard is implemented different than the other guards, the
'last stand' animation doesn't match the implementation. Work around
that by avoid that animation.

Found by @drakonorodny and fix suggested by @BjossiAlfreds.

Closes #68.
2021-11-13 12:43:09 +01:00
Yamagi
a7eb445151
Merge pull request #69 from BjossiAlfreds/playernoise
Fixed player_noise entity leak and improved stability surrounding player noises
2021-11-06 08:48:41 +01:00
BjossiAlfreds
0a4c45ddf2 Fixed player_noise entity leak and improved stability surrounding player noises 2021-11-06 02:24:28 +00:00
Yamagi
640d01364c Fix soldiers never showing their pain skins as long as they're alive.
Since `self->helth` is set after calling `master_start()`
`self->max_health is always 0. Found by @drakonorodny and
analyzed by @BjossiAlfreds.
2021-11-05 07:12:05 +01:00
Yamagi
f6b76c2374 Made the game able to handle entity overload better.
This is a port of yquake2 commit c3b57bc8.
2021-11-04 16:56:34 +01:00
Yamagi
e67c63a03e
Merge pull request #67 from De-Seppe/master
Feature request : add cvar to disable machine gun recoil in single player #741 (xatrix)
2021-09-28 18:34:21 +02:00
De-Seppe
020b142e7b Rename variable to conform to naming guidelines
Change the name of the cvar machinegun_norecoil to g_machinegun_norecoil to conform to the naming guidelines
2021-09-27 18:30:32 +02:00
De-Seppe
aa2a3fcda2 Add cvar machinegun_norecoil
Add cvar machinegun_norecoil
This cvar allows to disable machinegun recoil in single player.
The default value is the original Quake 2 behaviour.
2021-09-27 13:11:37 +02:00
Yamagi
f6d8c0fe61 Refine the g_footstep cvar.
There were complains that always generating footsteps is annoying,
because there will be footsteps while swimming or jumping. Refine
the cvar a little bit:

* `0`: No footsteps at all.
* `1`: Vanilla Quake II behavior.
* `2`: Always footsteps as long as the player has a ground entity.
* `3`: Always footsteps.

The changes the meaning of the values, `2` has become `3`.

Closes yquake2/yquake2#738.
2021-08-25 18:35:41 +02:00
Yamagi
c53bb15688 Add a warning that the CMakeLists.txt is unmaintained. 2021-07-23 08:34:10 +02:00
Yamagi
052066f355 Revert "Retire unmaintained CMakeLists.txt."
It turned out that there're some special cases not (yet) covered by the
Makefile. Crossbuilding in specialized chroot environments are one
example.
2021-07-23 08:29:01 +02:00
Yamagi
15791dc75e Retire unmaintained CMakeLists.txt.
I added the CMakeLists.txt 6 or 7 years ago so I could load the code
into Jetbrains Clion. I have moved to another editor years ago and the
cmake stuff is effectively unmaintained since then. We kept it around
in case that we'll do a MSVC port, but that's unlikely at this point.
Since bugreport and problems with the CMakeLists.txt keep coming up,
finally retire them. They can be resurrected from the git history if
we'll ever need them again.

Part of yquake2/yquake2#725.
2021-06-29 11:02:33 +02:00
57 changed files with 3518 additions and 1784 deletions

46
.github/workflows/linux_aarch64.yml vendored Normal file
View file

@ -0,0 +1,46 @@
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-xatrix-linux_aarch64-${{github.sha}}/misc/docs
# Copy release assets
cp -r release/* publish/quake2-xatrix-linux_aarch64-${{github.sha}}/
# Copy misc assets
cp -r stuff/mapfixes publish/quake2-xatrix-linux_aarch64-${{github.sha}}/misc
cp LICENSE publish/quake2-xatrix-linux_aarch64-${{github.sha}}/misc/docs/LICENSE.txt
cp README.md publish/quake2-xatrix-linux_aarch64-${{github.sha}}/misc/docs/README.txt
- name: Upload testbuild package
uses: actions/upload-artifact@v4
with:
name: quake2-xatrix-linux_aarch64-${{github.sha}}
path: publish/
if-no-files-found: error

46
.github/workflows/linux_x86_64.yml vendored Normal file
View file

@ -0,0 +1,46 @@
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-xatrix-linux_x86_64-${{github.sha}}/misc/docs
# Copy release assets
cp -r release/* publish/quake2-xatrix-linux_x86_64-${{github.sha}}/
# Copy misc assets
cp -r stuff/mapfixes publish/quake2-xatrix-linux_x86_64-${{github.sha}}/misc
cp LICENSE publish/quake2-xatrix-linux_x86_64-${{github.sha}}/misc/docs/LICENSE.txt
cp README.md publish/quake2-xatrix-linux_x86_64-${{github.sha}}/misc/docs/README.txt
- name: Upload testbuild package
uses: actions/upload-artifact@v4
with:
name: quake2-xatrix-linux_x86_64-${{github.sha}}
path: publish/
if-no-files-found: error

50
.github/workflows/macos.yml vendored Normal file
View file

@ -0,0 +1,50 @@
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-xatrix-macos-${{github.sha}}/misc/docs
# Copy release assets
cp -r release/* publish/quake2-xatrix-macos-${{github.sha}}/
# Copy misc assets
cp -r stuff/mapfixes publish/quake2-xatrix-macos-${{github.sha}}/misc
cp LICENSE publish/quake2-xatrix-macos-${{github.sha}}/misc/docs/LICENSE.txt
cp README.md publish/quake2-xatrix-macos-${{github.sha}}/misc/docs/README.txt
- name: Upload testbuild package
uses: actions/upload-artifact@v4
with:
name: quake2-xatrix-macos-${{github.sha}}
path: publish/
if-no-files-found: error

57
.github/workflows/win32.yml vendored Normal file
View file

@ -0,0 +1,57 @@
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-xatrix-win32-${{github.sha}}/misc/docs
# Copy release assets
cp -r release/* publish/quake2-xatrix-win32-${{github.sha}}/
# Copy misc assets
cp -r stuff/mapfixes publish/quake2-xatrix-win32-${{github.sha}}/misc
cp LICENSE publish/quake2-xatrix-win32-${{github.sha}}/misc/docs/LICENSE.txt
cp README.md publish/quake2-xatrix-win32-${{github.sha}}/misc/docs/README.txt
- name: Upload testbuild package
uses: actions/upload-artifact@v4
with:
name: quake2-xatrix-win32-${{github.sha}}
path: publish/
if-no-files-found: error

57
.github/workflows/win64.yml vendored Normal file
View file

@ -0,0 +1,57 @@
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-xatrix-win64-${{github.sha}}/misc/docs
# Copy release assets
cp -r release/* publish/quake2-xatrix-win64-${{github.sha}}/
# Copy misc assets
cp -r stuff/mapfixes publish/quake2-xatrix-win64-${{github.sha}}/misc
cp LICENSE publish/quake2-xatrix-win64-${{github.sha}}/misc/docs/LICENSE.txt
cp README.md publish/quake2-xatrix-win64-${{github.sha}}/misc/docs/README.txt
- name: Upload testbuild package
uses: actions/upload-artifact@v4
with:
name: quake2-xatrix-win64-${{github.sha}}
path: publish/
if-no-files-found: error

View file

@ -1,3 +1,48 @@
The Reckoning 2.13 to 2.14:
- Add weapon preview to the `cycleweap` command (by protocultor)
- Fix leaking temporary spawnflags into entities spawned mid-level. (by
BjossiAlfreds)
The Reckoning 2.12 to 2.13:
- Implement `g_quick_weap`. If set to 1, both weapprev and weapnext
commands will count how many times they have been called, making
possible to skip weapons by quickly tapping one of these keys. (by
protocultor)
- Work around naggy help icons. (by BjossiAlfreds)
- Implement `g_monsterfootsteps`. (by 0lvin)
The Reckoning 2.11 to 2.12:
- Relicense under GPL2.
- Implement `g_swap_speed`. This allows to skip frames of "putting down
weapon" and "raising weapon" animations, speeding them up. (by
protocultor)
- Several fixes to makron (by BjossiAlfreds)
- Fixed stand-ground gladiators not attacking at certain range. (by
BjossiAlfreds)
- Fixed monsters seeing players during intermissions. (by BjossiAlfreds)
The Reckoning 2.10 to 2.11:
- Implement faster weapon switching with the new 'cycleweap' command.
(by protocultor).
- Fixes pusher delta yaw manipulation. This fixes the infamous bug were
a player standing on a blocked elevator gets turned around (by
skuller).
- Fix several coop related bugs with the powercubes. (by BjossiAlfreds)
- A way better fix for dead bodies obstructing elevators or falling
through the worldmodel. (by BjossiAlfreds)
- Fix items already in water playing a splash sound at level start. (by
BjossiAlfreds)
- Phalanx explosions should be muffled under water. (by protocultor)
The Reckoning 2.09 to 2.10:
- Refine the 'g_footstep' cvar to match Quake II itself.
- Implement 'g_machinegun_norecoil'. The cvar is cheat protected. (by
De-Seppe)
- Fix soldiers never showing their pain skins as long as they're alive.
(by BjossiAlfreds)
- Fix laser guard trying to fire two shots when dying. (Found by
drakonorodny and fix suggested by BjossiAlfreds)
The Reckoning 2.08 to 2.09:
- Fix wrong sound for some items when activated. (by BjossiAlfreds)
- Port the 'aimfix' cvar. (by Mitchell Richters)

View file

@ -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)

580
LICENSE
View file

@ -1,328 +1,340 @@
LIMITED PROGRAM SOURCE CODE LICENSE
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
This Limited Program Source Code License (the "Agreement") is between
Id Software, Inc., a Texas corporation, (hereinafter "Id Software")
and Licensee (as defined below) and is made effective beginning on
the date you, the Licensee, download the Code, as defined below,
(the "Effective Date"). BY DOWNLOADING THE CODE, AS DEFINED
BELOW, YOU, THE LICENSEE, AGREE TO ALL THE TERMS AND CONDITIONS OF
THIS AGREEMENT. YOU SHOULD READ THIS AGREEMENT CAREFULLY BEFORE
DOWNLOADING THE CODE. EVERY PERSON IN POSSESSION OF AN AUTHORIZED
COPY, AS DEFINED BELOW, OF THE CODE SHALL BE SUBJECT TO THE TERMS
AND CONDITIONS OF THIS AGREEMENT.
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
R E C I T A L S
Preamble
WHEREAS, Id Software is the owner and developer of the computer software
program source code accompanied by this Agreement (the "Code");
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
WHEREAS, Id Software desires to license certain limited non-exclusive
rights regarding the Code to Licensee; and
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
WHEREAS, Licensee desires to receive a limited license for such rights.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
T E R M S A N D C O N D I T I O N S
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
NOW, THEREFORE, for and in consideration of the mutual premises
contained herein and for other good and valuable consideration,
the receipt and sufficiency of which is hereby acknowledged, the
undersigned parties do hereby agree as follows:
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
1. Definitions. The parties hereto agree the following definitions
shall apply to this Agreement:
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
a. "Authorized Copy" shall mean a copy of the Code obtained by
Authorized Means, as defined below. A copy of the Code is not
an "Authorized Copy" unless it is accompanied by a copy of this
Agreement and obtained by Authorized Means. A Modified Copy,
as defined below, is not an Authorized Copy;
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
b. "Authorized Means" shall mean obtaining an Authorized Copy only
by downloading the Authorized Copy from Id Software's Internet web
site or from another web site authorized or approved by Id Software
for such purposes or by obtaining an Authorized Copy by electronic
means via the Internet;
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
c. "Code" shall mean the computer software program source code
which accompanies this Agreement and includes Code included within
any Modified Copy and which is the code that constitutes the
Authorized Copy;
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
d. "Game" shall mean QUAKE II;
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
e. "Licensee" shall mean you, the person who is in possession of
an Authorized Copy by Authorized Means; and
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
f. "Modified Copy" shall mean a copy of the Code first obtained
by Authorized Means which is subsequently modified by Licensee,
as provided in paragraph 2. below.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. Grant of Rights. Subject to the terms and provisions of this
Agreement, Id Software hereby grants to Licensee and Licensee hereby
accepts, a limited, world-wide (except as otherwise provided herein),
non-exclusive, non-transferable, and non-assignable license to: (i)
use the Authorized Copy and the Modified Copy, as defined above, for
the development by Licensee of extra levels operable with the Game (the
"Extra Levels"); (ii) incorporate all or a portion of the Authorized Copy
and the Modified Copy within the Extra Levels; (iii) distribute by way
of a sublicense limited by the terms of this Agreement, free of charge
and at no cost, the Authorized Copy and the Modified Copy to the extent
such Modified Copy and such Authorized Copy, or a portion thereof, is
included within the Extra Levels; (iv) distribute by way of a sublicense
limited by the terms of this Agreement, free of charge and at no cost, by
electronic transmission via the Internet only the Authorized Copy without
any alteration or modification along with a copy of this Agreement which
must always accompany the Authorized Copy; (v) modify the Authorized Copy
in order to create a Modified Copy, as defined above; and (vi) distribute
the Modified Copy by way of a sublicense limited by the terms of this
Agreement, free of charge and at no cost, by electronic transmission via
the Internet only. Each person or entity who/which receives a copy of
the Code shall be subject to the terms of this Agreement but, no rights
are granted to any person or entity who/which obtains, receives, or is
in possession of any copy of the Code by other than Authorized Means.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
3. Reservation of Rights and Prohibitions. Id Software expressly
reserves all rights not granted herein. Licensee shall not make any use
of the trademarks relating to the Game or Id Software (the "Trademarks").
Any use by Licensee of the Authorized Copy or the Modified Copy not
expressly permitted in paragraph 2. above is expressly prohibited and
any such unauthorized use shall constitute a material breach of this
Agreement by Licensee. Any use of the Code, whether included within
a Modified Copy or otherwise, and/or the Authorized Copy not permitted
in this Agreement shall constitute an infringement or violation of Id
Software's copyright in the Code. Licensee shall not copy, reproduce,
manufacture or distribute (free of charge or otherwise) the Authorized
Copy or the Modified Copy in any tangible media, including, without
limitation, a CD ROM. Licensee shall not commercially exploit by sale,
lease, rental or otherwise the Authorized Copy or the Modified Copy
whether included within Extra Levels or otherwise. Licensee shall not
commercially exploit by sale, lease, rental or otherwise any Extra Levels
developed by the use of the Code, whether in whole or in part. Licensee
is not receiving any rights hereunder regarding the Game, the Trademarks
or any audio-visual elements, artwork, sound, music, images, characters,
or other element of the Game. Licensee may modify the Authorized Copy in
order to create a Modified Copy, as noted above, but all sublicensees who
receive the Modified Copy shall not receive any rights to commercially
exploit or to make any other use of the Code included therein except the
right to use such Code for such sublicensee's personal entertainment. By
way of example and not exclusion, a sublicensee for the Modified Copy
shall not further modify the Code within the Modified Copy. Only the
Licensee who obtains the Code by Authorized Means shall be permitted to
modify such Code on the terms as described in this Agreement.
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
4. Additional Obligations. In addition to the obligations of Licensee
otherwise set forth in this Agreement, during the Term, and thereafter
where specified, Licensee agrees that:
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
a. Licensee will not attack or challenge the ownership by Id
Software of the Code, the Authorized Copy, the Game, the Trademarks,
or any copyright, patent or trademark or other intellectual property
right related thereto and Licensee will not attack or challenge
the validity of the license granted hereunder during the Term or
thereafter; and
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
b. Licensee will promptly inform Id Software of any unauthorized
use of the Code, the Authorized Copy, the Trademarks, or the Game,
or any portions thereof, and will reasonably assist Id Software
in the enforcement of all rights Id Software may have against such
unauthorized users.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
5. Ownership. Title to and all ownership rights in and to the Code,
whether included within the Modified Copy, the Authorized Copy or
otherwise, the Game, the Authorized Copy, and the Trademarks and the
copyrights, trade secrets, trademarks, patents and all other intellectual
property rights related thereto shall remain with Id Software which shall
have the exclusive right to protect the same by copyright or otherwise.
Licensee shall have no ownership rights in or to the Game, the Code,
the Authorized Copy or the Trademarks. Licensee acknowledges that
Licensee, by this Agreement, is only receiving a limited license to use
the Authorized Copy, as specified in paragraph 2. of this Agreement.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
6. Compliance with Applicable Laws. In exercising Licensee's
limited rights hereunder, Licensee shall comply with all applicable
laws, [including, without limitation, 22 U.S.C., section 2778 and 22
U.S.C. C.F.R. Parts 120-130 (1995)] regulations, ordinances and statutes,
including, but not limited to, the import/export laws and regulations
of the United States and its governmental and regulatory agencies
(including, without limitation, the Bureau of Export Administration
and the U.S. Department of Commerce) and all applicable international
treaties and laws.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
7. Term and Termination.
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
a. The term of this Agreement and the license granted herein
begins on the Effective Date and shall expire, without notice,
on a date one (1) calendar year from the Effective Date (the "Term").
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
b. Either party may terminate this Agreement, for any reason or
no reason, on thirty (30) days written notice to the other party.
Termination will be effective on the thirtieth (30th) day following
delivery of the notice of termination. Notwithstanding anything
to the contrary herein, this Agreement shall immediately terminate,
without the requirement of any notice from Id Software to Licensee,
upon the occurrence of any of the following "Terminating Events":
(i) if Licensee files a petition in bankruptcy; (ii) if Licensee
makes an assignment for the benefit of creditors; (iii) if any
bankruptcy proceeding or assignment for benefit of creditors is
commenced against Licensee and not dismissed within sixty (60)
days after the date of its commencement; (iv) the insolvency of
Licensee; or (v) a breach, whether material or otherwise, of this
Agreement by Licensee. Upon the occurrence of a Terminating Event,
this Agreement and any and all rights hereunder shall terminate
without prejudice to any rights or claims Id Software may have,
and all rights granted hereunder shall revert, without notice,
to and be vested in Id Software.
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
c. Termination or expiration of this Agreement shall not create
any liability against Id Software and shall not relieve Licensee
from any liability which arises prior to termination or expiration.
Upon expiration or earlier termination of this Agreement, Licensee
shall have no further right to exercise the rights licensed hereunder
or otherwise acquired in relation to this Agreement.
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
8. Licensee's Warranties. Licensee warrants and represents that:
(i) Licensee has full legal rights and authority to enter into and
become bound by the terms of this Agreement; (ii) Licensee has full
legal rights and authority to perform Licensee?s obligations hereunder;
(iii) Licensee will comply, at all times during the Term, with all
applicable laws, as set forth hereinabove; (iv) all modifications which
Licensee performs on the Code in order to create the Modified Copy and
all non-Id Software property included within Extra Levels shall not
infringe against or misappropriate any third party rights, including,
without limitation, copyrights and trade secrets; and (v) the use or
non-use of all modifications which Licensee performs on the Code in order
to create the Modified Copy and all non-Id Software property included
within Extra Levels shall not infringe against or misappropriate any third
party rights, including, without limitation, copyrights and trade secrets.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
9. Indemnification. Licensee hereby agrees to indemnify, hold
harmless and defend Id Software and Id Software's predecessors,
successors, assigns, officers, directors, shareholders, employees,
agents, representatives, licensees (but not including Licensee),
sublicensees, distributors, attorneys and accountants (collectively,
the "Id Related Parties") from and against any and all "Claims", which
shall mean all damages, claims, losses, causes of action, liabilities,
lawsuits, judgments and expenses (including, without limitation,
reasonable attorneys' fees and expenses) arising from, relating to or in
connection with (i) a breach of this Agreement by Licensee and/or (ii)
Licensee's use or non-use of the Code, whether the Authorized Copy or
whether a portion of the Code as may be included within the Modified
Copy or within Extra Levels. Id Software agrees to notify Licensee
of any such Claims within a reasonable time after Id Software learns
of same. Licensee, at its own expense, shall defend Id Software and the
Id Related Parties from and against any and all Claims. Id Software and
the Id Related Parties reserve the right to participate in any defense
of the Claims with counsel of their choice, and at their own expense.
In the event Licensee fails to provide a defense, then Licensee shall be
responsible for paying the attorneys' fees and expenses incurred by Id
Software and the Id Related Parties regarding the defense of the Claims.
Id Software and the Id Related Parties, as applicable, agree to reasonably
assist in the defense of the Claims. No settlement by Licensee of any
Claims shall be valid unless Licensee receives the prior written consent
of Id Software and the Id Related Parties, as applicable, to any such
settlement, with consent may be withheld in Id Software's and the Id
Related Parties' sole discretion.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
10. Limitation of Liability. UNDER NO CIRCUMSTANCES SHALL ID SOFTWARE
BE LIABLE TO LICENSEE FOR ACTUAL, SPECIAL, INCIDENTAL, CONSEQUENTIAL
OR PUNITIVE DAMAGES OR ANY OTHER DAMAGES, WHETHER OR NOT ID SOFTWARE
RECEIVES NOTICE OF ANY SUCH DAMAGES.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. Disclaimer of Warranties. ID SOFTWARE EXPRESSLY DISCLAIMS ALL
WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, WITH REGARD TO THE CODE, THE AUTHORIZED COPY AND OTHERWISE.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
12. Goodwill. Licensee recognizes the great value of the goodwill
associated with the Game and the Trademarks, and acknowledges that such
goodwill, now existing and hereafter created, exclusively belongs to Id
Software and that the Trademarks have acquired a secondary meaning in
the mind of the public.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
13. Remedies. In the event of a breach of this Agreement by Id Software,
Licensee's sole remedy shall be to terminate this Agreement by delivering
written notice of termination to Id Software. In the event of a breach
by Licensee of this Agreement, Id Software may pursue the remedies to
which Id Software is entitled under applicable law and this Agreement.
Licensee agrees that Licensee's unauthorized use of the Authorized
Copy would immediately and irreparably damage Id Software, and in the
event of such threatened or actual unauthorized use, Id Software shall
be entitled to an injunctive order appropriately restraining and/or
prohibiting such unauthorized use without the necessity of Id Software
posting bond or other security. Pursuit of any remedy by Id Software
shall not constitute a waiver of any other right or remedy of Id Software
under this Agreement or under applicable law.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
14. Choice of Law, Venue and Service of Process. This Agreement shall
be construed in accordance with the laws of the State of Texas and
applicable United States federal law and all claims and/or lawsuits
in connection with this Agreement must be brought in Dallas County,
Texas where exclusive venue shall lie. Licensee hereby agrees that
service of process by certified mail to the address set forth below,
with return receipt requested, shall constitute valid service of process
upon Licensee. If for any reason Licensee has moved or cannot be validly
served, then Licensee appoints the Secretary of State of the state of
Texas to accept service of process on Licensee's behalf.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
15. Delivery of Notices. Unless otherwise directed in writing by
the parties, all notices given hereunder shall be sent to the last
known address of addressee. All notices, requests, consents and other
communications under this Agreement shall be in writing and shall be
deemed to have been delivered on the date personally delivered or on the
date deposited in the United States Postal Service, postage prepaid, by
certified mail, return receipt requested, or telegraphed and confirmed,
or delivered by electronic facsimile and confirmed. Any notice to Id
Software shall also be sent to its counsel: D. Wade Cloud, Jr., Hiersche,
Martens, Hayward, Drakeley & Urbach, P.C., 15303 Dallas Parkway, Suite
700, LB 17, Dallas, Texas 75248.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
16. No Partnership, Etc. This Agreement does not constitute and shall
not be construed as constituting a partnership or joint venture between
Id Software and Licensee. Neither party shall have any right to obligate
or bind the other party in any manner whatsoever, and nothing herein
contained shall give, or is intended to give, any rights of any kind to
any third persons.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
17. Entire agreement. This Agreement constitutes the entire
understanding between Licensee and Id Software regarding the subject
matter hereof. Each and every clause of this Agreement is severable from
the whole and shall survive unless the entire Agreement is declared
unenforceable. No prior or present agreements or representations
between the parties hereto regarding the subject matter hereof shall be
binding upon the parties hereto unless incorporated in this Agreement.
No modification or change in this Agreement shall be valid or binding
upon the parties hereto unless in writing and executed by the parties
to be bound thereby.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
18. Assignment. This Agreement shall bind and inure to the benefit of
Id Software, its successors and assigns, and Id Software may assign its
rights hereunder, in Id Software's sole discretion. This Agreement
is personal to Licensee, and Licensee shall not assign, transfer,
convey nor franchise its rights granted hereunder. As provided above,
Licensee may sublicense Licensee's limited rights herein by transferring
the Authorized Copy by Authorized Means. As noted, each sublicensee
in possession of a copy of the Authorized Copy shall be subject to the
terms and conditions of this Agreement.
NO WARRANTY
19. Survival. The following provisions shall survive the expiration
or earlier termination of this Agreement: paragraphs 5., 8., 9., 10.,
11., 12., 13., 14., 15., 16., 17., 19., 20.a. and 20.b.
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
20. Miscellaneous.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
a. All captions in this Agreement are intended solely for the
convenience of the parties, and none shall effect the meaning or
construction of any provision.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
b. The terms and conditions of this Agreement have been negotiated
fully and freely among the parties. Accordingly, the preparation
of this Agreement by counsel for a given party will not be material
to the construction hereof, and the terms of this Agreement shall
not be strictly construed against such party.
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
BY DOWNLOADING THE CODE, AS DEFINED ABOVE, YOU, THE LICENSEE, AGREE TO
ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
February 12, 1998
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -6,8 +6,8 @@
# #
# 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 #
@ -47,8 +47,12 @@ 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/^arm.*/arm/')
else
YQ2_ARCH ?= $(shell uname -m)
endif
endif
# On Windows / MinGW $(CC) is undefined by default.
@ -84,7 +88,7 @@ endif
# to get it there...
# -fwrapv for defined integer wrapping. MSVC6 did this
# and the game code requires it.
override CFLAGS += -std=gnu99 -fno-strict-aliasing -fwrapv
override CFLAGS += -fno-strict-aliasing -fwrapv
# -MMD to generate header dependencies. Unsupported by
# the Clang shipped with OS X.
@ -272,7 +276,7 @@ XATRIX_OBJS_ = \
# ----------
# Rewrite pathes to our object directory
# Rewrite paths to our object directory
XATRIX_OBJS = $(patsubst %,build/%,$(XATRIX_OBJS_))
# ----------

50
README
View file

@ -1,50 +0,0 @@
This is a bugfixed version of id Software's Quake II missionpack
"The Reckoning", developed by Xatrix Software. Hundred bugs were
fixed, this version should run much more stable than the the old
SDK version. It should be used with the "Yamagi Quake II Client",
but may work with other clients too. 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. Create a subdirectory xatrix/ in your quake2 directory.
3. Copy pak0.pak and videos/ from the the Reckoning CD to
the newly created directory xatrix/.
4. Copy release/game.so to xatrix/.
5. Start the game with "./quake2 +set game xatrix"
Installation for OS X:
----------------------
1. Create a subdirectory xatrix/ in your quake2 directory.
2. Copy pak0.pak and videos/ from the the Reckoning CD to
the newly created directory xatrix/.
3. Copy game.so from the zip-archive to xatrix/.
4. Start the game with "quake2 +set game xatrix"
If you want to compile 'xatrix' 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. Create a subdirectory xatrix\ in your quake2 directory.
2. Copy pak0.pak and videos\ from the the Reckoning CD to
the newly created directory xatrix\.
3. Copy game.dll from the zip-archive to xatrix/.
4. Start the game with "quake2.exe +set game xatrix"
If you want to compile 'xatrix' 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.
=======================================================================
FAQ
---
The sounds after starting "xship" aka "Stroggos Freightener" are
distorted and hurting my ears.
- Yeah, the quality of the sound samples is very low. Not much
we can do about it...

67
README.md Normal file
View file

@ -0,0 +1,67 @@
# The Reckoning for Yamagi Quake II
The Reckoning for Yamagi Quake II is a bugfixed version of the first
official missionpack released for Quake II. It's based upon the Quake
II SDK source code and licensed under GPL version 2:
* [LICENSE](https://github.com/yquake2/xatrix/blob/master/LICENSE)
Hundreds of bugs were fixed and some convenience features added. The
missionpack 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 The Reckoning for Yamagi Quake II has community support
for MacOS and most other unixoid operating systems, including NetBSD,
OpenBSD and Solaris.
## Development
The Reckoning 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/xatrix/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/xatrix/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
The Reckoning 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/xatrix/actions)

View file

@ -390,6 +390,10 @@ HuntTarget(edict_t *self)
{
VectorSubtract(self->enemy->s.origin, self->s.origin, vec);
}
else
{
VectorClear(vec);
}
self->ideal_yaw = vectoyaw(vec);
@ -516,15 +520,11 @@ FindTarget(edict_t *self)
else
{
client = level.sight_client;
if (!client)
{
return false; /* no clients to get mad at */
}
}
/* if the entity went away, forget it */
if (!client->inuse)
if (!client || !client->inuse ||
(client->client && level.intermissiontime))
{
return false;
}
@ -902,11 +902,38 @@ ai_run_slide(edict_t *self, float distance)
* Decides if we're going to
* attack or do something else
*/
static qboolean
hesDeadJim(const edict_t *self)
{
const edict_t *enemy = self->enemy;
if (!enemy || !enemy->inuse)
{
return true;
}
if (self->monsterinfo.aiflags & AI_MEDIC)
{
return (enemy->health > 0);
}
if (enemy->client && level.intermissiontime)
{
return true;
}
if (self->monsterinfo.aiflags & AI_BRUTAL)
{
return (enemy->health <= -80);
}
return (enemy->health <= 0);
}
qboolean
ai_checkattack(edict_t *self, float dist)
{
vec3_t temp;
qboolean hesDeadJim;
if (!self)
{
@ -958,41 +985,10 @@ ai_checkattack(edict_t *self, float dist)
enemy_vis = false;
/* see if the enemy is dead */
hesDeadJim = false;
if ((!self->enemy) || (!self->enemy->inuse))
{
hesDeadJim = true;
}
else if (self->monsterinfo.aiflags & AI_MEDIC)
{
if (self->enemy->health > 0)
{
hesDeadJim = true;
self->monsterinfo.aiflags &= ~AI_MEDIC;
}
}
else
{
if (self->monsterinfo.aiflags & AI_BRUTAL)
{
if (self->enemy->health <= -80)
{
hesDeadJim = true;
}
}
else
{
if (self->enemy->health <= 0)
{
hesDeadJim = true;
}
}
}
if (hesDeadJim)
if (hesDeadJim(self))
{
self->enemy = NULL;
self->monsterinfo.aiflags &= ~AI_MEDIC;
if (self->oldenemy && (self->oldenemy->health > 0))
{
@ -1156,8 +1152,15 @@ ai_run(edict_t *self, float dist)
return;
}
tempgoal = G_SpawnOptional();
if (!tempgoal)
{
M_MoveToGoal(self, dist);
return;
}
save = self->goalentity;
tempgoal = G_Spawn();
self->goalentity = tempgoal;
new = false;

View file

@ -759,14 +759,22 @@ Cmd_WeapPrev_f(edict_t *ent)
cl = ent->client;
if (!cl->pers.weapon)
if (g_quick_weap->value && cl->newweapon)
{
it = cl->newweapon;
}
else if (cl->pers.weapon)
{
it = cl->pers.weapon;
}
else
{
return;
}
selected_weapon = ITEM_INDEX(cl->pers.weapon);
selected_weapon = ITEM_INDEX(it);
/* scan for the next valid one */
/* scan for the next valid one */
for (i = 1; i <= MAX_ITEMS; i++)
{
index = (selected_weapon + MAX_ITEMS - i) % MAX_ITEMS;
@ -778,12 +786,7 @@ Cmd_WeapPrev_f(edict_t *ent)
it = &itemlist[index];
if (!it->use)
{
continue;
}
if (!(it->flags & IT_WEAPON))
if (!it->use || !(it->flags & IT_WEAPON))
{
continue;
}
@ -792,6 +795,12 @@ Cmd_WeapPrev_f(edict_t *ent)
if (cl->newweapon == it)
{
if (g_quick_weap->value)
{
cl->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(cl->newweapon->icon);
cl->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(cl->newweapon);
cl->pickup_msg_time = level.time + 0.9f;
}
return;
}
}
@ -812,14 +821,22 @@ Cmd_WeapNext_f(edict_t *ent)
cl = ent->client;
if (!cl->pers.weapon)
if (g_quick_weap->value && cl->newweapon)
{
it = cl->newweapon;
}
else if (cl->pers.weapon)
{
it = cl->pers.weapon;
}
else
{
return;
}
selected_weapon = ITEM_INDEX(cl->pers.weapon);
selected_weapon = ITEM_INDEX(it);
/* scan for the next valid one */
/* scan for the next valid one */
for (i = 1; i <= MAX_ITEMS; i++)
{
index = (selected_weapon + i) % MAX_ITEMS;
@ -831,12 +848,7 @@ Cmd_WeapNext_f(edict_t *ent)
it = &itemlist[index];
if (!it->use)
{
continue;
}
if (!(it->flags & IT_WEAPON))
if (!it->use || !(it->flags & IT_WEAPON))
{
continue;
}
@ -845,6 +857,12 @@ Cmd_WeapNext_f(edict_t *ent)
if (cl->newweapon == it)
{
if (g_quick_weap->value)
{
cl->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(cl->newweapon->icon);
cl->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(cl->newweapon);
cl->pickup_msg_time = level.time + 0.9f;
}
return;
}
}
@ -1088,14 +1106,81 @@ Cmd_Wave_f(edict_t *ent)
}
}
static qboolean
flooded(edict_t *ent)
{
gclient_t *cl;
int i;
int num_msgs;
int mx;
if (!ent)
{
return false;
}
if (!deathmatch->value && !coop->value)
{
return false;
}
num_msgs = flood_msgs->value;
if (num_msgs <= 0)
{
return false;
}
cl = ent->client;
mx = sizeof(cl->flood_when) / sizeof(cl->flood_when[0]);
if (num_msgs > mx)
{
gi.dprintf("flood_msgs lowered to max: 10\n");
num_msgs = mx;
gi.cvar_forceset("flood_msgs", "10");
}
if (level.time < cl->flood_locktill)
{
gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n",
(int)(cl->flood_locktill - level.time));
return true;
}
i = (cl->flood_whenhead - num_msgs) + 1;
if (i < 0)
{
i += mx;
}
if (cl->flood_when[i] &&
(level.time - cl->flood_when[i]) < flood_persecond->value)
{
cl->flood_locktill = level.time + flood_waitdelay->value;
gi.cprintf(ent, PRINT_CHAT,
"Flood protection: You can't talk for %d seconds.\n",
(int)flood_waitdelay->value);
return true;
}
cl->flood_whenhead = (cl->flood_whenhead + 1) % mx;
cl->flood_when[cl->flood_whenhead] = level.time;
return false;
}
void
Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0)
{
int i, j;
int j;
edict_t *other;
char *p;
char text[2048];
gclient_t *cl;
if (!ent)
{
@ -1107,6 +1192,11 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0)
return;
}
if (flooded(ent))
{
return;
}
if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
{
team = false;
@ -1148,39 +1238,6 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0)
strcat(text, "\n");
if (flood_msgs->value)
{
cl = ent->client;
if (level.time < cl->flood_locktill)
{
gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n",
(int)(cl->flood_locktill - level.time));
return;
}
i = cl->flood_whenhead - flood_msgs->value + 1;
if (i < 0)
{
i = (sizeof(cl->flood_when) / sizeof(cl->flood_when[0])) + i;
}
if (cl->flood_when[i] &&
(level.time - cl->flood_when[i] < flood_persecond->value))
{
cl->flood_locktill = level.time + flood_waitdelay->value;
gi.cprintf(ent, PRINT_CHAT,
"Flood protection: You can't talk for %d seconds.\n",
(int)flood_waitdelay->value);
return;
}
cl->flood_whenhead = (cl->flood_whenhead + 1) %
(sizeof(cl->flood_when) / sizeof(cl->flood_when[0]));
cl->flood_when[cl->flood_whenhead] = level.time;
}
if (dedicated->value)
{
gi.cprintf(NULL, PRINT_CHAT, "%s", text);
@ -1461,6 +1518,7 @@ cycle_weapon(edict_t *ent)
int i;
int start;
int num_weaps;
const char *weapname = NULL;
if (!ent)
{
@ -1477,11 +1535,20 @@ cycle_weapon(edict_t *ent)
num_weaps = gi.argc();
/* find where we want to start the search for the next eligible weapon */
if (cl->pers.weapon)
if (cl->newweapon)
{
weapname = cl->newweapon->classname;
}
else if (cl->pers.weapon)
{
weapname = cl->pers.weapon->classname;
}
if (weapname)
{
for (i = 1; i < num_weaps; i++)
{
if (Q_stricmp(cl->pers.weapon->classname, gi.argv(i)) == 0)
if (Q_stricmp(weapname, gi.argv(i)) == 0)
{
break;
}
@ -1561,6 +1628,120 @@ cycle_weapon(edict_t *ent)
void
Cmd_CycleWeap_f(edict_t *ent)
{
gitem_t *weap;
gclient_t *cl;
int num_weaps;
if (!ent)
{
return;
}
num_weaps = gi.argc();
if (num_weaps <= 1)
{
gi.cprintf(ent, PRINT_HIGH, "Usage: cycleweap classname1 classname2 .. classnameN\n");
return;
}
weap = cycle_weapon(ent);
if (!weap) return;
cl = ent->client;
if (cl->pers.inventory[ITEM_INDEX(weap)] <= 0)
{
gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", weap->pickup_name);
return;
}
weap->use(ent, weap);
if (num_weaps > 3 && cl->newweapon == weap)
{
cl->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(weap->icon);
cl->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(weap);
cl->pickup_msg_time = level.time + 0.7f;
}
}
static gitem_t *
preferred_weapon(edict_t *ent)
{
gclient_t *cl;
gitem_t *noammo_fallback;
gitem_t *noweap_fallback;
gitem_t *weap;
gitem_t *ammo;
int i;
int num_weaps;
if (!ent)
{
return NULL;
}
cl = ent->client;
if (!cl)
{
return NULL;
}
num_weaps = gi.argc();
noammo_fallback = NULL;
noweap_fallback = NULL;
/* find the first eligible weapon in the list we can switch to */
for (i = 1; i < num_weaps; i++)
{
weap = FindItemByClassname(gi.argv(i));
if (weap && (weap->flags & IT_WEAPON) && weap->use)
{
if (cl->pers.inventory[ITEM_INDEX(weap)] > 0)
{
if (weap->ammo)
{
ammo = FindItem(weap->ammo);
if (ammo)
{
if (cl->pers.inventory[ITEM_INDEX(ammo)] >= get_ammo_usage(weap))
{
return weap;
}
if (!noammo_fallback)
{
noammo_fallback = weap;
}
}
}
else
{
return weap;
}
}
else if (!noweap_fallback)
{
noweap_fallback = weap;
}
}
}
/* if no weapon was found, the fallbacks will be used for
printing the appropriate error message to the console
*/
if (noammo_fallback)
{
return noammo_fallback;
}
return noweap_fallback;
}
void
Cmd_PrefWeap_f(edict_t *ent)
{
gitem_t *weap;
@ -1571,11 +1752,11 @@ Cmd_CycleWeap_f(edict_t *ent)
if (gi.argc() <= 1)
{
gi.cprintf(ent, PRINT_HIGH, "Usage: cycleweap classname1 classname2 .. classnameN\n");
gi.cprintf(ent, PRINT_HIGH, "Usage: prefweap classname1 classname2 .. classnameN\n");
return;
}
weap = cycle_weapon(ent);
weap = preferred_weapon(ent);
if (weap)
{
if (ent->client->pers.inventory[ITEM_INDEX(weap)] <= 0)
@ -1741,6 +1922,10 @@ ClientCommand(edict_t *ent)
{
Cmd_CycleWeap_f(ent);
}
else if (Q_stricmp(cmd, "prefweap") == 0)
{
Cmd_PrefWeap_f(ent);
}
else /* anything that doesn't match a command will be a chat */
{
Cmd_Say_f(ent, false, true);

View file

@ -108,11 +108,6 @@ Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker,
return;
}
if (targ->health < -999)
{
targ->health = -999;
}
targ->enemy = attacker;
if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD))
@ -486,6 +481,24 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker)
}
}
static void
apply_knockback(edict_t *targ, vec3_t dir, float knockback, float scale)
{
vec3_t kvel;
float mass;
if (!knockback)
{
return;
}
mass = (targ->mass < 50) ? 50.0f : (float)targ->mass;
VectorNormalize2(dir, kvel);
VectorScale(kvel, scale * (knockback / mass), kvel);
VectorAdd(targ->velocity, kvel, targ->velocity);
}
void
T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
vec3_t point, vec3_t normal, int damage, int knockback, int dflags,
@ -552,8 +565,6 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
te_sparks = TE_SPARKS;
}
VectorNormalize(dir);
/* bonus damage for suprising a monster */
if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) &&
(attacker->client) && (!targ->enemy) && (targ->health > 0))
@ -567,36 +578,14 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
}
/* figure momentum add */
if (!(dflags & DAMAGE_NO_KNOCKBACK))
if (!(dflags & DAMAGE_NO_KNOCKBACK) &&
(targ->movetype != MOVETYPE_NONE) &&
(targ->movetype != MOVETYPE_BOUNCE) &&
(targ->movetype != MOVETYPE_PUSH) &&
(targ->movetype != MOVETYPE_STOP))
{
if ((knockback) && (targ->movetype != MOVETYPE_NONE) &&
(targ->movetype != MOVETYPE_BOUNCE) &&
(targ->movetype != MOVETYPE_PUSH) &&
(targ->movetype != MOVETYPE_STOP))
{
vec3_t kvel;
float mass;
if (targ->mass < 50)
{
mass = 50;
}
else
{
mass = targ->mass;
}
if (targ->client && (attacker == targ))
{
VectorScale(dir, 1600.0 * (float)knockback / mass, kvel); /* the rocket jump hack... */
}
else
{
VectorScale(dir, 500.0 * (float)knockback / mass, kvel);
}
VectorAdd(targ->velocity, kvel, targ->velocity);
}
apply_knockback (targ, dir, knockback,
((client && attacker == targ) ? 1600.0f : 500.0f));
}
take = damage;

View file

@ -1350,7 +1350,7 @@ door_go_down(edict_t *self)
void
door_go_up(edict_t *self, edict_t *activator)
{
if (!self || !activator)
if (!self)
{
return;
}
@ -1401,13 +1401,13 @@ door_go_up(edict_t *self, edict_t *activator)
void
door_use(edict_t *self, edict_t *other /* unused */, edict_t *activator)
{
if (!self || !activator)
edict_t *ent;
if (!self)
{
return;
}
edict_t *ent;
if (self->flags & FL_TEAMSLAVE)
{
return;
@ -2446,13 +2446,22 @@ void
trigger_elevator_use(edict_t *self, edict_t *other, edict_t *activator /* unused */)
{
edict_t *target;
edict_t *train;
if (!self || !other)
{
return;
}
if (self->movetarget->nextthink)
train = self->movetarget;
if (!train || !train->inuse ||
!train->classname || strcmp(train->classname, "func_train") != 0)
{
return;
}
if (train->nextthink)
{
return;
}
@ -2471,8 +2480,8 @@ trigger_elevator_use(edict_t *self, edict_t *other, edict_t *activator /* unused
return;
}
self->movetarget->target_ent = target;
train_resume(self->movetarget);
train->target_ent = target;
train_resume(train);
}
void

View file

@ -1713,7 +1713,7 @@ SpawnItem(edict_t *ent, gitem_t *item)
}
}
if (coop->value && (strcmp(ent->classname, "key_power_cube") == 0))
if (coop->value && !(ent->spawnflags & ITEM_NO_TOUCH) && (strcmp(ent->classname, "key_power_cube") == 0))
{
ent->spawnflags |= (1 << (8 + level.power_cubes));
level.power_cubes++;

View file

@ -37,6 +37,7 @@ cvar_t *maxentities;
cvar_t *g_select_empty;
cvar_t *dedicated;
cvar_t *g_footsteps;
cvar_t *g_monsterfootsteps;
cvar_t *g_fix_triggered;
cvar_t *filterban;
@ -67,6 +68,9 @@ cvar_t *sv_maplist;
cvar_t *gib_on;
cvar_t *aimfix;
cvar_t *g_machinegun_norecoil;
cvar_t *g_quick_weap;
cvar_t *g_swap_speed;
void SpawnEntities(char *mapname, char *entities, char *spawnpoint);
void ClientThink(edict_t *ent, usercmd_t *cmd);

View file

@ -181,14 +181,19 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type)
return;
}
gibsthisframe++;
if (gibsthisframe > MAX_GIBS)
{
return;
}
gib = G_Spawn();
gib = G_SpawnOptional();
if (!gib)
{
return;
}
gibsthisframe++;
VectorScale(self->size, 0.5, size);
VectorAdd(self->absmin, size, origin);
@ -198,6 +203,7 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type)
gi.setmodel(gib, gibname);
gib->solid = SOLID_BBOX;
gib->svflags = SVF_DEADMONSTER;
gib->s.effects |= EF_GIB;
gib->flags |= FL_NO_KNOCKBACK;
gib->takedamage = DAMAGE_YES;
@ -256,6 +262,10 @@ ThrowHead(edict_t *self, char *gibname, int damage, int type)
self->takedamage = DAMAGE_YES;
self->die = gib_die;
// The entity still has the monsters clipmaks.
// Reset it to MASK_SHOT to be on the save side.
self->clipmask = MASK_SHOT;
if (type == GIB_ORGANIC)
{
self->movetype = MOVETYPE_TOSS;
@ -437,6 +447,10 @@ ThrowClientHead(edict_t *self, int damage)
self->s.sound = 0;
self->flags |= FL_NO_KNOCKBACK;
// The entity still has the monsters clipmaks.
// Reset it to MASK_SHOT to be on the save side.
self->clipmask = MASK_SHOT;
self->movetype = MOVETYPE_BOUNCE;
VelocityForDamage(damage, vd);
VectorAdd(self->velocity, vd, self->velocity);
@ -478,14 +492,20 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin)
return;
}
debristhisframe++;
if (debristhisframe > MAX_DEBRIS)
{
return;
}
chunk = G_Spawn();
chunk = G_SpawnOptional();
if (!chunk)
{
return;
}
debristhisframe++;
VectorCopy(origin, chunk->s.origin);
gi.setmodel(chunk, modelname);
v[0] = 100 * crandom();
@ -808,7 +828,7 @@ SP_info_null(edict_t *self)
/*
* QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
* Used as a positional target for lightning.
* Used as a positional target for lighting.
*/
void
SP_info_notnull(edict_t *self)

View file

@ -35,15 +35,18 @@
edict_t *
SV_TestEntityPosition(edict_t *ent)
{
trace_t trace;
int mask;
if (!ent)
{
return NULL;
}
trace_t trace;
int mask;
if (ent->clipmask)
/* dead bodies are supposed to not be solid so lets
ensure they only collide with BSP during pushmoves
*/
if (ent->clipmask && !(ent->svflags & SVF_MONSTER))
{
mask = ent->clipmask;
}
@ -52,12 +55,8 @@ SV_TestEntityPosition(edict_t *ent)
mask = MASK_SOLID;
}
trace = gi.trace(ent->s.origin,
ent->mins,
ent->maxs,
ent->s.origin,
ent,
mask);
trace = gi.trace(ent->s.origin, ent->mins, ent->maxs,
ent->s.origin, ent, mask);
if (trace.startsolid)
{
@ -505,6 +504,17 @@ retry:
trace = gi.trace(start, ent->mins, ent->maxs, end, ent, mask);
/* startsolid treats different-content volumes
as continuous, like the bbox of a monster/player
and the floor of an elevator. So do another trace
that only collides with BSP so that we make a best
effort to keep these entities inside non-solid space
*/
if (trace.startsolid && (mask & ~MASK_SOLID))
{
trace = gi.trace (start, ent->mins, ent->maxs, end, ent, MASK_SOLID);
}
VectorCopy(trace.endpos, ent->s.origin);
gi.linkentity(ent);
@ -551,7 +561,6 @@ typedef struct
edict_t *ent;
vec3_t origin;
vec3_t angles;
float deltayaw;
} pushed_t;
pushed_t pushed[MAX_EDICTS], *pushed_p;
@ -602,12 +611,6 @@ SV_Push(edict_t *pusher, vec3_t move, vec3_t amove)
pushed_p->ent = pusher;
VectorCopy(pusher->s.origin, pushed_p->origin);
VectorCopy(pusher->s.angles, pushed_p->angles);
if (pusher->client)
{
pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW];
}
pushed_p++;
/* move the pusher to it's final position */
@ -675,11 +678,6 @@ SV_Push(edict_t *pusher, vec3_t move, vec3_t amove)
/* try moving the contacted entity */
VectorAdd(check->s.origin, move, check->s.origin);
if (check->client)
{
check->client->ps.pmove.delta_angles[YAW] += amove[YAW];
}
/* figure movement due to the pusher's amove */
VectorSubtract(check->s.origin, pusher->s.origin, org);
org2[0] = DotProduct(org, forward);
@ -744,11 +742,6 @@ SV_Push(edict_t *pusher, vec3_t move, vec3_t amove)
VectorCopy(p->origin, p->ent->s.origin);
VectorCopy(p->angles, p->ent->s.angles);
if (p->ent->client)
{
p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw;
}
gi.linkentity(p->ent);
}
@ -1015,8 +1008,12 @@ SV_Physics_Toss(edict_t *ent)
if (!wasinwater && isinwater)
{
gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO,
gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
/* don't play splash sound for entities already in water on level start */
if (level.framenum > 3)
{
gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO,
gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
}
}
else if (wasinwater && !isinwater)
{

View file

@ -744,6 +744,9 @@ SpawnEntities(const char *mapname, char *entities, const char *spawnpoint)
ED_CallSpawn(ent);
}
/* in case the last entity in the entstring has spawntemp fields */
memset(&st, 0, sizeof(st));
gi.dprintf("%i entities inhibited.\n", inhibit);
G_FindTeams();

View file

@ -159,11 +159,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

View file

@ -7,6 +7,9 @@
#include "header/local.h"
#define TARGET_HELP_PRIMARY 1
#define TARGET_HELP_THINK_DELAY 0.3f
/* QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8)
* Fire an origin based temp entity event to the clients.
*
@ -151,26 +154,72 @@ SP_target_speaker(edict_t *ent)
/* ========================================================== */
void
Use_Target_Help(edict_t *ent, edict_t *other, edict_t *activator)
static void
Target_Help_Apply(const char *msg, int is_primary)
{
if (!ent)
char *curr;
size_t sz;
if (!msg)
{
return;
}
if (ent->spawnflags & 1)
if (is_primary)
{
strncpy(game.helpmessage1, ent->message, sizeof(game.helpmessage2) - 1);
curr = game.helpmessage1;
sz = sizeof(game.helpmessage1);
}
else
{
strncpy(game.helpmessage2, ent->message, sizeof(game.helpmessage1) - 1);
curr = game.helpmessage2;
sz = sizeof(game.helpmessage2);
}
if (strcmp(curr, msg) == 0)
{
return;
}
Q_strlcpy(curr, msg, sz - 1);
game.helpchanged++;
}
void
Target_Help_Think(edict_t *ent)
{
if (!ent)
{
return;
}
Target_Help_Apply(ent->message, ent->spawnflags & TARGET_HELP_PRIMARY);
ent->think = NULL;
}
void
Use_Target_Help(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */)
{
if (!ent)
{
return;
}
if (level.time > TARGET_HELP_THINK_DELAY)
{
Target_Help_Apply(ent->message, ent->spawnflags & TARGET_HELP_PRIMARY);
}
else
{
/* The game is still pre-loading so delay the help message a bit,
otherwise its changes to game structure will leak past save loads
*/
ent->think = Target_Help_Think;
ent->nextthink = TARGET_HELP_THINK_DELAY;
}
}
/*
* QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1
* When fired, the "message" key becomes the current personal computer string,

View file

@ -210,7 +210,7 @@ G_UseTargets(edict_t *ent, edict_t *activator /* may be NULL */)
}
/* print the message */
if ((ent->message) && !(activator->svflags & SVF_MONSTER))
if (activator && (ent->message) && !(activator->svflags & SVF_MONSTER))
{
gi.centerprintf(activator, "%s", ent->message);
@ -462,38 +462,66 @@ G_InitEdict(edict_t *e)
}
/*
* Either finds a free edict, or allocates a new one.
* Try to avoid reusing an entity that was recently freed, because it
* can cause the client to think the entity morphed into something else
* instead of being removed and recreated, which can cause interpolated
* angles and bad trails.
* Either finds a free edict, or allocates a
* new one. Try to avoid reusing an entity
* that was recently freed, because it can
* cause the client to think the entity
* morphed into something else instead of
* being removed and recreated, which can
* cause interpolated angles and bad trails.
*/
edict_t *
G_Spawn(void)
#define POLICY_DEFAULT 0
#define POLICY_DESPERATE 1
static edict_t *
G_FindFreeEdict(int policy)
{
int i;
edict_t *e;
e = &g_edicts[(int)maxclients->value + 1];
for (i = maxclients->value + 1; i < globals.num_edicts; i++, e++)
for (e = g_edicts + game.maxclients + 1 ; e < &g_edicts[globals.num_edicts] ; e++)
{
/* the first couple seconds of server time can involve a lot of
freeing and allocating, so relax the replacement policy */
if (!e->inuse && ((e->freetime < 2) || (level.time - e->freetime > 0.5)))
freeing and allocating, so relax the replacement policy
*/
if (!e->inuse && (policy == POLICY_DESPERATE || e->freetime < 2.0f || (level.time - e->freetime) > 0.5f))
{
G_InitEdict(e);
G_InitEdict (e);
return e;
}
}
if (i == game.maxentities)
return NULL;
}
edict_t *
G_SpawnOptional(void)
{
edict_t *e = G_FindFreeEdict (POLICY_DEFAULT);
if (e)
{
gi.error("ED_Alloc: no free edicts");
return e;
}
globals.num_edicts++;
G_InitEdict(e);
if (globals.num_edicts >= game.maxentities)
{
return G_FindFreeEdict (POLICY_DESPERATE);
}
e = &g_edicts[globals.num_edicts++];
G_InitEdict (e);
return e;
}
edict_t *
G_Spawn(void)
{
edict_t *e = G_SpawnOptional();
if (!e)
gi.error ("ED_Alloc: no free edicts");
return e;
}

View file

@ -1061,7 +1061,14 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0);
self->solid = SOLID_NOT;
self->touch = NULL;
VectorMA(self->s.origin, -1 * FRAMETIME, self->velocity, self->s.origin);
/* move it back a bit from walls so the effects aren't cut off */
if (!other->takedamage)
{
VectorNormalize(self->velocity);
VectorMA(self->s.origin, -40.0f, self->velocity, self->s.origin);
}
VectorClear(self->velocity);
self->s.modelindex = gi.modelindex("sprites/s_bfg3.sp2");
self->s.frame = 0;
@ -1071,6 +1078,8 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
self->nextthink = level.time + FRAMETIME;
self->enemy = other;
gi.linkentity(self);
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_BFG_BIGEXPLOSION);
gi.WritePosition(self->s.origin);
@ -1483,7 +1492,16 @@ plasma_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
ent->dmg_radius, MOD_PHALANX);
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_PLASMA_EXPLOSION);
if (ent->waterlevel)
{
gi.WriteByte(TE_ROCKET_EXPLOSION_WATER);
}
else
{
gi.WriteByte(TE_PLASMA_EXPLOSION);
}
gi.WritePosition(origin);
gi.multicast(ent->s.origin, MULTICAST_PVS);

View file

@ -513,6 +513,7 @@ extern cvar_t *needpass;
extern cvar_t *g_select_empty;
extern cvar_t *dedicated;
extern cvar_t *g_footsteps;
extern cvar_t *g_monsterfootsteps;
extern cvar_t *g_fix_triggered;
extern cvar_t *filterban;
@ -541,6 +542,9 @@ extern cvar_t *flood_waitdelay;
extern cvar_t *sv_maplist;
extern cvar_t *aimfix;
extern cvar_t *g_machinegun_norecoil;
extern cvar_t *g_quick_weap;
extern cvar_t *g_swap_speed;
#define world (&g_edicts[0])
@ -620,6 +624,7 @@ void G_UseTargets(edict_t *ent, edict_t *activator);
void G_SetMovedir(vec3_t angles, vec3_t movedir);
void G_InitEdict(edict_t *e);
edict_t *G_SpawnOptional(void);
edict_t *G_Spawn(void);
void G_FreeEdict(edict_t *e);

View file

@ -18,8 +18,20 @@
#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)
@ -202,7 +214,7 @@ float BigFloat(float l);
float LittleFloat(float l);
void Swap_Init(void);
char *va(char *format, ...);
char *va(const char *format, ...);
/* ============================================= */

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* The berserker.
*
@ -15,10 +34,37 @@ static int sound_punch;
static int sound_sight;
static int sound_search;
static int sound_step;
static int sound_step2;
void
berserk_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("berserk/step1.wav");
sound_step2 = gi.soundindex("berserk/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
void
berserk_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -29,7 +75,7 @@ berserk_sight(edict_t *self, edict_t *other /* unused */)
void
berserk_search(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -39,7 +85,7 @@ berserk_search(edict_t *self)
void berserk_fidget(edict_t *self);
mframe_t berserk_frames_stand[] = {
static mframe_t berserk_frames_stand[] = {
{ai_stand, 0, berserk_fidget},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -47,17 +93,18 @@ mframe_t berserk_frames_stand[] = {
{ai_stand, 0, NULL}
};
mmove_t berserk_move_stand = {
mmove_t berserk_move_stand =
{
FRAME_stand1,
FRAME_stand5,
berserk_frames_stand,
NULL
FRAME_stand5,
berserk_frames_stand,
NULL
};
void
berserk_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -65,7 +112,7 @@ berserk_stand(edict_t *self)
self->monsterinfo.currentmove = &berserk_move_stand;
}
mframe_t berserk_frames_stand_fidget[] = {
static mframe_t berserk_frames_stand_fidget[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -88,7 +135,8 @@ mframe_t berserk_frames_stand_fidget[] = {
{ai_stand, 0, NULL}
};
mmove_t berserk_move_stand_fidget = {
mmove_t berserk_move_stand_fidget =
{
FRAME_standb1,
FRAME_standb20,
berserk_frames_stand_fidget,
@ -98,7 +146,7 @@ mmove_t berserk_move_stand_fidget = {
void
berserk_fidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -122,22 +170,23 @@ berserk_fidget(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_idle, 1, ATTN_IDLE, 0);
}
mframe_t berserk_frames_walk[] = {
static mframe_t berserk_frames_walk[] = {
{ai_walk, 9.1, NULL},
{ai_walk, 6.3, NULL},
{ai_walk, 4.9, NULL},
{ai_walk, 6.7, NULL},
{ai_walk, 6.7, berserk_footstep},
{ai_walk, 6.0, NULL},
{ai_walk, 8.2, NULL},
{ai_walk, 7.2, NULL},
{ai_walk, 6.1, NULL},
{ai_walk, 4.9, NULL},
{ai_walk, 4.9, berserk_footstep},
{ai_walk, 4.7, NULL},
{ai_walk, 4.7, NULL},
{ai_walk, 4.8, NULL}
};
mmove_t berserk_move_walk = {
mmove_t berserk_move_walk =
{
FRAME_walkc1,
FRAME_walkc11,
berserk_frames_walk,
@ -147,7 +196,7 @@ mmove_t berserk_move_walk = {
void
berserk_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -155,16 +204,17 @@ berserk_walk(edict_t *self)
self->monsterinfo.currentmove = &berserk_move_walk;
}
mframe_t berserk_frames_run1[] = {
static mframe_t berserk_frames_run1[] = {
{ai_run, 21, NULL},
{ai_run, 11, NULL},
{ai_run, 11, berserk_footstep},
{ai_run, 21, NULL},
{ai_run, 25, NULL},
{ai_run, 18, NULL},
{ai_run, 18, berserk_footstep},
{ai_run, 19, NULL}
};
mmove_t berserk_move_run1 = {
mmove_t berserk_move_run1 =
{
FRAME_run1,
FRAME_run6,
berserk_frames_run1,
@ -174,7 +224,7 @@ mmove_t berserk_move_run1 = {
void
berserk_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -194,7 +244,7 @@ berserk_attack_spike(edict_t *self)
{
static vec3_t aim = {MELEE_DISTANCE, 0, -24};
if (!self)
if (!self)
{
return;
}
@ -205,7 +255,7 @@ berserk_attack_spike(edict_t *self)
void
berserk_swing(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -213,7 +263,7 @@ berserk_swing(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_punch, 1, ATTN_NORM, 0);
}
mframe_t berserk_frames_attack_spike[] = {
static mframe_t berserk_frames_attack_spike[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, berserk_swing},
@ -224,7 +274,8 @@ mframe_t berserk_frames_attack_spike[] = {
{ai_charge, 0, NULL}
};
mmove_t berserk_move_attack_spike = {
mmove_t berserk_move_attack_spike =
{
FRAME_att_c1,
FRAME_att_c8,
berserk_frames_attack_spike,
@ -236,7 +287,7 @@ berserk_attack_club(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -245,10 +296,10 @@ berserk_attack_club(edict_t *self)
fire_hit(self, aim, (5 + (rand() % 6)), 400); /* Slower attack */
}
mframe_t berserk_frames_attack_club[] = {
{ai_charge, 0, NULL},
static mframe_t berserk_frames_attack_club[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, berserk_footstep},
{ai_charge, 0, NULL},
{ai_charge, 0, berserk_swing},
{ai_charge, 0, NULL},
@ -260,7 +311,8 @@ mframe_t berserk_frames_attack_club[] = {
{ai_charge, 0, NULL}
};
mmove_t berserk_move_attack_club = {
mmove_t berserk_move_attack_club =
{
FRAME_att_c9,
FRAME_att_c20,
berserk_frames_attack_club,
@ -274,24 +326,25 @@ berserk_strike(edict_t *self)
very PITA. Let it be... */
}
mframe_t berserk_frames_attack_strike[] = {
{ai_move, 0, NULL},
static mframe_t berserk_frames_attack_strike[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, berserk_footstep},
{ai_move, 0, berserk_swing},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, berserk_strike},
{ai_move, 0, NULL},
{ai_move, 0, berserk_footstep},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 9.7, NULL},
{ai_move, 13.6, NULL}
{ai_move, 13.6, berserk_footstep}
};
mmove_t berserk_move_attack_strike = {
mmove_t berserk_move_attack_strike =
{
FRAME_att_c21,
FRAME_att_c34,
berserk_frames_attack_strike,
@ -301,7 +354,7 @@ mmove_t berserk_move_attack_strike = {
void
berserk_melee(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -316,21 +369,22 @@ berserk_melee(edict_t *self)
}
}
mframe_t berserk_frames_pain1[] = {
static mframe_t berserk_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL}
};
mmove_t berserk_move_pain1 = {
mmove_t berserk_move_pain1 =
{
FRAME_painc1,
FRAME_painc4,
berserk_frames_pain1,
berserk_run
};
mframe_t berserk_frames_pain2[] = {
static mframe_t berserk_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -353,7 +407,8 @@ mframe_t berserk_frames_pain2[] = {
{ai_move, 0, NULL}
};
mmove_t berserk_move_pain2 = {
mmove_t berserk_move_pain2 =
{
FRAME_painb1,
FRAME_painb20,
berserk_frames_pain2,
@ -361,10 +416,10 @@ mmove_t berserk_move_pain2 = {
};
void
berserk_pain(edict_t *self, edict_t *other /* unsued */,
berserk_pain(edict_t *self, edict_t *other /* unused */,
float kick /* unused */, int damage)
{
if (!self)
if (!self)
{
return;
}
@ -400,7 +455,7 @@ berserk_pain(edict_t *self, edict_t *other /* unsued */,
void
berserk_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -413,7 +468,7 @@ berserk_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t berserk_frames_death1[] = {
static mframe_t berserk_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -429,14 +484,15 @@ mframe_t berserk_frames_death1[] = {
{ai_move, 0, NULL}
};
mmove_t berserk_move_death1 = {
mmove_t berserk_move_death1 =
{
FRAME_death1,
FRAME_death13,
berserk_frames_death1,
berserk_dead
};
mframe_t berserk_frames_death2[] = {
static mframe_t berserk_frames_death2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -447,20 +503,21 @@ mframe_t berserk_frames_death2[] = {
{ai_move, 0, NULL}
};
mmove_t berserk_move_death2 = {
mmove_t berserk_move_death2 =
{
FRAME_deathc1,
FRAME_deathc8,
FRAME_deathc8,
berserk_frames_death2,
berserk_dead
};
void
berserk_die(edict_t *self, edict_t *inflictor /* unsued */, edict_t *attacker /* unused */,
berserk_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */,
int damage, vec3_t point /* unused */)
{
int n;
if (!self)
if (!self)
{
return;
}
@ -471,15 +528,18 @@ berserk_die(edict_t *self, edict_t *inflictor /* unsued */, edict_t *attacker /*
for (n = 0; n < 2; n++)
{
ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/bone/tris.md2",
damage, GIB_ORGANIC);
}
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
}
ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
ThrowHead(self, "models/objects/gibs/head2/tris.md2",
damage, GIB_ORGANIC);
self->deadflag = DEAD_DEAD;
return;
}
@ -509,7 +569,7 @@ berserk_die(edict_t *self, edict_t *inflictor /* unsued */, edict_t *attacker /*
void
SP_monster_berserk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -520,6 +580,11 @@ SP_monster_berserk(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
/* pre-caches */
sound_pain = gi.soundindex("berserk/berpain2.wav");
sound_die = gi.soundindex("berserk/berdeth2.wav");

View file

@ -149,7 +149,7 @@ Boss2MachineGun(edict_t *self)
boss2_firebullet_right(self);
}
mframe_t boss2_frames_stand[] = {
static mframe_t boss2_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -180,7 +180,7 @@ mmove_t boss2_move_stand = {
NULL
};
mframe_t boss2_frames_fidget[] = {
static mframe_t boss2_frames_fidget[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -220,7 +220,7 @@ mmove_t boss2_move_fidget = {
NULL
};
mframe_t boss2_frames_walk[] = {
static mframe_t boss2_frames_walk[] = {
{ai_walk, 8, NULL},
{ai_walk, 8, NULL},
{ai_walk, 8, NULL},
@ -250,7 +250,7 @@ mmove_t boss2_move_walk = {
NULL
};
mframe_t boss2_frames_run[] = {
static mframe_t boss2_frames_run[] = {
{ai_run, 8, NULL},
{ai_run, 8, NULL},
{ai_run, 8, NULL},
@ -280,7 +280,7 @@ mmove_t boss2_move_run = {
NULL
};
mframe_t boss2_frames_attack_pre_mg[] = {
static mframe_t boss2_frames_attack_pre_mg[] = {
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
@ -299,7 +299,7 @@ mmove_t boss2_move_attack_pre_mg = {
NULL
};
mframe_t boss2_frames_attack_mg[] = {
static mframe_t boss2_frames_attack_mg[] = {
{ai_charge, 1, Boss2MachineGun},
{ai_charge, 1, Boss2MachineGun},
{ai_charge, 1, Boss2MachineGun},
@ -315,7 +315,7 @@ mmove_t boss2_move_attack_mg = {
NULL
};
mframe_t boss2_frames_attack_post_mg[] = {
static mframe_t boss2_frames_attack_post_mg[] = {
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
@ -329,7 +329,7 @@ mmove_t boss2_move_attack_post_mg = {
boss2_run
};
mframe_t boss2_frames_attack_rocket[] = {
static mframe_t boss2_frames_attack_rocket[] = {
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
@ -360,7 +360,7 @@ mmove_t boss2_move_attack_rocket = {
boss2_run
};
mframe_t boss2_frames_pain_heavy[] = {
static mframe_t boss2_frames_pain_heavy[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -388,7 +388,7 @@ mmove_t boss2_move_pain_heavy = {
boss2_run
};
mframe_t boss2_frames_pain_light[] = {
static mframe_t boss2_frames_pain_light[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -402,7 +402,7 @@ mmove_t boss2_move_pain_light = {
boss2_run
};
mframe_t boss2_frames_death[] = {
static mframe_t boss2_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -67,7 +67,7 @@ jorg_search(edict_t *self)
}
/* stand */
mframe_t jorg_frames_stand[] = {
static mframe_t jorg_frames_stand[] = {
{ai_stand, 0, jorg_idle},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -183,7 +183,7 @@ jorg_stand(edict_t *self)
self->monsterinfo.currentmove = &jorg_move_stand;
}
mframe_t jorg_frames_run[] = {
static mframe_t jorg_frames_run[] = {
{ai_run, 17, jorg_step_left},
{ai_run, 0, NULL},
{ai_run, 0, NULL},
@ -208,7 +208,7 @@ mmove_t jorg_move_run = {
};
/* walk */
mframe_t jorg_frames_start_walk[] = {
static mframe_t jorg_frames_start_walk[] = {
{ai_walk, 5, NULL},
{ai_walk, 6, NULL},
{ai_walk, 7, NULL},
@ -223,7 +223,7 @@ mmove_t jorg_move_start_walk = {
NULL
};
mframe_t jorg_frames_walk[] = {
static mframe_t jorg_frames_walk[] = {
{ai_walk, 17, NULL},
{ai_walk, 0, NULL},
{ai_walk, 0, NULL},
@ -247,7 +247,7 @@ mmove_t jorg_move_walk = {
NULL
};
mframe_t jorg_frames_end_walk[] = {
static mframe_t jorg_frames_end_walk[] = {
{ai_walk, 11, NULL},
{ai_walk, 0, NULL},
{ai_walk, 0, NULL},
@ -292,7 +292,7 @@ jorg_run(edict_t *self)
}
}
mframe_t jorg_frames_pain3[] = {
static mframe_t jorg_frames_pain3[] = {
{ai_move, -28, NULL},
{ai_move, -6, NULL},
{ai_move, -3, jorg_step_left},
@ -327,7 +327,7 @@ mmove_t jorg_move_pain3 = {
jorg_run
};
mframe_t jorg_frames_pain2[] = {
static mframe_t jorg_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL}
@ -340,7 +340,7 @@ mmove_t jorg_move_pain2 = {
jorg_run
};
mframe_t jorg_frames_pain1[] = {
static mframe_t jorg_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL}
@ -353,7 +353,7 @@ mmove_t jorg_move_pain1 = {
jorg_run
};
mframe_t jorg_frames_death1[] = {
static mframe_t jorg_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -413,7 +413,7 @@ mmove_t jorg_move_death = {
jorg_dead
};
mframe_t jorg_frames_attack2[] = {
static mframe_t jorg_frames_attack2[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -436,7 +436,7 @@ mmove_t jorg_move_attack2 = {
jorg_run
};
mframe_t jorg_frames_start_attack1[] = {
static mframe_t jorg_frames_start_attack1[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -454,7 +454,7 @@ mmove_t jorg_move_start_attack1 = {
jorg_attack1
};
mframe_t jorg_frames_attack1[] = {
static mframe_t jorg_frames_attack1[] = {
{ai_charge, 0, jorg_firebullet},
{ai_charge, 0, jorg_firebullet},
{ai_charge, 0, jorg_firebullet},
@ -470,7 +470,7 @@ mmove_t jorg_move_attack1 = {
jorg_reattack1
};
mframe_t jorg_frames_end_attack1[] = {
static mframe_t jorg_frames_end_attack1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -60,7 +60,7 @@ makron_taunt(edict_t *self)
}
/* stand */
mframe_t makron_frames_stand[] = {
static mframe_t makron_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -141,7 +141,7 @@ makron_stand(edict_t *self)
self->monsterinfo.currentmove = &makron_move_stand;
}
mframe_t makron_frames_run[] = {
static mframe_t makron_frames_run[] = {
{ai_run, 3, makron_step_left},
{ai_run, 12, NULL},
{ai_run, 8, NULL},
@ -227,19 +227,6 @@ makron_prerailgun(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM, 0);
}
mframe_t makron_frames_walk[] = {
{ai_walk, 3, makron_step_left},
{ai_walk, 12, NULL},
{ai_walk, 8, NULL},
{ai_walk, 8, NULL},
{ai_walk, 8, makron_step_right},
{ai_walk, 6, NULL},
{ai_walk, 12, NULL},
{ai_walk, 9, NULL},
{ai_walk, 6, NULL},
{ai_walk, 12, NULL}
};
mmove_t makron_move_walk = {
FRAME_walk204,
FRAME_walk213,
@ -276,7 +263,7 @@ makron_run(edict_t *self)
}
}
mframe_t makron_frames_pain6[] = {
static mframe_t makron_frames_pain6[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -313,7 +300,7 @@ mmove_t makron_move_pain6 = {
makron_run
};
mframe_t makron_frames_pain5[] = {
static mframe_t makron_frames_pain5[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -327,7 +314,7 @@ mmove_t makron_move_pain5 = {
makron_run
};
mframe_t makron_frames_pain4[] = {
static mframe_t makron_frames_pain4[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -341,7 +328,7 @@ mmove_t makron_move_pain4 = {
makron_run
};
mframe_t makron_frames_death2[] = {
static mframe_t makron_frames_death2[] = {
{ai_move, -15, NULL},
{ai_move, 3, NULL},
{ai_move, -12, NULL},
@ -446,7 +433,7 @@ mmove_t makron_move_death2 = {
makron_dead
};
mframe_t makron_frames_death3[] = {
static mframe_t makron_frames_death3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -476,7 +463,7 @@ mmove_t makron_move_death3 = {
NULL
};
mframe_t makron_frames_sight[] = {
static mframe_t makron_frames_sight[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -524,7 +511,7 @@ makronBFG(edict_t *self)
monster_fire_bfg(self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG);
}
mframe_t makron_frames_attack3[] = {
static mframe_t makron_frames_attack3[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -542,7 +529,7 @@ mmove_t makron_move_attack3 = {
makron_run
};
mframe_t makron_frames_attack4[] = {
static mframe_t makron_frames_attack4[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -578,7 +565,7 @@ mmove_t makron_move_attack4 = {
makron_run
};
mframe_t makron_frames_attack5[] = {
static mframe_t makron_frames_attack5[] = {
{ai_charge, 0, makron_prerailgun},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -759,12 +746,6 @@ makron_pain(edict_t *self, edict_t *other /* unused */,
void
makron_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
{
return;
}
self->monsterinfo.currentmove = &makron_move_sight;
}
void
@ -803,7 +784,14 @@ makron_torso_think(edict_t *self)
return;
}
if (self->owner && self->owner->inuse && self->owner->deadflag != DEAD_DEAD)
/* detach from the makron if the legs are gone completely */
if (self->owner && (!self->owner->inuse || (self->owner->health <= self->owner->gib_health)))
{
self->owner = NULL;
}
/* if the makron is revived the torso was put back on him */
if (self->owner && self->owner->deadflag != DEAD_DEAD)
{
G_FreeEdict(self);
return;
@ -817,24 +805,84 @@ makron_torso_think(edict_t *self)
self->nextthink = level.time + FRAMETIME;
}
void
makron_torso(edict_t *ent)
static void
makron_torso_origin(edict_t *self, edict_t *torso)
{
if (!ent)
vec3_t v;
trace_t tr;
AngleVectors(self->s.angles, v, NULL, NULL);
VectorMA(self->s.origin, -84.0f, v, v);
tr = gi.trace(self->s.origin, torso->mins, torso->maxs, v, self, MASK_SOLID);
VectorCopy (tr.endpos, torso->s.origin);
}
void
makron_torso_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */,
int damage /* unused */, vec3_t point /* unused */)
{
int n;
if (self->health > self->gib_health)
{
return;
}
ent->movetype = MOVETYPE_NONE;
ent->solid = SOLID_NOT;
VectorSet(ent->mins, -8, -8, 0);
VectorSet(ent->maxs, 8, 8, 8);
ent->s.frame = FRAME_death301;
ent->s.modelindex = gi.modelindex("models/monsters/boss3/rider/tris.md2");
ent->think = makron_torso_think;
ent->nextthink = level.time + 2 * FRAMETIME;
ent->s.sound = gi.soundindex("makron/spine.wav");
gi.linkentity(ent);
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2",
damage, GIB_METALLIC);
}
G_FreeEdict(self);
}
void
makron_torso(edict_t *self)
{
edict_t *torso;
if (!self)
{
return;
}
torso = G_SpawnOptional();
if (!torso)
{
return;
}
VectorCopy(self->s.angles, torso->s.angles);
VectorSet(torso->mins, -24, -24, 0);
VectorSet(torso->maxs, 24, 24, 16);
makron_torso_origin(self, torso);
torso->gib_health = -800;
torso->takedamage = DAMAGE_YES;
torso->die = makron_torso_die;
torso->deadflag = DEAD_DEAD;
torso->owner = self;
torso->movetype = MOVETYPE_TOSS;
torso->solid = SOLID_BBOX;
torso->svflags = SVF_MONSTER|SVF_DEADMONSTER;
torso->clipmask = MASK_MONSTERSOLID;
torso->s.frame = FRAME_death301;
torso->s.modelindex = gi.modelindex("models/monsters/boss3/rider/tris.md2");
torso->think = makron_torso_think;
torso->nextthink = level.time + 2 * FRAMETIME;
torso->s.sound = gi.soundindex("makron/spine.wav");
gi.linkentity(torso);
}
/* death */
@ -846,8 +894,8 @@ makron_dead(edict_t *self)
return;
}
VectorSet(self->mins, -60, -60, 0);
VectorSet(self->maxs, 60, 60, 72);
VectorSet(self->mins, -48, -48, 0);
VectorSet(self->maxs, 48, 48, 24);
self->movetype = MOVETYPE_TOSS;
self->svflags |= SVF_DEADMONSTER;
self->nextthink = 0;
@ -858,7 +906,6 @@ void
makron_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */,
int damage /* unused */, vec3_t point /* unused */)
{
edict_t *tempent;
int n;
if (!self)
@ -901,12 +948,11 @@ makron_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
self->deadflag = DEAD_DEAD;
self->takedamage = DAMAGE_YES;
tempent = G_Spawn();
VectorCopy(self->s.origin, tempent->s.origin);
VectorCopy(self->s.angles, tempent->s.angles);
tempent->s.origin[1] -= 84;
tempent->owner = self;
makron_torso(tempent);
makron_torso(self);
/* lower bbox since the torso is gone */
self->maxs[2] = 64;
gi.linkentity (self);
self->monsterinfo.currentmove = &makron_move_death2;
}
@ -1096,24 +1142,74 @@ void
MakronSpawn(edict_t *self)
{
vec3_t vec;
edict_t *player;
edict_t *enemy;
edict_t *oldenemy;
SP_monster_makron(self);
/* jump at player */
player = level.sight_client;
if (!player)
if (!self)
{
return;
}
VectorSubtract(player->s.origin, self->s.origin, vec);
self->s.angles[YAW] = vectoyaw(vec);
VectorNormalize(vec);
VectorMA(vec3_origin, 400, vec, self->velocity);
self->velocity[2] = 200;
/* spawning can mess with enemy state so clear it temporarily */
enemy = self->enemy;
self->enemy = NULL;
oldenemy = self->oldenemy;
self->oldenemy = NULL;
SP_monster_makron(self);
if (self->think)
{
self->think(self);
}
/* and re-link enemy state now that he's spawned */
if (enemy && enemy->inuse && enemy->deadflag != DEAD_DEAD)
{
self->enemy = enemy;
}
if (oldenemy && oldenemy->inuse && oldenemy->deadflag != DEAD_DEAD)
{
self->oldenemy = oldenemy;
}
if (!self->enemy)
{
self->enemy = self->oldenemy;
self->oldenemy = NULL;
}
enemy = self->enemy;
if (enemy)
{
FoundTarget(self);
VectorCopy(self->pos1, self->monsterinfo.last_sighting);
}
if (enemy && visible(self, enemy))
{
VectorSubtract(enemy->s.origin, self->s.origin, vec);
self->s.angles[YAW] = vectoyaw(vec);
VectorNormalize(vec);
}
else
{
AngleVectors(self->s.angles, vec, NULL, NULL);
}
VectorScale(vec, 400, self->velocity);
/* the jump frames are fixed length so best to normalize the up speed */
self->velocity[2] = 200.0f * (sv_gravity->value / 800.0f);
self->groundentity = NULL;
self->s.origin[2] += 1;
gi.linkentity(self);
self->pain_debounce_time = level.time + 1;
self->monsterinfo.currentmove = &makron_move_sight;
}
/*
@ -1124,10 +1220,20 @@ MakronToss(edict_t *self)
{
edict_t *ent;
if (!self)
{
return;
}
ent = G_Spawn();
ent->classname = "monster_makron";
ent->nextthink = level.time + 0.8;
ent->think = MakronSpawn;
ent->target = self->target;
VectorCopy(self->s.origin, ent->s.origin);
VectorCopy(self->s.angles, ent->s.angles);
VectorCopy(self->monsterinfo.last_sighting, ent->pos1);
ent->enemy = self->enemy;
ent->oldenemy = self->oldenemy;
}

View file

@ -53,7 +53,7 @@ boss5_search(edict_t *self)
}
/* stand */
mframe_t boss5_frames_stand[] = {
static mframe_t boss5_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -134,7 +134,7 @@ boss5_stand(edict_t *self)
self->monsterinfo.currentmove = &boss5_move_stand;
}
mframe_t boss5_frames_run[] = {
static mframe_t boss5_frames_run[] = {
{ai_run, 12, TreadSound2},
{ai_run, 12, NULL},
{ai_run, 12, NULL},
@ -163,7 +163,7 @@ mmove_t boss5_move_run = {
};
/* walk */
mframe_t boss5_frames_forward[] = {
static mframe_t boss5_frames_forward[] = {
{ai_walk, 4, TreadSound2},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
@ -231,7 +231,7 @@ boss5_run(edict_t *self)
}
}
mframe_t boss5_frames_turn_right[] = {
static mframe_t boss5_frames_turn_right[] = {
{ai_move, 0, TreadSound2},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -259,7 +259,7 @@ mmove_t boss5_move_turn_right = {
boss5_run
};
mframe_t boss5_frames_turn_left[] = {
static mframe_t boss5_frames_turn_left[] = {
{ai_move, 0, TreadSound2},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -287,7 +287,7 @@ mmove_t boss5_move_turn_left = {
boss5_run
};
mframe_t boss5_frames_pain3[] = {
static mframe_t boss5_frames_pain3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -301,7 +301,7 @@ mmove_t boss5_move_pain3 = {
boss5_run
};
mframe_t boss5_frames_pain2[] = {
static mframe_t boss5_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -315,7 +315,7 @@ mmove_t boss5_move_pain2 = {
boss5_run
};
mframe_t boss5_frames_pain1[] = {
static mframe_t boss5_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -329,7 +329,7 @@ mmove_t boss5_move_pain1 = {
boss5_run
};
mframe_t boss5_frames_death1[] = {
static mframe_t boss5_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -363,7 +363,7 @@ mmove_t boss5_move_death = {
boss5_dead
};
mframe_t boss5_frames_backward[] = {
static mframe_t boss5_frames_backward[] = {
{ai_walk, 0, TreadSound2},
{ai_walk, 0, NULL},
{ai_walk, 0, NULL},
@ -391,7 +391,7 @@ mmove_t boss5_move_backward = {
NULL
};
mframe_t boss5_frames_attack4[] = {
static mframe_t boss5_frames_attack4[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -407,7 +407,7 @@ mmove_t boss5_move_attack4 = {
boss5_run
};
mframe_t boss5_frames_attack3[] = {
static mframe_t boss5_frames_attack3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -444,7 +444,7 @@ mmove_t boss5_move_attack3 = {
boss5_run
};
mframe_t boss5_frames_attack2[] = {
static mframe_t boss5_frames_attack2[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -481,7 +481,7 @@ mmove_t boss5_move_attack2 = {
boss5_run
};
mframe_t boss5_frames_attack1[] = {
static mframe_t boss5_frames_attack1[] = {
{ai_charge, 0, boss5MachineGun},
{ai_charge, 0, boss5MachineGun},
{ai_charge, 0, boss5MachineGun},
@ -497,7 +497,7 @@ mmove_t boss5_move_attack1 = {
boss5_reattack1
};
mframe_t boss5_frames_end_attack1[] = {
static mframe_t boss5_frames_end_attack1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Brain.
*
@ -22,13 +41,42 @@ static int sound_search;
static int sound_melee1;
static int sound_melee2;
static int sound_melee3;
static int sound_step;
static int sound_step2;
void brain_run(edict_t *self);
void brain_dead(edict_t *self);
void
brain_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("brain/step1.wav");
sound_step2 = gi.soundindex("brain/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
void
brain_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -39,7 +87,7 @@ brain_sight(edict_t *self, edict_t *other /* unused */)
void
brain_search(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -49,7 +97,7 @@ brain_search(edict_t *self)
/* STAND */
mframe_t brain_frames_stand[] = {
static mframe_t brain_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -84,17 +132,18 @@ mframe_t brain_frames_stand[] = {
{ai_stand, 0, NULL}
};
mmove_t brain_move_stand = {
mmove_t brain_move_stand =
{
FRAME_stand01,
FRAME_stand30,
brain_frames_stand,
NULL
FRAME_stand30,
brain_frames_stand,
NULL
};
void
brain_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -104,7 +153,7 @@ brain_stand(edict_t *self)
/* IDLE */
mframe_t brain_frames_idle[] = {
static mframe_t brain_frames_idle[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -139,17 +188,18 @@ mframe_t brain_frames_idle[] = {
{ai_stand, 0, NULL}
};
mmove_t brain_move_idle = {
mmove_t brain_move_idle =
{
FRAME_stand31,
FRAME_stand60,
brain_frames_idle,
brain_stand
FRAME_stand60,
brain_frames_idle,
brain_stand
};
void
brain_idle(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -160,31 +210,32 @@ brain_idle(edict_t *self)
/* WALK */
mframe_t brain_frames_walk1[] = {
static mframe_t brain_frames_walk1[] = {
{ai_walk, 7, NULL},
{ai_walk, 2, NULL},
{ai_walk, 3, NULL},
{ai_walk, 3, NULL},
{ai_walk, 3, brain_footstep},
{ai_walk, 1, NULL},
{ai_walk, 0, NULL},
{ai_walk, 0, NULL},
{ai_walk, 9, NULL},
{ai_walk, -4, NULL},
{ai_walk, -1, NULL},
{ai_walk, -1, brain_footstep},
{ai_walk, 2, NULL}
};
mmove_t brain_move_walk1 = {
mmove_t brain_move_walk1 =
{
FRAME_walk101,
FRAME_walk111,
brain_frames_walk1,
NULL
brain_frames_walk1,
NULL
};
void
brain_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -192,7 +243,7 @@ brain_walk(edict_t *self)
self->monsterinfo.currentmove = &brain_move_walk1;
}
mframe_t brain_frames_defense[] = {
static mframe_t brain_frames_defense[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -204,14 +255,15 @@ mframe_t brain_frames_defense[] = {
{ai_move, 0, NULL}
};
mmove_t brain_move_defense = {
mmove_t brain_move_defense =
{
FRAME_defens01,
FRAME_defens08,
brain_frames_defense,
NULL
FRAME_defens08,
brain_frames_defense,
NULL
};
mframe_t brain_frames_pain3[] = {
static mframe_t brain_frames_pain3[] = {
{ai_move, -2, NULL},
{ai_move, 2, NULL},
{ai_move, 1, NULL},
@ -220,14 +272,15 @@ mframe_t brain_frames_pain3[] = {
{ai_move, -4, NULL}
};
mmove_t brain_move_pain3 = {
mmove_t brain_move_pain3 =
{
FRAME_pain301,
FRAME_pain306,
brain_frames_pain3,
brain_run
FRAME_pain306,
brain_frames_pain3,
brain_run
};
mframe_t brain_frames_pain2[] = {
static mframe_t brain_frames_pain2[] = {
{ai_move, -2, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -238,17 +291,18 @@ mframe_t brain_frames_pain2[] = {
{ai_move, -2, NULL}
};
mmove_t brain_move_pain2 = {
mmove_t brain_move_pain2 =
{
FRAME_pain201,
FRAME_pain208,
brain_frames_pain2,
brain_run
};
mframe_t brain_frames_pain1[] = {
static mframe_t brain_frames_pain1[] = {
{ai_move, -6, NULL},
{ai_move, -2, NULL},
{ai_move, -6, NULL},
{ai_move, -6, brain_footstep},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -265,15 +319,16 @@ mframe_t brain_frames_pain1[] = {
{ai_move, 1, NULL},
{ai_move, 7, NULL},
{ai_move, 0, NULL},
{ai_move, 3, NULL},
{ai_move, 3, brain_footstep},
{ai_move, -1, NULL}
};
mmove_t brain_move_pain1 = {
mmove_t brain_move_pain1 =
{
FRAME_pain101,
FRAME_pain121,
brain_frames_pain1,
brain_run
FRAME_pain121,
brain_frames_pain1,
brain_run
};
/* DUCK */
@ -281,7 +336,7 @@ mmove_t brain_move_pain1 = {
void
brain_duck_down(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -300,7 +355,7 @@ brain_duck_down(edict_t *self)
void
brain_duck_hold(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -318,7 +373,7 @@ brain_duck_hold(edict_t *self)
void
brain_duck_up(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -329,18 +384,19 @@ brain_duck_up(edict_t *self)
gi.linkentity(self);
}
mframe_t brain_frames_duck[] = {
static mframe_t brain_frames_duck[] = {
{ai_move, 0, NULL},
{ai_move, -2, brain_duck_down},
{ai_move, 17, brain_duck_hold},
{ai_move, -3, NULL},
{ai_move, -3, brain_footstep},
{ai_move, -1, brain_duck_up},
{ai_move, -5, NULL},
{ai_move, -6, NULL},
{ai_move, -6, NULL}
{ai_move, -6, brain_footstep}
};
mmove_t brain_move_duck = {
mmove_t brain_move_duck =
{
FRAME_duck01,
FRAME_duck08,
brain_frames_duck,
@ -370,7 +426,7 @@ brain_dodge(edict_t *self, edict_t *attacker, float eta)
self->monsterinfo.currentmove = &brain_move_duck;
}
mframe_t brain_frames_death2[] = {
static mframe_t brain_frames_death2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -378,14 +434,15 @@ mframe_t brain_frames_death2[] = {
{ai_move, 0, NULL}
};
mmove_t brain_move_death2 = {
mmove_t brain_move_death2 =
{
FRAME_death201,
FRAME_death205,
brain_frames_death2,
brain_dead
brain_dead
};
mframe_t brain_frames_death1[] = {
static mframe_t brain_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, -2, NULL},
@ -406,7 +463,8 @@ mframe_t brain_frames_death1[] = {
{ai_move, 0, NULL}
};
mmove_t brain_move_death1 = {
mmove_t brain_move_death1 =
{
FRAME_death101,
FRAME_death118,
brain_frames_death1,
@ -418,7 +476,7 @@ mmove_t brain_move_death1 = {
void
brain_swing_right(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -431,7 +489,7 @@ brain_hit_right(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -447,7 +505,7 @@ brain_hit_right(edict_t *self)
void
brain_swing_left(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -460,7 +518,7 @@ brain_hit_left(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -473,11 +531,11 @@ brain_hit_left(edict_t *self)
}
}
mframe_t brain_frames_attack1[] = {
static mframe_t brain_frames_attack1[] = {
{ai_charge, 8, NULL},
{ai_charge, 3, NULL},
{ai_charge, 5, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, brain_footstep},
{ai_charge, -3, brain_swing_right},
{ai_charge, 0, NULL},
{ai_charge, -5, NULL},
@ -491,20 +549,21 @@ mframe_t brain_frames_attack1[] = {
{ai_charge, -1, NULL},
{ai_charge, -3, NULL},
{ai_charge, 2, NULL},
{ai_charge, -11, NULL}
{ai_charge, -11, brain_footstep}
};
mmove_t brain_move_attack1 = {
mmove_t brain_move_attack1 =
{
FRAME_attak101,
FRAME_attak118,
brain_frames_attack1,
brain_run
FRAME_attak118,
brain_frames_attack1,
brain_run
};
void
brain_chest_open(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -519,7 +578,7 @@ brain_tentacle_attack(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -537,7 +596,7 @@ brain_tentacle_attack(edict_t *self)
void
brain_chest_closed(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -551,7 +610,7 @@ brain_chest_closed(edict_t *self)
}
}
mframe_t brain_frames_attack2[] = {
static mframe_t brain_frames_attack2[] = {
{ai_charge, 5, NULL},
{ai_charge, -4, NULL},
{ai_charge, -4, NULL},
@ -571,17 +630,18 @@ mframe_t brain_frames_attack2[] = {
{ai_charge, -6, NULL}
};
mmove_t brain_move_attack2 = {
mmove_t brain_move_attack2 =
{
FRAME_attak201,
FRAME_attak217,
brain_frames_attack2,
brain_run
FRAME_attak217,
brain_frames_attack2,
brain_run
};
void
brain_melee(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -806,7 +866,7 @@ brain_laserbeam_reattack(edict_t *self)
}
}
mframe_t brain_frames_attack3[] = {
static mframe_t brain_frames_attack3[] = {
{ai_charge, 5, NULL},
{ai_charge, -4, NULL},
{ai_charge, -4, NULL},
@ -833,7 +893,7 @@ mmove_t brain_move_attack3 = {
brain_run
};
mframe_t brain_frames_attack4[] = {
static mframe_t brain_frames_attack4[] = {
{ai_charge, 9, brain_laserbeam},
{ai_charge, 2, brain_laserbeam},
{ai_charge, 3, brain_laserbeam},
@ -888,23 +948,24 @@ brain_attack(edict_t *self)
/* RUN */
mframe_t brain_frames_run[] = {
static mframe_t brain_frames_run[] = {
{ai_run, 9, NULL},
{ai_run, 2, NULL},
{ai_run, 3, NULL},
{ai_run, 3, NULL},
{ai_run, 3, brain_footstep},
{ai_run, 1, NULL},
{ai_run, 0, NULL},
{ai_run, 0, NULL},
{ai_run, 10, NULL},
{ai_run, -4, NULL},
{ai_run, -1, NULL},
{ai_run, -1, brain_footstep},
{ai_run, 2, NULL}
};
mmove_t brain_move_run = {
mmove_t brain_move_run =
{
FRAME_walk101,
FRAME_walk111,
FRAME_walk111,
brain_frames_run,
NULL
};
@ -912,7 +973,7 @@ mmove_t brain_move_run = {
void
brain_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -935,7 +996,7 @@ brain_pain(edict_t *self, edict_t *other /* unused */,
{
float r;
if (!self)
if (!self)
{
return;
}
@ -979,7 +1040,7 @@ brain_pain(edict_t *self, edict_t *other /* unused */,
void
brain_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -998,7 +1059,7 @@ brain_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* u
{
int n;
if (!self)
if (!self)
{
return;
}
@ -1056,7 +1117,7 @@ brain_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* u
void
SP_monster_brain(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -1067,6 +1128,11 @@ SP_monster_brain(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_chest_open = gi.soundindex("brain/brnatck1.wav");
sound_tentacles_extend = gi.soundindex("brain/brnatck2.wav");
sound_tentacles_retract = gi.soundindex("brain/brnatck3.wav");

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Iron Maiden.
*
@ -32,10 +51,38 @@ static int sound_pain3;
static int sound_sight;
static int sound_search;
static int sound_step;
static int sound_step2;
void
chick_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("bitch/step1.wav");
sound_step2 = gi.soundindex("bitch/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
void
ChickMoan(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -50,7 +97,7 @@ ChickMoan(edict_t *self)
}
}
mframe_t chick_frames_fidget[] = {
static mframe_t chick_frames_fidget[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -83,7 +130,8 @@ mframe_t chick_frames_fidget[] = {
{ai_stand, 0, NULL}
};
mmove_t chick_move_fidget = {
mmove_t chick_move_fidget =
{
FRAME_stand201,
FRAME_stand230,
chick_frames_fidget,
@ -93,7 +141,7 @@ mmove_t chick_move_fidget = {
void
chick_fidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -109,7 +157,7 @@ chick_fidget(edict_t *self)
}
}
mframe_t chick_frames_stand[] = {
static mframe_t chick_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -142,7 +190,8 @@ mframe_t chick_frames_stand[] = {
{ai_stand, 0, chick_fidget},
};
mmove_t chick_move_stand = {
mmove_t chick_move_stand =
{
FRAME_stand101,
FRAME_stand130,
chick_frames_stand,
@ -152,7 +201,7 @@ mmove_t chick_move_stand = {
void
chick_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -160,7 +209,7 @@ chick_stand(edict_t *self)
self->monsterinfo.currentmove = &chick_move_stand;
}
mframe_t chick_frames_start_run[] = {
static mframe_t chick_frames_start_run[] = {
{ai_run, 1, NULL},
{ai_run, 0, NULL},
{ai_run, 0, NULL},
@ -173,47 +222,50 @@ mframe_t chick_frames_start_run[] = {
{ai_run, 3, NULL}
};
mmove_t chick_move_start_run = {
mmove_t chick_move_start_run =
{
FRAME_walk01,
FRAME_walk10,
chick_frames_start_run,
chick_run
};
mframe_t chick_frames_run[] = {
static mframe_t chick_frames_run[] = {
{ai_run, 6, NULL},
{ai_run, 8, NULL},
{ai_run, 8, chick_footstep},
{ai_run, 13, NULL},
{ai_run, 5, NULL},
{ai_run, 7, NULL},
{ai_run, 4, NULL},
{ai_run, 11, NULL},
{ai_run, 11, chick_footstep},
{ai_run, 5, NULL},
{ai_run, 9, NULL},
{ai_run, 7, NULL}
};
mmove_t chick_move_run = {
mmove_t chick_move_run =
{
FRAME_walk11,
FRAME_walk20,
chick_frames_run,
NULL
};
mframe_t chick_frames_walk[] = {
static mframe_t chick_frames_walk[] = {
{ai_walk, 6, NULL},
{ai_walk, 8, NULL},
{ai_walk, 8, chick_footstep},
{ai_walk, 13, NULL},
{ai_walk, 5, NULL},
{ai_walk, 7, NULL},
{ai_walk, 4, NULL},
{ai_walk, 11, NULL},
{ai_walk, 11, chick_footstep},
{ai_walk, 5, NULL},
{ai_walk, 9, NULL},
{ai_walk, 7, NULL}
};
mmove_t chick_move_walk = {
mmove_t chick_move_walk =
{
FRAME_walk11,
FRAME_walk20,
chick_frames_walk,
@ -223,7 +275,7 @@ mmove_t chick_move_walk = {
void
chick_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -234,7 +286,7 @@ chick_walk(edict_t *self)
void
chick_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -256,7 +308,7 @@ chick_run(edict_t *self)
}
}
mframe_t chick_frames_pain1[] = {
static mframe_t chick_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -264,14 +316,15 @@ mframe_t chick_frames_pain1[] = {
{ai_move, 0, NULL}
};
mmove_t chick_move_pain1 = {
mmove_t chick_move_pain1 =
{
FRAME_pain101,
FRAME_pain105,
chick_frames_pain1,
chick_run
};
mframe_t chick_frames_pain2[] = {
static mframe_t chick_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -279,14 +332,15 @@ mframe_t chick_frames_pain2[] = {
{ai_move, 0, NULL}
};
mmove_t chick_move_pain2 = {
mmove_t chick_move_pain2 =
{
FRAME_pain201,
FRAME_pain205,
chick_frames_pain2,
chick_frames_pain2,
chick_run
};
mframe_t chick_frames_pain3[] = {
static mframe_t chick_frames_pain3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, -6, NULL},
@ -310,10 +364,11 @@ mframe_t chick_frames_pain3[] = {
{ai_move, 2, NULL}
};
mmove_t chick_move_pain3 = {
mmove_t chick_move_pain3 =
{
FRAME_pain301,
FRAME_pain321,
chick_frames_pain3,
chick_frames_pain3,
chick_run
};
@ -323,7 +378,7 @@ chick_pain(edict_t *self, edict_t *other /* unused */,
{
float r;
if (!self)
if (!self)
{
return;
}
@ -377,7 +432,7 @@ chick_pain(edict_t *self, edict_t *other /* unused */,
void
chick_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -390,24 +445,24 @@ chick_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t chick_frames_death2[] = {
static mframe_t chick_frames_death2[] = {
{ai_move, -6, NULL},
{ai_move, 0, NULL},
{ai_move, -1, NULL},
{ai_move, -5, NULL},
{ai_move, -5, chick_footstep},
{ai_move, 0, NULL},
{ai_move, -1, NULL},
{ai_move, -2, NULL},
{ai_move, 1, NULL},
{ai_move, 10, NULL},
{ai_move, 2, NULL},
{ai_move, 3, NULL},
{ai_move, 3, chick_footstep},
{ai_move, 1, NULL},
{ai_move, 2, NULL},
{ai_move, 0, NULL},
{ai_move, 3, NULL},
{ai_move, 3, NULL},
{ai_move, 1, NULL},
{ai_move, 1, chick_footstep},
{ai_move, -3, NULL},
{ai_move, -5, NULL},
{ai_move, 4, NULL},
@ -416,14 +471,15 @@ mframe_t chick_frames_death2[] = {
{ai_move, 1, NULL}
};
mmove_t chick_move_death2 = {
mmove_t chick_move_death2 =
{
FRAME_death201,
FRAME_death223,
chick_frames_death2,
chick_dead
};
mframe_t chick_frames_death1[] = {
static mframe_t chick_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, -7, NULL},
@ -438,11 +494,12 @@ mframe_t chick_frames_death1[] = {
{ai_move, 0, NULL}
};
mmove_t chick_move_death1 = {
mmove_t chick_move_death1 =
{
FRAME_death101,
FRAME_death112,
chick_frames_death1,
chick_dead
FRAME_death112,
chick_frames_death1,
chick_dead
};
void
@ -452,7 +509,7 @@ chick_die(edict_t *self, edict_t *inflictor /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -507,7 +564,7 @@ chick_die(edict_t *self, edict_t *inflictor /* unused */,
void
chick_duck_down(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -527,7 +584,7 @@ chick_duck_down(edict_t *self)
void
chick_duck_hold(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -545,7 +602,7 @@ chick_duck_hold(edict_t *self)
void
chick_duck_up(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -556,7 +613,7 @@ chick_duck_up(edict_t *self)
gi.linkentity(self);
}
mframe_t chick_frames_duck[] = {
static mframe_t chick_frames_duck[] = {
{ai_move, 0, chick_duck_down},
{ai_move, 1, NULL},
{ai_move, 4, chick_duck_hold},
@ -566,15 +623,16 @@ mframe_t chick_frames_duck[] = {
{ai_move, 1, NULL}
};
mmove_t chick_move_duck = {
mmove_t chick_move_duck =
{
FRAME_duck01,
FRAME_duck07,
chick_frames_duck,
chick_run
FRAME_duck07,
chick_frames_duck,
chick_run
};
void
chick_dodge(edict_t *self, edict_t *attacker, float eta)
chick_dodge(edict_t *self, edict_t *attacker, float eta /* unused */)
{
if (!self || !attacker)
{
@ -600,7 +658,7 @@ ChickSlash(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -645,7 +703,7 @@ ChickRocket(edict_t *self)
void
Chick_PreAttack1(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -656,7 +714,7 @@ Chick_PreAttack1(edict_t *self)
void
ChickReload(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -664,7 +722,7 @@ ChickReload(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0);
}
mframe_t chick_frames_start_attack1[] = {
static mframe_t chick_frames_start_attack1[] = {
{ai_charge, 0, Chick_PreAttack1},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -673,63 +731,66 @@ mframe_t chick_frames_start_attack1[] = {
{ai_charge, -3, NULL},
{ai_charge, 3, NULL},
{ai_charge, 5, NULL},
{ai_charge, 7, NULL},
{ai_charge, 7, chick_footstep},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, chick_attack1}
};
mmove_t chick_move_start_attack1 = {
mmove_t chick_move_start_attack1 =
{
FRAME_attak101,
FRAME_attak113,
chick_frames_start_attack1,
NULL
FRAME_attak113,
chick_frames_start_attack1,
NULL
};
mframe_t chick_frames_attack1[] = {
static mframe_t chick_frames_attack1[] = {
{ai_charge, 19, ChickRocket},
{ai_charge, -6, NULL},
{ai_charge, -5, NULL},
{ai_charge, -5, chick_footstep},
{ai_charge, -2, NULL},
{ai_charge, -7, NULL},
{ai_charge, -7, chick_footstep},
{ai_charge, 0, NULL},
{ai_charge, 1, NULL},
{ai_charge, 10, ChickReload},
{ai_charge, 4, NULL},
{ai_charge, 5, NULL},
{ai_charge, 5, chick_footstep},
{ai_charge, 6, NULL},
{ai_charge, 6, NULL},
{ai_charge, 4, NULL},
{ai_charge, 4, chick_footstep},
{ai_charge, 3, chick_rerocket}
};
mmove_t chick_move_attack1 = {
mmove_t chick_move_attack1 =
{
FRAME_attak114,
FRAME_attak127,
chick_frames_attack1,
NULL
FRAME_attak127,
chick_frames_attack1,
NULL
};
mframe_t chick_frames_end_attack1[] = {
static mframe_t chick_frames_end_attack1[] = {
{ai_charge, -3, NULL},
{ai_charge, 0, NULL},
{ai_charge, -6, NULL},
{ai_charge, -4, NULL},
{ai_charge, -2, NULL}
{ai_charge, -2, chick_footstep}
};
mmove_t chick_move_end_attack1 = {
mmove_t chick_move_end_attack1 =
{
FRAME_attak128,
FRAME_attak132,
chick_frames_end_attack1,
chick_run
chick_run
};
void
chick_rerocket(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -755,7 +816,7 @@ chick_rerocket(edict_t *self)
void
chick_attack1(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -763,7 +824,7 @@ chick_attack1(edict_t *self)
self->monsterinfo.currentmove = &chick_move_attack1;
}
mframe_t chick_frames_slash[] = {
static mframe_t chick_frames_slash[] = {
{ai_charge, 1, NULL},
{ai_charge, 7, ChickSlash},
{ai_charge, -7, NULL},
@ -775,31 +836,33 @@ mframe_t chick_frames_slash[] = {
{ai_charge, -2, chick_reslash}
};
mmove_t chick_move_slash = {
mmove_t chick_move_slash =
{
FRAME_attak204,
FRAME_attak212,
chick_frames_slash,
NULL
FRAME_attak212,
chick_frames_slash,
NULL
};
mframe_t chick_frames_end_slash[] = {
static mframe_t chick_frames_end_slash[] = {
{ai_charge, -6, NULL},
{ai_charge, -1, NULL},
{ai_charge, -6, NULL},
{ai_charge, 0, NULL}
{ai_charge, 0, chick_footstep}
};
mmove_t chick_move_end_slash = {
mmove_t chick_move_end_slash =
{
FRAME_attak213,
FRAME_attak216,
chick_frames_end_slash,
chick_frames_end_slash,
chick_run
};
void
chick_reslash(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -827,26 +890,32 @@ chick_reslash(edict_t *self)
void
chick_slash(edict_t *self)
{
if (!self)
{
return;
}
self->monsterinfo.currentmove = &chick_move_slash;
}
mframe_t chick_frames_start_slash[] = {
static mframe_t chick_frames_start_slash[] = {
{ai_charge, 1, NULL},
{ai_charge, 8, NULL},
{ai_charge, 3, NULL}
{ai_charge, 3, chick_footstep}
};
mmove_t chick_move_start_slash = {
mmove_t chick_move_start_slash =
{
FRAME_attak201,
FRAME_attak203,
chick_frames_start_slash,
chick_slash
chick_slash
};
void
chick_melee(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -857,7 +926,7 @@ chick_melee(edict_t *self)
void
chick_attack(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -868,7 +937,7 @@ chick_attack(edict_t *self)
void
chick_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -882,7 +951,7 @@ chick_sight(edict_t *self, edict_t *other /* unused */)
void
SP_monster_chick(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -893,6 +962,11 @@ SP_monster_chick(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_missile_prelaunch = gi.soundindex("chick/chkatck1.wav");
sound_missile_launch = gi.soundindex("chick/chkatck2.wav");
sound_melee_swing = gi.soundindex("chick/chkatck3.wav");

View file

@ -691,7 +691,7 @@ fly_vertical2(edict_t *self)
}
}
mframe_t fixbot_frames_landing[] = {
static mframe_t fixbot_frames_landing[] = {
{ai_move, 0, NULL},
{ai_move, 0, fly_vertical2},
{ai_move, 0, fly_vertical2},
@ -765,7 +765,7 @@ mmove_t fixbot_move_landing = {
};
/* generic ambient stand */
mframe_t fixbot_frames_stand[] = {
static mframe_t fixbot_frames_stand[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -795,7 +795,7 @@ mmove_t fixbot_move_stand = {
NULL
};
mframe_t fixbot_frames_stand2[] = {
static mframe_t fixbot_frames_stand2[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -831,7 +831,7 @@ mmove_t fixbot_move_stand2 = {
* and take the object with it ( this may require a
* variant of liftoff and landing )
*/
mframe_t fixbot_frames_pickup[] = {
static mframe_t fixbot_frames_pickup[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -871,7 +871,7 @@ mmove_t fixbot_move_pickup = {
};
/* generic frame to move bot */
mframe_t fixbot_frames_roamgoal[] = {
static mframe_t fixbot_frames_roamgoal[] = {
{ai_move, 0, roam_goal}
};
@ -904,7 +904,7 @@ ai_facing(edict_t *self, float dist)
}
}
mframe_t fixbot_frames_turn[] = {
static mframe_t fixbot_frames_turn[] = {
{ai_facing, 0, NULL}
};
@ -927,7 +927,7 @@ go_roam(edict_t *self)
}
/* takeoff */
mframe_t fixbot_frames_takeoff[] = {
static mframe_t fixbot_frames_takeoff[] = {
{ai_move, 0.01, fly_vertical},
{ai_move, 0.01, fly_vertical},
{ai_move, 0.01, fly_vertical},
@ -955,7 +955,7 @@ mmove_t fixbot_move_takeoff = {
};
/* findout what this is */
mframe_t fixbot_frames_paina[] = {
static mframe_t fixbot_frames_paina[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -972,7 +972,7 @@ mmove_t fixbot_move_paina = {
};
/* findout what this is */
mframe_t fixbot_frames_painb[] = {
static mframe_t fixbot_frames_painb[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -995,7 +995,7 @@ mmove_t fixbot_move_painb = {
* call a generic painsound
* some spark effects
*/
mframe_t fixbot_frames_pain3[] = {
static mframe_t fixbot_frames_pain3[] = {
{ai_move, -1, NULL}
};
@ -1012,7 +1012,7 @@ mmove_t fixbot_move_pain3 = {
* ( may need second land if the
* bot is releasing jib into jib vat )
*/
mframe_t fixbot_frames_land[] = {
static mframe_t fixbot_frames_land[] = {
{ai_move, 0, NULL}
};
@ -1034,7 +1034,7 @@ ai_movetogoal(edict_t *self, float dist)
M_MoveToGoal(self, dist);
}
mframe_t fixbot_frames_forward[] = {
static mframe_t fixbot_frames_forward[] = {
{ai_movetogoal, 5, use_scanner}
};
@ -1045,7 +1045,7 @@ mmove_t fixbot_move_forward = {
NULL
};
mframe_t fixbot_frames_walk[] = {
static mframe_t fixbot_frames_walk[] = {
{ai_walk, 5, NULL}
};
@ -1056,7 +1056,7 @@ mmove_t fixbot_move_walk = {
NULL
};
mframe_t fixbot_frames_run[] = {
static mframe_t fixbot_frames_run[] = {
{ai_run, 10, NULL}
};
@ -1067,7 +1067,7 @@ mmove_t fixbot_move_run = {
NULL
};
mframe_t fixbot_frames_death1[] = {
static mframe_t fixbot_frames_death1[] = {
{ai_move, 0, NULL}
};
@ -1078,7 +1078,7 @@ mmove_t fixbot_move_death1 = {
fixbot_dead
};
mframe_t fixbot_frames_backward[] = {
static mframe_t fixbot_frames_backward[] = {
{ai_move, 0, NULL}
};
@ -1089,7 +1089,7 @@ mmove_t fixbot_move_backward = {
NULL
};
mframe_t fixbot_frames_start_attack[] = {
static mframe_t fixbot_frames_start_attack[] = {
{ai_charge, 0, NULL}
};
@ -1100,7 +1100,7 @@ mmove_t fixbot_move_start_attack = {
fixbot_attack
};
mframe_t fixbot_frames_attack1[] = {
static mframe_t fixbot_frames_attack1[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -1218,7 +1218,7 @@ fixbot_fire_laser(edict_t *self)
}
}
mframe_t fixbot_frames_laserattack[] = {
static mframe_t fixbot_frames_laserattack[] = {
{ai_charge, 0, fixbot_fire_laser},
{ai_charge, 0, fixbot_fire_laser},
{ai_charge, 0, fixbot_fire_laser},
@ -1236,7 +1236,7 @@ mmove_t fixbot_move_laserattack = {
/* need to get forward translation
data for the charge attack */
mframe_t fixbot_frames_attack2[] = {
static mframe_t fixbot_frames_attack2[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -1331,7 +1331,7 @@ ai_move2(edict_t *self, float dist)
M_ChangeYaw(self);
}
mframe_t fixbot_frames_weld_start[] = {
static mframe_t fixbot_frames_weld_start[] = {
{ai_move2, 0, NULL},
{ai_move2, 0, NULL},
{ai_move2, 0, NULL},
@ -1351,7 +1351,7 @@ mmove_t fixbot_move_weld_start = {
NULL
};
mframe_t fixbot_frames_weld[] = {
static mframe_t fixbot_frames_weld[] = {
{ai_move2, 0, fixbot_fire_welder},
{ai_move2, 0, fixbot_fire_welder},
{ai_move2, 0, fixbot_fire_welder},
@ -1368,7 +1368,7 @@ mmove_t fixbot_move_weld = {
NULL
};
mframe_t fixbot_frames_weld_end[] = {
static mframe_t fixbot_frames_weld_end[] = {
{ai_move2, -2, NULL},
{ai_move2, -2, NULL},
{ai_move2, -2, NULL},

View file

@ -21,7 +21,7 @@ static int sound_sight;
void flipper_stand(edict_t *self);
mframe_t flipper_frames_stand[] = {
static mframe_t flipper_frames_stand[] = {
{ai_stand, 0, NULL}
};
@ -43,7 +43,7 @@ flipper_stand(edict_t *self)
self->monsterinfo.currentmove = &flipper_move_stand;
}
mframe_t flipper_frames_run[] = {
static mframe_t flipper_frames_run[] = {
{ai_run, FLIPPER_RUN_SPEED, NULL}, /* 6 */
{ai_run, FLIPPER_RUN_SPEED, NULL},
{ai_run, FLIPPER_RUN_SPEED, NULL},
@ -90,7 +90,7 @@ flipper_run_loop(edict_t *self)
self->monsterinfo.currentmove = &flipper_move_run_loop;
}
mframe_t flipper_frames_run_start[] = {
static mframe_t flipper_frames_run_start[] = {
{ai_run, 8, NULL},
{ai_run, 8, NULL},
{ai_run, 8, NULL},
@ -118,7 +118,7 @@ flipper_run(edict_t *self)
}
/* Standard Swimming */
mframe_t flipper_frames_walk[] = {
static mframe_t flipper_frames_walk[] = {
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
@ -163,7 +163,7 @@ flipper_walk(edict_t *self)
self->monsterinfo.currentmove = &flipper_move_walk;
}
mframe_t flipper_frames_start_run[] = {
static mframe_t flipper_frames_start_run[] = {
{ai_run, 8, NULL},
{ai_run, 8, NULL},
{ai_run, 8, NULL},
@ -188,7 +188,7 @@ flipper_start_run(edict_t *self)
self->monsterinfo.currentmove = &flipper_move_start_run;
}
mframe_t flipper_frames_pain2[] = {
static mframe_t flipper_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -203,7 +203,7 @@ mmove_t flipper_move_pain2 = {
flipper_run
};
mframe_t flipper_frames_pain1[] = {
static mframe_t flipper_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -243,7 +243,7 @@ flipper_preattack(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0);
}
mframe_t flipper_frames_attack[] = {
static mframe_t flipper_frames_attack[] = {
{ai_charge, 0, flipper_preattack},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -353,7 +353,7 @@ flipper_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t flipper_frames_death[] = {
static mframe_t flipper_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -79,7 +79,7 @@ floater_fire_blaster(edict_t *self)
monster_fire_blaster(self, start, dir, 1, 1000, MZ2_FLOAT_BLASTER_1, effect);
}
mframe_t floater_frames_stand1[] = {
static mframe_t floater_frames_stand1[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -141,7 +141,7 @@ mmove_t floater_move_stand1 = {
NULL
};
mframe_t floater_frames_stand2[] = {
static mframe_t floater_frames_stand2[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -221,7 +221,7 @@ floater_stand(edict_t *self)
}
}
mframe_t floater_frames_activate[] = {
static mframe_t floater_frames_activate[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -261,7 +261,7 @@ mmove_t floater_move_activate = {
NULL
};
mframe_t floater_frames_attack1[] = {
static mframe_t floater_frames_attack1[] = {
{ai_charge, 0, NULL}, /* Blaster attack */
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -285,7 +285,7 @@ mmove_t floater_move_attack1 = {
floater_run
};
mframe_t floater_frames_attack2[] = {
static mframe_t floater_frames_attack2[] = {
{ai_charge, 0, NULL}, /* Claws */
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -320,7 +320,7 @@ mmove_t floater_move_attack2 = {
floater_run
};
mframe_t floater_frames_attack3[] = {
static mframe_t floater_frames_attack3[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -364,7 +364,7 @@ mmove_t floater_move_attack3 = {
floater_run
};
mframe_t floater_frames_death[] = {
static mframe_t floater_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -387,7 +387,7 @@ mmove_t floater_move_death = {
floater_dead
};
mframe_t floater_frames_pain1[] = {
static mframe_t floater_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -404,7 +404,7 @@ mmove_t floater_move_pain1 = {
floater_run
};
mframe_t floater_frames_pain2[] = {
static mframe_t floater_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -422,7 +422,7 @@ mmove_t floater_move_pain2 = {
floater_run
};
mframe_t floater_frames_pain3[] = {
static mframe_t floater_frames_pain3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -444,7 +444,7 @@ mmove_t floater_move_pain3 = {
floater_run
};
mframe_t floater_frames_walk[] = {
static mframe_t floater_frames_walk[] = {
{ai_walk, 5, NULL},
{ai_walk, 5, NULL},
{ai_walk, 5, NULL},
@ -506,7 +506,7 @@ mmove_t floater_move_walk = {
NULL
};
mframe_t floater_frames_run[] = {
static mframe_t floater_frames_run[] = {
{ai_run, 13, NULL},
{ai_run, 13, NULL},
{ai_run, 13, NULL},

View file

@ -59,7 +59,7 @@ flyer_pop_blades(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_sproing, 1, ATTN_NORM, 0);
}
mframe_t flyer_frames_stand[] = {
static mframe_t flyer_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -114,7 +114,7 @@ mmove_t flyer_move_stand = {
NULL
};
mframe_t flyer_frames_walk[] = {
static mframe_t flyer_frames_walk[] = {
{ai_walk, 5, NULL},
{ai_walk, 5, NULL},
{ai_walk, 5, NULL},
@ -169,7 +169,7 @@ mmove_t flyer_move_walk = {
NULL
};
mframe_t flyer_frames_run[] = {
static mframe_t flyer_frames_run[] = {
{ai_run, 10, NULL},
{ai_run, 10, NULL},
{ai_run, 10, NULL},
@ -264,7 +264,7 @@ flyer_stand(edict_t *self)
self->monsterinfo.currentmove = &flyer_move_stand;
}
mframe_t flyer_frames_start[] = {
static mframe_t flyer_frames_start[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -280,7 +280,7 @@ mmove_t flyer_move_start = {
NULL
};
mframe_t flyer_frames_stop[] = {
static mframe_t flyer_frames_stop[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -319,7 +319,7 @@ flyer_start(edict_t *self)
self->monsterinfo.currentmove = &flyer_move_start;
}
mframe_t flyer_frames_rollright[] = {
static mframe_t flyer_frames_rollright[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -338,7 +338,7 @@ mmove_t flyer_move_rollright = {
NULL
};
mframe_t flyer_frames_rollleft[] = {
static mframe_t flyer_frames_rollleft[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -357,7 +357,7 @@ mmove_t flyer_move_rollleft = {
NULL
};
mframe_t flyer_frames_pain3[] = {
static mframe_t flyer_frames_pain3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -371,7 +371,7 @@ mmove_t flyer_move_pain3 = {
flyer_run
};
mframe_t flyer_frames_pain2[] = {
static mframe_t flyer_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -385,7 +385,7 @@ mmove_t flyer_move_pain2 = {
flyer_run
};
mframe_t flyer_frames_pain1[] = {
static mframe_t flyer_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -404,7 +404,7 @@ mmove_t flyer_move_pain1 = {
flyer_run
};
mframe_t flyer_frames_defense[] = {
static mframe_t flyer_frames_defense[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL}, /* Hold this frame */
@ -420,7 +420,7 @@ mmove_t flyer_move_defense = {
NULL
};
mframe_t flyer_frames_bankright[] = {
static mframe_t flyer_frames_bankright[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -437,7 +437,7 @@ mmove_t flyer_move_bankright = {
NULL
};
mframe_t flyer_frames_bankleft[] = {
static mframe_t flyer_frames_bankleft[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -511,7 +511,7 @@ flyer_fireright(edict_t *self)
flyer_fire(self, MZ2_FLYER_BLASTER_2);
}
mframe_t flyer_frames_attack2[] = {
static mframe_t flyer_frames_attack2[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -568,7 +568,7 @@ flyer_slash_right(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0);
}
mframe_t flyer_frames_start_melee[] = {
static mframe_t flyer_frames_start_melee[] = {
{ai_charge, 0, flyer_pop_blades},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -584,7 +584,7 @@ mmove_t flyer_move_start_melee = {
flyer_loop_melee
};
mframe_t flyer_frames_end_melee[] = {
static mframe_t flyer_frames_end_melee[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL}
@ -597,7 +597,7 @@ mmove_t flyer_move_end_melee = {
flyer_run
};
mframe_t flyer_frames_loop_melee[] = {
static mframe_t flyer_frames_loop_melee[] = {
{ai_charge, 0, NULL}, /* Loop Start */
{ai_charge, 0, NULL},
{ai_charge, 0, flyer_slash_left}, /* Left Wing Strike */

View file

@ -325,7 +325,7 @@ ai_stand2(edict_t *self, float dist)
}
}
mframe_t gekk_frames_stand[] = {
static mframe_t gekk_frames_stand[] = {
{ai_stand2, 0, NULL},
{ai_stand2, 0, NULL},
{ai_stand2, 0, NULL},
@ -378,7 +378,7 @@ mmove_t gekk_move_stand = {
NULL
};
mframe_t gekk_frames_standunderwater[] = {
static mframe_t gekk_frames_standunderwater[] = {
{ai_stand2, 0, NULL},
{ai_stand2, 0, NULL},
{ai_stand2, 0, NULL},
@ -405,7 +405,7 @@ gekk_swim_loop(edict_t *self)
self->monsterinfo.currentmove = &gekk_move_swim_loop;
}
mframe_t gekk_frames_swim[] = {
static mframe_t gekk_frames_swim[] = {
{ai_run, 16, NULL},
{ai_run, 16, NULL},
{ai_run, 16, NULL},
@ -420,7 +420,7 @@ mmove_t gekk_move_swim_loop = {
gekk_swim_loop
};
mframe_t gekk_frames_swim_start[] = {
static mframe_t gekk_frames_swim_start[] = {
{ai_run, 14, NULL},
{ai_run, 14, NULL},
{ai_run, 14, NULL},
@ -516,7 +516,7 @@ gekk_idle_loop(edict_t *self)
}
}
mframe_t gekk_frames_idle[] = {
static mframe_t gekk_frames_idle[] = {
{ai_stand2, 0, gekk_search},
{ai_stand2, 0, NULL},
{ai_stand2, 0, NULL},
@ -586,7 +586,7 @@ gekk_idle(edict_t *self)
}
}
mframe_t gekk_frames_walk[] = {
static mframe_t gekk_frames_walk[] = {
{ai_walk, 3.849, gekk_check_underwater}, /* frame 0 */
{ai_walk, 19.606, NULL}, /* frame 1 */
{ai_walk, 25.583, NULL}, /* frame 2 */
@ -657,7 +657,7 @@ gekk_run(edict_t *self)
}
}
mframe_t gekk_frames_run[] = {
static mframe_t gekk_frames_run[] = {
{ai_run, 3.849, gekk_check_underwater}, /* frame 0 */
{ai_run, 19.606, NULL}, /* frame 1 */
{ai_run, 25.583, NULL}, /* frame 2 */
@ -673,7 +673,7 @@ mmove_t gekk_move_run = {
NULL
};
mframe_t gekk_frames_run_st[] = {
static mframe_t gekk_frames_run_st[] = {
{ai_run, 0.212, NULL}, /* frame 0 */
{ai_run, 19.753, NULL}, /* frame 1 */
};
@ -895,7 +895,7 @@ reloogie(edict_t *self)
}
}
mframe_t gekk_frames_spit[] = {
static mframe_t gekk_frames_spit[] = {
{ai_charge, 0.000, NULL},
{ai_charge, 0.000, NULL},
{ai_charge, 0.000, NULL},
@ -913,7 +913,7 @@ mmove_t gekk_move_spit = {
gekk_run_start
};
mframe_t gekk_frames_attack1[] = {
static mframe_t gekk_frames_attack1[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -934,7 +934,7 @@ mmove_t gekk_move_attack1 = {
gekk_run_start
};
mframe_t gekk_frames_attack2[] = {
static mframe_t gekk_frames_attack2[] = {
{ai_charge, 0.000, NULL},
{ai_charge, 0.000, NULL},
{ai_charge, 0.000, gekk_hit_left},
@ -969,7 +969,7 @@ gekk_check_underwater(edict_t *self)
}
}
mframe_t gekk_frames_leapatk[] = {
static mframe_t gekk_frames_leapatk[] = {
{ai_charge, 0.000, NULL}, /* frame 0 */
{ai_charge, -0.387, NULL}, /* frame 1 */
{ai_charge, -1.113, NULL}, /* frame 2 */
@ -999,7 +999,7 @@ mmove_t gekk_move_leapatk = {
gekk_run_start
};
mframe_t gekk_frames_leapatk2[] = {
static mframe_t gekk_frames_leapatk2[] = {
{ai_charge, 0.000, NULL}, /* frame 0 */
{ai_charge, -0.387, NULL}, /* frame 1 */
{ai_charge, -1.113, NULL}, /* frame 2 */
@ -1049,7 +1049,7 @@ gekk_preattack(edict_t *self)
/* Unused but PITA to remove */
}
mframe_t gekk_frames_attack[] = {
static mframe_t gekk_frames_attack[] = {
{ai_charge, 16, gekk_preattack},
{ai_charge, 16, NULL},
{ai_charge, 16, NULL},
@ -1296,7 +1296,7 @@ gekk_jump(edict_t *self)
}
}
mframe_t gekk_frames_pain[] = {
static mframe_t gekk_frames_pain[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.000, NULL}, /* frame 1 */
{ai_move, 0.000, NULL}, /* frame 2 */
@ -1312,7 +1312,7 @@ mmove_t gekk_move_pain = {
gekk_run_start
};
mframe_t gekk_frames_pain1[] = {
static mframe_t gekk_frames_pain1[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.000, NULL}, /* frame 1 */
{ai_move, 0.000, NULL}, /* frame 2 */
@ -1334,7 +1334,7 @@ mmove_t gekk_move_pain1 = {
gekk_run_start
};
mframe_t gekk_frames_pain2[] = {
static mframe_t gekk_frames_pain2[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.000, NULL}, /* frame 1 */
{ai_move, 0.000, NULL}, /* frame 2 */
@ -1480,7 +1480,7 @@ isgibfest(edict_t *self)
}
}
mframe_t gekk_frames_death1[] = {
static mframe_t gekk_frames_death1[] = {
{ai_move, -5.151, NULL}, /* frame 0 */
{ai_move, -12.223, NULL}, /* frame 1 */
{ai_move, -11.484, NULL}, /* frame 2 */
@ -1500,7 +1500,7 @@ mmove_t gekk_move_death1 = {
gekk_dead
};
mframe_t gekk_frames_death3[] = {
static mframe_t gekk_frames_death3[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.022, NULL}, /* frame 1 */
{ai_move, 0.169, NULL}, /* frame 2 */
@ -1517,7 +1517,7 @@ mmove_t gekk_move_death3 = {
gekk_dead
};
mframe_t gekk_frames_death4[] = {
static mframe_t gekk_frames_death4[] = {
{ai_move, 5.103, NULL}, /* frame 0 */
{ai_move, -4.808, NULL}, /* frame 1 */
{ai_move, -10.509, NULL}, /* frame 2 */
@ -1562,7 +1562,7 @@ mmove_t gekk_move_death4 = {
gekk_dead
};
mframe_t gekk_frames_wdeath[] = {
static mframe_t gekk_frames_wdeath[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.000, NULL}, /* frame 1 */
{ai_move, 0.000, NULL}, /* frame 2 */
@ -1731,7 +1731,7 @@ gekk_duck_hold(edict_t *self)
}
}
mframe_t gekk_frames_lduck[] = {
static mframe_t gekk_frames_lduck[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.000, NULL}, /* frame 1 */
{ai_move, 0.000, NULL}, /* frame 2 */
@ -1754,7 +1754,7 @@ mmove_t gekk_move_lduck = {
gekk_run_start
};
mframe_t gekk_frames_rduck[] = {
static mframe_t gekk_frames_rduck[] = {
{ai_move, 0.000, NULL}, /* frame 0 */
{ai_move, 0.000, NULL}, /* frame 1 */
{ai_move, 0.000, NULL}, /* frame 2 */

View file

@ -63,7 +63,7 @@ gladb_cleaver_swing(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0);
}
mframe_t gladb_frames_stand[] = {
static mframe_t gladb_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -91,7 +91,7 @@ gladb_stand(edict_t *self)
self->monsterinfo.currentmove = &gladb_move_stand;
}
mframe_t gladb_frames_walk[] = {
static mframe_t gladb_frames_walk[] = {
{ai_walk, 15, NULL},
{ai_walk, 7, NULL},
{ai_walk, 6, NULL},
@ -128,7 +128,7 @@ gladb_walk(edict_t *self)
self->monsterinfo.currentmove = &gladb_move_walk;
}
mframe_t gladb_frames_run[] = {
static mframe_t gladb_frames_run[] = {
{ai_run, 23, NULL},
{ai_run, 14, NULL},
{ai_run, 14, NULL},
@ -184,7 +184,7 @@ GladbMelee(edict_t *self)
}
}
mframe_t gladb_frames_attack_melee[] = {
static mframe_t gladb_frames_attack_melee[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -259,7 +259,7 @@ gladbGun_check(edict_t *self)
}
}
mframe_t gladb_frames_attack_gun[] = {
static mframe_t gladb_frames_attack_gun[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, gladbGun},
@ -289,13 +289,19 @@ gladb_attack(edict_t *self)
return;
}
/* a small safe zone */
VectorSubtract(self->s.origin, self->enemy->s.origin, v);
range = VectorLength(v);
if (range <= (MELEE_DISTANCE + 32))
/* a small safe zone
but not for stand-ground ones since players can
abuse it by standing still inside this range
*/
if (!(self->monsterinfo.aiflags & AI_STAND_GROUND))
{
return;
VectorSubtract(self->s.origin, self->enemy->s.origin, v);
range = VectorLength(v);
if (range <= (MELEE_DISTANCE + 32))
{
return;
}
}
/* charge up the railgun */
@ -305,7 +311,7 @@ gladb_attack(edict_t *self)
self->monsterinfo.currentmove = &gladb_move_attack_gun;
}
mframe_t gladb_frames_pain[] = {
static mframe_t gladb_frames_pain[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -320,7 +326,7 @@ mmove_t gladb_move_pain = {
gladb_frames_pain, gladb_run
};
mframe_t gladb_frames_pain_air[] = {
static mframe_t gladb_frames_pain_air[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -399,7 +405,7 @@ gladb_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t gladb_frames_death[] = {
static mframe_t gladb_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Gladiator.
*
@ -19,10 +38,37 @@ static int sound_idle;
static int sound_search;
static int sound_sight;
static int sound_step;
static int sound_step2;
void
gladiator_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("gladiator/step1.wav");
sound_step2 = gi.soundindex("gladiator/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
void
gladiator_idle(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -33,7 +79,7 @@ gladiator_idle(edict_t *self)
void
gladiator_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -44,7 +90,7 @@ gladiator_sight(edict_t *self, edict_t *other /* unused */)
void
gladiator_search(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -55,7 +101,7 @@ gladiator_search(edict_t *self)
void
gladiator_cleaver_swing(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -63,7 +109,7 @@ gladiator_cleaver_swing(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0);
}
mframe_t gladiator_frames_stand[] = {
static mframe_t gladiator_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -73,17 +119,18 @@ mframe_t gladiator_frames_stand[] = {
{ai_stand, 0, NULL}
};
mmove_t gladiator_move_stand = {
mmove_t gladiator_move_stand =
{
FRAME_stand1,
FRAME_stand7,
gladiator_frames_stand,
NULL
FRAME_stand7,
gladiator_frames_stand,
NULL
};
void
gladiator_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -91,12 +138,12 @@ gladiator_stand(edict_t *self)
self->monsterinfo.currentmove = &gladiator_move_stand;
}
mframe_t gladiator_frames_walk[] = {
static mframe_t gladiator_frames_walk[] = {
{ai_walk, 15, NULL},
{ai_walk, 7, NULL},
{ai_walk, 6, NULL},
{ai_walk, 5, NULL},
{ai_walk, 2, NULL},
{ai_walk, 2, gladiator_footstep},
{ai_walk, 0, NULL},
{ai_walk, 2, NULL},
{ai_walk, 8, NULL},
@ -104,23 +151,24 @@ mframe_t gladiator_frames_walk[] = {
{ai_walk, 8, NULL},
{ai_walk, 5, NULL},
{ai_walk, 5, NULL},
{ai_walk, 2, NULL},
{ai_walk, 2, gladiator_footstep},
{ai_walk, 2, NULL},
{ai_walk, 1, NULL},
{ai_walk, 8, NULL}
};
mmove_t gladiator_move_walk = {
mmove_t gladiator_move_walk =
{
FRAME_walk1,
FRAME_walk16,
gladiator_frames_walk,
NULL
FRAME_walk16,
gladiator_frames_walk,
NULL
};
void
gladiator_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -128,26 +176,27 @@ gladiator_walk(edict_t *self)
self->monsterinfo.currentmove = &gladiator_move_walk;
}
mframe_t gladiator_frames_run[] = {
static mframe_t gladiator_frames_run[] = {
{ai_run, 23, NULL},
{ai_run, 14, NULL},
{ai_run, 14, NULL},
{ai_run, 14, gladiator_footstep},
{ai_run, 21, NULL},
{ai_run, 12, NULL},
{ai_run, 13, NULL}
{ai_run, 13, gladiator_footstep}
};
mmove_t gladiator_move_run = {
mmove_t gladiator_move_run =
{
FRAME_run1,
FRAME_run6,
gladiator_frames_run,
NULL
FRAME_run6,
gladiator_frames_run,
NULL
};
void
gladiator_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -167,7 +216,7 @@ GaldiatorMelee(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -184,7 +233,7 @@ GaldiatorMelee(edict_t *self)
}
}
mframe_t gladiator_frames_attack_melee[] = {
static mframe_t gladiator_frames_attack_melee[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -204,17 +253,18 @@ mframe_t gladiator_frames_attack_melee[] = {
{ai_charge, 0, NULL}
};
mmove_t gladiator_move_attack_melee = {
mmove_t gladiator_move_attack_melee =
{
FRAME_melee1,
FRAME_melee17,
gladiator_frames_attack_melee,
gladiator_run
FRAME_melee17,
gladiator_frames_attack_melee,
gladiator_run
};
void
gladiator_melee(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -229,7 +279,7 @@ GladiatorGun(edict_t *self)
vec3_t dir;
vec3_t forward, right;
if (!self)
if (!self)
{
return;
}
@ -245,7 +295,7 @@ GladiatorGun(edict_t *self)
monster_fire_railgun(self, start, dir, 50, 100, MZ2_GLADIATOR_RAILGUN_1);
}
mframe_t gladiator_frames_attack_gun[] = {
static mframe_t gladiator_frames_attack_gun[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -257,11 +307,12 @@ mframe_t gladiator_frames_attack_gun[] = {
{ai_charge, 0, NULL}
};
mmove_t gladiator_move_attack_gun = {
mmove_t gladiator_move_attack_gun =
{
FRAME_attack1,
FRAME_attack9,
gladiator_frames_attack_gun,
gladiator_run
FRAME_attack9,
gladiator_frames_attack_gun,
gladiator_run
};
void
@ -270,18 +321,24 @@ gladiator_attack(edict_t *self)
float range;
vec3_t v;
if (!self)
if (!self)
{
return;
}
/* a small safe zone */
VectorSubtract(self->s.origin, self->enemy->s.origin, v);
range = VectorLength(v);
if (range <= (MELEE_DISTANCE + 32))
/* a small safe zone
but not for stand-ground ones since players can
abuse it by standing still inside this range
*/
if (!(self->monsterinfo.aiflags & AI_STAND_GROUND))
{
return;
VectorSubtract(self->s.origin, self->enemy->s.origin, v);
range = VectorLength(v);
if (range <= (MELEE_DISTANCE + 32))
{
return;
}
}
/* charge up the railgun */
@ -291,7 +348,7 @@ gladiator_attack(edict_t *self)
self->monsterinfo.currentmove = &gladiator_move_attack_gun;
}
mframe_t gladiator_frames_pain[] = {
static mframe_t gladiator_frames_pain[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -300,14 +357,15 @@ mframe_t gladiator_frames_pain[] = {
{ai_move, 0, NULL}
};
mmove_t gladiator_move_pain = {
mmove_t gladiator_move_pain =
{
FRAME_pain1,
FRAME_pain6,
gladiator_frames_pain,
gladiator_run
FRAME_pain6,
gladiator_frames_pain,
gladiator_run
};
mframe_t gladiator_frames_pain_air[] = {
static mframe_t gladiator_frames_pain_air[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -317,18 +375,19 @@ mframe_t gladiator_frames_pain_air[] = {
{ai_move, 0, NULL}
};
mmove_t gladiator_move_pain_air = {
mmove_t gladiator_move_pain_air =
{
FRAME_painup1,
FRAME_painup7,
gladiator_frames_pain_air,
gladiator_run
FRAME_painup7,
gladiator_frames_pain_air,
gladiator_run
};
void
gladiator_pain(edict_t *self, edict_t *other /* unused */,
float kick /* unused */, int damage)
{
if (!self)
if (!self)
{
return;
}
@ -378,7 +437,7 @@ gladiator_pain(edict_t *self, edict_t *other /* unused */,
void
gladiator_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -391,7 +450,7 @@ gladiator_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t gladiator_frames_death[] = {
static mframe_t gladiator_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -416,11 +475,12 @@ mframe_t gladiator_frames_death[] = {
{ai_move, 0, NULL}
};
mmove_t gladiator_move_death = {
mmove_t gladiator_move_death =
{
FRAME_death1,
FRAME_death22,
gladiator_frames_death,
gladiator_dead
FRAME_death22,
gladiator_frames_death,
gladiator_dead
};
void
@ -430,7 +490,7 @@ gladiator_die(edict_t *self, edict_t *inflictor /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -478,7 +538,7 @@ gladiator_die(edict_t *self, edict_t *inflictor /* unused */,
void
SP_monster_gladiator(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -489,6 +549,11 @@ SP_monster_gladiator(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_pain1 = gi.soundindex("gladiator/pain.wav");
sound_pain2 = gi.soundindex("gladiator/gldpain2.wav");
sound_die = gi.soundindex("gladiator/glddeth2.wav");

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Gunner.
*
@ -16,6 +35,9 @@ static int sound_open;
static int sound_search;
static int sound_sight;
static int sound_step;
static int sound_step2;
qboolean visible(edict_t *self, edict_t *other);
void GunnerGrenade(edict_t *self);
void GunnerFire(edict_t *self);
@ -23,10 +45,34 @@ void gunner_fire_chain(edict_t *self);
void gunner_refire_chain(edict_t *self);
void gunner_stand(edict_t *self);
void
gunner_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("gunner/step1.wav");
sound_step2 = gi.soundindex("gunner/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
void
gunner_idlesound(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -35,9 +81,9 @@ gunner_idlesound(edict_t *self)
}
void
gunner_sight(edict_t *self, edict_t *other)
gunner_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -48,7 +94,7 @@ gunner_sight(edict_t *self, edict_t *other)
void
gunner_search(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -56,7 +102,7 @@ gunner_search(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
}
mframe_t gunner_frames_fidget[] = {
static mframe_t gunner_frames_fidget[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -112,17 +158,18 @@ mframe_t gunner_frames_fidget[] = {
{ai_stand, 0, NULL}
};
mmove_t gunner_move_fidget = {
mmove_t gunner_move_fidget =
{
FRAME_stand31,
FRAME_stand70,
gunner_frames_fidget,
gunner_frames_fidget,
gunner_stand
};
void
gunner_fidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -143,7 +190,7 @@ gunner_fidget(edict_t *self)
}
}
mframe_t gunner_frames_stand[] = {
static mframe_t gunner_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -178,17 +225,18 @@ mframe_t gunner_frames_stand[] = {
{ai_stand, 0, gunner_fidget}
};
mmove_t gunner_move_stand = {
mmove_t gunner_move_stand =
{
FRAME_stand01,
FRAME_stand30,
gunner_frames_stand,
NULL
FRAME_stand30,
gunner_frames_stand,
NULL
};
void
gunner_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -196,33 +244,34 @@ gunner_stand(edict_t *self)
self->monsterinfo.currentmove = &gunner_move_stand;
}
mframe_t gunner_frames_walk[] = {
{ai_walk, 0, NULL},
static mframe_t gunner_frames_walk[] = {
{ai_walk, 0, gunner_footstep},
{ai_walk, 3, NULL},
{ai_walk, 4, NULL},
{ai_walk, 5, NULL},
{ai_walk, 7, NULL},
{ai_walk, 2, NULL},
{ai_walk, 2, gunner_footstep},
{ai_walk, 6, NULL},
{ai_walk, 4, NULL},
{ai_walk, 2, NULL},
{ai_walk, 7, NULL},
{ai_walk, 5, NULL},
{ai_walk, 7, NULL},
{ai_walk, 4, NULL}
{ai_walk, 4, gunner_footstep}
};
mmove_t gunner_move_walk = {
mmove_t gunner_move_walk =
{
FRAME_walk07,
FRAME_walk19,
gunner_frames_walk,
NULL
FRAME_walk19,
gunner_frames_walk,
NULL
};
void
gunner_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -230,28 +279,29 @@ gunner_walk(edict_t *self)
self->monsterinfo.currentmove = &gunner_move_walk;
}
mframe_t gunner_frames_run[] = {
static mframe_t gunner_frames_run[] = {
{ai_run, 26, NULL},
{ai_run, 9, NULL},
{ai_run, 9, gunner_footstep},
{ai_run, 9, NULL},
{ai_run, 9, NULL},
{ai_run, 15, NULL},
{ai_run, 10, NULL},
{ai_run, 10, gunner_footstep},
{ai_run, 13, NULL},
{ai_run, 6, NULL}
};
mmove_t gunner_move_run = {
mmove_t gunner_move_run =
{
FRAME_run01,
FRAME_run08,
gunner_frames_run,
NULL
gunner_frames_run,
NULL
};
void
gunner_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -266,26 +316,27 @@ gunner_run(edict_t *self)
}
}
mframe_t gunner_frames_runandshoot[] = {
static mframe_t gunner_frames_runandshoot[] = {
{ai_run, 32, NULL},
{ai_run, 15, NULL},
{ai_run, 15, gunner_footstep},
{ai_run, 10, NULL},
{ai_run, 18, NULL},
{ai_run, 8, NULL},
{ai_run, 8, gunner_footstep},
{ai_run, 20, NULL}
};
mmove_t gunner_move_runandshoot = {
mmove_t gunner_move_runandshoot =
{
FRAME_runs01,
FRAME_runs06,
FRAME_runs06,
gunner_frames_runandshoot,
NULL
NULL
};
void
gunner_runandshoot(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -293,7 +344,7 @@ gunner_runandshoot(edict_t *self)
self->monsterinfo.currentmove = &gunner_move_runandshoot;
}
mframe_t gunner_frames_pain3[] = {
static mframe_t gunner_frames_pain3[] = {
{ai_move, -3, NULL},
{ai_move, 1, NULL},
{ai_move, 1, NULL},
@ -301,35 +352,37 @@ mframe_t gunner_frames_pain3[] = {
{ai_move, 1, NULL}
};
mmove_t gunner_move_pain3 = {
mmove_t gunner_move_pain3 =
{
FRAME_pain301,
FRAME_pain305,
gunner_frames_pain3,
gunner_run
FRAME_pain305,
gunner_frames_pain3,
gunner_run
};
mframe_t gunner_frames_pain2[] = {
static mframe_t gunner_frames_pain2[] = {
{ai_move, -2, NULL},
{ai_move, 11, NULL},
{ai_move, 6, NULL},
{ai_move, 6, gunner_footstep},
{ai_move, 2, NULL},
{ai_move, -1, NULL},
{ai_move, -7, NULL},
{ai_move, -2, NULL},
{ai_move, -7, NULL}
{ai_move, -7, gunner_footstep}
};
mmove_t gunner_move_pain2 = {
mmove_t gunner_move_pain2 =
{
FRAME_pain201,
FRAME_pain208,
gunner_frames_pain2,
gunner_run
FRAME_pain208,
gunner_frames_pain2,
gunner_run
};
mframe_t gunner_frames_pain1[] = {
static mframe_t gunner_frames_pain1[] = {
{ai_move, 2, NULL},
{ai_move, 0, NULL},
{ai_move, -5, NULL},
{ai_move, -5, gunner_footstep},
{ai_move, 3, NULL},
{ai_move, -1, NULL},
{ai_move, 0, NULL},
@ -339,26 +392,27 @@ mframe_t gunner_frames_pain1[] = {
{ai_move, 1, NULL},
{ai_move, 1, NULL},
{ai_move, 2, NULL},
{ai_move, 1, NULL},
{ai_move, 1, gunner_footstep},
{ai_move, 0, NULL},
{ai_move, -2, NULL},
{ai_move, -2, NULL},
{ai_move, 0, NULL},
{ai_move, 0, gunner_footstep},
{ai_move, 0, NULL}
};
mmove_t gunner_move_pain1 = {
mmove_t gunner_move_pain1 =
{
FRAME_pain101,
FRAME_pain118,
gunner_frames_pain1,
gunner_run
FRAME_pain118,
gunner_frames_pain1,
gunner_run
};
void
gunner_pain(edict_t *self, edict_t *other /* unused */,
float kick /* unused */, int damage)
{
if (!self)
if (!self)
{
return;
}
@ -386,7 +440,7 @@ gunner_pain(edict_t *self, edict_t *other /* unused */,
if (skill->value == SKILL_HARDPLUS)
{
return; /* no pain anims in nightmare */
return; /* no pain anims in nightmare */
}
if (damage <= 10)
@ -406,7 +460,7 @@ gunner_pain(edict_t *self, edict_t *other /* unused */,
void
gunner_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -419,7 +473,7 @@ gunner_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t gunner_frames_death[] = {
static mframe_t gunner_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -433,11 +487,12 @@ mframe_t gunner_frames_death[] = {
{ai_move, 0, NULL}
};
mmove_t gunner_move_death = {
mmove_t gunner_move_death =
{
FRAME_death01,
FRAME_death11,
gunner_frames_death,
gunner_dead
FRAME_death11,
gunner_frames_death,
gunner_dead
};
void
@ -447,7 +502,7 @@ gunner_die(edict_t *self, edict_t *inflictor /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -459,15 +514,18 @@ gunner_die(edict_t *self, edict_t *inflictor /* unused */,
for (n = 0; n < 2; n++)
{
ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/bone/tris.md2",
damage, GIB_ORGANIC);
}
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
}
ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
ThrowHead(self, "models/objects/gibs/head2/tris.md2",
damage, GIB_ORGANIC);
self->deadflag = DEAD_DEAD;
return;
}
@ -487,7 +545,7 @@ gunner_die(edict_t *self, edict_t *inflictor /* unused */,
void
gunner_duck_down(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -516,7 +574,7 @@ gunner_duck_down(edict_t *self)
void
gunner_duck_hold(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -534,7 +592,7 @@ gunner_duck_hold(edict_t *self)
void
gunner_duck_up(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -545,7 +603,7 @@ gunner_duck_up(edict_t *self)
gi.linkentity(self);
}
mframe_t gunner_frames_duck[] = {
static mframe_t gunner_frames_duck[] = {
{ai_move, 1, gunner_duck_down},
{ai_move, 1, NULL},
{ai_move, 1, gunner_duck_hold},
@ -556,15 +614,16 @@ mframe_t gunner_frames_duck[] = {
{ai_move, -1, NULL}
};
mmove_t gunner_move_duck = {
mmove_t gunner_move_duck =
{
FRAME_duck01,
FRAME_duck08,
gunner_frames_duck,
gunner_run
gunner_run
};
void
gunner_dodge(edict_t *self, edict_t *attacker, float eta /* unsued */)
gunner_dodge(edict_t *self, edict_t *attacker, float eta /* unused */)
{
if (!self || !attacker)
{
@ -588,7 +647,7 @@ gunner_dodge(edict_t *self, edict_t *attacker, float eta /* unsued */)
void
gunner_opengun(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -605,7 +664,7 @@ GunnerFire(edict_t *self)
vec3_t aim;
int flash_number;
if (!self)
if (!self)
{
return;
}
@ -635,7 +694,7 @@ GunnerGrenade(edict_t *self)
vec3_t aim;
int flash_number;
if (!self)
if (!self)
{
return;
}
@ -660,13 +719,15 @@ GunnerGrenade(edict_t *self)
AngleVectors(self->s.angles, forward, right, NULL);
G_ProjectSource(self->s.origin, monster_flash_offset[flash_number],
forward, right, start);
VectorCopy(forward, aim);
monster_fire_grenade(self, start, aim, 50, 600, flash_number);
}
mframe_t gunner_frames_attack_chain[] = {
static mframe_t gunner_frames_attack_chain[] = {
{ai_charge, 0, gunner_opengun},
{ai_charge, 0, NULL},
{ai_charge, 0, gunner_footstep},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -674,14 +735,15 @@ mframe_t gunner_frames_attack_chain[] = {
{ai_charge, 0, NULL}
};
mmove_t gunner_move_attack_chain = {
mmove_t gunner_move_attack_chain =
{
FRAME_attak209,
FRAME_attak215,
gunner_frames_attack_chain,
gunner_fire_chain
FRAME_attak215,
gunner_frames_attack_chain,
gunner_fire_chain
};
mframe_t gunner_frames_fire_chain[] = {
static mframe_t gunner_frames_fire_chain[] = {
{ai_charge, 0, GunnerFire},
{ai_charge, 0, GunnerFire},
{ai_charge, 0, GunnerFire},
@ -692,31 +754,33 @@ mframe_t gunner_frames_fire_chain[] = {
{ai_charge, 0, GunnerFire}
};
mmove_t gunner_move_fire_chain = {
mmove_t gunner_move_fire_chain =
{
FRAME_attak216,
FRAME_attak223,
gunner_frames_fire_chain,
gunner_refire_chain
FRAME_attak223,
gunner_frames_fire_chain,
gunner_refire_chain
};
mframe_t gunner_frames_endfire_chain[] = {
static mframe_t gunner_frames_endfire_chain[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL}
{ai_charge, 0, gunner_footstep}
};
mmove_t gunner_move_endfire_chain = {
mmove_t gunner_move_endfire_chain =
{
FRAME_attak224,
FRAME_attak230,
gunner_frames_endfire_chain,
gunner_run
FRAME_attak230,
gunner_frames_endfire_chain,
gunner_run
};
mframe_t gunner_frames_attack_grenade[] = {
static mframe_t gunner_frames_attack_grenade[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -740,17 +804,18 @@ mframe_t gunner_frames_attack_grenade[] = {
{ai_charge, 0, NULL}
};
mmove_t gunner_move_attack_grenade = {
mmove_t gunner_move_attack_grenade =
{
FRAME_attak101,
FRAME_attak121,
gunner_frames_attack_grenade,
gunner_run
FRAME_attak121,
gunner_frames_attack_grenade,
gunner_run
};
void
gunner_attack(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -775,7 +840,7 @@ gunner_attack(edict_t *self)
void
gunner_fire_chain(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -786,7 +851,7 @@ gunner_fire_chain(edict_t *self)
void
gunner_refire_chain(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -812,7 +877,7 @@ gunner_refire_chain(edict_t *self)
void
SP_monster_gunner(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -823,6 +888,11 @@ SP_monster_gunner(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_death = gi.soundindex("gunner/death1.wav");
sound_pain = gi.soundindex("gunner/gunpain2.wav");
sound_pain2 = gi.soundindex("gunner/gunpain1.wav");
@ -863,4 +933,3 @@ SP_monster_gunner(edict_t *self)
walkmonster_start(self);
}

View file

@ -55,7 +55,7 @@ hover_search(edict_t *self)
}
}
mframe_t hover_frames_stand[] = {
static mframe_t hover_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -95,7 +95,7 @@ mmove_t hover_move_stand = {
NULL
};
mframe_t hover_frames_stop1[] = {
static mframe_t hover_frames_stop1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -114,7 +114,7 @@ mmove_t hover_move_stop1 = {
NULL
};
mframe_t hover_frames_stop2[] = {
static mframe_t hover_frames_stop2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -132,7 +132,7 @@ mmove_t hover_move_stop2 = {
NULL
};
mframe_t hover_frames_takeoff[] = {
static mframe_t hover_frames_takeoff[] = {
{ai_move, 0, NULL},
{ai_move, -2, NULL},
{ai_move, 5, NULL},
@ -172,7 +172,7 @@ mmove_t hover_move_takeoff = {
NULL
};
mframe_t hover_frames_pain3[] = {
static mframe_t hover_frames_pain3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -191,7 +191,7 @@ mmove_t hover_move_pain3 = {
hover_run
};
mframe_t hover_frames_pain2[] = {
static mframe_t hover_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -213,7 +213,7 @@ mmove_t hover_move_pain2 = {
hover_run
};
mframe_t hover_frames_pain1[] = {
static mframe_t hover_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 2, NULL},
@ -251,7 +251,7 @@ mmove_t hover_move_pain1 = {
hover_run
};
mframe_t hover_frames_land[] = {
static mframe_t hover_frames_land[] = {
{ai_move, 0, NULL}
};
@ -262,7 +262,7 @@ mmove_t hover_move_land = {
NULL
};
mframe_t hover_frames_forward[] = {
static mframe_t hover_frames_forward[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -307,7 +307,7 @@ mmove_t hover_move_forward = {
NULL
};
mframe_t hover_frames_walk[] = {
static mframe_t hover_frames_walk[] = {
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
@ -352,7 +352,7 @@ mmove_t hover_move_walk = {
NULL
};
mframe_t hover_frames_run[] = {
static mframe_t hover_frames_run[] = {
{ai_run, 10, NULL},
{ai_run, 10, NULL},
{ai_run, 10, NULL},
@ -397,7 +397,7 @@ mmove_t hover_move_run = {
NULL
};
mframe_t hover_frames_death1[] = {
static mframe_t hover_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -418,7 +418,7 @@ mmove_t hover_move_death1 = {
hover_dead
};
mframe_t hover_frames_backward[] = {
static mframe_t hover_frames_backward[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -452,7 +452,7 @@ mmove_t hover_move_backward = {
NULL
};
mframe_t hover_frames_start_attack[] = {
static mframe_t hover_frames_start_attack[] = {
{ai_charge, 1, NULL},
{ai_charge, 1, NULL},
{ai_charge, 1, NULL}
@ -465,7 +465,7 @@ mmove_t hover_move_start_attack = {
hover_attack
};
mframe_t hover_frames_attack1[] = {
static mframe_t hover_frames_attack1[] = {
{ai_charge, -10, hover_fire_blaster},
{ai_charge, -10, hover_fire_blaster},
{ai_charge, 0, hover_reattack},
@ -478,7 +478,7 @@ mmove_t hover_move_attack1 = {
NULL
};
mframe_t hover_frames_end_attack[] = {
static mframe_t hover_frames_end_attack[] = {
{ai_charge, 1, NULL},
{ai_charge, 1, NULL}
};

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Infantry.
*
@ -23,7 +42,34 @@ static int sound_sight;
static int sound_search;
static int sound_idle;
mframe_t infantry_frames_stand[] = {
static int sound_step;
static int sound_step2;
void
infantry_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("infantry/step1.wav");
sound_step2 = gi.soundindex("infantry/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
static mframe_t infantry_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -48,9 +94,10 @@ mframe_t infantry_frames_stand[] = {
{ai_stand, 0, NULL}
};
mmove_t infantry_move_stand = {
mmove_t infantry_move_stand =
{
FRAME_stand50,
FRAME_stand71,
FRAME_stand71,
infantry_frames_stand,
NULL
};
@ -58,7 +105,7 @@ mmove_t infantry_move_stand = {
void
infantry_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -66,13 +113,13 @@ infantry_stand(edict_t *self)
self->monsterinfo.currentmove = &infantry_move_stand;
}
mframe_t infantry_frames_fidget[] = {
static mframe_t infantry_frames_fidget[] = {
{ai_stand, 1, NULL},
{ai_stand, 0, NULL},
{ai_stand, 1, NULL},
{ai_stand, 3, NULL},
{ai_stand, 6, NULL},
{ai_stand, 3, NULL},
{ai_stand, 3, infantry_footstep},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -114,21 +161,22 @@ mframe_t infantry_frames_fidget[] = {
{ai_stand, -3, NULL},
{ai_stand, -2, NULL},
{ai_stand, -3, NULL},
{ai_stand, -3, NULL},
{ai_stand, -3, infantry_footstep},
{ai_stand, -2, NULL}
};
mmove_t infantry_move_fidget = {
mmove_t infantry_move_fidget =
{
FRAME_stand01,
FRAME_stand49,
infantry_frames_fidget,
infantry_stand
FRAME_stand49,
infantry_frames_fidget,
infantry_stand
};
void
infantry_fidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -137,14 +185,14 @@ infantry_fidget(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
}
mframe_t infantry_frames_walk[] = {
{ai_walk, 5, NULL},
static mframe_t infantry_frames_walk[] = {
{ai_walk, 5, infantry_footstep},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
{ai_walk, 5, NULL},
{ai_walk, 4, NULL},
{ai_walk, 5, NULL},
{ai_walk, 6, NULL},
{ai_walk, 6, infantry_footstep},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
@ -152,17 +200,18 @@ mframe_t infantry_frames_walk[] = {
{ai_walk, 5, NULL}
};
mmove_t infantry_move_walk = {
mmove_t infantry_move_walk =
{
FRAME_walk03,
FRAME_walk14,
infantry_frames_walk,
FRAME_walk14,
infantry_frames_walk,
NULL
};
void
infantry_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -170,21 +219,22 @@ infantry_walk(edict_t *self)
self->monsterinfo.currentmove = &infantry_move_walk;
}
mframe_t infantry_frames_run[] = {
static mframe_t infantry_frames_run[] = {
{ai_run, 10, NULL},
{ai_run, 20, NULL},
{ai_run, 20, infantry_footstep},
{ai_run, 5, NULL},
{ai_run, 7, NULL},
{ai_run, 30, NULL},
{ai_run, 35, NULL},
{ai_run, 35, infantry_footstep},
{ai_run, 2, NULL},
{ai_run, 6, NULL}
};
mmove_t infantry_move_run = {
mmove_t infantry_move_run =
{
FRAME_run01,
FRAME_run08,
infantry_frames_run,
FRAME_run08,
infantry_frames_run,
NULL
};
@ -206,44 +256,46 @@ infantry_run(edict_t *self)
}
}
mframe_t infantry_frames_pain1[] = {
static mframe_t infantry_frames_pain1[] = {
{ai_move, -3, NULL},
{ai_move, -2, NULL},
{ai_move, -1, NULL},
{ai_move, -2, NULL},
{ai_move, -1, NULL},
{ai_move, -1, infantry_footstep},
{ai_move, 1, NULL},
{ai_move, -1, NULL},
{ai_move, 1, NULL},
{ai_move, 6, NULL},
{ai_move, 2, NULL}
{ai_move, 2, infantry_footstep}
};
mmove_t infantry_move_pain1 = {
mmove_t infantry_move_pain1 =
{
FRAME_pain101,
FRAME_pain110,
infantry_frames_pain1,
infantry_run
};
mframe_t infantry_frames_pain2[] = {
static mframe_t infantry_frames_pain2[] = {
{ai_move, -3, NULL},
{ai_move, -3, NULL},
{ai_move, 0, NULL},
{ai_move, -1, NULL},
{ai_move, -2, NULL},
{ai_move, -2, infantry_footstep},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 2, NULL},
{ai_move, 5, NULL},
{ai_move, 2, NULL}
{ai_move, 2, infantry_footstep}
};
mmove_t infantry_move_pain2 = {
mmove_t infantry_move_pain2 =
{
FRAME_pain201,
FRAME_pain210,
infantry_frames_pain2,
infantry_run
FRAME_pain210,
infantry_frames_pain2,
infantry_run
};
void
@ -252,7 +304,7 @@ infantry_pain(edict_t *self, edict_t *other /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -311,7 +363,7 @@ InfantryMachineGun(edict_t *self)
vec3_t vec;
int flash_number;
if (!self)
if (!self)
{
return;
}
@ -337,7 +389,8 @@ InfantryMachineGun(edict_t *self)
}
else
{
flash_number = MZ2_INFANTRY_MACHINEGUN_2 + (self->s.frame - FRAME_death211);
flash_number = MZ2_INFANTRY_MACHINEGUN_2 +
(self->s.frame - FRAME_death211);
AngleVectors(self->s.angles, forward, right, NULL);
G_ProjectSource(self->s.origin, monster_flash_offset[flash_number],
@ -354,7 +407,7 @@ InfantryMachineGun(edict_t *self)
void
infantry_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -365,7 +418,7 @@ infantry_sight(edict_t *self, edict_t *other /* unused */)
void
infantry_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -379,16 +432,16 @@ infantry_dead(edict_t *self)
M_FlyCheck(self);
}
mframe_t infantry_frames_death1[] = {
static mframe_t infantry_frames_death1[] = {
{ai_move, -4, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, -1, NULL},
{ai_move, -4, NULL},
{ai_move, -4, infantry_footstep},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, -1, NULL},
{ai_move, -1, infantry_footstep},
{ai_move, 3, NULL},
{ai_move, 1, NULL},
{ai_move, 1, NULL},
@ -402,22 +455,23 @@ mframe_t infantry_frames_death1[] = {
{ai_move, -3, NULL}
};
mmove_t infantry_move_death1 = {
mmove_t infantry_move_death1 =
{
FRAME_death101,
FRAME_death120,
infantry_frames_death1,
infantry_dead
FRAME_death120,
infantry_frames_death1,
infantry_dead
};
/* Off with his head */
mframe_t infantry_frames_death2[] = {
static mframe_t infantry_frames_death2[] = {
{ai_move, 0, NULL},
{ai_move, 1, NULL},
{ai_move, 5, NULL},
{ai_move, -1, NULL},
{ai_move, 0, NULL},
{ai_move, 1, NULL},
{ai_move, 1, NULL},
{ai_move, 1, infantry_footstep},
{ai_move, 1, infantry_footstep},
{ai_move, 4, NULL},
{ai_move, 3, NULL},
{ai_move, 0, NULL},
@ -438,14 +492,15 @@ mframe_t infantry_frames_death2[] = {
{ai_move, 0, NULL}
};
mmove_t infantry_move_death2 = {
mmove_t infantry_move_death2 =
{
FRAME_death201,
FRAME_death225,
FRAME_death225,
infantry_frames_death2,
infantry_dead
};
mframe_t infantry_frames_death3[] = {
static mframe_t infantry_frames_death3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -457,7 +512,8 @@ mframe_t infantry_frames_death3[] = {
{ai_move, 0, NULL}
};
mmove_t infantry_move_death3 = {
mmove_t infantry_move_death3 =
{
FRAME_death301,
FRAME_death309,
infantry_frames_death3,
@ -471,7 +527,7 @@ infantry_die(edict_t *self, edict_t *inflictor /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -483,15 +539,18 @@ infantry_die(edict_t *self, edict_t *inflictor /* unused */,
for (n = 0; n < 2; n++)
{
ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/bone/tris.md2",
damage, GIB_ORGANIC);
}
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
}
ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
ThrowHead(self, "models/objects/gibs/head2/tris.md2",
damage, GIB_ORGANIC);
self->deadflag = DEAD_DEAD;
return;
}
@ -528,7 +587,7 @@ infantry_die(edict_t *self, edict_t *inflictor /* unused */,
void
infantry_duck_down(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -548,7 +607,7 @@ infantry_duck_down(edict_t *self)
void
infantry_duck_hold(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -566,7 +625,7 @@ infantry_duck_hold(edict_t *self)
void
infantry_duck_up(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -577,19 +636,20 @@ infantry_duck_up(edict_t *self)
gi.linkentity(self);
}
mframe_t infantry_frames_duck[] = {
static mframe_t infantry_frames_duck[] = {
{ai_move, -2, infantry_duck_down},
{ai_move, -5, infantry_duck_hold},
{ai_move, 3, NULL},
{ai_move, 4, infantry_duck_up},
{ai_move, 0, NULL}
{ai_move, 0, infantry_footstep}
};
mmove_t infantry_move_duck = {
mmove_t infantry_move_duck =
{
FRAME_duck01,
FRAME_duck05,
infantry_frames_duck,
infantry_run
FRAME_duck05,
infantry_frames_duck,
infantry_run
};
void
@ -619,7 +679,7 @@ infantry_set_firetime(edict_t *self)
{
int n;
if (!self)
if (!self)
{
return;
}
@ -642,7 +702,7 @@ infantry_cock_gun(edict_t *self)
void
infantry_fire(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -659,7 +719,7 @@ infantry_fire(edict_t *self)
}
}
mframe_t infantry_frames_attack1[] = {
static mframe_t infantry_frames_attack1[] = {
{ai_charge, 10, infantry_set_firetime},
{ai_charge, 6, NULL},
{ai_charge, 0, infantry_fire},
@ -677,17 +737,18 @@ mframe_t infantry_frames_attack1[] = {
{ai_charge, -1, NULL}
};
mmove_t infantry_move_attack1 = {
mmove_t infantry_move_attack1 =
{
FRAME_attak101,
FRAME_attak115,
infantry_frames_attack1,
infantry_frames_attack1,
infantry_run
};
void
infantry_swing(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -700,7 +761,7 @@ infantry_smack(edict_t *self)
{
vec3_t aim;
if (!self)
if (!self)
{
return;
}
@ -713,28 +774,29 @@ infantry_smack(edict_t *self)
}
}
mframe_t infantry_frames_attack2[] = {
static mframe_t infantry_frames_attack2[] = {
{ai_charge, 3, NULL},
{ai_charge, 6, NULL},
{ai_charge, 0, infantry_swing},
{ai_charge, 8, NULL},
{ai_charge, 8, infantry_footstep},
{ai_charge, 5, NULL},
{ai_charge, 8, infantry_smack},
{ai_charge, 6, NULL},
{ai_charge, 3, NULL},
};
mmove_t infantry_move_attack2 = {
mmove_t infantry_move_attack2 =
{
FRAME_attak201,
FRAME_attak208,
infantry_frames_attack2,
infantry_run
infantry_frames_attack2,
infantry_run
};
void
infantry_attack(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -755,7 +817,7 @@ infantry_attack(edict_t *self)
void
SP_monster_infantry(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -766,6 +828,11 @@ SP_monster_infantry(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_pain1 = gi.soundindex("infantry/infpain1.wav");
sound_pain2 = gi.soundindex("infantry/infpain2.wav");
sound_die1 = gi.soundindex("infantry/infdeth1.wav");
@ -809,4 +876,3 @@ SP_monster_infantry(edict_t *self)
walkmonster_start(self);
}

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* The insane earth soldiers.
*
@ -15,6 +34,11 @@ static int sound_shake;
static int sound_moan;
static int sound_scream[8];
static int sound_step;
static int sound_step2;
static int sound_step3;
static int sound_step4;
void insane_stand(edict_t *self);
void insane_dead(edict_t *self);
void insane_cross(edict_t *self);
@ -24,10 +48,47 @@ void insane_checkdown(edict_t *self);
void insane_checkup(edict_t *self);
void insane_onground(edict_t *self);
void
insane_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0 || sound_step3 == 0 || sound_step4 == 0)
{
sound_step = gi.soundindex("player/step1.wav");
sound_step2 = gi.soundindex("player/step2.wav");
sound_step3 = gi.soundindex("player/step3.wav");
sound_step4 = gi.soundindex("player/step4.wav");
}
int i;
i = randk() % 4;
if (i == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 0.7, ATTN_NORM, 0);
}
else if (i == 1)
{
gi.sound(self, CHAN_BODY, sound_step2, 0.7, ATTN_NORM, 0);
}
else if (i == 2)
{
gi.sound(self, CHAN_BODY, sound_step3, 0.7, ATTN_NORM, 0);
}
else if (i == 3)
{
gi.sound(self, CHAN_BODY, sound_step4, 0.7, ATTN_NORM, 0);
}
}
void
insane_fist(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -38,7 +99,7 @@ insane_fist(edict_t *self)
void
insane_shake(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -49,7 +110,7 @@ insane_shake(edict_t *self)
void
insane_moan(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -80,7 +141,7 @@ insane_scream(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_scream[rand() % 8], 1, ATTN_IDLE, 0);
}
mframe_t insane_frames_stand_normal[] = {
static mframe_t insane_frames_stand_normal[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -89,14 +150,15 @@ mframe_t insane_frames_stand_normal[] = {
{ai_stand, 0, insane_checkdown}
};
mmove_t insane_move_stand_normal = {
mmove_t insane_move_stand_normal =
{
FRAME_stand60,
FRAME_stand65,
FRAME_stand65,
insane_frames_stand_normal,
insane_stand
};
mframe_t insane_frames_stand_insane[] = {
static mframe_t insane_frames_stand_insane[] = {
{ai_stand, 0, insane_shake},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -129,14 +191,15 @@ mframe_t insane_frames_stand_insane[] = {
{ai_stand, 0, insane_checkdown}
};
mmove_t insane_move_stand_insane = {
mmove_t insane_move_stand_insane =
{
FRAME_stand65,
FRAME_stand94,
insane_frames_stand_insane,
insane_frames_stand_insane,
insane_stand
};
mframe_t insane_frames_uptodown[] = {
static mframe_t insane_frames_uptodown[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -182,14 +245,15 @@ mframe_t insane_frames_uptodown[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_uptodown = {
mmove_t insane_move_uptodown =
{
FRAME_stand1,
FRAME_stand40,
insane_frames_uptodown,
insane_onground
};
mframe_t insane_frames_downtoup[] = {
static mframe_t insane_frames_downtoup[] = {
{ai_move, -0.7, NULL}, /* 41 */
{ai_move, -1.2, NULL}, /* 42 */
{ai_move, -1.5, NULL}, /* 43 */
@ -208,17 +272,18 @@ mframe_t insane_frames_downtoup[] = {
{ai_move, -0.3, NULL}, /* 56 */
{ai_move, 0, NULL}, /* 57 */
{ai_move, 0, NULL}, /* 58 */
{ai_move, 0, NULL} /* 59 */
{ai_move, 0, NULL} /* 59 */
};
mmove_t insane_move_downtoup = {
mmove_t insane_move_downtoup =
{
FRAME_stand41,
FRAME_stand59,
insane_frames_downtoup,
insane_stand
FRAME_stand59,
insane_frames_downtoup,
insane_stand
};
mframe_t insane_frames_jumpdown[] = {
static mframe_t insane_frames_jumpdown[] = {
{ai_move, 0.2, NULL},
{ai_move, 11.5, NULL},
{ai_move, 5.1, NULL},
@ -226,14 +291,15 @@ mframe_t insane_frames_jumpdown[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_jumpdown = {
mmove_t insane_move_jumpdown =
{
FRAME_stand96,
FRAME_stand100,
FRAME_stand100,
insane_frames_jumpdown,
insane_onground
};
mframe_t insane_frames_down[] = {
static mframe_t insane_frames_down[] = {
{ai_move, 0, NULL}, /* 100 */
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -297,92 +363,97 @@ mframe_t insane_frames_down[] = {
{ai_move, 0, insane_checkup} /* 160 */
};
mmove_t insane_move_down = {
mmove_t insane_move_down =
{
FRAME_stand100,
FRAME_stand160,
FRAME_stand160,
insane_frames_down,
insane_onground
};
mframe_t insane_frames_walk_normal[] = {
static mframe_t insane_frames_walk_normal[] = {
{ai_walk, 0, insane_scream},
{ai_walk, 2.5, NULL},
{ai_walk, 3.5, NULL},
{ai_walk, 1.7, NULL},
{ai_walk, 2.3, NULL},
{ai_walk, 2.4, NULL},
{ai_walk, 2.2, NULL},
{ai_walk, 2.2, insane_footstep},
{ai_walk, 4.2, NULL},
{ai_walk, 5.6, NULL},
{ai_walk, 3.3, NULL},
{ai_walk, 2.4, NULL},
{ai_walk, 0.9, NULL},
{ai_walk, 0, NULL}
{ai_walk, 0, insane_footstep}
};
mmove_t insane_move_walk_normal = {
mmove_t insane_move_walk_normal =
{
FRAME_walk27,
FRAME_walk39,
insane_frames_walk_normal,
insane_walk
};
mmove_t insane_move_run_normal =
{
FRAME_walk27,
FRAME_walk39,
insane_frames_walk_normal,
insane_walk
insane_run
};
mmove_t insane_move_run_normal = {
FRAME_walk27,
FRAME_walk39,
insane_frames_walk_normal,
insane_run
};
mframe_t insane_frames_walk_insane[] = {
static mframe_t insane_frames_walk_insane[] = {
{ai_walk, 0, insane_scream}, /* walk 1 */
{ai_walk, 3.4, NULL}, /* walk 2 */
{ai_walk, 3.6, NULL}, /* 3 */
{ai_walk, 2.9, NULL}, /* 4 */
{ai_walk, 2.2, NULL}, /* 5 */
{ai_walk, 2.6, NULL}, /* 6 */
{ai_walk, 0, NULL}, /* 7 */
{ai_walk, 0, insane_footstep}, /* 7 */
{ai_walk, 0.7, NULL}, /* 8 */
{ai_walk, 4.8, NULL}, /* 9 */
{ai_walk, 5.3, NULL}, /* 10 */
{ai_walk, 1.1, NULL}, /* 11 */
{ai_walk, 2, NULL}, /* 12 */
{ai_walk, 2, insane_footstep}, /* 12 */
{ai_walk, 0.5, NULL}, /* 13 */
{ai_walk, 0, NULL}, /* 14 */
{ai_walk, 0, NULL}, /* 15 */
{ai_walk, 4.9, NULL}, /* 16 */
{ai_walk, 6.7, NULL}, /* 17 */
{ai_walk, 3.8, NULL}, /* 18 */
{ai_walk, 2, NULL}, /* 19 */
{ai_walk, 2, insane_footstep}, /* 19 */
{ai_walk, 0.2, NULL}, /* 20 */
{ai_walk, 0, NULL}, /* 21 */
{ai_walk, 3.4, NULL}, /* 22 */
{ai_walk, 6.4, NULL}, /* 23 */
{ai_walk, 5, NULL}, /* 24 */
{ai_walk, 1.8, NULL}, /* 25 */
{ai_walk, 1.8, insane_footstep}, /* 25 */
{ai_walk, 0, NULL} /* 26 */
};
mmove_t insane_move_walk_insane = {
mmove_t insane_move_walk_insane =
{
FRAME_walk1,
FRAME_walk26,
FRAME_walk26,
insane_frames_walk_insane,
insane_walk
};
mmove_t insane_move_run_insane = {
mmove_t insane_move_run_insane =
{
FRAME_walk1,
FRAME_walk26,
FRAME_walk26,
insane_frames_walk_insane,
insane_run
};
mframe_t insane_frames_stand_pain[] = {
{ai_move, 0, NULL},
static mframe_t insane_frames_stand_pain[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, insane_footstep},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -391,14 +462,15 @@ mframe_t insane_frames_stand_pain[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_stand_pain = {
mmove_t insane_move_stand_pain =
{
FRAME_st_pain2,
FRAME_st_pain12,
insane_frames_stand_pain,
insane_run
};
mframe_t insane_frames_stand_death[] = {
static mframe_t insane_frames_stand_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -418,14 +490,15 @@ mframe_t insane_frames_stand_death[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_stand_death = {
mmove_t insane_move_stand_death =
{
FRAME_st_death2,
FRAME_st_death18,
insane_frames_stand_death,
insane_dead
insane_dead
};
mframe_t insane_frames_crawl[] = {
static mframe_t insane_frames_crawl[] = {
{ai_walk, 0, insane_scream},
{ai_walk, 1.5, NULL},
{ai_walk, 2.1, NULL},
@ -437,21 +510,23 @@ mframe_t insane_frames_crawl[] = {
{ai_walk, 2.4, NULL}
};
mmove_t insane_move_crawl = {
mmove_t insane_move_crawl =
{
FRAME_crawl1,
FRAME_crawl9,
insane_frames_crawl,
NULL
};
mmove_t insane_move_runcrawl = {
mmove_t insane_move_runcrawl =
{
FRAME_crawl1,
FRAME_crawl9,
insane_frames_crawl,
insane_frames_crawl,
NULL
};
mframe_t insane_frames_crawl_pain[] = {
static mframe_t insane_frames_crawl_pain[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -463,14 +538,15 @@ mframe_t insane_frames_crawl_pain[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_crawl_pain = {
mmove_t insane_move_crawl_pain =
{
FRAME_cr_pain2,
FRAME_cr_pain10,
insane_frames_crawl_pain,
insane_run
};
mframe_t insane_frames_crawl_death[] = {
static mframe_t insane_frames_crawl_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -480,14 +556,15 @@ mframe_t insane_frames_crawl_death[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_crawl_death = {
mmove_t insane_move_crawl_death =
{
FRAME_cr_death10,
FRAME_cr_death16,
FRAME_cr_death16,
insane_frames_crawl_death,
insane_dead
};
mframe_t insane_frames_cross[] = {
static mframe_t insane_frames_cross[] = {
{ai_move, 0, insane_moan},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -505,14 +582,15 @@ mframe_t insane_frames_cross[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_cross = {
mmove_t insane_move_cross =
{
FRAME_cross1,
FRAME_cross15,
FRAME_cross15,
insane_frames_cross,
insane_cross
};
mframe_t insane_frames_struggle_cross[] = {
static mframe_t insane_frames_struggle_cross[] = {
{ai_move, 0, insane_scream},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -530,17 +608,18 @@ mframe_t insane_frames_struggle_cross[] = {
{ai_move, 0, NULL}
};
mmove_t insane_move_struggle_cross = {
mmove_t insane_move_struggle_cross =
{
FRAME_cross16,
FRAME_cross30,
insane_frames_struggle_cross,
insane_cross
insane_frames_struggle_cross,
insane_cross
};
void
insane_cross(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -558,7 +637,7 @@ insane_cross(edict_t *self)
void
insane_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -590,7 +669,7 @@ insane_walk(edict_t *self)
void
insane_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -625,7 +704,7 @@ insane_pain(edict_t *self, edict_t *other /* unused */,
{
int l, r;
if (!self)
if (!self)
{
return;
}
@ -676,7 +755,8 @@ insane_pain(edict_t *self, edict_t *other /* unused */,
if (((self->s.frame >= FRAME_crawl1) &&
(self->s.frame <= FRAME_crawl9)) ||
((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)))
((self->s.frame >= FRAME_stand99) &&
(self->s.frame <= FRAME_stand160)))
{
self->monsterinfo.currentmove = &insane_move_crawl_pain;
}
@ -689,7 +769,7 @@ insane_pain(edict_t *self, edict_t *other /* unused */,
void
insane_onground(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -700,7 +780,7 @@ insane_onground(edict_t *self)
void
insane_checkdown(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -726,11 +806,12 @@ insane_checkdown(edict_t *self)
void
insane_checkup(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
/* If Hold_Ground and Crawl are set */
if ((self->spawnflags & 4) && (self->spawnflags & 16))
{
return;
@ -745,7 +826,7 @@ insane_checkup(edict_t *self)
void
insane_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -755,6 +836,7 @@ insane_stand(edict_t *self)
self->monsterinfo.currentmove = &insane_move_cross;
self->monsterinfo.aiflags |= AI_STAND_GROUND;
}
/* If Hold_Ground and Crawl are set */
else if ((self->spawnflags & 4) && (self->spawnflags & 16))
{
self->monsterinfo.currentmove = &insane_move_down;
@ -773,7 +855,7 @@ insane_stand(edict_t *self)
void
insane_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -801,7 +883,7 @@ insane_die(edict_t *self, edict_t *inflictor /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -812,15 +894,18 @@ insane_die(edict_t *self, edict_t *inflictor /* unused */,
for (n = 0; n < 2; n++)
{
ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/bone/tris.md2",
damage, GIB_ORGANIC);
}
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
}
ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
ThrowHead(self, "models/objects/gibs/head2/tris.md2",
damage, GIB_ORGANIC);
self->deadflag = DEAD_DEAD;
return;
}
@ -862,7 +947,7 @@ insane_die(edict_t *self, edict_t *inflictor /* unused */,
void
SP_misc_insane(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -873,6 +958,13 @@ SP_misc_insane(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_step3 = 0;
sound_step4 = 0;
sound_fist = gi.soundindex("insane/insane11.wav");
sound_shake = gi.soundindex("insane/insane5.wav");
sound_moan = gi.soundindex("insane/insane7.wav");

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Medic.
*
@ -9,6 +28,7 @@
#include "medic.h"
qboolean visible(edict_t *self, edict_t *other);
static int sound_idle1;
static int sound_pain1;
static int sound_pain2;
@ -20,15 +40,41 @@ static int sound_hook_hit;
static int sound_hook_heal;
static int sound_hook_retract;
static int sound_step;
static int sound_step2;
void ED_CallSpawn(edict_t *ent);
void
medic_footstep(edict_t *self)
{
if (!g_monsterfootsteps->value)
return;
// Lazy loading for savegame compatibility.
if (sound_step == 0 || sound_step2 == 0)
{
sound_step = gi.soundindex("medic/step1.wav");
sound_step2 = gi.soundindex("medic/step2.wav");
}
if (randk() % 2 == 0)
{
gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
}
else
{
gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0);
}
}
edict_t *
medic_FindDeadMonster(edict_t *self)
{
edict_t *ent = NULL;
edict_t *best = NULL;
if (!self)
if (!self)
{
return NULL;
}
@ -92,7 +138,7 @@ medic_idle(edict_t *self)
{
edict_t *ent;
if (!self)
if (!self)
{
return;
}
@ -115,7 +161,7 @@ medic_search(edict_t *self)
{
edict_t *ent;
if (!self)
if (!self)
{
return;
}
@ -140,7 +186,7 @@ medic_search(edict_t *self)
void
medic_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -148,7 +194,7 @@ medic_sight(edict_t *self, edict_t *other /* unused */)
gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
}
mframe_t medic_frames_stand[] = {
static mframe_t medic_frames_stand[] = {
{ai_stand, 0, medic_idle},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -241,7 +287,8 @@ mframe_t medic_frames_stand[] = {
{ai_stand, 0, NULL},
};
mmove_t medic_move_stand = {
mmove_t medic_move_stand =
{
FRAME_wait1,
FRAME_wait90,
medic_frames_stand,
@ -251,7 +298,7 @@ mmove_t medic_move_stand = {
void
medic_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -259,22 +306,23 @@ medic_stand(edict_t *self)
self->monsterinfo.currentmove = &medic_move_stand;
}
mframe_t medic_frames_walk[] = {
static mframe_t medic_frames_walk[] = {
{ai_walk, 6.2, NULL},
{ai_walk, 18.1, NULL},
{ai_walk, 18.1, medic_footstep},
{ai_walk, 1, NULL},
{ai_walk, 9, NULL},
{ai_walk, 10, NULL},
{ai_walk, 9, NULL},
{ai_walk, 11, NULL},
{ai_walk, 11.6, NULL},
{ai_walk, 11.6, medic_footstep},
{ai_walk, 2, NULL},
{ai_walk, 9.9, NULL},
{ai_walk, 14, NULL},
{ai_walk, 9.3, NULL}
};
mmove_t medic_move_walk = {
mmove_t medic_move_walk =
{
FRAME_walk1,
FRAME_walk12,
medic_frames_walk,
@ -284,7 +332,7 @@ mmove_t medic_move_walk = {
void
medic_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -292,26 +340,27 @@ medic_walk(edict_t *self)
self->monsterinfo.currentmove = &medic_move_walk;
}
mframe_t medic_frames_run[] = {
{ai_run, 18, NULL},
static mframe_t medic_frames_run[] = {
{ai_run, 18, medic_footstep},
{ai_run, 22.5, NULL},
{ai_run, 25.4, NULL},
{ai_run, 23.4, NULL},
{ai_run, 24, NULL},
{ai_run, 24, medic_footstep},
{ai_run, 35.6, NULL}
};
mmove_t medic_move_run = {
mmove_t medic_move_run =
{
FRAME_run1,
FRAME_run6,
medic_frames_run,
FRAME_run6,
medic_frames_run,
NULL
};
void
medic_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -343,7 +392,7 @@ medic_run(edict_t *self)
}
}
mframe_t medic_frames_pain1[] = {
static mframe_t medic_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -354,14 +403,19 @@ mframe_t medic_frames_pain1[] = {
{ai_move, 0, NULL}
};
mmove_t medic_move_pain1 = {
mmove_t medic_move_pain1 =
{
FRAME_paina1,
FRAME_paina8,
FRAME_paina8,
medic_frames_pain1,
medic_run
};
mframe_t medic_frames_pain2[] = {
static mframe_t medic_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, medic_footstep},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -372,14 +426,11 @@ mframe_t medic_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL}
{ai_move, 0, medic_footstep}
};
mmove_t medic_move_pain2 = {
mmove_t medic_move_pain2 =
{
FRAME_painb1,
FRAME_painb15,
medic_frames_pain2,
@ -390,7 +441,7 @@ void
medic_pain(edict_t *self, edict_t *other /* unused */,
float kick, int damage /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -433,7 +484,7 @@ medic_fire_blaster(edict_t *self)
vec3_t dir;
int effect;
if (!self)
if (!self)
{
return;
}
@ -468,7 +519,7 @@ medic_fire_blaster(edict_t *self)
void
medic_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -481,7 +532,7 @@ medic_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t medic_frames_death[] = {
static mframe_t medic_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -514,7 +565,8 @@ mframe_t medic_frames_death[] = {
{ai_move, 0, NULL}
};
mmove_t medic_move_death = {
mmove_t medic_move_death =
{
FRAME_death1,
FRAME_death30,
medic_frames_death,
@ -528,7 +580,7 @@ medic_die(edict_t *self, edict_t *inflictor /* unused */,
{
int n;
if (!self)
if (!self)
{
return;
}
@ -546,15 +598,18 @@ medic_die(edict_t *self, edict_t *inflictor /* unused */,
for (n = 0; n < 2; n++)
{
ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/bone/tris.md2",
damage, GIB_ORGANIC);
}
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
}
ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
ThrowHead(self, "models/objects/gibs/head2/tris.md2",
damage, GIB_ORGANIC);
self->deadflag = DEAD_DEAD;
return;
}
@ -575,7 +630,7 @@ medic_die(edict_t *self, edict_t *inflictor /* unused */,
void
medic_duck_down(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -595,7 +650,7 @@ medic_duck_down(edict_t *self)
void
medic_duck_hold(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -613,7 +668,7 @@ medic_duck_hold(edict_t *self)
void
medic_duck_up(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -624,7 +679,7 @@ medic_duck_up(edict_t *self)
gi.linkentity(self);
}
mframe_t medic_frames_duck[] = {
static mframe_t medic_frames_duck[] = {
{ai_move, -1, NULL},
{ai_move, -1, NULL},
{ai_move, -1, medic_duck_down},
@ -643,7 +698,8 @@ mframe_t medic_frames_duck[] = {
{ai_move, -1, NULL}
};
mmove_t medic_move_duck = {
mmove_t medic_move_duck =
{
FRAME_duck1,
FRAME_duck16,
medic_frames_duck,
@ -653,7 +709,7 @@ mmove_t medic_move_duck = {
void
medic_dodge(edict_t *self, edict_t *attacker, float eta /* unused */)
{
if (!self || !attacker)
if (!self || !attacker)
{
return;
}
@ -672,7 +728,7 @@ medic_dodge(edict_t *self, edict_t *attacker, float eta /* unused */)
self->monsterinfo.currentmove = &medic_move_duck;
}
mframe_t medic_frames_attackHyperBlaster[] = {
static mframe_t medic_frames_attackHyperBlaster[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -691,7 +747,8 @@ mframe_t medic_frames_attackHyperBlaster[] = {
{ai_charge, 0, medic_fire_blaster}
};
mmove_t medic_move_attackHyperBlaster = {
mmove_t medic_move_attackHyperBlaster =
{
FRAME_attack15,
FRAME_attack30,
medic_frames_attackHyperBlaster,
@ -701,7 +758,7 @@ mmove_t medic_move_attackHyperBlaster = {
void
medic_continue(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -715,7 +772,7 @@ medic_continue(edict_t *self)
}
}
mframe_t medic_frames_attackBlaster[] = {
static mframe_t medic_frames_attackBlaster[] = {
{ai_charge, 0, NULL},
{ai_charge, 5, NULL},
{ai_charge, 5, NULL},
@ -742,7 +799,7 @@ mmove_t medic_move_attackBlaster = {
void
medic_hook_launch(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -771,7 +828,7 @@ medic_cable_attack(edict_t *self)
vec3_t dir, angles;
float distance;
if (!self)
if (!self)
{
return;
}
@ -871,7 +928,7 @@ medic_cable_attack(edict_t *self)
void
medic_hook_retract(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -880,7 +937,7 @@ medic_hook_retract(edict_t *self)
self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;
}
mframe_t medic_frames_attackCable[] = {
static mframe_t medic_frames_attackCable[] = {
{ai_move, 2, NULL},
{ai_move, 3, NULL},
{ai_move, 5, NULL},
@ -888,7 +945,7 @@ mframe_t medic_frames_attackCable[] = {
{ai_charge, 4.7, NULL},
{ai_charge, 5, NULL},
{ai_charge, 6, NULL},
{ai_charge, 4, NULL},
{ai_charge, 4, medic_footstep},
{ai_charge, 0, NULL},
{ai_move, 0, medic_hook_launch},
{ai_move, 0, medic_cable_attack},
@ -902,7 +959,7 @@ mframe_t medic_frames_attackCable[] = {
{ai_move, 0, medic_cable_attack},
{ai_move, -15, medic_hook_retract},
{ai_move, -1.5, NULL},
{ai_move, -1.2, NULL},
{ai_move, -1.2, medic_footstep},
{ai_move, -3, NULL},
{ai_move, -2, NULL},
{ai_move, 0.3, NULL},
@ -911,7 +968,8 @@ mframe_t medic_frames_attackCable[] = {
{ai_move, 1.3, NULL}
};
mmove_t medic_move_attackCable = {
mmove_t medic_move_attackCable =
{
FRAME_attack33,
FRAME_attack60,
medic_frames_attackCable,
@ -921,7 +979,7 @@ mmove_t medic_move_attackCable = {
void
medic_attack(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -939,7 +997,7 @@ medic_attack(edict_t *self)
qboolean
medic_checkattack(edict_t *self)
{
if (!self)
if (!self)
{
return false;
}
@ -959,7 +1017,7 @@ medic_checkattack(edict_t *self)
void
SP_monster_medic(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -970,6 +1028,11 @@ SP_monster_medic(edict_t *self)
return;
}
// Force recaching at next footstep to ensure
// that the sound indices are correct.
sound_step = 0;
sound_step2 = 0;
sound_idle1 = gi.soundindex("medic/idle.wav");
sound_pain1 = gi.soundindex("medic/medpain1.wav");
sound_pain2 = gi.soundindex("medic/medpain2.wav");

View file

@ -83,7 +83,7 @@ mutant_swing(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0);
}
mframe_t mutant_frames_stand[] = {
static mframe_t mutant_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -174,7 +174,7 @@ mutant_idle_loop(edict_t *self)
}
}
mframe_t mutant_frames_idle[] = {
static mframe_t mutant_frames_idle[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -209,7 +209,7 @@ mutant_idle(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
}
mframe_t mutant_frames_walk[] = {
static mframe_t mutant_frames_walk[] = {
{ai_walk, 3, NULL},
{ai_walk, 1, NULL},
{ai_walk, 5, NULL},
@ -242,7 +242,7 @@ mutant_walk_loop(edict_t *self)
self->monsterinfo.currentmove = &mutant_move_walk;
}
mframe_t mutant_frames_start_walk[] = {
static mframe_t mutant_frames_start_walk[] = {
{ai_walk, 5, NULL},
{ai_walk, 5, NULL},
{ai_walk, -2, NULL},
@ -267,7 +267,7 @@ mutant_walk(edict_t *self)
self->monsterinfo.currentmove = &mutant_move_start_walk;
}
mframe_t mutant_frames_run[] = {
static mframe_t mutant_frames_run[] = {
{ai_run, 40, NULL},
{ai_run, 40, mutant_step},
{ai_run, 24, NULL},
@ -364,7 +364,7 @@ mutant_check_refire(edict_t *self)
}
}
mframe_t mutant_frames_attack[] = {
static mframe_t mutant_frames_attack[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, mutant_hit_left},
@ -484,7 +484,7 @@ mutant_check_landing(edict_t *self)
}
}
mframe_t mutant_frames_jump[] = {
static mframe_t mutant_frames_jump[] = {
{ai_charge, 0, NULL},
{ai_charge, 17, NULL},
{ai_charge, 15, mutant_jump_takeoff},
@ -599,7 +599,7 @@ mutant_checkattack(edict_t *self)
return false;
}
mframe_t mutant_frames_pain1[] = {
static mframe_t mutant_frames_pain1[] = {
{ai_move, 4, NULL},
{ai_move, -3, NULL},
{ai_move, -8, NULL},
@ -614,7 +614,7 @@ mmove_t mutant_move_pain1 = {
mutant_run
};
mframe_t mutant_frames_pain2[] = {
static mframe_t mutant_frames_pain2[] = {
{ai_move, -24, NULL},
{ai_move, 11, NULL},
{ai_move, 5, NULL},
@ -630,7 +630,7 @@ mmove_t mutant_move_pain2 = {
mutant_run
};
mframe_t mutant_frames_pain3[] = {
static mframe_t mutant_frames_pain3[] = {
{ai_move, -22, NULL},
{ai_move, 3, NULL},
{ai_move, 3, NULL},
@ -715,7 +715,7 @@ mutant_dead(edict_t *self)
M_FlyCheck(self);
}
mframe_t mutant_frames_death1[] = {
static mframe_t mutant_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -734,7 +734,7 @@ mmove_t mutant_move_death1 = {
mutant_dead
};
mframe_t mutant_frames_death2[] = {
static mframe_t mutant_frames_death2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -1,4 +1,23 @@
/* =======================================================================
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Parasite.
*
@ -32,7 +51,7 @@ void parasite_refidget(edict_t *self);
void
parasite_launch(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -43,7 +62,7 @@ parasite_launch(edict_t *self)
void
parasite_reel_in(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -54,7 +73,7 @@ parasite_reel_in(edict_t *self)
void
parasite_sight(edict_t *self, edict_t *other /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -65,7 +84,7 @@ parasite_sight(edict_t *self, edict_t *other /* unused */)
void
parasite_tap(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -73,10 +92,19 @@ parasite_tap(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_tap, 1, ATTN_IDLE, 0);
}
void
parasite_footstep(edict_t *self)
{
if (g_monsterfootsteps->value)
{
parasite_tap(self);
}
}
void
parasite_scratch(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -87,7 +115,7 @@ parasite_scratch(edict_t *self)
void
parasite_search(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -95,21 +123,22 @@ parasite_search(edict_t *self)
gi.sound(self, CHAN_WEAPON, sound_search, 1, ATTN_IDLE, 0);
}
mframe_t parasite_frames_start_fidget[] = {
static mframe_t parasite_frames_start_fidget[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL}
};
mmove_t parasite_move_start_fidget = {
mmove_t parasite_move_start_fidget =
{
FRAME_stand18,
FRAME_stand21,
FRAME_stand21,
parasite_frames_start_fidget,
parasite_do_fidget
};
mframe_t parasite_frames_fidget[] = {
static mframe_t parasite_frames_fidget[] = {
{ai_stand, 0, parasite_scratch},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -118,14 +147,15 @@ mframe_t parasite_frames_fidget[] = {
{ai_stand, 0, NULL}
};
mmove_t parasite_move_fidget = {
mmove_t parasite_move_fidget =
{
FRAME_stand22,
FRAME_stand27,
parasite_frames_fidget,
parasite_refidget
};
mframe_t parasite_frames_end_fidget[] = {
static mframe_t parasite_frames_end_fidget[] = {
{ai_stand, 0, parasite_scratch},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -136,7 +166,8 @@ mframe_t parasite_frames_end_fidget[] = {
{ai_stand, 0, NULL}
};
mmove_t parasite_move_end_fidget = {
mmove_t parasite_move_end_fidget =
{
FRAME_stand28,
FRAME_stand35,
parasite_frames_end_fidget,
@ -146,7 +177,7 @@ mmove_t parasite_move_end_fidget = {
void
parasite_end_fidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -157,7 +188,7 @@ parasite_end_fidget(edict_t *self)
void
parasite_do_fidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -168,7 +199,7 @@ parasite_do_fidget(edict_t *self)
void
parasite_refidget(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -186,7 +217,7 @@ parasite_refidget(edict_t *self)
void
parasite_idle(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -194,7 +225,7 @@ parasite_idle(edict_t *self)
self->monsterinfo.currentmove = &parasite_move_start_fidget;
}
mframe_t parasite_frames_stand[] = {
static mframe_t parasite_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, parasite_tap},
@ -214,9 +245,10 @@ mframe_t parasite_frames_stand[] = {
{ai_stand, 0, parasite_tap}
};
mmove_t parasite_move_stand = {
mmove_t parasite_move_stand =
{
FRAME_stand01,
FRAME_stand17,
FRAME_stand17,
parasite_frames_stand,
parasite_stand
};
@ -224,7 +256,7 @@ mmove_t parasite_move_stand = {
void
parasite_stand(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -232,55 +264,58 @@ parasite_stand(edict_t *self)
self->monsterinfo.currentmove = &parasite_move_stand;
}
mframe_t parasite_frames_run[] = {
static mframe_t parasite_frames_run[] = {
{ai_run, 30, NULL},
{ai_run, 30, NULL},
{ai_run, 22, NULL},
{ai_run, 19, NULL},
{ai_run, 22, parasite_footstep},
{ai_run, 19, parasite_footstep},
{ai_run, 24, NULL},
{ai_run, 28, NULL},
{ai_run, 28, parasite_footstep},
{ai_run, 25, NULL}
};
mmove_t parasite_move_run = {
mmove_t parasite_move_run =
{
FRAME_run03,
FRAME_run09,
parasite_frames_run,
NULL
FRAME_run09,
parasite_frames_run,
NULL
};
mframe_t parasite_frames_start_run[] = {
static mframe_t parasite_frames_start_run[] = {
{ai_run, 0, NULL},
{ai_run, 30, NULL},
};
mmove_t parasite_move_start_run = {
mmove_t parasite_move_start_run =
{
FRAME_run01,
FRAME_run02,
FRAME_run02,
parasite_frames_start_run,
parasite_run
};
mframe_t parasite_frames_stop_run[] = {
static mframe_t parasite_frames_stop_run[] = {
{ai_run, 20, NULL},
{ai_run, 20, NULL},
{ai_run, 12, NULL},
{ai_run, 12, parasite_footstep},
{ai_run, 10, NULL},
{ai_run, 0, NULL},
{ai_run, 0, NULL}
};
mmove_t parasite_move_stop_run = {
mmove_t parasite_move_stop_run =
{
FRAME_run10,
FRAME_run15,
parasite_frames_stop_run,
NULL
FRAME_run15,
parasite_frames_stop_run,
NULL
};
void
parasite_start_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -298,7 +333,7 @@ parasite_start_run(edict_t *self)
void
parasite_run(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -313,45 +348,48 @@ parasite_run(edict_t *self)
}
}
mframe_t parasite_frames_walk[] = {
static mframe_t parasite_frames_walk[] = {
{ai_walk, 30, NULL},
{ai_walk, 30, NULL},
{ai_walk, 22, NULL},
{ai_walk, 22, parasite_footstep},
{ai_walk, 19, NULL},
{ai_walk, 24, NULL},
{ai_walk, 28, NULL},
{ai_walk, 24, parasite_footstep},
{ai_walk, 28, parasite_footstep},
{ai_walk, 25, NULL}
};
mmove_t parasite_move_walk = {
mmove_t parasite_move_walk =
{
FRAME_run03,
FRAME_run09,
parasite_frames_walk,
parasite_walk
FRAME_run09,
parasite_frames_walk,
parasite_walk
};
mframe_t parasite_frames_start_walk[] = {
static mframe_t parasite_frames_start_walk[] = {
{ai_walk, 0, NULL},
{ai_walk, 30, parasite_walk}
};
mmove_t parasite_move_start_walk = {
mmove_t parasite_move_start_walk =
{
FRAME_run01,
FRAME_run02,
FRAME_run02,
parasite_frames_start_walk,
NULL
};
mframe_t parasite_frames_stop_walk[] = {
static mframe_t parasite_frames_stop_walk[] = {
{ai_walk, 20, NULL},
{ai_walk, 20, NULL},
{ai_walk, 12, NULL},
{ai_walk, 12, parasite_footstep},
{ai_walk, 10, NULL},
{ai_walk, 0, NULL},
{ai_walk, 0, NULL}
};
mmove_t parasite_move_stop_walk = {
mmove_t parasite_move_stop_walk =
{
FRAME_run10,
FRAME_run15,
parasite_frames_stop_walk,
@ -361,7 +399,7 @@ mmove_t parasite_move_stop_walk = {
void
parasite_start_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -372,7 +410,7 @@ parasite_start_walk(edict_t *self)
void
parasite_walk(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -380,7 +418,7 @@ parasite_walk(edict_t *self)
self->monsterinfo.currentmove = &parasite_move_walk;
}
mframe_t parasite_frames_pain1[] = {
static mframe_t parasite_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -394,9 +432,10 @@ mframe_t parasite_frames_pain1[] = {
{ai_move, 0, NULL}
};
mmove_t parasite_move_pain1 = {
mmove_t parasite_move_pain1 =
{
FRAME_pain101,
FRAME_pain111,
FRAME_pain111,
parasite_frames_pain1,
parasite_start_run
};
@ -405,7 +444,7 @@ void
parasite_pain(edict_t *self, edict_t *other /* unused */,
float kick /* unused */, int damage /* unused */)
{
if (!self)
if (!self)
{
return;
}
@ -475,7 +514,7 @@ parasite_drain_attack(edict_t *self)
trace_t tr;
int damage;
if (!self)
if (!self)
{
return;
}
@ -537,7 +576,7 @@ parasite_drain_attack(edict_t *self)
damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN);
}
mframe_t parasite_frames_drain[] = {
static mframe_t parasite_frames_drain[] = {
{ai_charge, 0, parasite_launch},
{ai_charge, 0, NULL},
{ai_charge, 15, parasite_drain_attack}, /* Target hits */
@ -558,14 +597,15 @@ mframe_t parasite_frames_drain[] = {
{ai_charge, 0, NULL}
};
mmove_t parasite_move_drain = {
mmove_t parasite_move_drain =
{
FRAME_drain01,
FRAME_drain18,
parasite_frames_drain,
parasite_start_run
};
mframe_t parasite_frames_break[] = {
static mframe_t parasite_frames_break[] = {
{ai_charge, 0, NULL},
{ai_charge, -3, NULL},
{ai_charge, 1, NULL},
@ -600,18 +640,18 @@ mframe_t parasite_frames_break[] = {
{ai_charge, 1, NULL}
};
mmove_t parasite_move_break = {
mmove_t parasite_move_break =
{
FRAME_break01,
FRAME_break32,
parasite_frames_break,
FRAME_break32,
parasite_frames_break,
parasite_start_run
};
void
parasite_attack(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -622,7 +662,7 @@ parasite_attack(edict_t *self)
void
parasite_dead(edict_t *self)
{
if (!self)
if (!self)
{
return;
}
@ -635,7 +675,7 @@ parasite_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t parasite_frames_death[] = {
static mframe_t parasite_frames_death[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -645,7 +685,8 @@ mframe_t parasite_frames_death[] = {
{ai_move, 0, NULL}
};
mmove_t parasite_move_death = {
mmove_t parasite_move_death =
{
FRAME_death101,
FRAME_death107,
parasite_frames_death,
@ -671,15 +712,18 @@ parasite_die(edict_t *self, edict_t *inflictor /* unused */,
for (n = 0; n < 2; n++)
{
ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/bone/tris.md2",
damage, GIB_ORGANIC);
}
for (n = 0; n < 4; n++)
{
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
}
ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
ThrowHead(self, "models/objects/gibs/head2/tris.md2",
damage, GIB_ORGANIC);
self->deadflag = DEAD_DEAD;
return;
}
@ -702,7 +746,7 @@ parasite_die(edict_t *self, edict_t *inflictor /* unused */,
void
SP_monster_parasite(edict_t *self)
{
if (!self)
if (!self)
{
return;
}

File diff suppressed because it is too large Load diff

View file

@ -53,7 +53,7 @@ supertank_search(edict_t *self)
}
}
mframe_t supertank_frames_stand[] = {
static mframe_t supertank_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -134,7 +134,7 @@ supertank_stand(edict_t *self)
self->monsterinfo.currentmove = &supertank_move_stand;
}
mframe_t supertank_frames_run[] = {
static mframe_t supertank_frames_run[] = {
{ai_run, 12, TreadSound},
{ai_run, 12, NULL},
{ai_run, 12, NULL},
@ -162,7 +162,7 @@ mmove_t supertank_move_run = {
NULL
};
mframe_t supertank_frames_forward[] = {
static mframe_t supertank_frames_forward[] = {
{ai_walk, 4, TreadSound},
{ai_walk, 4, NULL},
{ai_walk, 4, NULL},
@ -230,7 +230,7 @@ supertank_run(edict_t *self)
}
}
mframe_t supertank_frames_turn_right[] = {
static mframe_t supertank_frames_turn_right[] = {
{ai_move, 0, TreadSound},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -258,7 +258,7 @@ mmove_t supertank_move_turn_right = {
supertank_run
};
mframe_t supertank_frames_turn_left[] = {
static mframe_t supertank_frames_turn_left[] = {
{ai_move, 0, TreadSound},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -286,7 +286,7 @@ mmove_t supertank_move_turn_left = {
supertank_run
};
mframe_t supertank_frames_pain3[] = {
static mframe_t supertank_frames_pain3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -300,7 +300,7 @@ mmove_t supertank_move_pain3 = {
supertank_run
};
mframe_t supertank_frames_pain2[] = {
static mframe_t supertank_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -314,7 +314,7 @@ mmove_t supertank_move_pain2 = {
supertank_run
};
mframe_t supertank_frames_pain1[] = {
static mframe_t supertank_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -328,7 +328,7 @@ mmove_t supertank_move_pain1 = {
supertank_run
};
mframe_t supertank_frames_death1[] = {
static mframe_t supertank_frames_death1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -362,7 +362,7 @@ mmove_t supertank_move_death = {
supertank_dead
};
mframe_t supertank_frames_backward[] = {
static mframe_t supertank_frames_backward[] = {
{ai_walk, 0, TreadSound},
{ai_walk, 0, NULL},
{ai_walk, 0, NULL},
@ -390,7 +390,7 @@ mmove_t supertank_move_backward = {
NULL
};
mframe_t supertank_frames_attack4[] = {
static mframe_t supertank_frames_attack4[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -406,7 +406,7 @@ mmove_t supertank_move_attack4 = {
supertank_run
};
mframe_t supertank_frames_attack3[] = {
static mframe_t supertank_frames_attack3[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -443,7 +443,7 @@ mmove_t supertank_move_attack3 = {
supertank_run
};
mframe_t supertank_frames_attack2[] = {
static mframe_t supertank_frames_attack2[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -480,7 +480,7 @@ mmove_t supertank_move_attack2 = {
supertank_run
};
mframe_t supertank_frames_attack1[] = {
static mframe_t supertank_frames_attack1[] = {
{ai_charge, 0, supertankMachineGun},
{ai_charge, 0, supertankMachineGun},
{ai_charge, 0, supertankMachineGun},
@ -496,7 +496,7 @@ mmove_t supertank_move_attack1 = {
supertank_reattack1
};
mframe_t supertank_frames_end_attack1[] = {
static mframe_t supertank_frames_end_attack1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},

View file

@ -78,7 +78,7 @@ tank_idle(edict_t *self)
gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
}
mframe_t tank_frames_stand[] = {
static mframe_t tank_frames_stand[] = {
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
{ai_stand, 0, NULL},
@ -129,7 +129,7 @@ tank_stand(edict_t *self)
self->monsterinfo.currentmove = &tank_move_stand;
}
mframe_t tank_frames_start_walk[] = {
static mframe_t tank_frames_start_walk[] = {
{ai_walk, 0, NULL},
{ai_walk, 6, NULL},
{ai_walk, 6, NULL},
@ -143,7 +143,7 @@ mmove_t tank_move_start_walk = {
tank_walk
};
mframe_t tank_frames_walk[] = {
static mframe_t tank_frames_walk[] = {
{ai_walk, 4, NULL},
{ai_walk, 5, NULL},
{ai_walk, 3, NULL},
@ -169,7 +169,7 @@ mmove_t tank_move_walk = {
NULL
};
mframe_t tank_frames_stop_walk[] = {
static mframe_t tank_frames_stop_walk[] = {
{ai_walk, 3, NULL},
{ai_walk, 3, NULL},
{ai_walk, 2, NULL},
@ -195,7 +195,7 @@ tank_walk(edict_t *self)
self->monsterinfo.currentmove = &tank_move_walk;
}
mframe_t tank_frames_start_run[] = {
static mframe_t tank_frames_start_run[] = {
{ai_run, 0, NULL},
{ai_run, 6, NULL},
{ai_run, 6, NULL},
@ -209,7 +209,7 @@ mmove_t tank_move_start_run = {
tank_run
};
mframe_t tank_frames_run[] = {
static mframe_t tank_frames_run[] = {
{ai_run, 4, NULL},
{ai_run, 5, NULL},
{ai_run, 3, NULL},
@ -235,7 +235,7 @@ mmove_t tank_move_run = {
NULL
};
mframe_t tank_frames_stop_run[] = {
static mframe_t tank_frames_stop_run[] = {
{ai_run, 3, NULL},
{ai_run, 3, NULL},
{ai_run, 2, NULL},
@ -284,7 +284,7 @@ tank_run(edict_t *self)
}
}
mframe_t tank_frames_pain1[] = {
static mframe_t tank_frames_pain1[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -298,7 +298,7 @@ mmove_t tank_move_pain1 = {
tank_run
};
mframe_t tank_frames_pain2[] = {
static mframe_t tank_frames_pain2[] = {
{ai_move, 0, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -313,7 +313,7 @@ mmove_t tank_move_pain2 = {
tank_run
};
mframe_t tank_frames_pain3[] = {
static mframe_t tank_frames_pain3[] = {
{ai_move, -7, NULL},
{ai_move, 0, NULL},
{ai_move, 0, NULL},
@ -547,7 +547,7 @@ TankMachineGun(edict_t *self)
DEFAULT_BULLET_VSPREAD, flash_number);
}
mframe_t tank_frames_attack_blast[] = {
static mframe_t tank_frames_attack_blast[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -573,7 +573,7 @@ mmove_t tank_move_attack_blast = {
tank_reattack_blaster
};
mframe_t tank_frames_reattack_blast[] = {
static mframe_t tank_frames_reattack_blast[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, TankBlaster},
@ -589,7 +589,7 @@ mmove_t tank_move_reattack_blast = {
tank_reattack_blaster
};
mframe_t tank_frames_attack_post_blast[] = {
static mframe_t tank_frames_attack_post_blast[] = {
{ai_move, 0, NULL}, /* 17 */
{ai_move, 0, NULL},
{ai_move, 2, NULL},
@ -638,7 +638,7 @@ tank_poststrike(edict_t *self)
tank_run(self);
}
mframe_t tank_frames_attack_strike[] = {
static mframe_t tank_frames_attack_strike[] = {
{ai_move, 3, NULL},
{ai_move, 2, NULL},
{ai_move, 2, NULL},
@ -686,7 +686,7 @@ mmove_t tank_move_attack_strike = {
tank_poststrike
};
mframe_t tank_frames_attack_pre_rocket[] = {
static mframe_t tank_frames_attack_pre_rocket[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -719,7 +719,7 @@ mmove_t tank_move_attack_pre_rocket = {
tank_doattack_rocket
};
mframe_t tank_frames_attack_fire_rocket[] = {
static mframe_t tank_frames_attack_fire_rocket[] = {
{ai_charge, -3, NULL}, /* Loop Start 22 */
{ai_charge, 0, NULL},
{ai_charge, 0, TankRocket}, /* 24 */
@ -738,7 +738,7 @@ mmove_t tank_move_attack_fire_rocket = {
tank_refire_rocket
};
mframe_t tank_frames_attack_post_rocket[] = {
static mframe_t tank_frames_attack_post_rocket[] = {
{ai_charge, 0, NULL}, /* 31 */
{ai_charge, -1, NULL},
{ai_charge, -1, NULL},
@ -773,7 +773,7 @@ mmove_t tank_move_attack_post_rocket = {
tank_run
};
mframe_t tank_frames_attack_chain[] = {
static mframe_t tank_frames_attack_chain[] = {
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
{ai_charge, 0, NULL},
@ -930,7 +930,7 @@ tank_dead(edict_t *self)
gi.linkentity(self);
}
mframe_t tank_frames_death1[] = {
static mframe_t tank_frames_death1[] = {
{ai_move, -7, NULL},
{ai_move, -2, NULL},
{ai_move, -2, NULL},

View file

@ -112,13 +112,15 @@ BeginIntermission(edict_t *targ)
}
/* strip players of all keys between units */
for (n = 0; n < MAX_ITEMS; n++)
for (n = 0; n < game.num_items; n++)
{
if (itemlist[n].flags & IT_KEY)
{
client->client->pers.inventory[n] = 0;
}
}
client->client->pers.power_cubes = 0;
}
}
}
@ -381,7 +383,7 @@ G_SetStats(edict_t *ent)
/* health */
ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health;
ent->client->ps.stats[STAT_HEALTH] = ent->health;
ent->client->ps.stats[STAT_HEALTH] = (ent->health < -99) ? -99 : ent->health;
/* ammo */
if (!ent->client->ammo_index)

View file

@ -1058,6 +1058,16 @@ G_SetClientEvent(edict_t *ent)
}
}
else if (g_footsteps->value == 2)
{
if (ent->groundentity)
{
if ((int)(current_client->bobtime + bobmove) != bobcycle)
{
ent->s.event = EV_FOOTSTEP;
}
}
}
else if (g_footsteps->value >= 3)
{
if ((int)(current_client->bobtime + bobmove) != bobcycle)
{

View file

@ -7,6 +7,10 @@
#include "../header/local.h"
#include "../monster/misc/player.h"
#include <limits.h>
#define PLAYER_NOISE_SELF 0
#define PLAYER_NOISE_IMPACT 1
#define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1)
#define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1)
@ -77,12 +81,111 @@ P_ProjectSource(edict_t *ent, vec3_t distance,
* Monsters that don't directly see the player can move
* to a noise in hopes of seeing the player from there.
*/
static edict_t *
PlayerNoise_Spawn(edict_t *who, int type)
{
edict_t *noise;
if (!who)
{
return NULL;
}
noise = G_SpawnOptional();
if (!noise)
{
return NULL;
}
noise->classname = "player_noise";
noise->spawnflags = type;
VectorSet (noise->mins, -8, -8, -8);
VectorSet (noise->maxs, 8, 8, 8);
noise->owner = who;
noise->svflags = SVF_NOCLIENT;
return noise;
}
static void
PlayerNoise_Verify(edict_t *who)
{
edict_t *e;
edict_t *n1;
edict_t *n2;
if (!who)
{
return;
}
n1 = who->mynoise;
n2 = who->mynoise2;
if (n1 && !n1->inuse)
{
n1 = NULL;
}
if (n2 && !n2->inuse)
{
n2 = NULL;
}
if (n1 && n2)
{
return;
}
for (e = g_edicts + 1 + game.maxclients; e < &g_edicts[globals.num_edicts]; e++)
{
if (!e->inuse || strcmp(e->classname, "player_noise") != 0)
{
continue;
}
if (e->owner && e->owner != who)
{
continue;
}
e->owner = who;
if (!n2 && (e->spawnflags == PLAYER_NOISE_IMPACT || n1))
{
n2 = e;
}
else
{
n1 = e;
}
if (n1 && n2)
{
break;
}
}
if (!n1)
{
n1 = PlayerNoise_Spawn(who, PLAYER_NOISE_SELF);
}
if (!n2)
{
n2 = PlayerNoise_Spawn(who, PLAYER_NOISE_IMPACT);
}
who->mynoise = n1;
who->mynoise2 = n2;
}
void
PlayerNoise(edict_t *who, vec3_t where, int type)
{
edict_t *noise;
if (!who)
if (!who || !who->client)
{
return;
}
@ -106,24 +209,7 @@ PlayerNoise(edict_t *who, vec3_t where, int type)
return;
}
if (!who->mynoise)
{
noise = G_Spawn();
noise->classname = "player_noise";
VectorSet(noise->mins, -8, -8, -8);
VectorSet(noise->maxs, 8, 8, 8);
noise->owner = who;
noise->svflags = SVF_NOCLIENT;
who->mynoise = noise;
noise = G_Spawn();
noise->classname = "player_noise";
VectorSet(noise->mins, -8, -8, -8);
VectorSet(noise->maxs, 8, 8, 8);
noise->owner = who;
noise->svflags = SVF_NOCLIENT;
who->mynoise2 = noise;
}
PlayerNoise_Verify(who);
if ((type == PNOISE_SELF) || (type == PNOISE_WEAPON))
{
@ -132,6 +218,11 @@ PlayerNoise(edict_t *who, vec3_t where, int type)
return;
}
if (!who->mynoise)
{
return;
}
noise = who->mynoise;
level.sound_entity = noise;
level.sound_entity_framenum = level.framenum;
@ -143,6 +234,11 @@ PlayerNoise(edict_t *who, vec3_t where, int type)
return;
}
if (!who->mynoise2)
{
return;
}
noise = who->mynoise2;
level.sound2_entity = noise;
level.sound2_entity_framenum = level.framenum;
@ -398,6 +494,31 @@ Think_Weapon(edict_t *ent)
}
}
/*
* Client (player) animation for changing weapon
*/
static void
Change_Weap_Animation(edict_t *ent)
{
if (!ent)
{
return;
}
ent->client->anim_priority = ANIM_REVERSE;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crpain4 + 1;
ent->client->anim_end = FRAME_crpain1;
}
else
{
ent->s.frame = FRAME_pain304 + 1;
ent->client->anim_end = FRAME_pain301;
}
}
/*
* Make the weapon ready if there is ammo
*/
@ -565,6 +686,9 @@ Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST,
int *fire_frames, void (*fire)(edict_t *ent))
{
int n;
const unsigned short int change_speed = (g_swap_speed->value > 1)?
(g_swap_speed->value < USHRT_MAX)? (unsigned short int)g_swap_speed->value : 1
: 1;
if (!ent || !fire_frames || !fire)
{
@ -578,41 +702,36 @@ Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST,
if (ent->client->weaponstate == WEAPON_DROPPING)
{
if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
if (ent->client->ps.gunframe >= FRAME_DEACTIVATE_LAST - change_speed + 1)
{
ChangeWeapon(ent);
return;
}
else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
else if ( (FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) >= (4 * change_speed) )
{
ent->client->anim_priority = ANIM_REVERSE;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
unsigned short int remainder = FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe;
// "if (remainder == 4)" at change_speed == 1
if ( ( remainder <= (4 * change_speed) )
&& ( remainder > (3 * change_speed) ) )
{
ent->s.frame = FRAME_crpain4 + 1;
ent->client->anim_end = FRAME_crpain1;
}
else
{
ent->s.frame = FRAME_pain304 + 1;
ent->client->anim_end = FRAME_pain301;
Change_Weap_Animation(ent);
}
}
ent->client->ps.gunframe++;
ent->client->ps.gunframe += change_speed;
return;
}
if (ent->client->weaponstate == WEAPON_ACTIVATING)
{
if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
if (ent->client->ps.gunframe >= FRAME_ACTIVATE_LAST - change_speed + 1)
{
ent->client->weaponstate = WEAPON_READY;
ent->client->ps.gunframe = FRAME_IDLE_FIRST;
return;
}
ent->client->ps.gunframe++;
ent->client->ps.gunframe += change_speed;
return;
}
@ -621,20 +740,9 @@ Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST,
ent->client->weaponstate = WEAPON_DROPPING;
ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
if ( (FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < (4 * change_speed) )
{
ent->client->anim_priority = ANIM_REVERSE;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crpain4 + 1;
ent->client->anim_end = FRAME_crpain1;
}
else
{
ent->s.frame = FRAME_pain304 + 1;
ent->client->anim_end = FRAME_pain301;
}
Change_Weap_Animation(ent);
}
return;
@ -1345,7 +1453,7 @@ Machinegun_Fire(edict_t *ent)
ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
/* raise the gun as it is firing */
if (!deathmatch->value)
if (!(deathmatch->value || g_machinegun_norecoil->value))
{
ent->client->machinegun_shots++;
@ -1690,10 +1798,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);
@ -2039,6 +2172,17 @@ weapon_phalanx_fire(edict_t *ent)
v[ROLL] = ent->client->v_angle[ROLL];
AngleVectors(v, forward, right, up);
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);
}
radius_damage = 30;
damage_radius = 120;
@ -2056,6 +2200,18 @@ weapon_phalanx_fire(edict_t *ent)
v[YAW] = ent->client->v_angle[YAW] + 1.5;
v[ROLL] = ent->client->v_angle[ROLL];
AngleVectors(v, forward, right, up);
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_plasma(ent, start, forward, damage, 725,
damage_radius, radius_damage);

View file

@ -47,12 +47,15 @@
#include "../header/local.h"
/*
* When ever the savegame version is changed, q2 will refuse to
* load older savegames. This should be bumped if the files
* in tables/ are changed, otherwise strange things may happen.
*/
#define SAVEGAMEVER "YQ2-4"
* When ever the savegame version is changed, q2 will refuse to
* load older savegames. This should be bumped if the files
* in tables/ are changed, otherwise strange things may happen.
*/
#define SAVEGAMEVER "YQ2-5"
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
/*
* This macros are used to prohibit loading of savegames
@ -142,12 +145,12 @@ typedef struct
* to each of the functions
* prototyped above.
*/
functionList_t functionList[] = {
static functionList_t functionList[] = {
#include "tables/gamefunc_list.h"
};
/*
* Prtotypes for forward
* Prototypes for forward
* declaration for all game
* mmove_t functions.
*/
@ -159,12 +162,12 @@ functionList_t functionList[] = {
* functions prototyped
* above.
*/
mmoveList_t mmoveList[] = {
static mmoveList_t mmoveList[] = {
#include "tables/gamemmove_list.h"
};
/*
* Fields to be saved
* Fields to be saved (used in g_spawn.c)
*/
field_t fields[] = {
#include "tables/fields.h"
@ -174,7 +177,7 @@ field_t fields[] = {
* Level fields to
* be saved
*/
field_t levelfields[] = {
static field_t levelfields[] = {
#include "tables/levelfields.h"
};
@ -182,7 +185,7 @@ field_t levelfields[] = {
* Client fields to
* be saved
*/
field_t clientfields[] = {
static field_t clientfields[] = {
#include "tables/clientfields.h"
};
@ -197,7 +200,7 @@ void
InitGame(void)
{
gi.dprintf("Game is starting up.\n");
gi.dprintf("Game is %s built on %s.\n", GAMEVERSION, __DATE__);
gi.dprintf("Game is %s built on %s.\n", GAMEVERSION, BUILD_DATE);
gun_x = gi.cvar ("gun_x", "0", 0);
gun_y = gi.cvar ("gun_y", "0", 0);
@ -213,7 +216,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);
maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO);
deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);
@ -223,6 +226,7 @@ InitGame(void)
skill = gi.cvar ("skill", "1", CVAR_LATCH);
maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH);
g_footsteps = gi.cvar ("g_footsteps", "1", CVAR_ARCHIVE);
g_monsterfootsteps = gi.cvar("g_monsterfootsteps", "0", CVAR_ARCHIVE);
g_fix_triggered = gi.cvar ("g_fix_triggered", "0", 0);
/* change anytime vars */
@ -250,6 +254,9 @@ InitGame(void)
/* others */
aimfix = gi.cvar("aimfix", "0", CVAR_ARCHIVE);
g_machinegun_norecoil = gi.cvar("g_machinegun_norecoil", "0", CVAR_ARCHIVE);
g_quick_weap = gi.cvar("g_quick_weap", "1", CVAR_ARCHIVE);
g_swap_speed = gi.cvar("g_swap_speed", "1", CVAR_ARCHIVE);
/* items */
InitItems ();
@ -834,6 +841,7 @@ ReadGame(const char *filename)
{"YQ2-2", 2},
{"YQ2-3", 3},
{"YQ2-4", 4},
{"YQ2-5", 5},
};
for (i=0; i < sizeof(version_mappings)/sizeof(version_mappings[0]); ++i)
@ -844,7 +852,7 @@ ReadGame(const char *filename)
break;
}
}
if (save_ver == 0) // not found in mappings table
{
fclose(f);
@ -954,7 +962,7 @@ WriteEdict(FILE *f, edict_t *ent)
}
/*
* Helper fcuntion to write the
* Helper function to write the
* level local data into a file.
* Called by WriteLevel.
*/
@ -1070,10 +1078,10 @@ ReadLevelLocals(FILE *f)
/*
* Reads a level back into the memory.
* SpawnEntities were allready called
* SpawnEntities were already called
* in the same way when the level was
* saved. All world links were cleared
* befor this function was called. When
* before this function was called. When
* this function is called, no clients
* are connected to the server.
*/
@ -1169,4 +1177,3 @@ ReadLevel(const char *filename)
}
}
}

View file

@ -1,4 +1,23 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 2011 Yamagi Burmeister
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Prototypes for every function in the game.so.
@ -34,7 +53,7 @@ extern int Q_strncasecmp ( char * s1 , char * s2 , int n ) ;
extern int Q_stricmp ( const char * s1 , const char * s2 ) ;
extern void Com_PageInMemory ( byte * buffer , int size ) ;
extern char * COM_Parse ( char * * data_p ) ;
extern char * va ( char * format , ... ) ;
extern char * va ( const char * format , ... ) ;
extern void Swap_Init ( void ) ;
extern float FloatNoSwap ( float f ) ;
extern float FloatSwap ( float f ) ;
@ -263,6 +282,7 @@ extern void SP_monster_soldier_ss ( edict_t * self ) ;
extern void SP_monster_soldier ( edict_t * self ) ;
extern void SP_monster_soldier_light ( edict_t * self ) ;
extern void SP_monster_soldier_x ( edict_t * self ) ;
extern void soldier_footstep( edict_t *self ) ;
extern void soldier_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void soldier_dead ( edict_t * self ) ;
extern void soldier_fire7 ( edict_t * self ) ;
@ -349,6 +369,7 @@ extern void M_ChangeYaw ( edict_t * ent ) ;
extern qboolean SV_movestep ( edict_t * ent , vec3_t move , qboolean relink ) ;
extern qboolean M_CheckBottom ( edict_t * ent ) ;
extern void SP_monster_medic ( edict_t * self ) ;
extern void medic_footstep( edict_t *self ) ;
extern qboolean medic_checkattack ( edict_t * self ) ;
extern void medic_attack ( edict_t * self ) ;
extern void medic_hook_retract ( edict_t * self ) ;
@ -371,6 +392,7 @@ extern void medic_search ( edict_t * self ) ;
extern void medic_idle ( edict_t * self ) ;
extern edict_t * medic_FindDeadMonster ( edict_t * self ) ;
extern void SP_misc_insane ( edict_t * self ) ;
extern void insane_footstep( edict_t *self ) ;
extern void insane_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void insane_dead ( edict_t * self ) ;
extern void insane_stand ( edict_t * self ) ;
@ -386,6 +408,7 @@ extern void insane_moan ( edict_t * self ) ;
extern void insane_shake ( edict_t * self ) ;
extern void insane_fist ( edict_t * self ) ;
extern void SP_monster_infantry ( edict_t * self ) ;
extern void infantry_footstep( edict_t *self ) ;
extern void infantry_attack ( edict_t * self ) ;
extern void infantry_smack ( edict_t * self ) ;
extern void infantry_swing ( edict_t * self ) ;
@ -420,6 +443,7 @@ extern void hover_reattack ( edict_t * self ) ;
extern void hover_search ( edict_t * self ) ;
extern void hover_sight ( edict_t * self , edict_t * other ) ;
extern void SP_monster_gunner ( edict_t * self ) ;
extern void gunner_footstep( edict_t *self ) ;
extern void gunner_refire_chain ( edict_t * self ) ;
extern void gunner_fire_chain ( edict_t * self ) ;
extern void gunner_attack ( edict_t * self ) ;
@ -442,6 +466,7 @@ extern void gunner_search ( edict_t * self ) ;
extern void gunner_sight ( edict_t * self , edict_t * other ) ;
extern void gunner_idlesound ( edict_t * self ) ;
extern void SP_monster_gladiator ( edict_t * self ) ;
extern void gladiator_footstep( edict_t *self ) ;
extern void gladiator_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void gladiator_dead ( edict_t * self ) ;
extern void gladiator_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
@ -600,6 +625,7 @@ extern edict_t * fixbot_FindDeadMonster ( edict_t * self ) ;
extern float crand ( void ) ;
extern void SP_monster_chick_heat ( edict_t * self ) ;
extern void SP_monster_chick ( edict_t * self ) ;
extern void chick_footstep( edict_t *self ) ;
extern void chick_sight ( edict_t * self , edict_t * other ) ;
extern void chick_attack ( edict_t * self ) ;
extern void chick_melee ( edict_t * self ) ;
@ -624,6 +650,7 @@ extern void chick_stand ( edict_t * self ) ;
extern void chick_fidget ( edict_t * self ) ;
extern void ChickMoan ( edict_t * self ) ;
extern void SP_monster_brain ( edict_t * self ) ;
extern void brain_footstep( edict_t *self ) ;
extern void brain_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void brain_dead ( edict_t * self ) ;
extern void brain_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
@ -671,6 +698,7 @@ extern void SP_monster_makron ( edict_t * self ) ;
extern void MakronPrecache ( void ) ;
extern qboolean Makron_CheckAttack ( edict_t * self ) ;
extern void makron_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void makron_torso_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void makron_dead ( edict_t * self ) ;
extern void makron_torso ( edict_t * ent ) ;
extern void makron_torso_think ( edict_t * self ) ;
@ -731,6 +759,7 @@ extern void boss2_firebullet_right ( edict_t * self ) ;
extern void Boss2Rocket ( edict_t * self ) ;
extern void boss2_search ( edict_t * self ) ;
extern void SP_monster_berserk ( edict_t * self ) ;
extern void berserk_footstep( edict_t *self ) ;
extern void berserk_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void berserk_dead ( edict_t * self ) ;
extern void berserk_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
@ -868,6 +897,7 @@ extern void SP_target_secret ( edict_t * ent ) ;
extern void use_target_secret ( edict_t * ent , edict_t * other , edict_t * activator ) ;
extern void SP_target_help ( edict_t * ent ) ;
extern void Use_Target_Help ( edict_t * ent , edict_t * other , edict_t * activator ) ;
extern void Target_Help_Think ( edict_t * ent ) ;
extern void SP_target_speaker ( edict_t * ent ) ;
extern void Use_Target_Speaker ( edict_t * ent , edict_t * other , edict_t * activator ) ;
extern void SP_target_temp_entity ( edict_t * ent ) ;

View file

@ -1,4 +1,23 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 2011 Yamagi Burmeister
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Functionpointers to every function in the game.so.
@ -263,6 +282,7 @@
{"SP_monster_soldier", (byte *)SP_monster_soldier},
{"SP_monster_soldier_light", (byte *)SP_monster_soldier_light},
{"SP_monster_soldier_x", (byte *)SP_monster_soldier_x},
{"soldier_footstep", (byte *)soldier_footstep},
{"soldier_die", (byte *)soldier_die},
{"soldier_dead", (byte *)soldier_dead},
{"soldier_fire7", (byte *)soldier_fire7},
@ -349,6 +369,7 @@
{"SV_movestep", (byte *)SV_movestep},
{"M_CheckBottom", (byte *)M_CheckBottom},
{"SP_monster_medic", (byte *)SP_monster_medic},
{"medic_footstep", (byte *)medic_footstep},
{"medic_checkattack", (byte *)medic_checkattack},
{"medic_attack", (byte *)medic_attack},
{"medic_hook_retract", (byte *)medic_hook_retract},
@ -371,6 +392,7 @@
{"medic_idle", (byte *)medic_idle},
{"medic_FindDeadMonster", (byte *)medic_FindDeadMonster},
{"SP_misc_insane", (byte *)SP_misc_insane},
{"insane_footstep", (byte *)insane_footstep},
{"insane_die", (byte *)insane_die},
{"insane_dead", (byte *)insane_dead},
{"insane_stand", (byte *)insane_stand},
@ -386,6 +408,7 @@
{"insane_shake", (byte *)insane_shake},
{"insane_fist", (byte *)insane_fist},
{"SP_monster_infantry", (byte *)SP_monster_infantry},
{"infantry_footstep", (byte *)infantry_footstep},
{"infantry_attack", (byte *)infantry_attack},
{"infantry_smack", (byte *)infantry_smack},
{"infantry_swing", (byte *)infantry_swing},
@ -420,6 +443,7 @@
{"hover_search", (byte *)hover_search},
{"hover_sight", (byte *)hover_sight},
{"SP_monster_gunner", (byte *)SP_monster_gunner},
{"gunner_footstep", (byte *)gunner_footstep},
{"gunner_refire_chain", (byte *)gunner_refire_chain},
{"gunner_fire_chain", (byte *)gunner_fire_chain},
{"gunner_attack", (byte *)gunner_attack},
@ -442,6 +466,7 @@
{"gunner_sight", (byte *)gunner_sight},
{"gunner_idlesound", (byte *)gunner_idlesound},
{"SP_monster_gladiator", (byte *)SP_monster_gladiator},
{"gladiator_footstep", (byte *)gladiator_footstep},
{"gladiator_die", (byte *)gladiator_die},
{"gladiator_dead", (byte *)gladiator_dead},
{"gladiator_pain", (byte *)gladiator_pain},
@ -600,6 +625,7 @@
{"crand", (byte *)crand},
{"SP_monster_chick_heat", (byte *)SP_monster_chick_heat},
{"SP_monster_chick", (byte *)SP_monster_chick},
{"chick_footstep", (byte *)chick_footstep},
{"chick_sight", (byte *)chick_sight},
{"chick_attack", (byte *)chick_attack},
{"chick_melee", (byte *)chick_melee},
@ -624,6 +650,7 @@
{"chick_fidget", (byte *)chick_fidget},
{"ChickMoan", (byte *)ChickMoan},
{"SP_monster_brain", (byte *)SP_monster_brain},
{"brain_footstep", (byte *)brain_footstep},
{"brain_die", (byte *)brain_die},
{"brain_dead", (byte *)brain_dead},
{"brain_pain", (byte *)brain_pain},
@ -671,6 +698,7 @@
{"MakronPrecache", (byte *)MakronPrecache},
{"Makron_CheckAttack", (byte *)Makron_CheckAttack},
{"makron_die", (byte *)makron_die},
{"makron_torso_die", (byte *)makron_torso_die},
{"makron_dead", (byte *)makron_dead},
{"makron_torso", (byte *)makron_torso},
{"makron_torso_think", (byte *)makron_torso_think},
@ -731,6 +759,7 @@
{"Boss2Rocket", (byte *)Boss2Rocket},
{"boss2_search", (byte *)boss2_search},
{"SP_monster_berserk", (byte *)SP_monster_berserk},
{"berserk_footstep", (byte *)berserk_footstep},
{"berserk_die", (byte *)berserk_die},
{"berserk_dead", (byte *)berserk_dead},
{"berserk_pain", (byte *)berserk_pain},
@ -868,6 +897,7 @@
{"use_target_secret", (byte *)use_target_secret},
{"SP_target_help", (byte *)SP_target_help},
{"Use_Target_Help", (byte *)Use_Target_Help},
{"Target_Help_Think", (byte *)Target_Help_Think},
{"SP_target_speaker", (byte *)SP_target_speaker},
{"Use_Target_Speaker", (byte *)Use_Target_Speaker},
{"SP_target_temp_entity", (byte *)SP_target_temp_entity},

View file

@ -503,20 +503,9 @@ VectorNormalize(vec3_t v)
vec_t
VectorNormalize2(vec3_t v, vec3_t out)
{
float length, ilength;
VectorCopy(v, out);
length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
length = (float)sqrt(length);
if (length)
{
ilength = 1 / length;
out[0] = v[0] * ilength;
out[1] = v[1] * ilength;
out[2] = v[2] * ilength;
}
return length;
return VectorNormalize(out);
}
void
@ -884,7 +873,7 @@ Swap_Init(void)
* need to have varargs versions of all text functions.
*/
char *
va(char *format, ...)
va(const char *format, ...)
{
va_list argptr;
static char string[1024];
@ -1333,7 +1322,7 @@ Info_SetValueForKey(char *s, char *key, char *value)
Com_sprintf(newi, sizeof(newi), "\\%s\\%s", key, value);
if (strlen(newi) + strlen(s) > maxsize)
if (strlen(newi) + strlen(s) >= maxsize)
{
Com_Printf("Info string length exceeded\n");
return;