Compare commits

...

98 Commits

Author SHA1 Message Date
Xylemon 92722445aa Fixes for scientist body types 2024-03-17 18:54:41 -07:00
Marco Cawthorne d33059c516
HLMultiplayerRules: Fix some warnings. 2024-03-06 19:38:57 -08:00
Marco Cawthorne 00827d44b4
monster_sitting_scientist: fix hitbox, and make use of `sequence` key. 2024-03-06 19:32:29 -08:00
Marco Cawthorne 42f7c82029
FX_Corpse: transfer player bbox to corpse, so we can handle crouching etc. 2024-03-06 19:09:40 -08:00
Marco Cawthorne 153a711955
HLMultiplayerRules: Support death animation variations. 2024-03-06 19:03:26 -08:00
Marco Cawthorne d66bc506ca
Client: Suit pickup will now supress excess notifications. 2024-03-06 19:01:26 -08:00
Marco Cawthorne 5324616382
Client: add a subtle tint to the damage display. Set cg_damageFill to tweak. 2024-03-06 18:59:29 -08:00
Marco Cawthorne f2aba72c0c
Remove in-code spawn point definitions.
Fix some typos.
Add some force loop flags to the train moving soundDefs.
2024-03-05 23:32:09 -08:00
Marco Cawthorne 9d3ec2b89c
monster_alien_grunt: Fix health value. 2024-03-04 18:40:57 -08:00
Marco Cawthorne ba23ecfab0
FX_Corpse: change movetype to MOVETYPE_BOUNCE 2024-03-04 11:47:31 -08:00
Marco Cawthorne 64c793126c
Update README.md 2024-03-02 09:33:58 -08:00
Marco Cawthorne f3596f2aef
Corpses: Ensure frame1time is reset whenever we inherit someones corpse.
Items: Ensure we re-adjust our position post-spawn so we don't fall through
yet-to-spawn geometry.
Delete a whole bunch of now unused code.
2024-03-02 00:43:10 -08:00
Marco Cawthorne c3975f5315
monster_human_grunt: remove the dlights from their projectiles. 2024-02-27 12:45:35 -08:00
Marco Cawthorne 135e97d276
WEAPON_TRIPMINE: set tripmine model only for visual appearance, bypassing the dodgy hitbox (engine bug?) 2024-02-27 12:44:47 -08:00
Marco Cawthorne 24a8c78367
Move skill files around to the new conventions, tweak various sounds/particles and definitions. 2024-02-23 14:00:41 -08:00
Marco Cawthorne a1638d3c65
Add zpak001.pk3dir/sound/func_tracktrain.sndshd 2024-02-13 22:52:22 -08:00
Marco Cawthorne b47a64b850
Server: Fix precache of the item_weaponbox pickup sound. 2024-01-30 00:40:03 -08:00
Marco Cawthorne 4e232c6875
Remove "bot_add" command, add zpak001.pk3dir/scripts/bots.txt 2024-01-26 19:27:32 -08:00
Marco Cawthorne 381412e4ba
Gamerules: update player death sound def name 2024-01-08 15:29:28 -08:00
Marco Cawthorne a8aa141778
Client: Remove duplicate g_specmodes[] definition 2024-01-08 15:28:44 -08:00
Marco Cawthorne a44c86c1a0
Manifest: update protocol name 2024-01-08 15:28:35 -08:00
Marco Cawthorne 7d27c29c07
Updates to the sound definitions and other minor fixes against upstream Nuclide. 2023-11-17 19:44:34 -08:00
Marco Cawthorne a483cad84c
Remove code that's no longer being run 2023-11-13 10:46:42 -08:00
Marco Cawthorne 63a407bb71
WEAPON_EGON: Fix parameter order on Damage_Radius() 2023-11-13 10:46:02 -08:00
Marco Cawthorne 1be1c6bf47
WEAPON_CROWBAR: Don't create an impact spark 2023-11-13 10:45:41 -08:00
Marco Cawthorne 436dbe4641
Server: Respect mp_forcerespawn in multiplayer 2023-11-13 10:44:32 -08:00
Marco Cawthorne fa22d59818
Add source files for the DM level shots. 2023-10-29 10:34:32 -07:00
Xylemon 82e31a6538 Every official HL map is now waypointed 2023-10-15 21:10:25 -07:00
Marco Cawthorne 64887cdabf
Remove view.qc and modelevent.qc 2023-10-12 14:41:00 -07:00
Marco Cawthorne 8bf7e5a221
Merge Maxwell's branch 2023-09-27 14:10:31 -07:00
Marco Cawthorne b1365cce22
Client: support game title fade-in 2023-09-27 14:07:45 -07:00
Maxwell eed9faf63b Trail is supposed to be on the explosive bolt. It was inversed. 2023-09-22 20:55:19 -04:00
Maxwell 9ab028abd7 Woah there. All of the head defines were ahead by 1. Walter is now default, not Head 1. Fixed all other heads too. 2023-09-22 18:00:13 -04:00
Maxwell 6ede261eeb Removed some OP4 dead versions from Valve. HL has no concept of these, not even animations for them in their respective models. 2023-09-22 17:50:15 -04:00
Xylemon df78e8dee6 NPC updates, added dead variants and some various fixes 2023-09-20 22:32:54 -07:00
Marco Cawthorne a2086c3de6
Scripts: Create blood decals upon gib model impact 2023-09-20 15:11:55 -07:00
Marco Cawthorne 995b00eb3f
monster_gman: Change walking speed to 77 units per second 2023-09-20 10:39:32 -07:00
Marco Cawthorne 1d00e324dc
Client: Explicit precache of the muzzleflash models. 2023-09-18 18:46:19 -07:00
Marco Cawthorne b2b5bf6bb8
monster_barney_dead: example dead monster 2023-09-18 15:50:28 -07:00
Marco Cawthorne f152ffb0f8
Add more stubby entityDefs for monsters, as work began on those 2023-09-08 09:41:05 -07:00
Marco Cawthorne b18c87cccb
Adjust the flashlight a bit 2023-07-31 17:15:46 -07:00
Marco Cawthorne 06ec2f0310
monster_headcrab: leaping, plus noise 2023-07-30 10:06:45 -07:00
Marco Cawthorne 914884b9fc
monster_alien_grunt: give hornet projectile a trail 2023-07-30 10:06:20 -07:00
Marco Cawthorne 6d3474b707
WEAPON_HANDGRENADE: projectile conversion to EDef 2023-07-30 10:06:03 -07:00
Marco Cawthorne 98b9bb56bd
monster_barney: define attack_ranged_range to 1024 units. 2023-07-30 10:05:42 -07:00
Marco Cawthorne 2607ee4f04
Define EDef for monster_babycrab 2023-07-30 10:05:24 -07:00
Marco Cawthorne f5c9583003
EntityDefs: Give explosives some decals upon detonation 2023-07-29 18:46:47 -07:00
Marco Cawthorne e342e72160
FX_Corpse: adjust bbox slightly, make it smaller. 2023-07-29 18:46:01 -07:00
Marco Cawthorne 25ac379c83
FX_Corpse: Add server-side animation code for the model 2023-07-29 18:01:46 -07:00
Marco Cawthorne aaf15a3f28
WEAPON_SATCHEL: Don't use private APIs when blowing up the satchel bombs. 2023-07-27 23:48:16 -07:00
Marco Cawthorne 753af7e8fb
Ripping things out, move most weapon projectiles into EntityDef 2023-07-27 23:08:26 -07:00
Marco Cawthorne 24964d27c9
Get rid of FX_GibHuman and FX_GibAlien, use PropData system instead 2023-07-17 11:32:59 -07:00
Marco Cawthorne e49810be8b
Restructuring of monster/weapon entitydef files 2023-07-16 22:47:01 -07:00
Marco Cawthorne 7a014d91e9
monster_barney: specify submodel group on weapon draw 2023-07-06 16:34:01 -07:00
Marco Cawthorne 0eec24c7aa
Update the body key/value pairs inside the monster edefs 2023-06-28 14:30:17 -07:00
Marco Cawthorne 6a8ac02add
Weapons now respect the startammo parameter passed over their pickup function. (needed by OP4CTF) 2023-06-28 08:52:39 -07:00
Marco Cawthorne dde42e481c
Yank out the monster's out of the codebase. Use entityDefs instead. 2023-06-20 21:23:15 -07:00
Marco Cawthorne 67d2f03a26
Remove QUAKED comments for weapon pickups (handled by build_game.sh and defs now) 2023-06-01 10:16:25 -07:00
Marco Cawthorne 454313f115
Add a Radiant compatible game definition files. 2023-05-27 12:01:49 -07:00
Marco Cawthorne cb2a517624
Fix the weaponbox not spawning properly in MP. 2023-05-10 14:36:46 -07:00
Marco Cawthorne 0b2955695a
Use entityDefs instead of hard-coded item pickups 2023-05-08 11:17:52 -07:00
Marco Cawthorne 6dd45060c2
install_from_cd_goty.sh: New script that uses rewise by CYBERDEViL instead of Wine 2023-05-08 11:14:18 -07:00
Marco Cawthorne b96929cddf
surfaceproperties.txt: play sfx_impact.concrete for gs_material_rocks 2023-05-01 06:17:11 -07:00
Marco Cawthorne 70f1ed409f
Script definition tweaks for func_breakable behaviour/sounds 2023-05-01 05:51:20 -07:00
Xylemon c8ac0d596b spawn.qc remove this hack (for scientist hunt and other team mods) 2023-04-27 01:18:26 -07:00
Xylemon 422e57d3d8 weapon_gauss: Add special effect for overcharge, fix a mistake with overcharge damage, update gauss to use new weapon sound API 2023-04-26 17:33:12 -07:00
Xylemon 15e93d619b weapon_gauss: Secondary fire improvements
- move around velocity code so it's predicted and simpler, since we can't read gamerules here a simple MP check will do for now @eukara
- make sure we fire immediately if we release secondary fire after first spin cycle, with these changes the gauss should be nearly identical to Half-Life, minus the OP damage @xylemon
2023-04-25 23:51:18 -07:00
Xylemon 4d111ed96e Temp fix so snark doesn't do this hilarious bug anymore 2023-04-24 22:40:13 -07:00
Marco Cawthorne c68d2d7c60
Tweak the UI color defaults a little. 2023-04-03 11:16:44 -07:00
Marco Cawthorne 30ecbd1453
Multiplayer: Load and display a server message of the day if present. 2023-03-25 17:34:26 -07:00
Marco Cawthorne 8dc3da6aac
Add zpak001.pk3dir/sound/func_plat.sndshd 2023-03-25 17:33:41 -07:00
Marco Cawthorne e935029c3f
Remove install_shareware_data.sh 2023-02-20 12:54:11 -08:00
Marco Cawthorne 2daaf2b1ad
Client: use frametime over clframetime for the bob. 2023-02-17 12:24:51 -08:00
Marco Cawthorne 7d58725d76
PMove: change maxspeed to 270 for the time being, as that's the default for MP anyway. 2023-02-16 18:23:48 -08:00
Marco Cawthorne 9f9dd78458
Fix compiler warnings. 2023-02-14 12:54:45 -08:00
Marco Cawthorne 07453056a4
Remove dependency from base/src. 2023-02-12 12:54:57 -08:00
Marco Cawthorne 3a37d21257
item_pickup: Call respawn item sound in a separate method for sanity's sake 2023-02-07 17:35:47 -08:00
Marco Cawthorne 22d5b36d1c
Server: Shuffle some code inside the monster files around so that we re-set starting values after all constructors have executed 2023-02-07 09:08:55 -08:00
Marco Cawthorne c8397d2474
Client: clamp the armor subpic size to 1.0 (fixes graphical artifacts in TFC) 2023-02-07 09:08:00 -08:00
Marco Cawthorne dfeff42e6a
WEAPON_TRIPMINE: use Destroy() instead of remove() 2023-01-17 22:03:39 -08:00
Marco Cawthorne ed30225de7
ITEM_SUIT: destroy when we're running on game 'bshift' 2023-01-17 22:03:29 -08:00
Marco Cawthorne e152392132
Client: don't dictate g_hud_color when in TFC 2023-01-17 22:02:06 -08:00
Maxwell 4c1d6569a9 Made Gauss jumping MP only. 2023-01-17 18:39:18 -05:00
Maxwell 96324141cb Added Crossbow bolt trail on explosive MP bolt akin to Turok. This change is based upon documented cut content 2023-01-17 16:51:06 -05:00
Marco Cawthorne 0452916719
Client: add a vertical camera bobbing effect. 2023-01-12 16:50:37 -08:00
Marco Cawthorne bef240a1de
HLMultiplayerRules: add PlayerRequestSpawn method override 2023-01-11 18:04:17 -08:00
Marco Cawthorne 70167ed233
Removal of Game_Input which has been made obsolete. 2023-01-11 17:44:32 -08:00
Marco Cawthorne 22b5c6a84f
oops, finger slipped... 2023-01-10 10:08:01 -08:00
Marco Cawthorne 3b659fbddf
install_shareware_data.sh: exit early with return code 0s 2023-01-10 09:32:22 -08:00
Marco Cawthorne 7637686ace
input: add a hacky quick-respawn (needs proper multiplayer separation...) 2023-01-07 17:00:34 -08:00
Marco Cawthorne 3db04eb85b
monster_snark: run physics using point sized bbox 2023-01-07 16:59:59 -08:00
Marco Cawthorne e1d7febbf7
default.cfg: Set rate to '30000' in the hope of override outdated defaults 2023-01-07 16:59:43 -08:00
Marco Cawthorne 9e62ff350a
WEAPON_RPG: Gives 2 rockets on pickup. 2023-01-06 13:00:43 -08:00
Marco Cawthorne 512b1ac2ee
manifest.fmf: load ffmpeg plugin by default and override default chatroom name. 2023-01-05 23:36:14 -08:00
Marco Cawthorne 9544c98f04
Slight cleanups and cvar changes. 2023-01-05 23:35:43 -08:00
Marco Cawthorne 8652d02464
WEAPON_SATCHEL: Dropp satchel bbox causing issues, so compromise: make it thin, but retain the same height. 2023-01-05 23:33:33 -08:00
Marco Cawthorne 5a900bc834
manifest.fmf: set chatroom to 'halflife' 2022-12-30 12:09:44 -08:00
Marco Cawthorne 7c94b26fc8
Client: Use the new Crosshair drawing functions to help with cl_thirdperson and remove
obsolete routines.
2022-12-28 16:50:29 -08:00
208 changed files with 12998 additions and 8430 deletions

View File

@ -11,29 +11,29 @@ are present.
This is 100% original code, feel free to audit however you wish.
No proprietary SDKs have been looked at or taken apart, unlike similar projects.
The engine you want to use to run this is FTEQW (https://www.fteqw.org), which is a project
unrelated to this. It just happens to support the file-formats FreeHL needs.
![Preview 1](img/preview1.jpg)
![Preview 2](img/preview2.jpg)
![Preview 3](img/preview3.jpg)
![Preview 4](img/preview4.jpg)
## Installing
To run it, all you need is [FTEQW](https://www.fteqw.org) and [the latest release .pk3 file](https://www.frag-net.com/pkgs/package_valve.pk3), which you save into `Half-Life/valve/`. That's about it. You can install updates through the **Configuration > Updates** menu.
## Building
Clone the repository into the Nuclide-SDK:
Clone the repository into the Nuclide-SDK and build it:
> git clone REPOURL valve
```
$ git clone https://code.idtech.space/fn/valve valve
$ SKIP_UPDATE=1 SKIP_RADIANT=1 ./build_game.sh valve
```
then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside
./valve/src!
Obviously make sure that Nuclide has fteqw and fteqcc set-up for building and that you have some proficiency in QuakeC.
You can also issue `make` inside `valve/src/`, but it won't build an `entities.def` file for use in Radiant (level editor family).
## Notes
If you're playing a mod that relies on FreeHL, selecting it from the Custom Game
menu alone works fine. However if you want to launch it via the command-line
you need to make sure to add `-game valve` before `-game modname`.
The order is important.
The engine should automatically detect Half-Life when placed within the game directory, however you may need to pass `-halflife` just in case you have one massive directory with multiple FTE-supported games in it for example.
You can also launch mods like this: `fteqw -halflife -game cstrike`
Useful for development, so you don't always have to use the **Custom Game** menu.
## Community
@ -48,10 +48,18 @@ and other such things. It's bridged with the Matrix room of the same name!
### Others
We've had people ask in the oddest of places for help, please don't do that.
## Special Thanks
- Spike for FTEQW and for being the most helpful person all around!
- Xylemon for the hundreds of test maps, verifying entity and game-logic behaviour
- Theuaredead`, preston22, dqus for various patches
- To my supporters on Patreon, who are always eager to follow what I do.
- Any and all people trying it, tinkering with it etc. :)
## License
ISC License
Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
Copyright (c) 2016-2024 Marco Hladik <marco@icculus.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

202
install_from_cd_goty.sh Executable file → Normal file
View File

@ -1,137 +1,95 @@
#!/bin/sh
# I mean... this sucks, I get it - but sadly we have to use Wine for this
# because no one has made an installer extractor for Wine that works on
# Linux. Sorry.
# all new script that dumps the Half-Life: Game of the Year edition
# data onto your hard disk. make sure you have the CD-ROM inserted!
# builds a pk3 file that's alphabetically sorted
mk_pk3()
{
tree -fi > ./build_contents.txt
sed -i '/build_contents/d' ./build_contents.txt
sed -i '/directories,/d' ./build_contents.txt
zip -0 "$1".pk3 -@ < ./build_contents.txt
rm ./build_contents.txt
mv "$1".pk3 ../"$1".pk3
}
# pass HLDIR to tell it where to put the Half-Life files to.
# e.g. HLDIR=/tmp/Half-Life
# otherwise, it'll put it into the parent dir, of the working directory.
SCRPATH="$( cd "$( dirname $(readlink -nf $0) )" && pwd )"
OUTPK3DIR="pak01_retail.pk3dir"
# pass TMPDIR to tell it where to put temporary install files to.
# e.g. TMPDIR=/tmp/gotycd
# otherwise, it'll put it into the current working directory.
if ! [ -x "$(command -v wine)" ]; then
printf "Error: wine is not installed.\n" >&2
exit 1
set -e
SETUP_SHA256="3b2b35e27aa7c54bedd39dd0074193dfcba9a3054623e93fc29f8f71779b082b"
TMPDIR="$(pwd)/tmp"
# allow user override
if [ -z "$CDROM_PATH" ]
then
CDROM_PATH="/mnt/cdrom"
SETUP_FILE="$CDROM_PATH/setup.exe"
fi
if [ -z "$HLDIR" ]
then
HLDIR="$(pwd)/.."
fi
if [ -z "$TMPDIR" ]
then
TMPDIR="$(pwd)/tmp"
fi
if ! [ $# -gt 0 ]; then
printf "Path to MOUNTED CD-ROM folder, e.g. /mnt/cdrom:\n"
read CDROM_PATH
if [ "$1" = "-h" ]
then
printf "%s help\n\n" "$(basename $0)"
printf "pass HLDIR to tell it where to put the Half-Life files to.\n"
printf "e.g. HLDIR=/tmp/Half-Life.\n"
printf "otherwise, it'll put it into the parent dir, of the working directory\n\n"
printf "pass TMPDIR to tell it where to put temporary install files to.\n"
printf "e.g. TMPDIR=/tmp/gotycd.\n"
printf "otherwise, it'll put it into the current working directory.\n\n"
printf "HLDIR will require at least 356M disk space.\n"
printf "TMPDIR will require at least 462M disk space.\n"
exit 0
fi
if [ ! -x "$(command -v rewise)" ]
then
printf "rewise is not present. please build it and place it in PATH.\n"
printf "src: https://notabug.org/CYBERDEViL/REWise\n"
exit 2
fi
if [ ! -f "$SETUP_FILE" ]
then
printf "Please mount the Game of the Year edition CD-ROM.\n"
exit 2
fi
if [ -x "$(command -v sha256sum)" ]
then
CHECK=$(sha256sum "$SETUP_FILE" | awk '{ print $1 }')
elif [ -x "$(command -v sha256)" ]
then
CHECK=$(sha256 -q "$SETUP_FILE")
else
CDROM_PATH="$1"
printf "No tool to validate sha256 sums with!\n"
exit 2
fi
if ! [ -f "$CDROM_PATH"/setup.exe ]; then
printf "Error: install.EXE not found in $CDROM_PATH.\n" >&2
exit 1
if [ ! "$CHECK" = "$SETUP_SHA256" ]
then
printf "%s checksum mismatch.\n" "$SETUP_FILE"
exit 2
fi
# Set up a prefix that's 32-bit inside
export WINEPREFIX="${SCRPATH}/prefix"
export WINEARCH=win32
DATA_PATH="${WINEPREFIX}/drive_c/Sierra/Half-Life/"
# No pak0 present
if ! [ -f "$SCRPATH/pak0_cd.pk3" ]; then
# Check if we need to install the content, or throw a warning.
if ! [ -f "$SCRPATH/$OUTPK3DIR/liblist.gam" ]; then
# May already have been extracted here (debug)
if ! [ -f "$DATA_PATH"/hl.exe ]; then
# Because /x does NOT preserve directories.
wine "$CDROM_PATH"/setup.exe /s
fi
# Transplant the pak0.pak out of the data dir
if ! [ -f "$SCRPATH/pak00_cd.pak" ]; then
mv "$DATA_PATH/valve/pak0.pak" "$SCRPATH/pak00_cd.pak"
fi
# Move valve to become OUTPK3DIR
mv "$DATA_PATH/valve" "$SCRPATH/$OUTPK3DIR"
# Logos need to be in the game-dir
mv "$DATA_PATH/logos" "$SCRPATH/$OUTPK3DIR/logos"
else
printf "$OUTPK3DIR already exists... everything okay?\n"
fi
# Make the pk3 archive
cd "$SCRPATH/$OUTPK3DIR"
mk_pk3 pak01_cd
if [ -d "$TMPDIR" ]
then
rm -rf "$TMPDIR"
fi
# Make sure we're back in here
cd "$SCRPATH"
mkdir -p "$TMPDIR"
rewise -x "$TMPDIR" "$SETUP_FILE" &> /dev/null
# check if we need an icon.tga
if ! [ -f "$SCRPATH/icon.tga" ]; then
# imagemagick will help us get our icon
if [ -x "$(command -v convert)" ]; then
printf "Detected ImageMagick's convert... giving you a nice icon!\n"
convert "$DATA_PATH/valve.ico" "$SCRPATH/valve.tga"
rm "$SCRPATH/valve-0.tga"
rm "$SCRPATH/valve-1.tga"
rm "$SCRPATH/valve-3.tga"
mv "$SCRPATH/valve-2.tga" "$SCRPATH/icon.tga"
else
printf "No ImageMagick found... can't give you a window icon then.\n"
fi
fi
# Make sure we're back in here
cd "$SCRPATH"
printf "All done. Would you like to rip the the Compact Disc Digital Audio for music?\ny/n: "
read CHOICE
if [[ "$CHOICE" == [Yy]* ]]; then
# check if we require rippin tunes
if ! [ -f "$SCRPATH/music/track02.wav" ] && ! [ -f "$SCRPATH/music/track02.ogg" ]; then
if [ -x "$(command -v cdparanoia)" ]; then
mkdir -p "./music"
cd "./music"
cdparanoia -B
rename ".cdda." "." *.wav
# Maybe the user does not have the physical disc and cdp fails.
if [ -f "$SCRPATH/music/track02.wav" ]; then
# I'd offer FLAC, but that also requires the ffmpeg plugin
if [ -x "$(command -v oggenc)" ]; then
printf "All done. Would you like to convert them to OGG for playback compatibility\nas well as space preservation (frees up ~330 MB)?\ny/n: "
read CHOICE
if [[ "$CHOICE" == [Yy]* ]]; then
oggenc *.wav
rm *.wav
fi
fi
fi
else
printf "cdparanoia is missing. Cannot rip music.\nPlease run the installer again once you've got it installed.\n"
fi
else
printf "Music was already present.\n"
fi
fi
cd "$SCRPATH"
# Grab patches, GOTY is at 1.1.0.6
grab_patch()
{
wget -nc -O ./pak$2.pk4 http://archive.org/download/hl_shareware_data/valve/$1.zip
}
grab_patch 11071108 14_1108
grab_patch 11081109 15_1109
grab_patch 11091110 16_1110
# Be real careful here
rm -rfv "./$OUTPK3DIR"
rm -rfv "./prefix"
# traverse the tmpdir, move files into the output location
while read LINE
do
FILE=$(printf "$LINE" | awk '{ print $2 }')
TMPFILE="$TMPDIR/MAINDIR/$FILE"
mkdir -p "$HLDIR/$(dirname $FILE)"
cp "$TMPFILE" "$HLDIR/$FILE"
done < "install_from_cd_goty.sha256"

103
install_from_cd_goty.sha256 Normal file
View File

@ -0,0 +1,103 @@
4d86a3362c721e0e63a1a5426e65d001945ad910e4450ca281c72c2eb3835b14 valve/gfx/shell/cb_checked.bmp
3733d610783c5bb34e00063746452037de0ac169ba9de932bfea59b351c3e4b2 valve/gfx/shell/cb_disabled.bmp
5c6ec4c93db93690bcb1df918569afea0171cc276a26f6ffa32d77e8c07cd46b valve/gfx/shell/cb_down.bmp
e7ab820798e6a0a93a7b9c3e82d192b5a20740495d18e7f4c634a57e7342d938 valve/gfx/shell/cb_empty.bmp
7647a8ec321f65fc937bf2cd2d772c6f9c4fbbb06aac62bf0b1dfb0aa9b60978 valve/gfx/shell/cb_over.bmp
f0c864ce1549d0530b8a0b5a6b9d62fee8ee507004dd7dd6fe97c070d5a58687 valve/gfx/shell/cls_d.bmp
41d9c63adfa1ed4071b91969ce3c02dc49fe5c6c3d2b4dad62283e57e1c7153e valve/gfx/shell/cls_f.bmp
637052253efb9d8ee007550419f9ff3f22ee29242d1f5e6e2d02afdd7a836c62 valve/gfx/shell/cls_n.bmp
f2c0923674e31c03d77f6687d8237f0c6e7b429c39b92cac5c46dd91297f6091 valve/gfx/shell/Colors.lst
d2bc816cdea1c1dc4a1786cde28e191a89c93ef3127c64400017903356fa1f1a valve/gfx/shell/dedicate.bmp
0b1de714c26bf1b1eef29c79996ab2acb6857cc76ba057f4a649baf32604dff4 valve/gfx/shell/dnarrowd.bmp
c07158f47c21faea540f003a5e81245e10c53df768bd3d9f4fc6f48f12707bed valve/gfx/shell/dnarrowf.bmp
cb22c16041c8194bec6afbeb19a55778ead6ab204a6b37c2b5b961436de762de valve/gfx/shell/dnarrowp.bmp
486279aa9f8af9987bde2b11e4000535304e784bd5ffdec2f5701afbe2ec4420 valve/gfx/shell/down.bmp
1d6dbe71ac9cc99a51a8d2fe00b1fbe42b11fbae5202b460a6592172a82f9058 valve/gfx/shell/favorite.bmp
b1e9f6b602109815fe398b45d4b6d6d479f53bd693ef88be27a98861932ff649 valve/gfx/shell/kb_keys.lst
f318d94070fa71ce4b8e6dee3c6913ab55db8d60b1cedeeb30449742e424a448 valve/gfx/shell/larrowdefault.bmp
83eebb65a6b2154ef373cb294363a3fcd2d68a5cde92e81fc445f075463a7627 valve/gfx/shell/larrowflyover.bmp
a63070cd328b3a5080578eaaea957d71aea24ed636d978e0ed70f442973a9969 valve/gfx/shell/larrowpressed.bmp
d204fabc1c3551bf67df38c8e5a31348d849262e7c67cd5bcd8d56dccb4004d2 valve/gfx/shell/linux.bmp
fbebef999e158ea5169825193ee5dc584caee5f609bd6ec447ea8fe49261f18a valve/gfx/shell/listen.bmp
0fc66cbb649d0ebc3ea3933aa9db40b28f334cf831ec7e76e2c10bf5ca6827fc valve/gfx/shell/lock.bmp
e931c1448be432e20a32b02a61a54ad6af829d3530379dd6baa2a4a2712ea8d0 valve/gfx/shell/min_d.bmp
6a41babaaf746a51ebd4544365f4a93ad209d41d301ed0306b8a212efd4fc983 valve/gfx/shell/min_f.bmp
40c068d930dfb672abfc91c7bd843acaec705d00604f3985db5401272a48e7da valve/gfx/shell/min_n.bmp
ab79f35bb12d7350a78f53929a7a05c87a6fd2e02b02d219b2c4b83a464b842b valve/gfx/shell/nonfav.bmp
54fb2ec5692d5d8447c96d6a70eb86058aba853d77bd7586fe024ae081feffe9 valve/gfx/shell/pcg.bmp
cc2c5f55d07faa26bd4ea55d5b5430f6797447bfeb372727d25888ebd7e42623 valve/gfx/shell/rarrowdefault.bmp
bf8c3bfb1bce4a51f1935769891f2ab314eecbbabc175711a349d70e6f2eb85e valve/gfx/shell/rarrowflyover.bmp
107542508bde0517ab1752cd6d0620656f8cc89f3f106b157dceb5d77b98949b valve/gfx/shell/rarrowpressed.bmp
daff5568f611fc027fc3fa82f64dc6c39fcd78d68381a8ae0740207d297c2852 valve/gfx/shell/slider.bmp
c59ec9ce1c81049386024358148f0296cb3d7e77968cf95c075bcbf36040b168 valve/gfx/shell/sm_dnarf.bmp
13a05e5260cd7ccaa62e1f70dbc73c591d7586affe7be8021907dbcae52d59e0 valve/gfx/shell/sm_dnarw.bmp
1ed59029bcbfa703af000dd8277746ad876218d37d8f99a2fc39866c6d4262d5 valve/gfx/shell/thumb.bmp
bcf5ed86e9d724e1601cb06e5bd8b027f9e215c42610b865e8101676c877a431 valve/gfx/shell/unlock.bmp
15473ef64c4dbcd3650ab2416dacde36afc8680de40ca2589562580cd7834f40 valve/gfx/shell/up.bmp
1482d4dadf5025de843eb0186771fcac3ee469cf7b01df51c82038ed44658334 valve/gfx/shell/uparrowd.bmp
7c15f1e4e9b405c173c6515e982815d5d31e142414bf2bd63d0c714a9ef2599b valve/gfx/shell/uparrowf.bmp
d6456543c2bcd2f408a218e4d2a034430b7ab6c9cdf2fa0f5866f4eca2289fe0 valve/gfx/shell/uparrowp.bmp
ba236c88bf2927f8582be9a587dbb51908a484fd88ef51b1200f4f1f2705cead valve/gfx/shell/windows.bmp
ba48340d3cd52d785b04505848b458bb81d5264eb41c23420c20ecf16cb597fc valve/gfx/shell/btns_main.bmp
080795bb1c4cdb225f1d49e0c9ce9e598c7141a0aa8726324c8a17f4720d6aae valve/gfx/shell/head_advoptions.bmp
aed37bc448e2128d35c21264352d59ece99c524a992260eb13fe3c15a1fdf9b2 valve/gfx/shell/head_custom.bmp
8ea4cdb4636392a31fd1fabb9ff4d1e2c0a64270867c898bbaf88f12b42dcc4d valve/gfx/shell/kb_act.lst
1a09320c1bec4d1ec2c7bceb9b481494a72651c5b01f292fa25439b999893583 valve/gfx/shell/kb_def.lst
5768afa6d5852d71d2551319ee8a62200592e9ae5e2a62dc4d921da2a23b7cd9 valve/gfx/vgui/mouse.tga
96d9fb3d9ac5201d0ad134e487994e9a8645c4e76299b018b437b7bb268fafa3 valve/models/player/barney/barney.bmp
8bba02d6801db546259e8ee20847a4d3e96f2a1d60fa043f26ec9d3224bf6bea valve/models/player/barney/barney.mdl
3c246c9b1d0c187b733c25c617eed8e9e6bf16820dea612a3e7305a045a291f4 valve/models/player/gman/gman.BMP
3870ed2fd72487c0c34490f97c2b358454be78efd2549002bb762189d9fc965a valve/models/player/gman/Gman.mdl
f8f6058119a63f7829aaf8a4e7438a47bdd98a4cafea9333bd60470709ffc532 valve/models/player/hgrunt/hgrunt.bmp
5fee8caae9095361aa534cc6f6b0f2895c9da2387fc6edbc6a3fbaf9e1007057 valve/models/player/hgrunt/Hgrunt.mdl
c11f8a98985c4691254b03c2fdbdc875c3331a071828d4d39cfa27d8fbf8a4fd valve/models/player/recon/recon.bmp
76e20d4bea5867280333995805f08b494b0aa7e116db316746df771b6621cb94 valve/models/player/recon/recon.mdl
bea7d0ee672e6356ef62d6027474dd27fc03696e9d6bea82e48a7e326e88286c valve/models/player/robo/Robo.bmp
c929fd09db1075194e4644acc0ed41a4278eba12f86cc24d1f8fc29d0b90bec1 valve/models/player/robo/robo.mdl
08865ba940e8fa88df5fa2232fa17d229131b2e1791d785ea7fbcacee14ee15d valve/models/player/zombie/zombie.bmp
a73009e66baf727ff4fecf715a36d36567a8cea633207f343d0792a8ba2b27e0 valve/models/player/zombie/zombie.mdl
bd8cc2e5f111735bc3e1a051f97075d9a1804c8e98692e3a868857e95e23a232 valve/liblist.gam
efce3f5735ffb05ccf493c980bd61b774e43ce37ec12c0402d43400e07a6743e valve/mapcycle.txt
cd36d358e0a0ab5f654816a0e3d606e1267aa6014ff9f11462b3b4ede5f59487 valve/profile.lst
521849d70e2a7927e119e8c1fd438f4d43a80a68f447b4f1e85a01eea4f6b734 valve/rooms.lst
837091d76e885116a38949012bbbc99d2a5d46438586e76c6983c3a02a21d008 valve/settings.scr
0c47a50f4970a65b05914cb758e6f47f9f0d45a7e7d85076aef94a1d48d80d92 valve/titles.txt
1a5071189aa2596d488e3801c63b1e742cddd1f49da0f06c30643f40b641d020 valve/user.scr
5b1b2dd68c2ff1fc6cda3f415cfa7087884ca075c371574aa19c1e4474c4d540 valve/valve.rc
6222243e0839022f3041e6b9e97776ce54d0cf87d4c3810e627b8b2815b555f5 valve/maps/crossfire.bsp
752abc65a1bef9755efe9b0177f932cd9d617a59bffd43aed330076ca5c7f5cc valve/maps/frenzy.bsp
c96d75b16d8507dc996c49294aeda8bb7d5279a5930576aa5b6494e89d07f9bc valve/maps/rapidcore.bsp
3a8178df0cda00bf44bf7982ac5f260ba4335bc661da83a06ee99faa379f530b valve/media/launch_deny1.wav
98e2d0a6c5a8c0adf9f75bdbe627b433d36d2d9c26a7b7843fe8ea892b6d7356 valve/media/launch_deny2.wav
4bbc4680030a300fc535279ab08362e5b5ded8189065f852b3b78052ddfd11bf valve/media/launch_dnmenu1.wav
5140ee43c6ba8cfab956c405f22f4ec989f427305d5b921be115b2c789451b3f valve/media/launch_glow1.wav
894ef53ebfaad82a3b2c900b4d2eff5ba4e8fdf1ee339cdbb2e82f6e614fb1df valve/media/launch_select1.wav
bb580215824dd89825f114f4fbe5514f0e9783a1ca7bb7aed2376fadc349b6aa valve/media/launch_select2.wav
913ead8450ba2e23c2b10aad5bf29ba923f21fb1ba58943044081a7938ddf915 valve/media/launch_upmenu1.wav
89eea4b29e3c5272a688e1a42db8a17f6b878c805ffea467edb1e5ad03b47f3d valve/media/logo.avi
f3429e06124e28f6a69e6ef6bcb89d22103612158de6a0f8348725be1e9ea4b3 valve/media/sierra.avi
4ce170dfa11f980075f8b6a8a85c3cf78eb59f8766a26b721bff0910ad3baf2d valve/media/valve.avi
a03140547f462ff1e593ed91b29c34ba712f348f866bc8947bdd05bc84e61f6c valve/pak0.pak
ccd07f0ddf0226f3207d4f36603ff4065b0e798e0dfcf4ff69c24aec0d2ee91a valve/sprites/hud.txt
7c6d3b5719cadce1f5ea55df021c4e5941c55d550e0686bb03a5ac78f0c350bc valve/sprites/shellchrome.spr
b9ac3a6c455fa54a11d4f00f8248909800b8b19f84e84bb35e826e4c137f262d valve/cached.wad
17726e8174729011c7ea4e1e37b4ccfe7a9aa4abb82c2aaca87872cbe0c106d0 valve/decals.wad
d6989bb9fc90c437f9957cc7bceb8f2550b38b8791df679753b7c08c98632b80 valve/fonts.wad
6fd53d6ef8d704299734018e3069ec12551e7fb2065804a1d4e5c936ac4033bd valve/gfx.wad
38ababf773463fdf6133005d13e543098fc42392b458057f239469b764691300 valve/halflife.wad
0f5c3ae49af4e72f4f26752c1fd5dfbea8f88859f1097badf8733fa6093a8f95 valve/liquids.wad
bff7ad40b9b6ff446d56cf3fd05fd2e50c8d8d186dade45549e3313680815e82 valve/spraypaint.wad
d63e152db6d950f671356c4da0d8a1966e0d940a2166b61678e3a6d46644cd7c valve/xeno.wad
9f5a3aa0b49609b6461593f2d1af0e7deb6e2c6883a114487a96c7b61b0fced8 logos/8ball1.bmp
f35918394959002e44919b9b4c090630e0dd807154a8dd8b28896f13c88faf4a logos/andre.bmp
49a9549f6ef5b5c578609a5f291119b97571e669db4fb2b7d22b6a8a23ec1143 logos/camp1.bmp
30540cce8c36b0cd8b2f5d0790288c82175096d0236d24f47c8b6a591385cf41 logos/chick1.bmp
88bc2cd2dac6482c37132b691e2039dc793da95a1e7a548210682b56b52374c2 logos/chuckskull.bmp
a03bb48e4599c5c1d15554119db31622a53bb9989e5b51d27f835ff70b40dcc8 logos/devl1.bmp
93ad5c9ac6af96dca019c59b2832c3d90b9db7ee7615a6d1d93d260f8f3ae240 logos/gun1.bmp
1af36b03a2df6da208575c6a54fa8244f7c7ab8c1ad4b1d2208ef0c28e94715d logos/lambda.bmp
b8471cb9c6a85760cfbf29b814a168a37532e98e125485c3357dff31cfe8bd42 logos/skull.bmp
fed3427703ddee0a8e0ec08e645eaf039f97d4e42c3a48241ae1791188ad00ec logos/smiley.bmp
1734d46ebe96c82da9107db988727f78218f7f7d417a268d4dca38941dc7852f logos/splatt.bmp
555eb2ffe4789715c488a5b1298cbddbe807619a58201afd0f3e10074744cc33 logos/tiki.bmp
81cf60e1eed45acb0160374a78f0398e5005e5328e071b4692dcfdbd3175a65b logos/v_1.bmp

View File

@ -1,107 +0,0 @@
#!/bin/sh
# grabs a patch .zip from archive.org and saves it as a pk3
grab_patch()
{
wget -nc -O ./pak$2.pk4 http://archive.org/download/hl_shareware_data/valve/$1.zip
}
# grabs a song on YouTube and stores it in OGG vorbis format
yt_grab()
{
echo "Grabbing the official music track for Track $2..."
yt-dlp -o track$2.ogg --extract-audio --audio-format vorbis https://www.youtube.com/watch?v=$1 &> /dev/null
}
SCRPATH="$( cd "$( dirname $(readlink -nf $0) )" && pwd )"
if ! [ -x "$(command -v wget)" ]; then
printf "Error: wget is not installed.\n" >&2
exit 1
fi
cd "$SCRPATH"
# Get the latest patch, because that'll fix the menu assets and add more fun, free content
echo "============================================================="
echo "Downloading data for Half-Life: Day One"
echo "This was a free demo that let you experience the first 'day'"
echo "at Black Mesa. It contains earlier data than the CD release."
echo "============================================================="
grab_patch dayone 00_dayone
echo "============================================================="
echo "Downloading data for Half-Life: Uplink"
echo "A demo containing a whole new chapter that was not present"
echo "in the CD release. It is newer than the CD disc pressing."
echo "============================================================="
grab_patch uplink 01_uplink
echo "============================================================="
echo "Downloading data for Half-Life from the RealMedia TFC demo"
echo "The freeware version of Team Fortress Classic put out by"
echo "RealMedia contained some Half-Life data we can make use of."
echo "============================================================="
grab_patch realmedia 02_realmedia
echo "============================================================="
echo "Downloading data for Half-Life from the Opposing Force demo"
echo "The demo of Half-Life: Opposing Force contains additional"
echo "data we can make use of to complete our data collection."
echo "============================================================="
grab_patch opfordemo 03_opfordemo
echo "============================================================="
echo "Downloading data for Half-Life Patch 1.1.1.0"
echo "This patch data contained updates to menu graphics, maps"
echo "and more for an enhanced multiplayer experience."
echo "============================================================="
grab_patch patch1110 04_patch1110
echo "============================================================="
echo "Downloading data for Half-Life's Dedicated Server"
echo "While this dataset contains no client-side game data, it"
echo "makes up for it in server-side content."
echo "============================================================="
grab_patch hlds 05_hlds
# Valve once had music tracks available on YouTube, however due to rights
# issues this is no more. As I'm not comfortable with unofficial uploads
# due to the nature of this project, this ends here.
exit 1
if ! [ -x "$(command -v yt-dlp)" ]; then
printf "Error: yt-dlp is not installed.\nUnable to download music\n" >&2
exit 1
fi
cd "$SCRPATH"
mkdir music
cd music
yt_grab lx1qQOeMk10 02
yt_grab 8KxNBtMjSlk 03
yt_grab 4c-R_KBuZ2A 04
yt_grab iUaNjxlBMNs 05
yt_grab YlLg-UAgZBY 06
yt_grab LJ3XN8yiE3A 07
yt_grab aBYdo8aeico 08
yt_grab EkX_4HsrYXQ 09
yt_grab GXc-Qk6YlGI 10
yt_grab DdcdeS9kzFo 11
yt_grab Zy0mdIS04sw 12
yt_grab qwP2QPzBI4Q 13
yt_grab 3BkG2pi8OAU 14
yt_grab VAJzipo22L8 15
yt_grab dvxX42uczNU 16
yt_grab 8xmJmGYbHd0 17
yt_grab itvxpfCep_4 18
yt_grab -iYoXSw7aek 19
yt_grab jp6tXuGnE10 20
yt_grab DQcvP-2L9KQ 21
yt_grab w3ctKDiYHpE 22
yt_grab Op__51Bngjg 23
yt_grab l2EKVHKiVfk 24
yt_grab 7bywJmv8tvQ 25
yt_grab fEFW2ha-ZYE 26
yt_grab FupijP4YUw8 27
yt_grab 9XuTPUi4-A4 28

View File

@ -1,13 +1,19 @@
FTEMANIFEST 1
GAME valve
NAME "Half-Life"
BASEGAME platform
FTEMANIFEST 1
GAME valve
NAME "Half-Life"
BASEGAME platform
BASEGAME valve
// you don't really want to change these
RTCBROKER master.frag-net.com:27950
PROTOCOLNAME "FreeHL"
MAINCONFIG game.cfg
DOWNLOADSURL "http://www.frag-net.com/dl/packages"
-exec platform_default.cfg
// you don't really want to change these
RTCBROKER master.frag-net.com:27950
PROTOCOLNAME "FTE-HalfLife"
MAINCONFIG game.cfg
DOWNLOADSURL "http://www.frag-net.com/dl/packages"
-exec platform_default.cfg
// load ffmpeg for the logo.avi file
-plug_load ffmpeg
// override some liblist.gam entries
-set gameinfo_chatroom "halflife"

26
radiant.game Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<game
type="hl"
name="Half-Life"
enginepath_linux="/usr/local/games/halflife/"
enginepath_win32="c:/sierra/half-life/"
engine_win32="hl.exe"
engine_linux="hl_linux"
basegame="valve"
basegamename="Half-Life"
unknowngamename="Custom Half-Life modification"
default_scale="1.0"
no_patch="1"
no_bsp_monitor="1"
show_wads="1"
archivetypes="pak wad"
texturetypes="tga jpg mip hlw"
modeltypes="mdl"
maptypes="mapq1"
shaders="quake3"
entityclass="quake3"
entityclasstype="def xml"
entities="quake3"
brushtypes="quake"
patchtypes="quake3"
/>

76
radiant.xml Normal file
View File

@ -0,0 +1,76 @@
<?xml version="1.0"?>
<!--
to avoid naming conflicts, the tools are assumed to be named 'hlcsg', 'hlbsp', 'hlvis' and 'hlrad' in your path
-->
<project version="2.0">
<var name="csg">"hlcsg"</var>
<var name="bsp">"hlbsp"</var>
<var name="vis">"hlvis"</var>
<var name="light">"hlrad"</var>
<var name="qbsp">qbsp -hlbsp -basedir "[EnginePath]" -gamedir "[GameName]" -path "[UserEnginePath]"</var>
<var name="qvis">qvis -basedir "[EnginePath]" -gamedir "[GameName]" -path "[UserEnginePath]"</var>
<var name="qlight">qlight -basedir "[EnginePath]" -gamedir "[GameName]" -path "[UserEnginePath]"</var>
<build name="extra fidelity">
<command>[csg] "[MapFile]"</command>
<command>[bsp] "[MapFile]"</command>
<command>[vis] -full "[MapFile]"</command>
<command>[light] -extra "[MapFile]"</command>
</build>
<build name="standard fidelity">
<command>[csg] "[MapFile]"</command>
<command>[bsp] "[MapFile]"</command>
<command>[vis] "[MapFile]"</command>
<command>[light] "[MapFile]"</command>
</build>
<build name="quick compile">
<command>[csg] "[MapFile]"</command>
<command>[bsp] "[MapFile]"</command>
<command>[vis] -fast "[MapFile]"</command>
<command>[light] -fast "[MapFile]"</command>
</build>
<build name="fast vis only">
<command>[csg] "[MapFile]"</command>
<command>[bsp] "[MapFile]"</command>
<command>[vis] -fast "[MapFile]"</command>
</build>
<build name="no vis, no lighting">
<command>[csg] "[MapFile]"</command>
<command>[bsp] "[MapFile]"</command>
</build>
<build name="only entities">
<command>[csg] -onlyents "[MapFile]"</command>
<command>[bsp]"[MapFile]"</command>
</build>
<!--
in case you want to use free-software tools
-->
<build name="tyrutils extra fidelity">
<command>[qbsp] "[MapFile]"</command>
<command>[qvis] "[MapFile]"</command>
<command>[qlight] -extra "[MapFile]"</command>
</build>
<build name="tyrutils standard fidelity">
<command>[qbsp] "[MapFile]"</command>
<command>[qvis] "[MapFile]"</command>
<command>[qlight] "[MapFile]"</command>
</build>
<build name="tyrutils quick compile">
<command>[qbsp] "[MapFile]"</command>
<command>[qvis] -fast "[MapFile]"</command>
<command>[qlight] -fast "[MapFile]"</command>
</build>
<build name="tyrutils fast vis only">
<command>[qbsp] "[MapFile]"</command>
<command>[qvis] -fast "[MapFile]"</command>
</build>
<build name="tyrutils no vis, no lighting">
<command>[qbsp] "[MapFile]"</command>
</build>
<build name="tyrutils only entities">
<command>[qbsp] -onlyents "[MapFile]"</command>
</build>
</project>

View File

@ -45,7 +45,7 @@ Camera_RunBob(__inout vector camera_angle)
pCamBob->m_flTime = 0.0f; /* progress has halted, start anew */
return;
} else if (pSeat->m_ePlayer.flags & FL_ONGROUND) {
pCamBob->m_flMove = clframetime * (pCamBob->m_flSpeed * 0.01);
pCamBob->m_flMove = frametime * (pCamBob->m_flSpeed * 0.01);
}
pCamBob->m_flTime = (pCamBob->m_flTime += pCamBob->m_flMove);
@ -77,3 +77,15 @@ Camera_StrafeRoll(__inout vector camera_angle)
camera_angle[2] += roll;
}
float Viewmodel_GetBob(void);
/* tilts the camera for a head-bob like effect when moving */
void
Camera_RunPosBob(vector angles, __inout vector camera_pos)
{
int s = (float)getproperty(VF_ACTIVESEAT);
pCamBob = &g_camBobVars[s];
makevectors(view_angles);
camera_pos += (v_up * Viewmodel_GetBob());
}

View File

@ -3,6 +3,8 @@ var string g_damage_spr_b;
var string g_damage_spr_l;
var string g_damage_spr_r;
var float autocvar_cg_damageFill = 0.25f;
void
Damage_Precache(void)
{
@ -12,6 +14,8 @@ Damage_Precache(void)
g_damage_spr_l = spriteframe("sprites/640_pain.spr", 3, 0.0f);
}
void HUD_DamageNotify_Check();
void
Damage_Draw(void)
@ -58,5 +62,11 @@ Damage_Draw(void)
[48,128], [1,1,1], rt_alpha, DRAWFLAG_ADDITIVE);
}
if (autocvar_cg_damageFill > 0.0) {
vector finalColor = [1,1,1];
finalColor[1] = finalColor[2] = 1.0 - (pSeat->m_flDamageAlpha * autocvar_cg_damageFill);
drawpic(video_mins, "fade_modulate", video_res, finalColor, 1.0, DRAWFLAG_NORMAL);
}
pSeat->m_flDamageAlpha -= clframetime;
}

View File

@ -58,10 +58,11 @@ struct
int m_iItemsOld;
float m_flDamageIndicator;
float m_flTitleAlpha;
} g_seatslocal[4], *pSeatLocal;
void HUD_DrawAmmo1(void);
void HUD_DrawAmmo2(void);
void HUD_DrawAmmo3(void);
void HUD_DrawAmmoBar(vector pos, float val, float max, float a);
void HUD_WeaponPickupNotify(int);
void HUD_WeaponPickupNotify(int);

61
src/client/draw.qc Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
ClientGame_PreDraw(void)
{
}
void
ClientGame_PostDraw(void)
{
if (pSeatLocal->m_flTitleAlpha > 0.0) {
vector title1Pos = g_hudmins + (g_hudres / 2) + [-238,-15];
vector title2Pos = g_hudmins + (g_hudres / 2) + [18,-15];
float titleAlpha = pSeatLocal->m_flTitleAlpha;
if (titleAlpha > 3.0)
titleAlpha = 4.0 - titleAlpha;
if (titleAlpha > 1.0)
titleAlpha = 1.0f;
drawsubpic(
title1Pos,
[256, 30],
g_hud4_spr,
[0, 226/256],
[1, 30/256],
[1,1,1] * titleAlpha,
1.0,
DRAWFLAG_ADDITIVE
);
drawsubpic(
title2Pos,
[220, 30],
g_hud5_spr,
[0, 226/256],
[220/256, 30/256],
[1,1,1] * titleAlpha,
1.0f,
DRAWFLAG_ADDITIVE
);
pSeatLocal->m_flTitleAlpha -= frametime;
}
}

View File

@ -24,31 +24,9 @@ ClientGame_EventParse(float fHeader)
case EV_HITNOTIFY:
pSeatLocal->m_flDamageIndicator = 1.0f;
break;
case EV_SPARK:
vector vSparkPos, vSparkAngle;
vSparkPos[0] = readcoord();
vSparkPos[1] = readcoord();
vSparkPos[2] = readcoord();
vSparkAngle[0] = readcoord();
vSparkAngle[1] = readcoord();
vSparkAngle[2] = readcoord();
FX_Spark(vSparkPos, vSparkAngle);
break;
case EV_GIBHUMAN:
vector vGibPos;
vGibPos[0] = readcoord();
vGibPos[1] = readcoord();
vGibPos[2] = readcoord();
vector vDir;
vDir[0] = readcoord();
vDir[1] = readcoord();
vDir[2] = readcoord();
float flForce = readfloat();
FX_GibHuman(vGibPos, vDir, flForce);
break;
case EV_BLOOD:
vector vBloodPos;
vector vBloodColor;
vector vBloodPos = g_vec_null;
vector vBloodColor = g_vec_null;
vBloodPos[0] = readcoord();
vBloodPos[1] = readcoord();
@ -60,45 +38,6 @@ ClientGame_EventParse(float fHeader)
FX_Blood(vBloodPos, vBloodColor);
break;
case EV_EXPLOSION:
vector vExploPos;
vExploPos[0] = readcoord();
vExploPos[1] = readcoord();
vExploPos[2] = readcoord();
FX_Explosion(vExploPos);
break;
case EV_MODELGIB:
vector vecPos;
vecPos[0] = readcoord();
vecPos[1] = readcoord();
vecPos[2] = readcoord();
vector vSize;
vSize[0] = readcoord();
vSize[1] = readcoord();
vSize[2] = readcoord();
float fStyle = readbyte();
int count = readbyte();
FX_BreakModel(count, vecPos, vSize, [0,0,0], fStyle);
break;
case EV_IMPACT:
int iType;
vector vOrigin, vNormal;
iType = (int)readbyte();
vOrigin[0] = readcoord();
vOrigin[1] = readcoord();
vOrigin[2] = readcoord();
vNormal[0] = readcoord();
vNormal[1] = readcoord();
vNormal[2] = readcoord();
FX_Impact(iType, vOrigin, vNormal);
break;
case EV_GAUSSBEAM:
FX_GaussBeam_Parse();
break;
@ -107,14 +46,14 @@ ClientGame_EventParse(float fHeader)
float fTeam = readbyte();
string sMessage = readstring();
CSQC_Parse_Print(sprintf("%s: %s", getplayerkeyvalue(fSender, "name"), sMessage), PRINT_CHAT);
CSQC_Parse_Print(Util_ChatFormat(fSender, 0, sMessage), PRINT_CHAT);
break;
case EV_CHAT_TEAM:
float fSender2 = readbyte();
float fTeam2 = readbyte();
string sMessage2 = readstring();
CSQC_Parse_Print(sprintf("[TEAM] %s: %s", getplayerkeyvalue(fSender2, "name"), sMessage2), PRINT_CHAT);
CSQC_Parse_Print(Util_ChatFormat(fSender2, fTeam2, sMessage2), PRINT_CHAT);
break;
case EV_VIEWMODEL:
View_PlayAnimation(readbyte());

View File

@ -211,7 +211,7 @@ HUD_DrawArmor(void)
);
if (pl.armor > 0) {
float perc = (pl.armor / 100);
float perc = bound(0, (pl.armor / 100), 1.0);
drawsubpic(
pos + [-80,-9] + [0, 40 * (1.0-perc)],
[40, 40 * perc],
@ -455,13 +455,36 @@ HUD_DrawDamageIndicator(void)
pSeatLocal->m_flDamageIndicator -= clframetime;
}
void
HUD_TimeRemaining(void)
{
vector iconPos = g_hudmins + [16, g_hudres[1] - 64];
/* display time if timelimit is being hit */
if (serverkeyfloat("timelimit")) {
string tempstr = strcat("Time Remaining: ", Util_GetTime());
Font_DrawText_RGB(iconPos, tempstr, g_hud_color, FONT_20);
}
}
/* main entry */
void
HUD_Draw(void)
{
player pl = (player)pSeat->m_ePlayer;
#ifndef TFC
#ifndef GEARBOX
g_hud_color = autocvar_con_color * (1 / 255);
#else
if (getplayerkeyfloat(pl.entnum-1, "*team") == 1)
g_hud_color = [255, 150, 0] / 255;
else if (getplayerkeyfloat(pl.entnum-1, "*team") == 2)
g_hud_color = [0, 1, 0];
else
g_hud_color = autocvar_con_color * (1 / 255);
#endif
#endif
/* little point in not drawing these, even if you don't have a suit */
Weapons_DrawCrosshair(pl);
@ -470,6 +493,8 @@ HUD_Draw(void)
Obituary_Draw();
Textmenu_Draw();
HUD_TimeRemaining();
if (!(pl.g_items & ITEM_SUIT)) {
return;
}
@ -482,12 +507,6 @@ HUD_Draw(void)
Damage_Draw();
}
string g_specmodes[] = {
"Free Camera",
"Third Person",
"First Person"
};
/* specatator main entry */
void
HUD_DrawSpectator(void)

View File

@ -78,16 +78,33 @@ HUD_ItemNotify_Insert(int type, int count)
void
HUD_ItemNotify_Check(player pl)
{
int healthdiff = bound(0, pl.health - pSeatLocal->m_iHealthOld, 100);
int armordiff = bound(0, pl.armor - pSeatLocal->m_iArmorOld, 100);
int longjumpdiff = ((pl.g_items & ITEM_LONGJUMP) > (pSeatLocal->m_iItemsOld & ITEM_LONGJUMP)) == TRUE;
int healthdiff = (int)bound(0, pl.health - pSeatLocal->m_iHealthOld, 100);
int armordiff = (int)bound(0, pl.armor - pSeatLocal->m_iArmorOld, 100);
bool ljDiff = ((pl.g_items & ITEM_LONGJUMP) > (pSeatLocal->m_iItemsOld & ITEM_LONGJUMP)) ? true : false;
bool suitDiff = ((pl.g_items & ITEM_SUIT) > (pSeatLocal->m_iItemsOld & ITEM_SUIT)) ? true : false;
if (healthdiff > 1)
HUD_ItemNotify_Insert(1, 1);
if (armordiff > 1)
HUD_ItemNotify_Insert(0, 1);
if (longjumpdiff)
HUD_ItemNotify_Insert(2, 1);
if ((pl.g_items & ITEM_SUIT)) {
if (suitDiff == false) {
if (healthdiff > 1i) {
HUD_ItemNotify_Insert(1, 1);
}
if (armordiff > 1i) {
HUD_ItemNotify_Insert(0, 1);
}
if (ljDiff) {
HUD_ItemNotify_Insert(2, 1);
}
} else {
/* just picked up a suit, reset display values */
pSeatLocal->m_iHealthOld = (int)pl.health;
pSeatLocal->m_iArmorOld = (int)pl.armor;
pSeatLocal->m_iAmmo1Old = (int)pl.a_ammo1;
pSeatLocal->m_iAmmo2Old = (int)pl.a_ammo2;
pSeatLocal->m_iAmmo3Old = (int)pl.a_ammo3;
pSeatLocal->m_iPickupWeapon = 0i;
pSeatLocal->m_flPickupAlpha = 0.0f;
}
}
pSeatLocal->m_iItemsOld = pl.g_items;
}

137
src/client/hud_sprite.qc Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
typedef struct
{
string m_strImage;
vector m_vecSize;
vector m_vecCanvasSize;
vector m_vecCanvasPos;
} hlsprite_t;
hlsprite_t *g_hlsprites;
var hashtable g_hashhlsprite;
void
HLSprite_Init(void)
{
filestream hudFile;
vector imgSize;
int spriteCount = 0i;
int i = 0i;
int c = 0i;
string line;
hudFile = fopen("sprites/hud.txt", FILE_READ);
if (hudFile < 0) {
NSError("Missing file sprites/hud.txt");
return;
}
/* count valid entries */
while ((line = fgets(hudFile))) {
c = tokenize_console(line);
if (c != 7)
continue;
if (argv(1) != "640")
continue;
spriteCount++;
}
/* if we couldn't find anything, don't bother */
if (spriteCount <= 0i)
return;
/* allocate our hashtable */
if (!g_hashhlsprite) {
g_hashhlsprite = hash_createtab(2, HASH_ADD);
}
/* to the beginning we go. */
fseek(hudFile, 0);
/* allocate valid entries */
g_hlsprites = memalloc(sizeof(hlsprite_t) * spriteCount);
/* read the data into our banks */
while ((line = fgets(hudFile))) {
c = tokenize_console(line);
if (c != 7)
continue;
if (argv(1) != "640")
continue;
g_hlsprites[i].m_strImage = spriteframe(sprintf("sprites/%s.spr", argv(2)), 0, 0.0f);
g_hlsprites[i].m_vecSize[0] = stof(argv(5));
g_hlsprites[i].m_vecSize[1] = stof(argv(6));
imgSize = drawgetimagesize(g_hlsprites[i].m_strImage);
g_hlsprites[i].m_vecCanvasPos[0] = stof(argv(3)) / imgSize[0];
g_hlsprites[i].m_vecCanvasPos[1] = stof(argv(4)) / imgSize[1];
g_hlsprites[i].m_vecCanvasSize[0] = g_hlsprites[i].m_vecSize[0] / imgSize[0];
g_hlsprites[i].m_vecCanvasSize[1] = g_hlsprites[i].m_vecSize[1] / imgSize[1];
hash_add(g_hashhlsprite, argv(0), (int)i);
i++;
}
NSLog("...initialized %i HL sprites.", spriteCount);
}
void
HLSprite_Draw_RGBA(string spriteName, vector spritePos, vector spriteColor, float spriteAlpha, bool isAdditive)
{
int spriteNum = -1i;
spriteNum = (int)hash_get(g_hashhlsprite, spriteName, -1i);
if (spriteNum == -1i) {
NSError("Cannot draw sprite %S!", spriteName);
return;
}
drawsubpic(
spritePos,
g_hlsprites[spriteNum].m_vecSize,
g_hlsprites[spriteNum].m_strImage,
g_hlsprites[spriteNum].m_vecCanvasPos,
g_hlsprites[spriteNum].m_vecCanvasSize,
spriteColor,
spriteAlpha,
isAdditive ? DRAWFLAG_ADDITIVE : 0
);
}
void
HLSprite_Draw(string spriteName, vector spritePos, bool isAdditive)
{
HLSprite_Draw_RGBA(spriteName, spritePos, [1,1,1], 1.0f, isAdditive);
}
void
HLSprite_Draw_A(string spriteName, vector spritePos, float spriteAlpha, bool isAdditive)
{
HLSprite_Draw_RGBA(spriteName, spritePos, [1,1,1], spriteAlpha, isAdditive);
}
void
HLSprite_Draw_RGB(string spriteName, vector spritePos, vector spriteColor, bool isAdditive)
{
HLSprite_Draw_RGBA(spriteName, spritePos, spriteColor, 1.0f, isAdditive);
}

View File

@ -14,6 +14,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void View_ForceChange(player pl, int targetWeapon);
vector g_vecHUDNums[6] =
{
[168 / 256, 72 / 128],
@ -52,9 +54,10 @@ HUD_DrawWeaponSelect_Forward(void)
if (pSeat->m_flHUDWeaponSelectTime < time) {
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionOpen", CHAN_ITEM, false);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionMoveSlot", CHAN_ITEM, false);
pSeat->m_iHUDWeaponSelected--;
if (pSeat->m_iHUDWeaponSelected <= 0) {
pSeat->m_iHUDWeaponSelected = g_weapons.length - 1;
@ -83,9 +86,10 @@ HUD_DrawWeaponSelect_Back(void)
if (pSeat->m_flHUDWeaponSelectTime < time) {
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionOpen", CHAN_ITEM, false);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionMoveSlot", CHAN_ITEM, false);
pSeat->m_iHUDWeaponSelected++;
if (pSeat->m_iHUDWeaponSelected >= g_weapons.length) {
pSeat->m_iHUDWeaponSelected = 1;
@ -107,11 +111,10 @@ HUD_DrawWeaponSelect_Trigger(void)
player pl = (player)pSeat->m_ePlayer;
if (pl.activeweapon != pSeat->m_iHUDWeaponSelected)
sendevent("PlayerSwitchWeapon", "i", pSeat->m_iHUDWeaponSelected);
View_ForceChange(pl, pSeat->m_iHUDWeaponSelected);
pl.activeweapon = pSeat->m_iHUDWeaponSelected;
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_select.wav", 0.5f, ATTN_NONE);
Sound_Play(pSeat->m_ePlayer, CHAN_ITEM, "Player.WeaponSelected");
pSeat->m_iHUDWeaponSelected = pSeat->m_flHUDWeaponSelectTime = 0;
}
@ -120,8 +123,7 @@ HUD_DrawWeaponSelect_Last(void)
{
player pl = (player)pSeat->m_ePlayer;
if (pl.g_items & g_weapons[pSeat->m_iOldWeapon].id) {
pl.activeweapon = pSeat->m_iOldWeapon;
sendevent("PlayerSwitchWeapon", "i", pSeat->m_iOldWeapon);
View_ForceChange(pl, pSeat->m_iOldWeapon);
}
}
@ -165,9 +167,9 @@ HUD_SlotSelect(int slot)
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionOpen", CHAN_ITEM, false);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionMoveSlot", CHAN_ITEM, false);
}
/* weren't in that slot? select the first one then */
@ -210,7 +212,7 @@ HUD_DrawWeaponSelect(void)
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
if (pSeat->m_iHUDWeaponSelected) {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudoff.wav", 0.5, ATTN_NONE);
pl.StartSoundDef("Player.WeaponSelectionClose", CHAN_ITEM, false);
pSeat->m_iHUDWeaponSelected = 0;
}
return;

View File

@ -28,9 +28,18 @@ ClientGame_Init(float apilevel, string enginename, float engineversion)
registercommand("chooseteam");
}
void VGUI_ShowMOTD();
void
ClientGame_InitDone(void)
{
VGUI_ShowMOTD();
bool gameTitle = serverkeyfloat("gametitle");
if (gameTitle == true) {
pSeatLocal->m_flTitleAlpha = 4.0f;
}
}
void
@ -40,6 +49,9 @@ ClientGame_RendererRestart(string rstr)
precache_model("models/shotgunshell.mdl");
/* there's also muzzleflash.spr, but that's just MUZZLE_SMALL again */
precache_model("sprites/muzzleflash1.spr");
precache_model("sprites/muzzleflash2.spr");
precache_model("sprites/muzzleflash3.spr");
MUZZLE_RIFLE = (int)getmodelindex("sprites/muzzleflash1.spr");
MUZZLE_SMALL = (int)getmodelindex("sprites/muzzleflash2.spr");
MUZZLE_WEIRD = (int)getmodelindex("sprites/muzzleflash3.spr");
@ -48,11 +60,6 @@ ClientGame_RendererRestart(string rstr)
Obituary_Precache();
FX_Blood_Init();
FX_BreakModel_Init();
FX_Explosion_Init();
FX_GibHuman_Init();
FX_Spark_Init();
FX_Impact_Init();
FX_GaussBeam_Init();
BEAM_TRIPMINE = particleeffectnum("weapon_tripmine.beam");

View File

@ -110,6 +110,10 @@ Obituary_Add(string attacker, string victim, float weapon, float flags)
int x, y;
x = OBITUARY_LINES;
if (attacker == "worldspawn" || attacker == victim) {
attacker = "";
}
/* we're not full yet, so fill up the buffer */
if (g_obituary_count < x) {
y = g_obituary_count;
@ -157,6 +161,8 @@ Obituary_Draw(void)
g_obituary[i].icon = g_obituary[i+1].icon;
}
g_obituary[OBITUARY_LINES-1].attacker = "";
g_obituary[OBITUARY_LINES-1].victim = "";
g_obituary[OBITUARY_LINES-1].icon = 0;
g_obituary_time = OBITUARY_TIME;
g_obituary_count--;
@ -170,7 +176,7 @@ Obituary_Draw(void)
for (i = 0; i < OBITUARY_LINES; i++) {
string a, v;
if (!g_obituary[i].attacker) {
if (!g_obituary[i].victim) {
break;
}

View File

@ -19,26 +19,26 @@ defs.h
../../../src/gs-entbase/shared.src
../shared/include.src
../../../base/src/client/draw.qc
draw.qc
damage.qc
init.qc
flashlight.qc
../../../valve/src/client/flashlight.qc
entities.qc
cmds.qc
game_event.qc
../../../valve/src/client/camera.qc
../../../valve/src/client/viewmodel.qc
view.qc
obituary.qc
hud_sprite.qc
hud_itemnotify.qc
hud_dmgnotify.qc
hud_ammonotify.qc
hud.qc
hud_weaponselect.qc
scoreboard.qc
../../../base/src/client/modelevent.qc
../../../src/client/include.src
vgui_motd.qc
../../../src/shared/include.src
#endlist

View File

@ -19,11 +19,13 @@
var int autocvar_cl_centerscores = FALSE;
var int g_scores_teamplay = 0;
var bool g_scores_scorepoints = false;
void
Scores_Init(void)
{
g_scores_teamplay = (int)serverkeyfloat("teamplay");
g_scores_scorepoints = (bool)serverkeyfloat("scorepoints");
}
void
@ -33,7 +35,12 @@ Scores_DrawTeam(player pl, vector pos)
drawfont = Font_GetID(FONT_20);
drawstring(pos + [0,-18], "Teams", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [124,-18], "kills / deaths", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
if (g_scores_scorepoints)
drawstring(pos + [124-32,-18], "kills / deaths / score", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
else
drawstring(pos + [124,-18], "kills / deaths", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [240,-18], "latency", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
pos[1] += 12;
@ -63,34 +70,61 @@ Scores_DrawTeam(player pl, vector pos)
}
drawstring(pos + [24,0], getplayerkeyvalue(i, "name"), [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [154,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the kills and align them left to right */
temp = getplayerkeyvalue(i, "frags");
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [150 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
if (g_scores_scorepoints) {
drawstring(pos + [154-32,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Deaths are right to left aligned */
temp = getplayerkeyvalue(i, "*deaths");
drawstring(pos + [165,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the kills and align them left to right */
temp = getplayerkeyvalue(i, "frags");
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [150 - 32 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [154+26,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Deaths are right to left aligned */
temp = getplayerkeyvalue(i, "*deaths");
if (!temp) temp = "0";
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [165 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Deaths are right to left aligned */
temp = getplayerkeyvalue(i, "*score");
if (!temp) temp = "0";
drawstring(pos + [165+32,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
} else {
drawstring(pos + [154,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the kills and align them left to right */
temp = getplayerkeyvalue(i, "frags");
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [150 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Deaths are right to left aligned */
temp = getplayerkeyvalue(i, "*deaths");
drawstring(pos + [165,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
}
vector tmpColor;
temp = getplayerkeyvalue(i, "*icon1");
if (temp) {
tmpColor[0] = getplayerkeyfloat(i, "*icon1_r");
tmpColor[1] = getplayerkeyfloat(i, "*icon1_g");
tmpColor[2] = getplayerkeyfloat(i, "*icon1_b");
HLSprite_Draw_RGB(temp, pos - [8, 0], tmpColor, true);
}
temp = getplayerkeyvalue(i, "*icon2");
if (temp) {
tmpColor[0] = getplayerkeyfloat(i, "*icon2_r");
tmpColor[1] = getplayerkeyfloat(i, "*icon2_g");
tmpColor[2] = getplayerkeyfloat(i, "*icon2_b");
HLSprite_Draw_RGB(temp, pos + [8, 0], tmpColor, true);
}
/* Get the latency and align it left to right */
temp = getplayerkeyvalue(i, "ping");
l = stringwidth(temp, FALSE, [20,20]);
if (getplayerkeyfloat(i, "*dead") == 1) {
drawsubpic(
pos - [8,0],
[32,16],
g_hud1_spr,
[224/256, 240/256],
[32/256, 16/256],
[1,0,0],
1.0f,
DRAWFLAG_ADDITIVE
);
}
drawstring(pos + [290 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
pos[1] += 20;
}

65
src/client/vgui_motd.qc Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
VGUI_ShowMOTD(void)
{
static int initialized;
static VGUIButton winMotdClose;
static VGUIWindow winMotd;
static VGUILabel winMotdHostname;
static VGUILabel winMotdBody;
static void VGUI_ShowMOTD_Close(void)
{
winMotd.Hide();
}
if (MOTD_GetLineCount() < 1i)
return;
if (!initialized) {
initialized = TRUE;
winMotd = spawn(VGUIWindow);
winMotd.SetTitle("Message Of The Day");
winMotd.SetSize('424 312');
winMotd.SetStyleMask(0);
winMotdClose = spawn(VGUIButton);
winMotdClose.SetTitle("OK");
winMotdClose.SetPos([16, 266]);
winMotdClose.SetSize([160, 30]);
winMotdClose.SetFunc(VGUI_ShowMOTD_Close);
winMotdHostname = spawn(VGUILabel);
winMotdHostname.SetTitle(serverkey("hostname"));
winMotdHostname.SetTextSize(19);
winMotdHostname.SetPos([16, 20]);
winMotdBody = spawn(VGUILabel);
winMotdBody.SetTitle(MOTD_GetTextBody());
winMotdBody.SetPos([16, 48]);
winMotdBody.SetSize([392, 210]);
g_uiDesktop.Add(winMotd);
winMotd.Add(winMotdClose);
winMotd.Add(winMotdHostname);
winMotd.Add(winMotdBody);
}
winMotd.Show();
winMotd.SetPos((video_res / 2) - (winMotd.GetSize() / 2));
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
View_UpdateWeapon(player pl, entity vm, entity mflash)
{
/* only bother upon change */
if (pSeat->m_iLastWeapon == pl.activeweapon) {
return;
}
pSeat->m_iOldWeapon = pSeat->m_iLastWeapon;
pSeat->m_iLastWeapon = pl.activeweapon;
if (!pl.activeweapon) {
return;
}
/* we forced a weapon call outside the prediction,
* thus we need to update all the net variables to
* make sure these updates are recognized. this is
* vile but it'll have to do for now */
SAVE_STATE(pl.w_attack_next)
SAVE_STATE(pl.w_idle_next)
SAVE_STATE(pl.viewzoom)
SAVE_STATE(pl.weapontime)
SAVE_STATE(pl.weaponframe)
/* hack, we changed the wep, move this into Game_Input/PMove */
Weapons_Draw(pl);
/* we forced a weapon call outside the prediction,
* thus we need to update all the net variables to
* make sure these updates are recognized. this is
* vile but it'll have to do for now */
ROLL_BACK(pl.w_attack_next)
ROLL_BACK(pl.w_idle_next)
ROLL_BACK(pl.viewzoom)
ROLL_BACK(pl.weapontime)
ROLL_BACK(pl.weaponframe)
/* figure out when the attachments start. in FTE attachments for
* HLMDL are treated as bones. they start at numbones + 1 */
skel_delete(mflash.skeletonindex);
mflash.skeletonindex = skel_create(vm.modelindex);
pSeat->m_iVMBones = skel_get_numbones(mflash.skeletonindex) + 1;
}

View File

@ -56,7 +56,7 @@ Viewmodel_CalcBob(void)
iCycle = (pViewBob->m_flBobTime / var_cycle);
/* increment the input value for our cycle */
pViewBob->m_flBobTime += clframetime;
pViewBob->m_flBobTime += frametime;
/* calculate the point in the cycle based on the input time */
pViewBob->m_flBobCycle = pViewBob->m_flBobTime - (iCycle * var_cycle);
@ -78,12 +78,23 @@ Viewmodel_CalcBob(void)
pViewBob->m_flBob = bound(-8, flBob, 4);
/* make sure it's adjusted for scale */
pViewBob->m_flBob *= autocvar_r_viewmodelscale;
pViewBob->m_flBob *= autocvar_cg_viewmodelScale;
}
float
Viewmodel_GetBob(void)
{
int s = (float)getproperty(VF_ACTIVESEAT);
pViewBob = &g_viewBobVars[s];
return pViewBob->m_flBob;
}
void
Viewmodel_ApplyBob(entity gun)
{
int s = (float)getproperty(VF_ACTIVESEAT);
pViewBob = &g_viewBobVars[s];
// Give the gun a tilt effect like in old HL/CS versions
if (autocvar(v_bobclassic, 1, "Viewmodel bob classic tilt switch") == 1) {
gun.angles[2] = -pViewBob->m_flBob;
@ -91,7 +102,7 @@ Viewmodel_ApplyBob(entity gun)
/* apply the gun offset based on our bob */
gun.origin += [0,0,-1] + (v_forward * (pViewBob->m_flBob * 0.4))
+ (v_forward * autocvar_v_gunofs[0])
+ (v_right * autocvar_v_gunofs[1])
+ (v_up * autocvar_v_gunofs[2]);
+ (v_forward * autocvar_cg_viewmodelOffset[0])
+ (v_right * autocvar_cg_viewmodelOffset[1])
+ (v_up * autocvar_cg_viewmodelOffset[2]);
}

View File

@ -1,4 +1,4 @@
CC=fteqcc
all:
$(CC) -fwasm progs.src
$(CC) progs.src

View File

@ -46,6 +46,13 @@ item_ammo::Touch(entity eToucher)
void
item_ammo::Respawn(void)
{
static void AdjustSpawnPos(void) {
RestoreAngles();
SetOrigin(GetSpawnOrigin());
DropToFloor();
SetMovetype(MOVETYPE_TOSS);
}
SetSolid(SOLID_TRIGGER);
SetMovetype(MOVETYPE_TOSS);
SetOrigin(GetSpawnOrigin());
@ -57,7 +64,7 @@ item_ammo::Respawn(void)
if (real_owner && time > 30.0f)
Sound_Play(this, CHAN_ITEM, "ammo.respawn");
droptofloor();
ScheduleThink(AdjustSpawnPos, 0.0f);
}
void

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* called every input frame */
void
Game_RunClientCommand(void)
{
player pl = (player)self;
pl.Physics_Run();
}
/* custom chat packet */
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM);
WriteByte(MSG_MULTICAST, num_for_edict(sender) - 1);
WriteByte(MSG_MULTICAST, sender.team);
WriteString(MSG_MULTICAST, msg);
if (eEnt) {
msg_entity = eEnt;
multicast([0,0,0], MULTICAST_ONE);
} else {
multicast([0,0,0], MULTICAST_ALL);
}
localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg));
}
/* client cmd overrides happen here */
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("timelimit") - (time / 60);
timestring = Util_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
bprint(PRINT_CHAT, msg);
return;
}
if (argv(0) == "say") {
SV_SendChat(self, argv(1), world, 0);
return;
} else if (argv(0) == "say_team") {
entity a;
for (a = world; (a = find(a, ::classname, "player"));) {
if (a.team == self.team) {
SV_SendChat(self, argv(1), a, 1);
}
}
return;
}
clientcommand(self, cmd);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,17 +12,4 @@
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Game_SpectatorThink(void)
{
}
void Game_SpectatorConnect(void)
{
}
void Game_SpectatorDisconnect(void)
{
}
*/

View File

@ -35,8 +35,9 @@ void Flashlight_Toggle(void)
if (self.gflags & GF_FLASHLIGHT) {
self.gflags &= ~GF_FLASHLIGHT;
Sound_Play(self, CHAN_ITEM, "Player.FlashLightOff");
} else {
self.gflags |= GF_FLASHLIGHT;
Sound_Play(self, CHAN_ITEM, "Player.FlashLightOn");
}
sound(self, CHAN_ITEM, "items/flashlight1.wav", 1, ATTN_IDLE);
}

View File

@ -16,16 +16,18 @@
class HLGameRules:CGameRules
{
virtual void(NSClientPlayer) PlayerConnect;
virtual void(NSClientPlayer) PlayerDisconnect;
virtual void(NSClientPlayer) PlayerKill;
virtual void(NSClientPlayer) PlayerPostFrame;
virtual void PlayerConnect(NSClientPlayer);
virtual void PlayerDisconnect(NSClientPlayer);
virtual void PlayerKill(NSClientPlayer);
virtual void PlayerPostFrame(NSClientPlayer);
virtual void(NSClientPlayer) LevelDecodeParms;
virtual void(NSClientPlayer) LevelChangeParms;
virtual void(void) LevelNewParms;
virtual void LevelDecodeParms(NSClientPlayer);
virtual void LevelChangeParms(NSClientPlayer);
virtual void LevelNewParms(void);
virtual bool(void) IsMultiplayer;
virtual bool IsMultiplayer(void);
virtual bool ImpulseCommand(NSClient, float);
};
class HLSingleplayerRules:HLGameRules
@ -34,6 +36,7 @@ class HLSingleplayerRules:HLGameRules
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
virtual bool(void) IsMultiplayer;
virtual bool ImpulseCommand(NSClient, float);
};
class HLMultiplayerRules:HLGameRules
@ -55,4 +58,5 @@ class HLMultiplayerRules:HLGameRules
virtual bool(void) IsMultiplayer;
virtual bool(void) IsTeamplay;
virtual void(void) InitPostEnts;
virtual bool PlayerRequestRespawn(NSClientPlayer);
};

View File

@ -27,12 +27,11 @@ HLGameRules::LevelDecodeParms(NSClientPlayer pp)
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.SetAngles([parm4, parm5, parm6]);
pl.SetVelocity([parm7, parm8, parm9]);
/* game specific stuff */
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
@ -58,10 +57,11 @@ HLGameRules::LevelDecodeParms(NSClientPlayer pp)
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
/* reset bounds */
if (pl.HasFlags(FL_CROUCHING)) {
pl.SetSize(VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
}
}
@ -78,7 +78,7 @@ HLGameRules::LevelChangeParms(NSClientPlayer pp)
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm64 = pl.GetFlags();
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
@ -123,27 +123,40 @@ HLGameRules::PlayerPostFrame(NSClientPlayer pl)
void
HLGameRules::PlayerConnect(NSClientPlayer pl)
{
if (Plugin_PlayerConnect(pl) == FALSE)
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
super::PlayerConnect(pl);
}
void
HLGameRules::PlayerDisconnect(NSClientPlayer pl)
{
if (Plugin_PlayerDisconnect(pl) == FALSE)
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = -1;
super::PlayerDisconnect(pl);
}
void
HLGameRules::PlayerKill(NSClientPlayer pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
}
void
TriggerFlashlight(NSClient target)
{
entity oldself = self;
self = target;
Flashlight_Toggle();
self = oldself;
}
bool
HLGameRules::ImpulseCommand(NSClient bp, float num)
{
switch (num) {
case 100:
TriggerFlashlight(bp);
break;
default:
return super::ImpulseCommand(bp, num);
}
return true;
}

View File

@ -23,6 +23,17 @@ HLMultiplayerRules::IsMultiplayer(void)
return true;
}
bool
HLMultiplayerRules::PlayerRequestRespawn(NSClientPlayer bp)
{
if (bp.TimeSinceDeath() > 0.5f) {
bp.ScheduleThink(PutClientInServer, 0.0f);
return true;
}
return false;
}
bool
HLMultiplayerRules::IsTeamplay(void)
{
@ -32,6 +43,10 @@ HLMultiplayerRules::IsTeamplay(void)
void
HLMultiplayerRules::InitPostEnts(void)
{
MOTD_LoadDefault();
forceinfokey(world, "scorepoints", "0");
if (IsTeamplay() == true) {
int c;
@ -94,7 +109,7 @@ HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
/* death-counter */
pl.deaths++;
forceinfokey(pl, "*deaths", ftos(pl.deaths));
pl.SetInfoKey("*deaths", ftos(pl.deaths));
/* update score-counter */
if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER)
@ -114,22 +129,56 @@ HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
/* either gib, or make a corpse */
if (pl.health < -50) {
FX_GibHuman(pl.origin, vectoangles(pl.origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
vector gibDir = vectoangles(pl.origin - g_dmg_eAttacker.origin);
float gibStrength = g_dmg_iDamage * 2.0f;
BreakModel_Entity(pl, gibDir, gibStrength);
} else {
FX_Corpse_Spawn((player)pl, ANIM_DIESIMPLE);
float deathAnimation = ANIM_DIESIMPLE;
switch (g_dmg_iHitBody) {
case BODY_HEAD:
deathAnimation = ANIM_DIEHEADSHOT;
break;
case BODY_CHEST:
deathAnimation = ANIM_DIESPIN;
break;
case BODY_STOMACH:
deathAnimation = ANIM_DIEGUTSHOT;
break;
default:
bool isFacing = pl.IsFacingPosition(g_dmg_vecLocation);
/* we still want a change to play ANIM_DIESIMPLE */
if (random() < 0.5)
if (isFacing == false) {
deathAnimation = ANIM_DIEFORWARD;
} else {
deathAnimation = random() < 0.5 ? ANIM_DIEBACKWARDS1 : ANIM_DIEBACKWARDS1;
}
break;
}
NSEntity newCorpse = (NSEntity)FX_Corpse_Spawn((player)pl, deathAnimation);
/* if we were crouching, adjust the bbox (thx 2 lack of crouch death animation) */
if (pl.flags & FL_CROUCHING) {
newCorpse.SetSize(VEC_HULL_MIN, [16, 16, -16]);
}
}
/* now let's make the real client invisible */
pl.Death();
pl.takedamage = DAMAGE_NO;
pl.SetTakedamage(DAMAGE_NO);
pl.gflags &= ~GF_FLASHLIGHT;
pl.gflags &= ~GF_EGONBEAM;
Sound_Play(pl, CHAN_AUTO, "player.die");
pl.StartSoundDef("Player.Death", CHAN_AUTO, true);
/* force respawn */
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
if (cvar("mp_forcerespawn") == 1) {
pl.ScheduleThink(PutClientInServer, 4.0f);
}
/* have we gone over the fraglimit? */
CheckRules();
@ -139,38 +188,58 @@ void
HLMultiplayerRules::PlayerSpawn(NSClientPlayer pp)
{
player pl = (player)pp;
string playerModel;
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.SetMaxHealth(100);
pl.SetHealth(100);
pl.SetTakedamage(DAMAGE_YES);
pl.SetSolid(SOLID_SLIDEBOX);
pl.SetMovetype(MOVETYPE_WALK);
pl.flags = FL_CLIENT;
pl.AddFlags(FL_CLIENT);
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
/* player model selection */
if (IsTeamplay() == true) {
int teamCount = tokenizebyseparator(m_strTeamList, ";");
int playerTeam = (int)pl.GetTeam();
/* not part of a team? pick one of the ones we have */
/* TODO: this should sort us into the lowest team */
if (playerTeam == 0) {
playerTeam = 1i + (int)floor(random(0, (float)teamCount)); /* teams start at 1 after all */
pl.SetTeam(playerTeam);
}
/* assign our player model */
playerModel = sprintf("models/player/%s/%s.mdl", argv(playerTeam - 1i), argv(playerTeam - 1i));
} else {
/* interpret the 'model' InfoKey */
playerModel = pl.GetInfoKey("model");
if (playerModel) {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.velocity = [0,0,0];
/* fallback is always models/player.mdl for Half-Life */
if not (whichpack(playerModel)) {
playerModel = "models/player.mdl";
}
pl.SetModel(playerModel);
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
pl.ClearVelocity();
pl.gravity = __NULL__;
pl.frame = 1;
//pl.SendEntity = Player_SendEntity;
pl.SetFrame(1);
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*dead", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
pl.SetInfoKey("*spec", "0");
pl.SetInfoKey("*dead", "0");
pl.SetInfoKey("*deaths", ftos(pl.deaths));
pl.SetPropData("actor_human");
pl.SetCanBleed(true);
LevelNewParms();
LevelDecodeParms(pl);
@ -180,32 +249,11 @@ HLMultiplayerRules::PlayerSpawn(NSClientPlayer pp)
pl.activeweapon = WEAPON_GLOCK;
pl.glock_mag = 18;
pl.ammo_9mm = 44;
if (IsTeamplay() == true) {
int c = tokenizebyseparator(m_strTeamList, ";");
/* not part of a team? pick one of the ones we have */
/* TODO: this should sort us into the lowest team */
if (pl.team == 0) {
pl.team = 1 + floor(random(0, c));
forceinfokey(pl, "*team", sprintf("%d", pl.team));
}
/* assign our player model */
mymodel = sprintf("models/player/%s/%s.mdl", argv(pl.team - 1), argv(pl.team - 1));
if (whichpack(mymodel))
pl.model = mymodel;
setmodel(pl, pl.model);
}
#endif
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.Transport(spot.origin, spot.angles);
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
@ -215,16 +263,6 @@ HLMultiplayerRules::ConsoleCommand(NSClientPlayer pp, string cmd)
tokenize(cmd);
switch (argv(0)) {
case "bot_add":
bot pete = (bot)Bot_AddQuick();
Bot_RandomColormap(pete);
searchhandle pm = search_begin("models/player/*/*.mdl", TRUE, TRUE);
int r = floor(random(0, search_getsize(pm)));
string mdl = substring(search_getfilename(pm, r), 0, -5);
tokenizebyseparator(mdl, "/");
forceinfokey(pete, "model", argv(2));
search_end(pm);
break;
case "jumptest":
makevectors(pp.v_angle);
traceline(pp.origin + pp.view_ofs, pp.origin + pp.view_ofs + v_forward * 1024, FALSE, pp);
@ -252,27 +290,26 @@ HLMultiplayerRules::HLMultiplayerRules(void)
}
void
CSEv_HLDM_Chooseteam_s(string teamname)
CSEv_HLDM_Chooseteam_s(string teamName)
{
HLGameRules rules = (HLGameRules)g_grMode;
player pl = (player)self;
if (!teamname)
if (!teamName)
return;
if (rules.IsMultiplayer() == false)
return;
if (rules.IsTeamplay() == false)
return;
if (pl.health <= 0)
if (pl.IsDead() == true)
return;
HLMultiplayerRules mprules = (HLMultiplayerRules)rules;
int c = tokenizebyseparator(mprules.m_strTeamList, ";");
for (int i = 0; i < c; i++) {
if (argv(i) == teamname) {
pl.team = (float)i + 1;
forceinfokey(pl, "*team", sprintf("%d", pl.team));
if (argv(i) == teamName) {
pl.SetTeam((float)i + 1);
Damage_Apply(pl, pl, 100, 0, DMG_SKIP_ARMOR);
return;
}

View File

@ -23,21 +23,23 @@ HLSingleplayerRules::IsMultiplayer(void)
void
HLSingleplayerRules::PlayerDeath(NSClientPlayer pl)
{
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.SetMovetype(MOVETYPE_NONE);
pl.SetSolid(SOLID_NOT);
pl.SetTakedamage(DAMAGE_NO);
pl.SetHealth(0);
pl.StartSoundDef("Player.Death", CHAN_AUTO, true);
pl.gflags &= ~GF_FLASHLIGHT;
pl.armor = pl.activeweapon = pl.g_items = pl.weapon = 0;
pl.health = 0;
Sound_Play(pl, CHAN_AUTO, "player.die");
if (cvar("coop") == 1) {
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
pl.ScheduleThink(PutClientInServer, 4.0f);
}
if (pl.health < -50) {
FX_GibHuman(pl.origin, vectoangles(pl.origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
/* so much damage we're gonna gib */
if (pl.GetHealth() < -50) {
//pl.Gib();
//FX_GibHuman(pl.origin, vectoangles(pl.origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
}
/* Let's handle corpses on the clientside */
@ -56,53 +58,90 @@ HLSingleplayerRules::PlayerDeath(NSClientPlayer pl)
void
HLSingleplayerRules::PlayerSpawn(NSClientPlayer pl)
{
string playerModel = "models/player.mdl";
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.SetHealth(100);
pl.SetMaxHealth(100);
pl.SetTakedamage(DAMAGE_YES);
pl.SetSolid(SOLID_SLIDEBOX);
pl.SetMovetype(MOVETYPE_WALK);
pl.flags = FL_CLIENT;
pl.AddFlags(FL_CLIENT);
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
/* if in cooperative mode, we want to respect the player model */
if (cvar("coop") == 1) {
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
string testModel = infokey(pl, "model");
if (testModel) {
testModel = sprintf("models/player/%s/%s.mdl", testModel, testModel);
if (whichpack(testModel)) {
playerModel = testModel;
}
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
//pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* this is where the mods want to deviate */
entity spot;
pl.SetModel(playerModel);
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
pl.ClearVelocity();
pl.SetInfoKey("*spec", "0");
pl.SetInfoKey("*deaths", ftos(pl.deaths));
pl.SetCanBleed(true);
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
LevelDecodeParms(pl);
setorigin(pl, Landmark_GetSpot());
pl.SetOrigin(Landmark_GetSpot());
} else {
entity spawnPoint;
LevelNewParms();
spot = find(world, ::classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
spawnPoint = find(world, ::classname, "info_player_start");
pl.Transport(spawnPoint.origin, spawnPoint.angles);
}
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
bool
HLSingleplayerRules::ImpulseCommand(NSClient bp, float num)
{
switch (num) {
case 101:
player pl = (player)bp;
pl.SetHealth(100);
pl.SetMaxHealth(100);
pl.SetArmor(100);
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_CROWBAR, -1);
Weapons_AddItem(pl, WEAPON_GLOCK, -1);
Weapons_AddItem(pl, WEAPON_PYTHON, -1);
Weapons_AddItem(pl, WEAPON_MP5, -1);
Weapons_AddItem(pl, WEAPON_SHOTGUN, -1);
Weapons_AddItem(pl, WEAPON_CROSSBOW, -1);
Weapons_AddItem(pl, WEAPON_RPG, -1);
Weapons_AddItem(pl, WEAPON_GAUSS, -1);
Weapons_AddItem(pl, WEAPON_EGON, -1);
Weapons_AddItem(pl, WEAPON_HORNETGUN, -1);
Weapons_AddItem(pl, WEAPON_HANDGRENADE, -1);
Weapons_AddItem(pl, WEAPON_SATCHEL, -1);
Weapons_AddItem(pl, WEAPON_TRIPMINE, -1);
Weapons_AddItem(pl, WEAPON_SNARK, -1);
pl.ammo_m203_grenade = 10;
#ifdef GEARBOX
Weapons_AddItem(pl, WEAPON_PIPEWRENCH, -1);
Weapons_AddItem(pl, WEAPON_KNIFE, -1);
Weapons_AddItem(pl, WEAPON_GRAPPLE, -1);
Weapons_AddItem(pl, WEAPON_EAGLE, -1);
Weapons_AddItem(pl, WEAPON_PENGUIN, -1);
Weapons_AddItem(pl, WEAPON_M249, -1);
Weapons_AddItem(pl, WEAPON_DISPLACER, -1);
Weapons_AddItem(pl, WEAPON_SNIPERRIFLE, -1);
Weapons_AddItem(pl, WEAPON_SPORELAUNCHER, -1);
Weapons_AddItem(pl, WEAPON_SHOCKRIFLE, -1);
#endif
break;
default:
return super::ImpulseCommand(bp, num);
}
return true;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_armorvest (0 0 0.8) (-16 -16 0) (16 16 36) SUIT_LONGINTRO
HALF-LIFE (1998) ENTITY
HEV Suit
Provides the player with armor, a flashlight and a Heads-Up-Display.
When SUIT_LONGINTRO is set, the intro dialog will be longer.
*/
class item_armorvest:NSRenderableEntity
{
string m_strOnPlayerTouch;
void(void) item_armorvest;
virtual void(void) Spawned;
virtual void(entity) Touch;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
};
void
item_armorvest::Touch(entity eToucher)
{
if (other.classname != "player") {
return;
}
player pl = (player)other;
if (pl.g_items & ITEM_SUIT) {
return;
}
Logging_Pickup(other, this, __NULL__);
pl.g_items |= ITEM_SUIT;
m_iValue = TRUE;
if (!target) {
UseOutput(other, m_strOnPlayerTouch);
} else {
UseTargets(other, TRIG_TOGGLE, m_flDelay);
}
if (real_owner || cvar("sv_playerslots") == 1) {
Destroy();
} else {
Disappear();
ScheduleThink(Respawn, 30.0f);
}
}
void
item_armorvest::Respawn(void)
{
SetSolid(SOLID_TRIGGER);
SetMovetype(MOVETYPE_TOSS);
SetOrigin(GetSpawnOrigin());
SetModel(GetSpawnModel());
SetSize(VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
m_iValue = FALSE;
ReleaseThink();
if (!real_owner && time > 30.0f)
Sound_Play(this, CHAN_ITEM, "item.respawn");
DropToFloor();
}
void
item_armorvest::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "OnPlayerTouch":
strValue = strreplace(",", ",_", strValue);
m_strOnPlayerTouch = strcat(m_strOnPlayerTouch, ",_", strValue);
break;
default:
super::SpawnKey(strKey, strValue);
break;
}
}
void
item_armorvest::Spawned(void)
{
super::Spawned();
precache_model(model);
if (m_strOnPlayerTouch)
m_strOnPlayerTouch = CreateOutput(m_strOnPlayerTouch);
}
void
item_armorvest::item_armorvest(void)
{
model = "models/barney_vest.mdl";
}

View File

View File

@ -45,17 +45,19 @@ item_suit::Touch(entity eToucher)
}
player pl = (player)other;
if (pl.g_items & ITEM_SUIT) {
return;
}
Logging_Pickup(other, this, __NULL__);
sound(other, CHAN_ITEM, "fvox/bell.wav", 1, ATTN_NORM);
sound(other, CHAN_VOICE, "fvox/hev_logon.wav", 1, ATTN_NORM);
StartSound("fvox/bell.wav", CHAN_ITEM, 0, true);
StartSound("fvox/hev_logon.wav", CHAN_VOICE, 0, true);
pl.g_items |= ITEM_SUIT;
m_iValue = TRUE;
if (!target) {
if (HasTriggerTarget() == false) {
UseOutput(other, m_strOnPlayerTouch);
} else {
UseTargets(other, TRIG_TOGGLE, m_flDelay);
@ -72,31 +74,45 @@ item_suit::Touch(entity eToucher)
void
item_suit::Respawn(void)
{
/* we need to delay the DropToFloor() by at least a frame.
otherwise they may just fall through an entity (func_wall, func_train etc.)
that came after this entity in the lump. */
static void AdjustSpawnPos(void) {
RestoreAngles();
SetOrigin(GetSpawnOrigin());
DropToFloor();
SetMovetype(MOVETYPE_TOSS);
}
if (cvar_string("fs_game") == "bshift") {
Destroy();
return;
}
SetSolid(SOLID_TRIGGER);
SetMovetype(MOVETYPE_TOSS);
SetOrigin(GetSpawnOrigin());
SetMovetype(MOVETYPE_TOSS);
SetModel(GetSpawnModel());
SetSize(VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
m_iValue = FALSE;
ReleaseThink();
if (!real_owner && time > 30.0f) {
StartSoundDef("item.respawn", CHAN_ITEM, true);
}
if (!real_owner && time > 30.0f)
Sound_Play(this, CHAN_ITEM, "item.respawn");
DropToFloor();
ScheduleThink(AdjustSpawnPos, 0.0f);
}
void
item_suit::SpawnKey(string strKey, string strValue)
item_suit::SpawnKey(string keyName, string setValue)
{
switch (strKey) {
switch (keyName) {
case "OnPlayerTouch":
strValue = strreplace(",", ",_", strValue);
m_strOnPlayerTouch = strcat(m_strOnPlayerTouch, ",_", strValue);
setValue = strreplace(",", ",_", setValue);
m_strOnPlayerTouch = strcat(m_strOnPlayerTouch, ",_", setValue);
break;
default:
super::SpawnKey(strKey, strValue);
super::SpawnKey(keyName, setValue);
break;
}
}

View File

@ -54,7 +54,7 @@ item_weaponbox::Touch(entity eToucher)
player pl = (player)eToucher;
Logging_Pickup(eToucher, this, __NULL__);
sound(pl, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM);
StartSoundDef("item_weaponbox.Pickup", CHAN_ITEM, true);
pl.ammo_9mm += ammo_9mm;
pl.ammo_357 += ammo_357;
@ -166,6 +166,7 @@ void
weaponbox_spawn(player spawner)
{
item_weaponbox weaponbox = spawn(item_weaponbox);
weaponbox.Spawned();
weaponbox.SetOrigin(spawner.origin);
weaponbox.setup(spawner);
}

View File

@ -21,11 +21,12 @@ class item_pickup:NSRenderableEntity
int m_iClip;
int m_iWasDropped;
int id;
void(void) item_pickup;
void item_pickup(void);
virtual void(void) Spawned;
virtual void(entity) Touch;
virtual void(int i) SetItem;
virtual void(void) Respawn;
virtual void(int) SetFloating;
virtual void Spawned(void);
virtual void Touch(entity);
virtual void SetItem(int i);
virtual void Respawn(void);
virtual void SetFloating(int);
virtual void PickupRespawn(void);
};

View File

@ -34,7 +34,7 @@ void item_pickup::Touch(entity eToucher)
Destroy();
} else {
Disappear();
ScheduleThink(Respawn, 30.0f);
ScheduleThink(PickupRespawn, 30.0f);
}
}
@ -51,10 +51,30 @@ void item_pickup::SetFloating(int i)
m_bFloating = rint(bound(0, m_bFloating, 1));
}
void
item_pickup::PickupRespawn(void)
{
Respawn();
Sound_Play(this, CHAN_ITEM, "item.respawn");
}
void item_pickup::Respawn(void)
{
SetSolid(SOLID_TRIGGER);
/* we need to delay the DropToFloor() by at least a frame.
otherwise they may just fall through an entity (func_wall, func_train etc.)
that came after this entity in the lump. */
static void AdjustSpawnPos(void) {
RestoreAngles();
SetOrigin(GetSpawnOrigin());
if (!m_bFloating) {
DropToFloor();
SetMovetype(MOVETYPE_TOSS);
}
}
SetOrigin(GetSpawnOrigin());
SetSolid(SOLID_TRIGGER);
botinfo = BOTINFO_WEAPON;
/* At some points, the item id might not yet be set */
@ -63,19 +83,7 @@ void item_pickup::Respawn(void)
}
SetSize([-16,-16,0], [16,16,16]);
ReleaseThink();
if (!m_iWasDropped && cvar("sv_playerslots") > 1) {
if (!real_owner && time > 30.0f)
Sound_Play(this, CHAN_ITEM, "item.respawn");
m_iClip = -1;
}
if (!m_bFloating) {
DropToFloor();
SetMovetype(MOVETYPE_TOSS);
}
ScheduleThink(AdjustSpawnPos, 0.0f);
}
void

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,22 +12,14 @@
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_babycrab (0 0.8 0.8) (-16 -16 0) (16 16 36)
HALF-LIFE (1998) ENTITY
Baby Headcrab
*/
class monster_babycrab:monster_headcrab
{
void(void) monster_babycrab;
};
void
monster_babycrab::monster_babycrab(void)
Game_ServerModelEvent(float flTimeStamp, int iCode, string strData)
{
switch (iCode) {
default:
Event_ServerModelEvent(flTimeStamp, iCode, strData);
break;
}
}

View File

@ -1,127 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_alien_controller (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Alien Controller
*/
enum
{
CON_ATTACK,
CON_ATTACK2,
CON_THROW,
CON_IDLE2,
CON_BLOCK,
CON_SHOOT,
CON_FLINCH,
CON_FLINCH2,
CON_FALL,
CON_FORWARD,
CON_BACKWARD,
CON_UP,
CON_DOWN,
CON_RIGHT,
CON_LEFT,
CON_IDLE,
CON_UNUSED,
CON_UNUSED2,
CON_DIE
};
class monster_alien_controller:NSMonster
{
float m_flIdleTime;
float m_flPainTime;
void(void) monster_alien_controller;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
};
void
monster_alien_controller::Pain(void)
{
super::Pain();
if (m_flPainTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_alien_controller.die");
SetFrame(CON_FLINCH + floor(random(0, 2)));
m_flPainTime = time + 0.25f;
}
void
monster_alien_controller::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(CON_DIE);
Sound_Play(this, CHAN_VOICE, "monster_alien_controller.die");
}
/* set the functional differences */
super::Death();
}
void
monster_alien_controller::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_alien_controller.idle");
}
void
monster_alien_controller::Respawn(void)
{
super::Respawn();
SetFrame(CON_IDLE);
}
void
monster_alien_controller::monster_alien_controller(void)
{
Sound_Precache("monster_alien_controller.alert");
Sound_Precache("monster_alien_controller.attack");
Sound_Precache("monster_alien_controller.die");
Sound_Precache("monster_alien_controller.idle");
Sound_Precache("monster_alien_controller.pain");
netname = "Alien Controller";
model = "models/controller.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
}

View File

@ -1,152 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_alien_grunt (0 0.8 0.8) (-32 -32 0) (32 32 64)
HALF-LIFE (1998) ENTITY
Alien Grunt
*/
enum
{
AG_IDLE,
AG_THREAT,
AG_WALK,
AG_RUN,
AG_LEFT,
AG_RIGHT,
AG_FLINCH,
AG_FLINCHBIG,
AG_ATTACK,
AG_ATTACK2,
AG_VICTORYSQUAT,
AG_VICTORYEAT,
AG_VICTORYSTAND,
AG_FLINCHARML,
AG_FLINCHLEGL,
AG_FLINCHARMR,
AG_FLINCHLEGR,
AG_SHOOTUP,
AG_SHOOTDOWN,
AG_SHOOT,
AG_SHOOTQUICK,
AG_SHOOTLONG,
AG_DIEHS,
AG_DIEGUT,
AG_DIEFORWARD,
AG_DIE,
AG_DIEBACK,
AG_FLOAT,
AG_SCARE,
AG_OPEN,
AG_SMASHRAIL,
AG_LAND
};
class monster_alien_grunt:NSMonster
{
float m_flIdleTime;
float m_flPainTime;
void(void) monster_alien_grunt;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
};
void
monster_alien_grunt::Pain(void)
{
super::Pain();
if (m_flPainTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_alien_grunt.pain");
SetFrame(AG_FLINCH + floor(random(0, 2)));
m_flPainTime = time + 0.25f;
}
void
monster_alien_grunt::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
/* headshots == different animation */
if (g_dmg_iHitBody == BODY_HEAD) {
if (random() < 0.5) {
SetFrame(AG_DIEHS);
} else {
SetFrame(AG_DIEFORWARD);
}
} else {
SetFrame(AG_DIE + floor(random(0, 2)));
}
Sound_Play(this, CHAN_VOICE, "monster_alien_grunt.die");
}
/* set the functional differences */
super::Death();
}
void
monster_alien_grunt::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_alien_grunt.idle");
}
void
monster_alien_grunt::Respawn(void)
{
super::Respawn();
SetFrame(AG_IDLE);
}
void
monster_alien_grunt::monster_alien_grunt(void)
{
Sound_Precache("monster_alien_grunt.alert");
Sound_Precache("monster_alien_grunt.attack");
Sound_Precache("monster_alien_grunt.die");
Sound_Precache("monster_alien_grunt.idle");
Sound_Precache("monster_alien_grunt.pain");
netname = "Alien Grunt";
model = "models/agrunt.mdl";
base_mins = [-32,-32,0];
base_maxs = [32,32,64];
base_health = Skill_GetValue("agrunt_health", 90);
}

View File

@ -1,253 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_alien_slave (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Alien Slave
*/
enum
{
SLV_IDLE,
SLV_IDLE2,
SLV_IDLE3,
SLV_CROUCH,
SLV_WALK,
SLV_WALK2,
SLV_RUN,
SLV_RIGHT,
SLV_LEFT,
SLV_JUMP,
SLV_STAIRUP,
SLV_ATTACK,
SLV_ATTACKZAP,
SLV_FLINCH,
SLV_FLINCHLA,
SLV_FLINCHRA,
SLV_FLINCHL,
SLV_FLINCHR,
SLV_DIEHS,
SLV_DIE,
SLV_DIEBACK,
SLV_DIEFORWARD,
SLV_COLLAR,
SLV_COLLAR2,
SLV_PUSHUP,
SLV_GRAB,
SLV_UPDOWN,
SLV_DOWNUP,
SLV_JIBBER,
SLV_JABBER
};
class monster_alien_slave:NSTalkMonster
{
float m_flIdleTime;
float m_flPainTime;
void(void) monster_alien_slave;
virtual void(void) Death;
virtual void(void) Pain;
virtual void(void) IdleChat;
virtual void(void) Respawn;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
virtual int(void) AttackMelee;
virtual void(void) AttackFlail;
virtual int(void) AttackRanged;
virtual void(void) AttackBeam;
};
int
monster_alien_slave::AnimIdle(void)
{
return SLV_IDLE;
}
int
monster_alien_slave::AnimWalk(void)
{
return SLV_WALK;
}
int
monster_alien_slave::AnimRun(void)
{
return SLV_RUN;
}
int
monster_alien_slave::AttackMelee(void)
{
/* visual */
AnimPlay(SLV_ATTACK);
m_flAttackThink = m_flAnimTime;
/* functional */
think = AttackFlail;
nextthink = time + 0.25f;
return (1);
}
void
monster_alien_slave::AttackFlail(void)
{
traceline(origin, m_eEnemy.origin, FALSE, this);
if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) {
Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss");
return;
}
Damage_Apply(trace_ent, this, 25, 0, 0);
Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit");
}
int
monster_alien_slave::AttackRanged(void)
{
/* visual */
AnimPlay(SLV_ATTACKZAP);
m_flAttackThink = m_flAnimTime;
Sound_Play(this, CHAN_VOICE, "monster_alien_slave.attack_charge");
/* functional */
think = AttackBeam;
nextthink = time + 1.5f;
return (1);
}
void
monster_alien_slave::AttackBeam(void)
{
traceline(origin, m_eEnemy.origin, FALSE, this);
Sound_Play(this, CHAN_WEAPON, "monster_alien_slave.attack_shoot");
if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) {
//Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss");
return;
}
Damage_Apply(trace_ent, this, 100, 0, 0);
}
void
monster_alien_slave::IdleChat(void)
{
if (m_flIdleTime > time) {
return;
}
Sentence(m_talkIdle);
m_flIdleTime = time + 5.0f + random(0,20);
}
void
monster_alien_slave::Pain(void)
{
super::Pain();
if (m_flPainTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_alien_slave.pain");
SetFrame(SLV_FLINCH + floor(random(0, 2)));
m_flPainTime = time + 0.25f;
}
void
monster_alien_slave::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
/* headshots == different animation */
if (g_dmg_iHitBody == BODY_HEAD) {
if (random() < 0.5) {
SetFrame(SLV_DIEHS);
} else {
SetFrame(SLV_DIEBACK);
}
} else {
SetFrame(SLV_DIE + floor(random(0, 3)));
}
Sound_Play(this, CHAN_VOICE, "monster_alien_slave.die");
}
/* set the functional differences */
super::Death();
}
void
monster_alien_slave::Respawn(void)
{
super::Respawn();
SetFrame(SLV_IDLE);
}
void
monster_alien_slave::monster_alien_slave(void)
{
Sound_Precache("monster_alien_slave.die");
Sound_Precache("monster_alien_slave.pain");
Sound_Precache("monster_alien_slave.attack_charge");
Sound_Precache("monster_alien_slave.attack_shoot");
Sound_Precache("monster_zombie.attackhit");
Sound_Precache("monster_zombie.attackmiss");
m_talkAnswer = "";
m_talkAsk = "";
m_talkAllyShot = "";
m_talkGreet = "SLV_ALERT";
m_talkIdle = "!SLV_IDLE";
m_talkSmelling = "";
m_talkStare = "";
m_talkSurvived = "";
m_talkWounded = "";
m_talkPlayerAsk = "";
m_talkPlayerGreet = "!SLV_ALERT";
m_talkPlayerIdle = "";
m_talkPlayerWounded1 = "";
m_talkPlayerWounded2 = "";
m_talkPlayerWounded3 = "";
m_talkUnfollow = "";
m_talkFollow = "";
m_talkStopFollow = "";
netname = "Alien Slave";
model = "models/islave.mdl";
base_health = Skill_GetValue("islave_health", 30);
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
m_iAlliance = MAL_ALIEN;
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_apache (0 0.8 0.8) (-300 -300 -172) (300 300 8)
HALF-LIFE (1998) ENTITY
Boeing AH-64 Apache
*/
class monster_apache:NSMonster
{
void(void) monster_apache;
virtual void(void) Respawn;
};
void monster_apache::Respawn(void)
{
super::Respawn();
movetype = MOVETYPE_NONE;
takedamage = DAMAGE_NO;
iBleeds = FALSE;
setsize(this, [-300,-300,-172], [300, 300, 8]);
}
void monster_apache::monster_apache(void)
{
netname = "Apache";
model = "models/apache.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
base_health = Skill_GetValue("apache_health", 250);
}

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_barnacle (0 0.8 0.8) (-16 -16 -36) (16 16 0)
HALF-LIFE (1998) ENTITY
Barnacle
*/
enum
{
BCL_IDLE,
BCL_IDLE2,
BCL_IDLE3,
BCL_FLINCH,
BCL_ATTACK,
BCL_CHEW,
BCL_DIE
};
class monster_barnacle:NSMonster
{
void(void) monster_barnacle;
virtual void(void) Death;
virtual void(void) Respawn;
virtual void(void) Physics;
};
void
monster_barnacle::Physics(void)
{
movetype = MOVETYPE_NONE;
}
void
monster_barnacle::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(BCL_DIE);
Sound_Play(this, CHAN_VOICE, "monster_barnacle.die");
}
/* set the functional differences */
super::Death();
}
void
monster_barnacle::Respawn(void)
{
super::Respawn();
SetFrame(BCL_IDLE);
}
void monster_barnacle::monster_barnacle(void)
{
Sound_Precache("monster_barnacle.attackchew");
Sound_Precache("monster_barnacle.attackpull");
Sound_Precache("monster_barnacle.die");
netname = "Barnacle";
model = "models/barnacle.mdl";
base_mins = [-16,-16,-36];
base_maxs = [16,16,0];
base_health = Skill_GetValue("barnacle_health", 25);
}

View File

@ -1,226 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_barney (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Barney Calhoun
*/
enum
{
BA_IDLE1,
BA_IDLE2,
BA_IDLE3,
BA_IDLE4,
BA_WALK,
BA_RUN,
BA_SHOOT1,
BA_SHOOT2,
BA_DRAW,
BA_HOLSTER,
BA_RELOAD,
BA_TURNLEFT,
BA_TURNRIGHT,
BA_FLINCH_LA,
BA_FLINCH_RA,
BA_FLINCH_LL,
BA_FLINCH_RL,
BA_FLINCH_SML
};
class monster_barney:NSTalkMonster
{
void(void) monster_barney;
virtual void(void) Respawn;
virtual void(void) OnPlayerUse;
virtual void(void) Pain;
virtual void(void) Death;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
virtual void(void) AttackDraw;
virtual void(void) AttackHolster;
virtual int(void) AttackMelee;
virtual int(void) AttackRanged;
virtual void(monsterState_t, monsterState_t) StateChanged;
};
int
monster_barney::AnimIdle(void)
{
return BA_IDLE1;
}
int
monster_barney::AnimWalk(void)
{
return BA_WALK;
}
int
monster_barney::AnimRun(void)
{
return BA_RUN;
}
void
monster_barney::AttackDraw(void)
{
AnimPlay(BA_DRAW);
m_flAttackThink = m_flAnimTime;
}
void
monster_barney::AttackHolster(void)
{
AnimPlay(BA_HOLSTER);
m_flAttackThink = m_flAnimTime;
}
int
monster_barney::AttackMelee(void)
{
return AttackRanged();
}
int
monster_barney::AttackRanged(void)
{
/* visual */
AnimPlay(BA_SHOOT1);
m_flAttackThink = time + 0.4f;
/* functional */
v_angle = vectoangles(m_eEnemy.origin - origin);
TraceAttack_FireBullets(1, origin + [0,0,16], 8, [0.01,0.01], 2);
Sound_Play(this, CHAN_WEAPON, "weapon_glock.fire");
return (1);
}
void
monster_barney::StateChanged(monsterState_t oldState, monsterState_t newState)
{
super::StateChanged(oldState, newState);
switch (newState) {
case MONSTER_AIMING:
if (oldState == MONSTER_ALERT)
AttackDraw();
break;
case MONSTER_ALERT:
if (oldState == MONSTER_AIMING)
AttackHolster();
break;
}
}
void
monster_barney::OnPlayerUse(void)
{
if (spawnflags & MSF_PREDISASTER) {
Sentence("!BA_POK");
return;
}
super::OnPlayerUse();
}
void
monster_barney::Pain(void)
{
/* don't bother if we're fully dead */
if (IsAlive() == false)
return;
super::Pain();
if (InAnimation() == true)
return;
if (random() < 0.25f)
return;
Sound_Speak(this, "monster_barney.pain");
AnimPlay(BA_FLINCH_LA + floor(random(0, 5)));
m_flAttackThink = m_flAnimTime;
}
void
monster_barney::Death(void)
{
if (IsAlive() == true) {
SetFrame(25 + floor(random(0, 6)));
Sound_Speak(this, "monster_barney.die");
}
/* now mark our state as 'dead' */
super::Death();
}
void
monster_barney::Respawn(void)
{
super::Respawn();
m_iFlags |= MONSTER_CANFOLLOW;
PlayerUse = OnPlayerUse;
}
void
monster_barney::monster_barney(void)
{
Sound_Precache("monster_barney.die");
Sound_Precache("monster_barney.pain");
/* TODO
* BA_MAD - When player gets too naughty
* */
m_talkAnswer = "!BA_ANSWER";
m_talkAsk = "!BA_QUESTION";
m_talkAllyShot = "!BA_SHOOT";
m_talkGreet = "";
m_talkIdle = "!BA_IDLE";
m_talkHearing = "!BA_HEAR";
m_talkSmelling = "!BA_SMELL";
m_talkStare = "!BA_STARE";
m_talkSurvived = "!BA_WOUND";
m_talkWounded = "!BA_WOUND";
m_talkPlayerAsk = "!BA_QUESTION";
m_talkPlayerGreet = "!BA_HELLO";
m_talkPlayerIdle = "!BA_IDLE";
m_talkPlayerWounded1 = "!BA_CUREA";
m_talkPlayerWounded2 = "!BA_CUREB";
m_talkPlayerWounded3 = "!BA_CUREC";
m_talkUnfollow = "!BA_WAIT";
m_talkFollow = "!BA_OK";
m_talkStopFollow = "!BA_STOP";
model = "models/barney.mdl";
netname = "Barney";
base_health = Skill_GetValue("barney_health", 35);
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
m_iAlliance = MAL_FRIEND;
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_barney_dead (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Barney's corpse
*/
class monster_barney_dead:NSTalkMonster
{
int m_iPose;
void(void) monster_barney_dead;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
};
void
monster_barney_dead::Respawn(void)
{
v_angle = GetSpawnAngles();
v_angle[0] = Math_FixDelta(v_angle[0]);
v_angle[1] = Math_FixDelta(v_angle[1]);
v_angle[2] = Math_FixDelta(v_angle[2]);
SetOrigin(GetSpawnOrigin());
SetAngles(v_angle);
SetSolid(SOLID_CORPSE);
SetMovetype(MOVETYPE_NONE);
SetModel(GetSpawnModel());
SetSize(VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
SetTakedamage(DAMAGE_YES);
SetHealth(0);
SetVelocity([0,0,0]);
SetFrame(35 + m_iPose);
iBleeds = TRUE;
}
void
monster_barney_dead::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "pose":
m_iPose = stoi(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
monster_barney_dead::monster_barney_dead(void)
{
model = "models/barney.mdl";
}

View File

@ -1,131 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_bigmomma (0 0.8 0.8) (-95 -95 0) (95 95 190)
HALF-LIFE (1998) ENTITY
Gonarch
*/
enum
{
GON_IDLE,
GON_IDLE2,
GON_WALK,
GON_RUN,
GON_DIE,
GON_CLAW,
GON_CLAW2,
GON_CLAW3,
GON_SPAWN,
GON_SHOOT,
GON_FLINCH,
GON_DEFEND,
GON_JUMP,
GON_ANGRY,
GON_ANGRY2,
GON_ANGRY3,
GON_BREAKWALL,
GON_FALL,
GON_FALL2,
GON_FALLDIE
};
class monster_bigmomma:NSMonster
{
float m_flIdleTime;
void(void) monster_bigmomma;
virtual void(void) Death;
virtual void(void) Pain;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
};
void
monster_bigmomma::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
/* timing needs to adjusted as sounds conflict */
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_bigmomma.idle");
}
void
monster_bigmomma::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_bigmomma.pain");
SetFrame(GON_FLINCH);
m_flAnimTime = time + 0.25f;
}
void
monster_bigmomma::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(GON_DIE);
Sound_Play(this, CHAN_VOICE, "monster_bigmomma.die");
}
/* set the functional differences */
super::Death();
}
void
monster_bigmomma::Respawn(void)
{
super::Respawn();
SetFrame(GON_IDLE);
}
void monster_bigmomma::monster_bigmomma(void)
{
Sound_Precache("monster_bigmomma.alert");
Sound_Precache("monster_bigmomma.attack");
Sound_Precache("monster_bigmomma.child");
Sound_Precache("monster_bigmomma.die");
Sound_Precache("monster_bigmomma.idle");
Sound_Precache("monster_bigmomma.pain");
Sound_Precache("monster_bigmomma.step");
netname = "Gonarch";
model = "models/big_mom.mdl";
/* health is based on factor, for it's not killable until last stage */
base_health = Skill_GetValue("bigmomma_health_factor", 1.5) * 300;
base_mins = [-95,-95,0];
base_maxs = [95,95,190];
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_bloater (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Flocking Floater
*/
class monster_bloater:NSMonster
{
void(void) monster_bloater;
};
void monster_bloater::monster_bloater(void)
{
netname = "Floater";
model = "models/floater.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
}

View File

@ -1,154 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_bullchicken (0 0.8 0.8) (-32 -32 0) (32 32 64)
HALF-LIFE (1998) ENTITY
Bullsquid
*/
enum
{
BULL_WALK,
BULL_RUN,
BULL_SURPIRSE,
BULL_FLINCH,
BULL_FLINCH2,
BULL_LEFT,
BULL_RIGHT,
BULL_IDLE,
BULL_WHIP,
BULL_BITE,
BULL_RANGE,
BULL_LOOK,
BULL_SEECRAB,
BULL_EAT,
BULL_INSPECT,
BULL_SNIFF,
BULL_DIE,
BULL_DIE2,
BULL_JUMP,
BULL_DRAGIDLE,
BULL_DRAG,
BULL_SCARE,
BULL_FALLIDLE,
BULL_FALL
};
/* the growls are used in combination with the bite sounds
* for close range attacks
*/
class monster_bullchicken:NSMonster
{
float m_flIdleTime;
void(void) monster_bullchicken;
virtual void(void) Death;
virtual void(void) Pain;
virtual void(void) IdleNoise;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
};
int
monster_bullchicken::AnimIdle(void)
{
return BULL_IDLE;
}
int
monster_bullchicken::AnimWalk(void)
{
return BULL_WALK;
}
int
monster_bullchicken::AnimRun(void)
{
return BULL_RUN;
}
void
monster_bullchicken::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
/* timing needs to adjusted as sounds conflict */
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_bullchicken.idle");
}
void
monster_bullchicken::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_bullchicken.pain");
SetFrame((random() < 0.5) ? BULL_FLINCH : BULL_FLINCH2);
m_flAnimTime = time + 0.25f;
}
void
monster_bullchicken::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
/* two different animations */
SetFrame((random() < 0.5) ? BULL_DIE : BULL_DIE2);
Sound_Play(this, CHAN_VOICE, "monster_bullchicken.die");
}
/* set the functional differences */
super::Death();
}
void monster_bullchicken::monster_bullchicken(void)
{
Sound_Precache("monster_bullchicken.alert");
Sound_Precache("monster_bullchicken.attack");
Sound_Precache("monster_bullchicken.attackbite");
Sound_Precache("monster_bullchicken.attackshoot");
Sound_Precache("monster_bullchicken.die");
Sound_Precache("monster_bullchicken.idle");
Sound_Precache("monster_bullchicken.pain");
netname = "Bullsquid";
model = "models/bullsquid.mdl";
base_health = Skill_GetValue("bullsquid_health", 40);
base_mins = [-32,-32,0];
base_maxs = [32,32,64];
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_cockroach (0 0.8 0.8) (-4 -4 0) (4 4 4)
HALF-LIFE (1998) ENTITY
Cockroach
*/
class monster_cockroach:NSMonster
{
void(void) monster_cockroach;
virtual void(void) Death;
};
void
monster_cockroach::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
Sound_Play(this, CHAN_VOICE, "monster_cockroach.die");
}
/* make sure we gib this thing */
health = -100;
/* set the functional differences */
super::Death();
}
void monster_cockroach::monster_cockroach(void)
{
Sound_Precache("monster_cockroach.die");
netname = "Cockroach";
model = "models/roach.mdl";
base_mins = [-1,-1,0];
base_maxs = [1,1,1];
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_flyer_flock (0 0.8 0.8) (-16 -16 0) (16 16 16)
HALF-LIFE (1998) ENTITY
Boid
*/
class monster_flyer_flock:NSMonster
{
void(void) monster_flyer_flock;
};
void monster_flyer_flock::monster_flyer_flock(void)
{
netname = "Boid";
model = "models/aflock.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,16];
}

View File

@ -1,145 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_gargantua (0 0.8 0.8) (-32 -32 0) (32 32 128)
HALF-LIFE (1998) ENTITY
Gargantua
*/
enum
{
GARG_IDLE,
GARG_IDLE2,
GARG_IDLE3,
GARG_IDLE4,
GARG_WALK,
GARG_RUN,
GARG_SHOOT,
GARG_SHOOT2,
GARG_ATTACK,
GARG_STOMP,
GARG_LEFT,
GARG_RIGHT,
GARG_FLINCH,
GARG_FLINCH2,
GARG_DIE,
GARG_BITEHEAD,
GARG_THROW,
GARG_SMASH,
GARG_ROLLCAR,
GARG_KICKCAR,
GARG_PUSHCAR,
GARG_BUST
};
class monster_gargantua:NSMonster
{
float m_flIdleTime;
void(void) monster_gargantua;
virtual void(void) Spawned;
virtual void(void) Death;
virtual void(void) Pain;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
};
void
monster_gargantua::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
/* timing needs to adjusted as sounds conflict */
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_gargantua.idle");
}
void
monster_gargantua::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_gargantua.pain");
SetFrame((random() < 0.5) ? GARG_FLINCH : GARG_FLINCH2);
m_flAnimTime = time + 0.25f;
}
void
monster_gargantua::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(GARG_DIE);
Sound_Play(this, CHAN_VOICE, "monster_gargantua.die");
}
/* set the functional differences */
super::Death();
}
void
monster_gargantua::Respawn(void)
{
super::Respawn();
SetFrame(GARG_IDLE);
/* takes damage from explosives only
* takedamage = DAMAGE_NO; */
iBleeds = FALSE;
}
void
monster_gargantua::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_gargantua.alert");
Sound_Precache("monster_gargantua.attack");
Sound_Precache("monster_gargantua.attackflame");
Sound_Precache("monster_gargantua.attackflameon");
Sound_Precache("monster_gargantua.attackflameoff");
Sound_Precache("monster_gargantua.die");
Sound_Precache("monster_gargantua.idle");
Sound_Precache("monster_gargantua.pain");
Sound_Precache("monster_gargantua.step");
}
void monster_gargantua::monster_gargantua(void)
{
netname = "Gargantua";
model = "models/garg.mdl";
base_health = Skill_GetValue("gargantua_health", 800);
base_mins = [-32,-32,0];
base_maxs = [32,32,128];
}

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_gman (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
G-Man
*/
enum
{
GMAN_IDLE,
GMAN_IDLETIE,
GMAN_IDLELOOK,
GMAN_IDLE2,
GMAN_OPEN,
GMAN_STAND,
GMAN_WALK,
GMAN_YES,
GMAN_NO,
GMAN_NOBIG,
GMAN_YESBIG,
GMAN_LISTEN,
GMAN_LOOKDOWN,
GMAN_LOOKDOWN2
};
class monster_gman:NSTalkMonster
{
void(void) monster_gman;
virtual void(void) Respawn;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
};
int
monster_gman::AnimIdle(void)
{
return GMAN_IDLE;
}
int
monster_gman::AnimWalk(void)
{
return GMAN_WALK;
}
int
monster_gman::AnimRun(void)
{
return GMAN_WALK;
}
void monster_gman::Respawn(void)
{
/* he can't die, he's the G-Man! */
super::Respawn();
SetFrame(GMAN_IDLE);
takedamage = DAMAGE_NO;
iBleeds = FALSE;
}
void monster_gman::monster_gman(void)
{
netname = "G-Man";
model = "models/gman.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
}

View File

@ -1,187 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_headcrab (0 0.8 0.8) (-16 -16 0) (16 16 36)
HALF-LIFE (1998) ENTITY
Headcrab
*/
enum
{
HC_IDLE1,
HC_IDLE2,
HC_IDLE3,
HC_WALK,
HC_RUN,
HC_ANGRY,
HC_FLINCH,
HC_DIE,
HC_180_LEFT,
HC_180_RIGHT,
HC_JUMP,
HC_JUMP_VARIATION1,
HC_JUMP_VARIATION2,
HC_YAW_ADJUSTMENT,
HC_HEADCRABBED1,
HC_HEADCRABBED2,
HC_HEADIDLE,
HC_CRASHIDLE,
HC_CRASH,
HC_STRUGGLEIDLE,
HC_STRUGGLE
};
class monster_headcrab:NSMonster
{
float m_flIdleTime;
void(void) monster_headcrab;
virtual void(void) Spawned;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) IdleNoise;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
virtual int(void) AttackRanged;
virtual void(entity) Touch;
};
int
monster_headcrab::AnimIdle(void)
{
return HC_IDLE1;
}
int
monster_headcrab::AnimWalk(void)
{
return HC_WALK;
}
int
monster_headcrab::AnimRun(void)
{
return HC_RUN;
}
int
monster_headcrab::AttackRanged(void)
{
/* visual */
if (random() < 0.5)
AnimPlay(HC_JUMP);
else
AnimPlay(HC_JUMP_VARIATION1);
m_flAttackThink = m_flAnimTime;
Sound_Play(this, CHAN_VOICE, "monster_headcrab.attack");
/* functional */
makevectors(vectoangles(m_eEnemy.origin - origin));
velocity = v_forward * 512 + [0,0,250];
return (1);
}
void
monster_headcrab::Touch(entity eToucher)
{
if (eToucher.takedamage == DAMAGE_YES)
if (frame == HC_JUMP || frame == HC_JUMP_VARIATION1)
Damage_Apply(eToucher, this, 500, 0, 0);
}
void
monster_headcrab::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_headcrab.pain");
SetFrame(HC_FLINCH);
m_flAnimTime = time + 0.25f;
}
void
monster_headcrab::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(HC_DIE);
Sound_Play(this, CHAN_VOICE, "monster_headcrab.die");
}
/* set the functional differences */
super::Death();
}
void
monster_headcrab::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_headcrab.idle");
}
void
monster_headcrab::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_headcrab.alert");
Sound_Precache("monster_headcrab.attack");
Sound_Precache("monster_headcrab.attackhit");
Sound_Precache("monster_headcrab.die");
Sound_Precache("monster_headcrab.idle");
Sound_Precache("monster_headcrab.pain");
}
void
monster_headcrab::monster_headcrab(void)
{
if (classname == "monster_babycrab") {
netname = "Baby Headcrab";
model = "models/baby_headcrab.mdl";
base_health = Skill_GetValue ("headcrab_health", 10) /4;
} else {
netname = "Headcrab";
model = "models/headcrab.mdl";
base_health = Skill_GetValue("headcrab_health", 10);
}
base_mins = [-16,-16,0];
base_maxs = [16,16,36];
m_iAlliance = MAL_ALIEN;
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_hevsuit_dead (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
HEV-Suit/Player's corpse
*/
class monster_hevsuit_dead:NSMonster
{
int m_iPose;
void(void) monster_hevsuit_dead;
virtual void(void) Respawn;
virtual void(void) Gib;
virtual void(string, string) SpawnKey;
};
void
monster_hevsuit_dead::Gib(void)
{
takedamage = DAMAGE_NO;
FX_GibHuman(origin, vectoangles(origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
Disappear();
}
void
monster_hevsuit_dead::Respawn(void)
{
v_angle = GetSpawnAngles();
v_angle[0] = Math_FixDelta(v_angle[0]);
v_angle[1] = Math_FixDelta(v_angle[1]);
v_angle[2] = Math_FixDelta(v_angle[2]);
SetOrigin(GetSpawnOrigin());
angles = v_angle;
solid = SOLID_CORPSE;
movetype = MOVETYPE_NONE;
SetModel(GetSpawnModel());
setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
takedamage = DAMAGE_YES;
health = 0;
velocity = [0,0,0];
iBleeds = TRUE;
SetFrame(73 + m_iPose);
}
void
monster_hevsuit_dead::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "pose":
m_iPose = stoi(strValue);
break;
case "body":
SetBody(stoi(strValue) + 1);
break;
case "skin":
SetSkin(stoi(strValue));
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
monster_hevsuit_dead::monster_hevsuit_dead(void)
{
model = "models/player.mdl";
m_iBody = 2;
}

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_hgrunt_dead (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Human Grunt's corpse
*/
class monster_hgrunt_dead:NSMonster
{
int m_iPose;
void(void) monster_hgrunt_dead;
virtual void(void) Respawn;
virtual void(void) Gib;
virtual void(string, string) SpawnKey;
};
void
monster_hgrunt_dead::Gib(void)
{
takedamage = DAMAGE_NO;
FX_GibHuman(origin, vectoangles(origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
Disappear();
}
void
monster_hgrunt_dead::Respawn(void)
{
v_angle = GetSpawnAngles();
v_angle[0] = Math_FixDelta(v_angle[0]);
v_angle[1] = Math_FixDelta(v_angle[1]);
v_angle[2] = Math_FixDelta(v_angle[2]);
SetOrigin(GetSpawnOrigin());
angles = v_angle;
solid = SOLID_CORPSE;
movetype = MOVETYPE_NONE;
SetModel(GetSpawnModel());
setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
takedamage = DAMAGE_YES;
health = 0;
velocity = [0,0,0];
iBleeds = TRUE;
SetFrame(44 + m_iPose);
}
void
monster_hgrunt_dead::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "pose":
m_iPose = stoi(strValue);
break;
case "body":
m_iBody = stoi(strValue) + 1;
break;
case "skin":
skin = stoi(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
monster_hgrunt_dead::monster_hgrunt_dead(void)
{
model = "models/hgrunt.mdl";
}

View File

@ -1,209 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_houndeye (0 0.8 0.8) (-16 -16 0) (16 16 36)
HALF-LIFE (1998) ENTITY
Houndeye
*/
#define HE_BLAST_RADIUS 384
enum
{
HE_IDLE,
HE_IDLE2,
HE_IDLE3,
HE_RUN,
HE_RUN2,
HE_RUN3,
HE_DIE,
HE_DIE2,
HE_DIE3,
HE_DIE4,
HE_ATTACK,
HE_FLINCH,
HE_FLINCH2,
HE_DIE5,
HE_WALKLIMP,
HE_WALK2,
HE_LEADERLOOK,
HE_SLEEP,
HE_GOTOSLEEP,
HE_WAKE,
HE_IDLEMAD,
HE_IDLEMAD2,
HE_IDLEMAD3,
HE_INSPECT,
HE_EAT,
HE_LEFT,
HE_RIGHT,
HE_JUMPBACK,
HE_WAKEFAST,
HE_WHIMPER,
HE_JUMPWINDOW
};
class monster_houndeye:NSMonster
{
float m_flIdleTime;
void(void) monster_houndeye;
virtual void(void) Spawned;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
virtual int(void) AttackMelee;
virtual void(void) AttackBlast;
};
int
monster_houndeye::AttackMelee(void)
{
AnimPlay(HE_ATTACK);
Sound_Play(this, CHAN_WEAPON, "monster_houndeye.attack");
m_flAttackThink = m_flAnimTime + 0.5f;
think = AttackBlast;
nextthink = m_flAnimTime;
return (1);
}
void
monster_houndeye::AttackBlast(void)
{
float new_dmg;
float dist;
float diff;
vector pos;
float dmg = 50; /* TODO: set proper damage */
for (entity e = world; (e = findfloat(e, ::takedamage, DAMAGE_YES));) {
pos[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
pos[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
if (e.classname == "monster_houndeye")
continue;
/* don't bother if it's not anywhere near us */
dist = vlen(origin - pos);
if (dist > HE_BLAST_RADIUS) {
continue;
}
/* can we physically hit this thing? */
other = world;
traceline(e.origin, origin, MOVE_OTHERONLY, this);
if (trace_fraction < 1.0f)
dmg *= 0.5f;
/* calculate new damage values */
diff = vlen(origin - pos);
diff = (HE_BLAST_RADIUS - diff) / HE_BLAST_RADIUS;
new_dmg = rint(dmg * diff);
if (diff > 0) {
Damage_Apply(e, this, new_dmg, 0, DMG_EXPLODE);
}
}
Sound_Play(this, CHAN_WEAPON, "monster_houndeye.blast");
}
void
monster_houndeye::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_houndeye.pain");
SetFrame(HE_FLINCH + floor(random(0, 2)));
m_flAnimTime = time + 0.25f;
}
void
monster_houndeye::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(HE_DIE + floor(random(0, 4)));
Sound_Play(this, CHAN_VOICE, "monster_houndeye.die");
}
/* set the functional differences */
super::Death();
}
void
monster_houndeye::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_houndeye.idle");
}
void
monster_houndeye::Respawn(void)
{
super::Respawn();
SetFrame(HE_IDLE);
}
void
monster_houndeye::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_houndeye.alert");
Sound_Precache("monster_houndeye.attack");
Sound_Precache("monster_houndeye.blast");
Sound_Precache("monster_houndeye.die");
Sound_Precache("monster_houndeye.idle");
Sound_Precache("monster_houndeye.pain");
}
void
monster_houndeye::monster_houndeye(void)
{
netname = "Houndeye";
model = "models/houndeye.mdl";
base_health = Skill_GetValue("houndeye_health", 20);
base_mins = [-16,-16,0];
base_maxs = [16,16,36];
m_iAlliance = MAL_ALIEN;
}

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_human_assassin (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Black Ops - Assassin
*/
enum
{
HAS_IDLE,
HAS_IDLE3,
HAS_IDLE2,
HAS_RUN,
HAS_WALK,
HAS_SHOOT,
HAS_NADETHROW,
HAS_KICK,
HAS_KICK2,
HAS_DIERUN,
HAS_DIEBACK,
HAS_DIE,
HAS_JUMP,
HAS_UP,
HAS_UNUSED,
HAS_ATTACKDOWN,
HAS_LAND
};
class monster_human_assassin:NSMonster
{
float m_flIdleTime;
void(void) monster_human_assassin;
virtual void(void) Death;
virtual void(void) Respawn;
};
void
monster_human_assassin::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
/* headshots == different animation */
/* this animation may not have been used, but it looks cool */
if (g_dmg_iHitBody == BODY_HEAD) {
if (random() < 0.5) {
SetFrame(HAS_DIERUN);
} else {
SetFrame(HAS_DIEBACK);
}
} else {
SetFrame(HAS_DIE);
}
}
/* set the functional differences */
super::Death();
}
void
monster_human_assassin::Respawn(void)
{
super::Respawn();
frame = HAS_IDLE;
}
void
monster_human_assassin::monster_human_assassin(void)
{
netname = "Assassin";
model = "models/hassassin.mdl";
base_health = Skill_GetValue("hassassin_health", 50);
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
}

View File

@ -1,323 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_human_grunt (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
HECU - Human Grunt
*/
enum
{
GR_WALK,
GR_RUN,
GR_VICTORYDANCE,
GR_COWER,
GR_FLINCH,
GR_LEFTLEGFLINCH,
GR_RIGHTLEGFLINCH,
GR_RIGHTARMFLINCH,
GR_LEFTARMFLINCH,
GR_LAUNCHNADE,
GR_THROWNADE,
GR_IDLE,
GR_IDLE2,
GR_COMBATIDLE,
GR_FRONTKICK,
GR_CROUCHIDLE,
GR_CROUCHWAIT,
GR_CROUCHSHOOTMP5,
GR_STANDSHOOTMP5,
GR_RELOADMP5,
GR_CROUCHSHOOTSG,
GR_STANDSHOOTSG,
GR_RELOADSG,
GR_SIGNALADV,
GR_SIGNALFLANK,
GR_SIGNALRETREAT,
GR_DROPNADE,
GR_LIMPWALK,
GR_LIMPRUN,
GR_TURNLEFT,
GR_TURNRIGHT,
GR_STRAFELEFT,
GR_STRAFERIGHT,
GR_DIEBACK,
GR_DIEFORWARD,
GR_DIE,
GR_DIEBACK2,
GR_DIEHS,
GR_DIEGUT,
GR_BARNACLE1,
GR_BARNACLE2,
GR_BARNACLE3,
GR_BARNACLE4,
GR_DEADSTOMACH,
GR_DEADSTOMACH2,
GR_DEADSIDE,
GR_DEADSITTING,
GR_REPELJUMP,
GR_REPEL,
GR_REPELSHOOT,
GR_REPELLAND,
GR_REPELDIE,
GR_DRAGHOLEIDLE,
GR_DRAGHOLE,
GR_BUSTWALL,
GR_HOPRAIL,
GR_CONVERSE1,
GR_CONVERSE2,
GR_STARTLELEFT,
GR_STRRTLERIGHT,
GR_DIVE,
GR_DEFUSE,
GR_CORNER1,
GR_CORNER2,
GR_STONETOSS,
GR_CLIFFDIE,
GR_DIVESIDEIDLE,
GR_DIVESIDE,
GR_DIVEKNEELIDLE,
GR_DIVEKNEEL,
GR_WMBUTTON,
GR_WM,
GR_WMJUMP,
GR_BUSTWINDOW,
GR_DRAGLEFT,
GR_DRAGRIGHT,
GR_TRACKWAVE,
GR_TRACKDIVE,
GR_FLYBACK,
GR_IMPALED,
GR_JUMPTRACKS,
GR_THROWPIPE,
GR_PLUNGER
};
class monster_human_grunt:NSTalkMonster
{
float m_flIdleTime;
int m_iMP5Burst;
void(void) monster_human_grunt;
virtual void(void) Scream;
virtual void(void) IdleChat;
virtual void(void) Respawn;
virtual void(void) Spawned;
virtual void(void) Pain;
virtual void(void) Death;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
virtual int(void) AttackRanged;
virtual int(void) AttackMelee;
virtual void(void) AttackKick;
};
int
monster_human_grunt::AnimIdle(void)
{
return GR_IDLE;
}
int
monster_human_grunt::AnimWalk(void)
{
return GR_WALK;
}
int
monster_human_grunt::AnimRun(void)
{
return GR_RUN;
}
int
monster_human_grunt::AttackMelee(void)
{
/* visual */
AnimPlay(GR_FRONTKICK);
m_flAttackThink = m_flAnimTime;
Sound_Play(this, CHAN_VOICE, "monster_zombie.attack");
/* functional */
think = AttackKick;
nextthink = time + 0.25f;
return (1);
}
void
monster_human_grunt::AttackKick(void)
{
traceline(origin, m_eEnemy.origin, FALSE, this);
if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) {
//Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss");
return;
}
Damage_Apply(trace_ent, this, 25, 0, 0);
//Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit");
}
int
monster_human_grunt::AttackRanged(void)
{
/* visual */
AnimPlay(GR_STANDSHOOTMP5);
Sound_Play(this, CHAN_WEAPON, "weapon_mp5.shoot");
if (m_iMP5Burst >= 2) {
m_iMP5Burst = 0;
m_flAttackThink = time + 0.4f;
} else {
m_iMP5Burst++;
m_flAttackThink = time + 0.1f;
}
/* functional */
v_angle = vectoangles(m_eEnemy.origin - origin);
TraceAttack_FireBullets(1, origin + [0,0,16], 8, [0.01,0.01], 2);
return (1);
}
void monster_human_grunt::Scream(void)
{
if (m_flIdleTime > time) {
return;
}
Sentence(m_talkAllyShot);
m_flIdleTime = time + 5.0f;
}
void monster_human_grunt::IdleChat(void)
{
if (m_flIdleTime > time) {
return;
}
Sentence(m_talkIdle);
/* Sentence(m_talkPlayerIdle); */
/* come up with logic to make them repsone to questions
* Sentence(m_talkAsk);
* Sentence(m_talkAnswer);
*/
m_flIdleTime = time + 5.0f + random(0,20);
}
void
monster_human_grunt::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_human_grunt.pain");
SetFrame(GR_FLINCH);
m_flAnimTime = time + 0.25f;
}
void
monster_human_grunt::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
/* headshots == different animation */
/* this animation may not have been used, but it looks cool */
if (g_dmg_iHitBody == BODY_HEAD) {
if (random() < 0.5) {
SetFrame(GR_DIEHS);
} else {
SetFrame(GR_DIEBACK);
}
} else {
SetFrame(GR_DIE);
}
}
Sound_Play(this, CHAN_VOICE, "monster_human_grunt.die");
/* set the functional differences */
super::Death();
}
void
monster_human_grunt::Respawn(void)
{
super::Respawn();
SetFrame(GR_IDLE);
}
void
monster_human_grunt::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_human_grunt.die");
Sound_Precache("monster_human_grunt.pain");
}
void monster_human_grunt::monster_human_grunt(void)
{
/* Adding some into other slots in hopes it feels right
* listed below are other setences that might need their own:
* !HG_MONST - Monster HG_ALERT
* !HG_GREN - Grenade toss
* !HG_CHECK - Sector check question
* !HG_CLEAR - Sector clear response */
m_talkAnswer = "!HG_ANSWER";
m_talkAsk = "!HG_QUEST";
m_talkAllyShot = "!HG_COVER";
m_talkGreet = "";
m_talkIdle = "!HG_IDLE";
m_talkSmelling = "";
m_talkStare = "";
m_talkSurvived = "!HG_CLEAR";
m_talkWounded = "!HG_CHECK";
m_talkPlayerAsk = "";
m_talkPlayerGreet = "!HG_ALERT";
m_talkPlayerIdle = "!HG_CHARGE";
m_talkPlayerWounded1 = "";
m_talkPlayerWounded2 = "";
m_talkPlayerWounded3 = "";
m_talkUnfollow = "";
m_talkFollow = "";
m_talkStopFollow = "";
netname = "Grunt";
model = "models/hgrunt.mdl";
base_health = Skill_GetValue("hgrunt_health", 50);
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
m_iAlliance = MAL_ENEMY;
}

View File

@ -1,144 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_ichthyosaur (0 0.8 0.8) (-32 -32 0) (32 32 64)
HALF-LIFE (1998) ENTITY
Ichthyosaur
*/
enum
{
ICHY_IDLE,
ICHY_SWIM,
ICHY_THRUST,
ICHY_DIE1,
ICHY_DIE2,
ICHY_FLINCH,
ICHY_FLINCH2,
ICHY_DIE3,
ICHY_BITER,
ICHY_BITEL,
ICHY_ATTACK,
ICHY_RIGHT,
ICHY_LEFT,
ICHY_180,
ICHY_HITCAGE,
ICHY_JUMP
};
class monster_ichthyosaur:NSMonster
{
float m_flIdleTime;
void(void) monster_ichthyosaur;
virtual void(void) Spawned;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
};
void
monster_ichthyosaur::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_ichthyosaur.pain");
SetFrame(ICHY_FLINCH + floor(random(0, 2)));
m_flAnimTime = time + 0.25f;
}
void
monster_ichthyosaur::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
int r = floor(random(0,3));
switch (r) {
case 1:
SetFrame(ICHY_DIE2);
break;
case 2:
SetFrame(ICHY_DIE3);
break;
default:
SetFrame(ICHY_DIE1);
break;
}
Sound_Play(this, CHAN_VOICE, "monster_ichthyosaur.die");
}
/* set the functional differences */
super::Death();
}
void
monster_ichthyosaur::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_ichthyosaur.idle");
}
void
monster_ichthyosaur::Respawn(void)
{
super::Respawn();
SetFrame(ICHY_IDLE);
}
void
monster_ichthyosaur::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_ichthyosaur.alert");
Sound_Precache("monster_ichthyosaur.attack");
Sound_Precache("monster_ichthyosaur.die");
Sound_Precache("monster_ichthyosaur.idle");
Sound_Precache("monster_ichthyosaur.pain");
}
void
monster_ichthyosaur::monster_ichthyosaur(void)
{
netname = "Ichthyosaur";
model = "models/icky.mdl";
base_mins = [-32,-32,0];
base_maxs = [32,32,64];
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_leech (0 0.8 0.8) (-6 -6 0) (6 6 6)
HALF-LIFE (1998) ENTITY
Leech
*/
enum
{
LEECH_SWIM,
LEECH_SWIM2,
LEECH_ATTACK,
LEECH_HOVER,
LEECH_LEFT,
LEECH_RIGHT,
LEECH_DIE,
LEECH_DIEEND
};
class monster_leech:NSMonster
{
float m_flIdleTime;
void(void) monster_leech;
virtual void(void) Spawned;
virtual void(void) Death;
virtual void(void) DeathEnd;
virtual void(void) Respawn;
};
void
monster_leech::DeathEnd(void)
{
SetFrame(LEECH_DIEEND);
}
void
monster_leech::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(LEECH_DIE);
think = DeathEnd;
nextthink = time + 1.0f;
}
/* set the functional differences */
super::Death();
}
void
monster_leech::Respawn(void)
{
super::Respawn();
SetFrame(LEECH_SWIM);
}
void
monster_leech::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_leech.alert");
Sound_Precache("monster_leech.attack");
}
void monster_leech::monster_leech(void)
{
netname = "Leech";
model = "models/leech.mdl";
base_mins = [-6,-6,0];
base_maxs = [6,6,6];
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_miniturret (0 0.8 0.8) (-16 -16 -32) (16 16 32)
HALF-LIFE (1998) ENTITY
Automatic Turret (small)
*/
enum
{
TUR_IDLE,
TUR_FIRE,
TUR_SPIN,
TUR_DEPLOY,
TUR_RETIRE,
TUR_DIE
};
class monster_miniturret:NSMonster
{
void(void) monster_miniturret;
};
void monster_miniturret::monster_miniturret(void)
{
netname = "Mini-Turret";
model = "models/miniturret.mdl";
base_mins = [-16,-16,-32];
base_maxs = [16,16,32];
}

View File

@ -1,142 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_nihilanth (0 0.8 0.8) (-192 -192 0) (192 192 384)
HALF-LIFE (1998) ENTITY
Nihilanth
*/
enum
{
NIL_IDLE,
NIL_ATTACK,
NIL_ATTACK2,
NIL_THROW,
NIL_BLOCK,
NIL_RECHARGE,
NIL_IDLEOPEN,
NIL_ATTACKOPEN,
NIL_ATTACKOPEN2,
NIL_FLINCH,
NIL_FLINCH2,
NIL_FALL,
NIL_DIE,
NIL_FORWARD,
NIL_BACK,
NIL_UP,
NIL_DOWN,
NIL_RIGHT,
NIL_LEFT,
NIL_WALK2,
NIL_SHOOT
};
class monster_nihilanth:NSMonster
{
float m_flIdleTime;
void(void) monster_nihilanth;
virtual void(void) Spawned;
virtual void(void) Death;
virtual void(void) Pain;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
};
void
monster_nihilanth::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
/* timing needs to adjusted as sounds conflict */
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_nihilanth.idle");
}
void
monster_nihilanth::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_nihilanth.pain");
SetFrame((random() < 0.5) ? NIL_FLINCH : NIL_FLINCH2);
m_flAnimTime = time + 0.25f;
}
void
monster_nihilanth::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(NIL_DIE);
Sound_Play(this, CHAN_VOICE, "monster_nihilanth.die");
}
/* set the functional differences */
super::Death();
}
void
monster_nihilanth::Respawn(void)
{
super::Respawn();
SetFrame(NIL_IDLE);
}
void
monster_nihilanth::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_nihilanth.attack");
Sound_Precache("monster_nihilanth.attackball");
Sound_Precache("monster_nihilanth.attackballmove");
Sound_Precache("monster_nihilanth.die");
Sound_Precache("monster_nihilanth.idle");
Sound_Precache("monster_nihilanth.pain");
Sound_Precache("monster_nihilanth.recharge");
}
void
monster_nihilanth::monster_nihilanth(void)
{
netname = "Nihilanth";
model = "models/nihilanth.mdl";
base_health = Skill_GetValue("nihilanth_health", 800);
base_mins = [-192,-192,-32];
base_maxs = [192,192,384];
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_osprey (0 0.8 0.8) (-480 -480 -112) (480 480 24)
HALF-LIFE (1998) ENTITY
Bell Boeing VV-22 Osprey
*/
class monster_osprey:NSMonster
{
void(void) monster_osprey;
virtual void(void) Respawn;
};
void monster_osprey::Respawn(void)
{
super::Respawn();
takedamage = DAMAGE_NO;
iBleeds = FALSE;
}
void monster_osprey::monster_osprey(void)
{
netname = "Osprey";
model = "models/osprey.mdl";
base_mins = [-480,-480,-112];
base_maxs = [480,480,24];
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_rat (0 0.8 0.8) (-6 -6 0) (6 6 6)
HALF-LIFE (1998) ENTITY
Rat
*/
class monster_rat:NSMonster
{
void(void) monster_rat;
};
void monster_rat::monster_rat(void)
{
netname = "Rat";
model = "models/bigrat.mdl";
base_mins = [-6,-6,-0];
base_maxs = [6,6,6];
}

View File

@ -1,221 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_scientist (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Scientist
*/
enum
{
SCIA_WALK,
SCIA_WALKSCARED,
SCIA_RUN,
SCIA_RUNSCARED,
SCIA_RUNLOOK,
SCIA_180LEFT,
SCIA_180RIGHT,
SCIA_FLINCH,
SCIA_PAIN,
SCIA_PAINLEFT,
SCIA_PAINRIGHT,
SCIA_PAINLEGLEFT,
SCIA_PAINLEGRIGHT,
SCIA_IDLE1,
SCIA_IDLE2,
SCIA_IDLE3,
SCIA_IDLE4,
SCIA_IDLE5,
SCIA_IDLE6,
SCIA_SCARED_END,
SCIA_SCARED1,
SCIA_SCARED2,
SCIA_SCARED3,
SCIA_SCARED4,
SCIA_PANIC,
SCIA_FEAR1,
SCIA_FEAR2,
SCIA_CRY,
SCIA_SCI1,
SCIA_SCI2,
SCIA_SCI3,
SCIA_DIE_SIMPLE,
SCIA_DIE_FORWARD1,
SCIA_DIE_FORWARD2,
SCIA_DIE_BACKWARD,
SCIA_DIE_HEADSHOT,
SCIA_DIE_GUTSHOT,
SCIA_LYING1,
SCIA_LYING2,
SCIA_DEADSIT,
SCIA_DEADTABLE1,
SCIA_DEADTABLE2,
SCIA_DEADTABLE3
};
class monster_scientist:NSTalkMonster
{
void(void) monster_scientist;
virtual void(void) Spawned;
virtual void(void) Respawn;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) PlayerUse;
virtual void(string, string) SpawnKey;
};
void
monster_scientist::PlayerUse(void)
{
if (spawnflags & MSF_PREDISASTER) {
Sentence("!SC_POK");
return;
}
super::OnPlayerUse();
}
void
monster_scientist::Pain(void)
{
WarnAllies();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
if (IsAlive() == true) {
Sound_Speak(this, "monster_scientist.pain");
SetFrame(SCIA_FLINCH + floor(random(0, 6)));
m_iFlags |= MONSTER_FEAR;
m_flAnimTime = time + 0.25f;
}
}
void
monster_scientist::Death(void)
{
WarnAllies();
if (IsAlive() == true) {
SetFrame(SCIA_DIE_SIMPLE + floor(random(0, 6)));
Sound_Speak(this, "monster_scientist.die");
}
/* now mark our state as 'dead' */
super::Death();
}
void
monster_scientist::Respawn(void)
{
super::Respawn();
m_iFlags |= MONSTER_CANFOLLOW;
}
void
monster_scientist::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "body":
SetBody(stoi(strValue) + 1);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
monster_scientist::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_scientist.die");
Sound_Precache("monster_scientist.pain");
/* has the body not been overriden, etc. choose a character for us */
if (m_iBody == -1) {
SetBody((int)floor(random(1,5)));
}
switch (m_iBody) {
case 1:
m_flPitch = 105;
netname = "Walter";
break;
case 2:
m_flPitch = 100;
netname = "Einstein";
break;
case 3:
m_flPitch = 95;
netname = "Luther";
SetSkin(1);
break;
default:
m_flPitch = 100;
netname = "Slick";
}
}
void
monster_scientist::monster_scientist(void)
{
if (spawnflags & MSF_PREDISASTER) {
m_talkAsk = "";
m_talkPlayerAsk = "!SC_PQUEST";
m_talkPlayerGreet = "!SC_PHELLO";
m_talkPlayerIdle = "!SC_PIDLE";
} else {
m_talkAsk = "!SC_QUESTION";
m_talkPlayerAsk = "!SC_QUESTION";
m_talkPlayerGreet = "!SC_HELLO";
m_talkPlayerIdle = "!SC_PIDLE";
}
m_talkAnswer = "!SC_ANSWER";
m_talkAllyShot = "!SC_PLFEAR";
m_talkGreet = "";
m_talkIdle = "!SC_IDLE";
m_talkHearing = "!SC_HEAR";
m_talkSmelling = "!SC_SMELL";
m_talkStare = "!SC_STARE";
m_talkSurvived = "!SC_WOUND";
m_talkWounded = "!SC_MORTAL";
/* they seem to use predisaster lines regardless of disaster state */
m_talkPlayerWounded1 = "!SC_CUREA";
m_talkPlayerWounded2 = "!SC_CUREB";
m_talkPlayerWounded3 = "!SC_CUREC";
m_talkUnfollow = "!SC_WAIT";
m_talkFollow = "!SC_OK";
m_talkStopFollow = "!SC_STOP";
m_iBody = -1;
model = "models/scientist.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
base_health = Skill_GetValue("scientist_health", 20);
}

View File

@ -1,121 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_scientist_dead (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Scientists' corpse
*/
enum
{
DSCIA_LYING1 = 37,
DSCIA_LYING2,
DSCIA_DEADSIT,
DSCIA_DEADTABLE1,
DSCIA_DEADTABLE2,
DSCIA_DEADTABLE3,
DSCIA_DEADHANG
};
class monster_scientist_dead:NSMonster
{
int m_iPose;
void(void) monster_scientist_dead;
virtual void(void) Respawn;
virtual void(void) Gib;
virtual void(string, string) SpawnKey;
};
void
monster_scientist_dead::Gib(void)
{
takedamage = DAMAGE_NO;
FX_GibHuman(origin, vectoangles(origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
Disappear();
}
void
monster_scientist_dead::Respawn(void)
{
v_angle = GetSpawnAngles();
v_angle[0] = Math_FixDelta(v_angle[0]);
v_angle[1] = Math_FixDelta(v_angle[1]);
v_angle[2] = Math_FixDelta(v_angle[2]);
SetOrigin(GetSpawnOrigin());
angles = v_angle;
solid = SOLID_CORPSE;
movetype = MOVETYPE_NONE;
SetModel(GetSpawnModel());
setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MIN + [0,0,36]);
takedamage = DAMAGE_YES;
health = 0;
velocity = [0,0,0];
iBleeds = TRUE;
switch (m_iPose) {
case 1:
SetFrame(DSCIA_LYING2);
break;
case 2:
SetFrame(DSCIA_DEADSIT);
break;
case 3:
SetFrame(DSCIA_DEADHANG);
break;
case 4:
SetFrame(DSCIA_DEADTABLE1);
break;
case 5:
SetFrame(DSCIA_DEADTABLE2);
break;
case 6:
SetFrame(DSCIA_DEADTABLE3);
break;
default:
SetFrame(DSCIA_LYING1);
}
DropToFloor();
}
void
monster_scientist_dead::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "pose":
m_iPose = stoi(strValue);
break;
case "body":
SetBody(stoi(strValue) + 1);
break;
case "skin":
SetSkin(stoi(strValue));
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
monster_scientist_dead::monster_scientist_dead(void)
{
model = "models/scientist.mdl";
}

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_sentry (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Sentry Gun
*/
enum
{
SENT_IDLE,
SENT_FIRE,
SENT_SPIN,
SENT_DEPLOY,
SENT_RETIRE,
SENT_DIE
};
class monster_sentry:NSMonster
{
void(void) monster_sentry;
virtual void(void) Spawned;
virtual void(void) Death;
virtual void(void) Respawn;
};
void
monster_sentry::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
SetFrame(SENT_DIE);
Sound_Play(this, CHAN_VOICE, "monster_sentry.die");
}
/* set the functional differences */
super::Death();
}
void
monster_sentry::Respawn(void)
{
super::Respawn();
SetFrame(SENT_IDLE);
iBleeds = FALSE;
}
void
monster_sentry::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_sentry.alert");
Sound_Precache("monster_sentry.die");
Sound_Precache("monster_sentry.idle");
Sound_Precache("monster_sentry.retract");
}
void monster_sentry::monster_sentry(void)
{
netname = "Sentry";
model = "models/sentry.mdl";
base_health = Skill_GetValue("sentry_health", 40);
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
}

View File

@ -1,139 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_sitting_scientist (0 0.8 0.8) (-14 -14 0) (14 14 36)
HALF-LIFE (1998) ENTITY
Sitting scientists
*/
enum
{
DSCIA_LYING1 = 37,
DSCIA_LYING2,
DSCIA_DEADSIT,
DSCIA_DEADTABLE1,
DSCIA_DEADTABLE2,
DSCIA_DEADTABLE3,
DSCIA_DEADHANG
};
class monster_sitting_scientist:NSTalkMonster
{
int m_iPose;
void(void) monster_sitting_scientist;
virtual void(void) Respawn;
virtual void(void) Spawned;
virtual void(void) Death;
virtual void(void) Gib;
virtual void(string, string) SpawnKey;
};
void
monster_sitting_scientist::Gib(void)
{
SetTakedamage(DAMAGE_NO);
FX_GibHuman(GetOrigin(), vectoangles(GetOrigin() - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
Disappear();
}
void
monster_sitting_scientist::Death(void)
{
if (GetHealth() < -50) {
Gib();
return;
}
}
void
monster_sitting_scientist::Respawn(void)
{
v_angle = GetSpawnAngles();
v_angle[0] = Math_FixDelta(v_angle[0]);
v_angle[1] = Math_FixDelta(v_angle[1]);
v_angle[2] = Math_FixDelta(v_angle[2]);
SetOrigin(GetSpawnOrigin());
SetAngles(v_angle);
SetSolid(SOLID_BBOX);
SetMovetype(MOVETYPE_NONE);
SetModel(GetSpawnModel());
SetSize([-14,-14,0],[14,14,36]);
SetTakedamage(DAMAGE_YES);
SetHealth(0);
SetVelocity([0,0,0]);
SetFrame(74);
DropToFloor();
iBleeds = TRUE;
}
void
monster_sitting_scientist::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "pose":
m_iPose = stoi(strValue);
break;
case "body":
SetBody(stoi(strValue) + 1);
break;
case "skin":
SetSkin(stoi(strValue));
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
monster_sitting_scientist::Spawned(void)
{
super::Spawned();
/* has the body not been overriden, etc. choose a character for us */
if (m_iBody == -1) {
SetBody((int)floor(random(1,5)));
}
switch (m_iBody) {
case 1:
m_flPitch = 105;
netname = "Walter";
break;
case 2:
m_flPitch = 100;
netname = "Einstein";
break;
case 3:
m_flPitch = 95;
netname = "Luther";
SetSkin(1);
break;
default:
m_flPitch = 100;
netname = "Slick";
}
}
void
monster_sitting_scientist::monster_sitting_scientist(void)
{
model = "models/scientist.mdl";
}

View File

@ -1,139 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_tentacle (0 0.8 0.8) (-32 -32 0) (32 32 64)
HALF-LIFE (1998) ENTITY
Tentacle
*/
enum
{
TE_IDLEPIT,
TE_RISE,
TE_TOFLOOR1,
TE_IDLE,
TE_PISSED,
TE_SMALLRISE,
TE_WAVE,
TE_STRIKE,
TE_TAP,
TE_ROTATE,
TE_REAR,
TE_REARIDLE,
TE_TOLEV1,
TE_IDELLEV1,
TE_FIDGETLEV1,
TE_SNAPLEV1,
TE_STRIKELEV1,
TE_TAPLEV1,
TE_ROTATELEV1,
TE_REARLEV1,
TE_REARIDELLEV1,
TE_TOLEV2,
TE_IDLELEV2,
TE_FIDGETLEV2,
TE_SNAPLEV2,
TE_SWINGLEV2,
TE_TUTLEV2,
TE_STRIKELEV2,
TE_TAPLEV2,
TE_ROTATELEV2,
TE_REARLEV2,
TE_FREAKDIE,
TE_REARIDLE2,
TE_TOLEV3,
TE_IDLELEV3,
TE_FIDGETLEV3,
TE_SIDELEV3,
TE_SWIPELEV3,
TE_STRIKELEV3,
TE_TAPLEV3,
TE_ROTATELEV3,
TE_REARLEV3,
TE_REARIDLELEV3,
TE_DOORLEV1,
TE_ENGINELEV3,
TE_ENGINEIDLE,
TE_ENGINESWAY,
TE_ENGINESWAT,
TE_ENGINEBOB,
TE_ENGINEDEATH,
TE_ENGINEDEATH2,
TE_ENGINEDEATH3,
TE_GRABIDLE,
TE_GRAB
};
class monster_tentacle:NSMonster
{
float m_flIdleTime;
void(void) monster_tentacle;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
virtual void(void) Spawned;
};
void
monster_tentacle::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
/* timing needs to adjusted as sounds conflict */
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_tentacle.idle");
}
void
monster_tentacle::Respawn(void)
{
super::Respawn();
/* not entirely true, takes damage then retreats and reheals */
takedamage = DAMAGE_NO;
iBleeds = FALSE;
SetFrame(TE_IDLE);
}
void
monster_tentacle::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_tentacle.alert");
Sound_Precache("monster_tentacle.attack");
Sound_Precache("monster_tentacle.die");
Sound_Precache("monster_tentacle.idle");
}
void
monster_tentacle::monster_tentacle(void)
{
netname = "Tentacle";
model = "models/tentacle2.mdl";
base_mins = [-32,-32,0];
base_maxs = [32,32,64];
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_turret (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Automatic Turret (large)
*/
enum
{
TUR_IDLE,
TUR_FIRE,
TUR_SPIN,
TUR_DEPLOY,
TUR_RETIRE,
TUR_DIE
};
class monster_turret:NSMonster
{
void(void) monster_turret;
};
void monster_turret::monster_turret(void)
{
netname = "Turret";
model = "models/turret.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
}

View File

@ -1,229 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED monster_zombie (0 0.8 0.8) (-16 -16 0) (16 16 72)
HALF-LIFE (1998) ENTITY
Zombie
*/
enum
{
ZO_IDLE,
ZO_TURNLEFT,
ZO_TURNRIGHT,
ZO_FLINCHSM,
ZO_FLINCH,
ZO_FLINCHBIG,
ZO_RISE,
ZO_FALLING,
ZO_ATTACK1,
ZO_ATTACK2,
ZO_WALK,
ZO_FLINCHLA,
ZO_FLINCHRA,
ZO_FLINCHLEFT,
ZO_FLINCHRIGHT,
ZO_DIEHS,
ZO_DIEHS2,
ZO_DIE,
ZO_DIE2,
ZO_DIE3,
ZO_PAUSE,
ZO_WALLBUST,
ZO_WALLKICK,
ZO_WINDOWBUST,
ZO_SODA,
ZO_SLIDEIDLE,
ZO_SLIDE,
ZO_VENTIDLE,
ZO_VENT,
ZO_DEADIDLE,
ZO_DEAD,
ZO_FREAKDIE,
ZO_FREAK,
ZO_EATTABLE,
ZO_EAT,
ZO_EATSTAND,
ZO_DOORIP,
ZO_PULLSCI,
ZO_EAT2,
ZO_EAT2STAND,
ZO_VENT2IDLE,
ZO_VENT2,
ZO_HAUL,
ZO_RISESNACK
};
class monster_zombie:NSMonster
{
float m_flIdleTime;
void(void) monster_zombie;
virtual void(void) Spawned;
virtual void(void) Pain;
virtual void(void) Death;
virtual void(void) IdleNoise;
virtual void(void) Respawn;
virtual int(void) AnimIdle;
virtual int(void) AnimWalk;
virtual int(void) AnimRun;
virtual int(void) AttackMelee;
virtual void(void) AttackFlail;
};
int
monster_zombie::AnimIdle(void)
{
return ZO_IDLE;
}
int
monster_zombie::AnimWalk(void)
{
return ZO_WALK;
}
int
monster_zombie::AnimRun(void)
{
return ZO_WALK;
}
int
monster_zombie::AttackMelee(void)
{
/* visual */
if (random() < 0.5)
AnimPlay(ZO_ATTACK1);
else
AnimPlay(ZO_ATTACK2);
m_flAttackThink = m_flAnimTime;
Sound_Play(this, CHAN_VOICE, "monster_zombie.attack");
/* functional */
think = AttackFlail;
nextthink = time + 0.25f;
return (1);
}
void
monster_zombie::AttackFlail(void)
{
traceline(origin, m_eEnemy.origin, FALSE, this);
if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) {
Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss");
return;
}
Damage_Apply(trace_ent, this, 25, 0, 0);
Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit");
}
void
monster_zombie::Pain(void)
{
super::Pain();
if (m_flAnimTime > time) {
return;
}
if (random() < 0.25f) {
return;
}
Sound_Play(this, CHAN_VOICE, "monster_zombie.pain");
SetFrame(ZO_FLINCH + floor(random(0, 2)));
m_flAnimTime = time + 0.25f;
}
void
monster_zombie::Death(void)
{
/* if we're already dead (corpse) don't change animations */
if (IsAlive() == true) {
/* headshots == different animation */
if (g_dmg_iHitBody == BODY_HEAD) {
if (random() < 0.5) {
SetFrame(ZO_DIEHS);
} else {
SetFrame(ZO_DIEHS2);
}
} else {
SetFrame(ZO_DIE + floor(random(0, 3)));
}
Sound_Play(this, CHAN_VOICE, "monster_zombie.pain");
}
/* set the functional differences */
super::Death();
}
void
monster_zombie::IdleNoise(void)
{
/* don't make noise if we're dead (corpse) */
if (IsAlive() == false) {
return;
}
if (m_flIdleTime > time) {
return;
}
m_flIdleTime = time + random(2,10);
Sound_Play(this, CHAN_VOICE, "monster_zombie.idle");
}
void
monster_zombie::Respawn(void)
{
super::Respawn();
SetFrame(ZO_IDLE);
}
void
monster_zombie::Spawned(void)
{
super::Spawned();
Sound_Precache("monster_zombie.alert");
Sound_Precache("monster_zombie.attack");
Sound_Precache("monster_zombie.attackhit");
Sound_Precache("monster_zombie.attackmiss");
Sound_Precache("monster_zombie.idle");
Sound_Precache("monster_zombie.pain");
}
void
monster_zombie::monster_zombie(void)
{
netname = "Zombie";
model = "models/zombie.mdl";
base_health = Skill_GetValue("zombie_health", 50);
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
m_iAlliance = MAL_ALIEN;
}

View File

@ -14,89 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
====================
UseWorkaround
====================
*/
void
UseWorkaround(entity eTarget)
{
eActivator = self;
entity eOldSelf = self;
self = eTarget;
self.PlayerUse();
self = eOldSelf;
}
void
UnUseWorkaround(entity eTarget)
{
eActivator = self;
entity eOldSelf = self;
self = eTarget;
if (self.PlayerUseUnpressed)
self.PlayerUseUnpressed();
self = eOldSelf;
}
/*
====================
Player_UseDown
====================
*/
void
Player_UseDown(void)
{
vector vecSrc;
player pl = (player)self;
if (self.health <= 0) {
return;
} else if (!(self.flags & FL_USE_RELEASED)) {
return;
}
makevectors(self.v_angle);
vecSrc = self.origin + self.view_ofs;
int oldmask = self.hitcontentsmaski;
self.hitcontentsmaski = CONTENTBITS_POINTSOLID;
traceline(vecSrc, vecSrc + (v_forward * 64), MOVE_HITMODEL, self);
self.hitcontentsmaski = oldmask;
if (trace_ent.PlayerUse) {
self.flags &= ~FL_USE_RELEASED;
UseWorkaround(trace_ent);
pl.last_used = trace_ent;
/* Some entities want to support Use spamming */
if (!(self.flags & FL_USE_RELEASED)) {
sound(self, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE);
}
} else {
sound(self, CHAN_ITEM, "common/wpn_denyselect.wav", 0.25, ATTN_IDLE);
self.flags &= ~FL_USE_RELEASED;
}
}
/*
====================
Player_UseUp
====================
*/
void
Player_UseUp(void) {
player pl = (player)self;
if (!(self.flags & FL_USE_RELEASED)) {
UnUseWorkaround(pl.last_used);
pl.last_used = world;
self.flags |= FL_USE_RELEASED;
}
}
void Weapons_Draw(player pl);
void

41
src/server/progs.src Executable file → Normal file
View File

@ -19,43 +19,7 @@ defs.h
../shared/include.src
monster_apache.qc
monster_alien_controller.qc
monster_alien_grunt.qc
monster_alien_slave.qc
monster_barnacle.qc
monster_barney.qc
monster_barney_dead.qc
monster_bigmomma.qc
monster_bloater.qc
monster_bullchicken.qc
monster_cockroach.qc
monster_flyer_flock.qc
monster_gargantua.qc
monster_gman.qc
monster_headcrab.qc
monster_babycrab.qc
monster_hevsuit_dead.qc
monster_houndeye.qc
monster_human_grunt.qc
monster_hgrunt_dead.qc
monster_human_assassin.qc
monster_ichthyosaur.qc
monster_leech.qc
monster_miniturret.qc
monster_nihilanth.qc
monster_osprey.qc
monster_rat.qc
monster_scientist_dead.qc
monster_sitting_scientist.qc
monster_scientist.qc
monster_sentry.qc
monster_tentacle.qc
monster_turret.qc
monster_zombie.qc
player.qc
spectator.qc
items.qc
item_longjump.qc
item_suit.qc
@ -75,11 +39,10 @@ ammo.qc
gamerules.qc
gamerules_singleplayer.qc
gamerules_multiplayer.qc
client.qc
server.qc
../../../base/src/server/damage.qc
damage.qc
flashlight.qc
../../../base/src/server/modelevent.qc
modelevent.qc
spawn.qc

View File

@ -27,9 +27,9 @@ Game_InitRules(void)
void
Game_Worldspawn(void)
{
Sound_Precache("player.die");
Sound_Precache("player.fall");
Sound_Precache("player.lightfall");
Sound_Precache("Player.FlashLightOff");
Sound_Precache("Player.FlashLightOn");
Sound_Precache("item_weaponbox.Pickup");
precache_model("models/player.mdl");
precache_model("models/w_weaponbox.mdl");

View File

@ -13,35 +13,3 @@
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void info_player_start(void)
{
self.solid = SOLID_TRIGGER;
self.botinfo = BOTINFO_SPAWNPOINT;
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
setorigin_safe(self, self.origin);
}
void info_player_deathmatch(void)
{
self.solid = SOLID_TRIGGER;
self.botinfo = BOTINFO_SPAWNPOINT;
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
setorigin_safe(self, self.origin);
}
void info_player_team1(void)
{
self.classname = "info_player_deathmatch";
self.botinfo = BOTINFO_SPAWNPOINT;
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
setorigin_safe(self, self.origin);
}
void info_player_team2(void)
{
self.classname = "info_player_deathmatch";
self.botinfo = BOTINFO_SPAWNPOINT;
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
setorigin_safe(self, self.origin);
}

View File

@ -16,5 +16,6 @@
enum
{
EV_GAUSSBEAM = EV_SEPARATOR
EV_GAUSSBEAM = EV_SEPARATOR,
EV_GIBALIEN
};

View File

@ -45,7 +45,7 @@ FX_Blood(vector pos, vector color)
#else
static void Blood_Touch(void)
{
if (self.think != Util_Destroy) {
if (self.think != NSEntity::Destroy) {
if (serverkeyfloat("*bspversion") == BSPVER_HL)
Decals_Place(self.origin, sprintf("{blood%d", floor(random(1,9))));
else {
@ -54,7 +54,21 @@ FX_Blood(vector pos, vector color)
}
}
self.think = Util_Destroy;
self.think = NSEntity::Destroy;
self.nextthink = time + 5.0f;
}
static void ABlood_Touch(void)
{
if (self.think != NSEntity::Destroy) {
if (serverkeyfloat("*bspversion") == BSPVER_HL)
Decals_Place(self.origin, sprintf("{yblood%d", floor(random(1,9))));
else {
decal_pickwall(self, self.origin);
pointparticles(DECAL_BLOOD, g_tracedDecal.endpos, g_tracedDecal.normal, 1);
}
}
self.think = NSEntity::Destroy;
self.nextthink = time + 5.0f;
}
@ -89,7 +103,10 @@ FX_Blood(vector pos, vector color)
ePart.SetSolid(SOLID_BBOX);
ePart.SetSize([0,0,0], [0,0,0]);
ePart.touch = Blood_Touch;
if (color[1] != 0 && color[2] != 0)
ePart.touch = ABlood_Touch;
else
ePart.touch = Blood_Touch;
/* ignore player physics */
ePart.dimension_solid = 1;

View File

@ -1,164 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
void
FX_BreakModel_Init(void)
{
precache_model("models/glassgibs.mdl");
precache_model("models/woodgibs.mdl");
precache_model("models/metalplategibs.mdl");
precache_model("models/fleshgibs.mdl");
precache_model("models/ceilinggibs.mdl");
precache_model("models/computergibs.mdl");
precache_model("models/rockgibs.mdl");
precache_model("models/cindergibs.mdl");
precache_sound("debris/bustglass1.wav");
precache_sound("debris/bustglass2.wav");
precache_sound("debris/bustglass3.wav");
precache_sound("debris/bustcrate1.wav");
precache_sound("debris/bustcrate2.wav");
precache_sound("debris/bustcrate3.wav");
precache_sound("debris/bustmetal1.wav");
precache_sound("debris/bustmetal2.wav");
precache_sound("debris/bustflesh1.wav");
precache_sound("debris/bustflesh2.wav");
precache_sound("debris/bustconcrete1.wav");
precache_sound("debris/bustconcrete2.wav");
precache_sound("debris/bustceiling.wav");
}
#endif
void
FX_BreakModel(int count, vector vMins, vector vMaxs, vector vVel, float fStyle)
{
#ifdef SERVER
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_MODELGIB);
WriteCoord(MSG_MULTICAST, vMins[0]);
WriteCoord(MSG_MULTICAST, vMins[1]);
WriteCoord(MSG_MULTICAST, vMins[2]);
WriteCoord(MSG_MULTICAST, vMaxs[0]);
WriteCoord(MSG_MULTICAST, vMaxs[1]);
WriteCoord(MSG_MULTICAST, vMaxs[2]);
WriteByte(MSG_MULTICAST, fStyle);
WriteByte(MSG_MULTICAST, count);
msg_entity = self;
vector vWorldPos;
vWorldPos[0] = vMins[0] + (0.5 * (vMaxs[0] - vMins[0]));
vWorldPos[1] = vMins[1] + (0.5 * (vMaxs[1] - vMins[1]));
vWorldPos[2] = vMins[2] + (0.5 * (vMaxs[2] - vMins[2]));
multicast(vWorldPos, MULTICAST_PVS);
#else
static void FX_BreakModel_Remove(void) { remove(self) ; }
float fModelCount = 0;
vector vecPos;
string sModel = "";
switch (fStyle) {
case GSMATERIAL_GLASS:
case GSMATERIAL_GLASS_UNBREAKABLE:
sModel = "models/glassgibs.mdl";
fModelCount = 8;
break;
case GSMATERIAL_WOOD:
sModel = "models/woodgibs.mdl";
fModelCount = 3;
break;
case GSMATERIAL_METAL:
sModel = "models/metalplategibs.mdl";
fModelCount = 13;
break;
case GSMATERIAL_FLESH:
sModel = "models/fleshgibs.mdl";
fModelCount = 4;
break;
case GSMATERIAL_TILE:
sModel = "models/ceilinggibs.mdl";
fModelCount = 4;
break;
case GSMATERIAL_COMPUTER:
sModel = "models/computergibs.mdl";
fModelCount = 15;
break;
case GSMATERIAL_ROCK:
sModel = "models/rockgibs.mdl";
fModelCount = 3;
break;
default:
case GSMATERIAL_CINDER:
sModel = "models/cindergibs.mdl";
fModelCount = 9;
break;
}
vector vWorldPos;
vWorldPos = vMins + (0.5 * (vMaxs - vMins));
switch (fStyle) {
case GSMATERIAL_GLASS:
pointsound(vWorldPos, sprintf("debris/bustglass%d.wav", random(1, 4)), 1.0f, ATTN_NORM);
break;
case GSMATERIAL_WOOD:
pointsound(vWorldPos, sprintf("debris/bustcrate%d.wav", random(1, 4)), 1.0f, ATTN_NORM);
break;
case GSMATERIAL_METAL:
case GSMATERIAL_COMPUTER:
pointsound(vWorldPos, sprintf("debris/bustmetal%d.wav", random(1, 3)), 1.0f, ATTN_NORM);
break;
case GSMATERIAL_FLESH:
pointsound(vWorldPos, sprintf("debris/bustflesh%d.wav", random(1, 3)), 1.0f, ATTN_NORM);
break;
case GSMATERIAL_CINDER:
case GSMATERIAL_ROCK:
pointsound(vWorldPos, sprintf("debris/bustconcrete%d.wav", random(1, 4)), 1.0f, ATTN_NORM);
break;
case GSMATERIAL_TILE:
pointsound(vWorldPos, "debris/bustceiling.wav", 1.0f, ATTN_NORM);
break;
}
for (int i = 0; i < count; i++) {
entity eGib = spawn();
eGib.classname = "gib";
vecPos[0] = vMins[0] + (random() * (vMaxs[0] - vMins[0]));
vecPos[1] = vMins[1] + (random() * (vMaxs[1] - vMins[1]));
vecPos[2] = vMins[2] + (random() * (vMaxs[2] - vMins[2]));
setorigin(eGib, vecPos);
setmodel(eGib, sModel);
setcustomskin(eGib, "", sprintf("geomset 0 %f\n", random(1, fModelCount + 1)));
eGib.movetype = MOVETYPE_BOUNCE;
eGib.solid = SOLID_NOT;
eGib.avelocity[0] = random()*600;
eGib.avelocity[1] = random()*600;
eGib.avelocity[2] = random()*600;
eGib.think = FX_BreakModel_Remove;
eGib.nextthink = time + 10;
if ((fStyle == GSMATERIAL_GLASS) || (fStyle == GSMATERIAL_GLASS_UNBREAKABLE)) {
eGib.alpha = 0.5f;
}
eGib.drawmask = MASK_ENGINE;
}
#endif
}

80
src/shared/fx_corpse.qc Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef SERVER
#define CORPSES_MAX 16
entity g_bodies;
void
FX_Corpse_Init(void)
{
entity next = spawn(NSRenderableEntity);
g_bodies = next;
for ( int i = 0; i <= CORPSES_MAX; i++ ) {
next.classname = "corpse";
next.owner = spawn(NSRenderableEntity);
if ( i == CORPSES_MAX ) {
next.owner = g_bodies;
} else {
next = next.owner;
}
}
}
entity
FX_Corpse_Next(void)
{
entity r = g_bodies;
g_bodies = g_bodies.owner;
return r;
}
void
FX_Corpse_Update(void)
{
NSEntity meSelf = (NSEntity)self;
meSelf.frame1time += frametime;
if (meSelf.frame1time < 10.0)
meSelf.ScheduleThink(FX_Corpse_Update, 0.0f);
}
entity
FX_Corpse_Spawn(player pl, float anim)
{
NSRenderableEntity body_next = (NSRenderableEntity)FX_Corpse_Next();
body_next.SetMovetype(MOVETYPE_BOUNCE);
body_next.SetSolid(SOLID_CORPSE);
body_next.SetModel(pl.GetModel());
if (pl.flags & FL_CROUCHING) {
body_next.SetOrigin(pl.GetOrigin() + [0,0,32]);
} else {
body_next.SetOrigin(pl.GetOrigin());
}
body_next.SetSize(pl.GetMins(), pl.GetMaxs());
body_next.SetAngles(pl.GetAngles());
body_next.SetVelocity(pl.GetVelocity() + [0,0,120]);
body_next.SetFrame(anim);
body_next.ScheduleThink(FX_Corpse_Update, 0.0f);
body_next.colormap = pl.colormap;
body_next.frame1time = 0.0f;
return (entity)body_next;
}
#endif

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
var int FX_EXPLOSION_MAIN;
var int FX_EXPLOSION_BS;
var int FX_EXPLOSION_SPARK;
void
FX_Explosion_Init(void)
{
Sound_Precache("fx.explosion");
precache_model("sprites/fexplo.spr");
FX_EXPLOSION_MAIN = particleeffectnum("fx_explosion.main");
FX_EXPLOSION_BS = particleeffectnum("fx_explosion.blacksmoke");
FX_EXPLOSION_SPARK = particleeffectnum("fx_spark.effect");
}
#endif
void
FX_Explosion(vector vecPos)
{
#ifdef SERVER
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_EXPLOSION);
WriteCoord(MSG_MULTICAST, vecPos[0]);
WriteCoord(MSG_MULTICAST, vecPos[1]);
WriteCoord(MSG_MULTICAST, vecPos[2]);
msg_entity = self;
multicast(vecPos, MULTICAST_PVS);
#else
static void FX_Explosion_Spark(void)
{
if (self.alpha < 0) {
remove(self);
return;
}
pointparticles(FX_EXPLOSION_SPARK, self.origin, randomvec(), 1);
self.alpha--;
self.nextthink = time + 0.1f + (random() * 0.1f);
}
static float FX_Explosion_DLight(void)
{
dynamiclight_add(self.origin, 256 * self.alpha, [1.0,0.45,0]);
self.alpha -= frametime;
if (self.alpha <= 0.0f) {
remove(self);
} else {
addentity(self);
}
return PREDRAW_NEXT;
}
entity dlight = spawn();
setorigin(dlight, vecPos);
dlight.predraw = FX_Explosion_DLight;
dlight.drawmask = MASK_ENGINE;
dlight.alpha = 2.0f;
DecalGroups_Place("ExplosionScorch", vecPos);
vecPos[2] += 48;
env_sprite eExplosion = spawn(env_sprite);
makevectors(view_angles);
setorigin(eExplosion, vecPos + [0,0,48] + (v_forward * -32));
setmodel(eExplosion, "sprites/fexplo.spr");
Sound_Play(eExplosion, CHAN_WEAPON, "fx.explosion");
//eExplosion.think = FX_Explosion_Animate;
eExplosion.SetRenderMode(RM_ADDITIVE);
eExplosion.SetRenderAmt(1.0f);
eExplosion.SetRenderColor([1,1,1]);
eExplosion.drawmask = MASK_ENGINE;
eExplosion.m_iMaxFrame = modelframecount(eExplosion.modelindex);
eExplosion.m_bLoops = 0;
eExplosion.m_flFramerate = 20;
eExplosion.nextthink = time + 0.05f;
eExplosion.scale = 2.0f;
for (int i = 0; i < 2; i++) {
entity sparks = spawn();
sparks.alpha = 5;
sparks.movetype = MOVETYPE_TOSS;
sparks.think = FX_Explosion_Spark;
sparks.nextthink = time + 0.1f;
sparks.drawmask = MASK_ENGINE;
sparks.velocity[0] = random(-128,128);
sparks.velocity[1] = random(-128,128);
sparks.velocity[2] = (400 + random() * 64);
setorigin(sparks, vecPos);
}
pointparticles(FX_EXPLOSION_MAIN, vecPos, [0,0,0], 1);
pointparticles(FX_EXPLOSION_BS, vecPos, [0,0,0], 1);
#endif
}

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
string g_hgibs[] = {
"models/gib_b_bone.mdl",
"models/gib_legbone.mdl",
"models/gib_lung.mdl",
"models/gib_skull.mdl",
"models/gib_b_gib.mdl"
};
void
FX_GibHuman_Init(void)
{
precache_model("models/gib_b_bone.mdl");
precache_model("models/gib_legbone.mdl");
precache_model("models/gib_lung.mdl");
precache_model("models/gib_skull.mdl");
precache_model("models/gib_b_gib.mdl");
precache_sound("common/bodysplat.wav");
}
#endif
void
FX_GibHuman(vector vecOrigin, vector vecDir, float flForce)
{
#ifdef SERVER
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_GIBHUMAN);
WriteCoord(MSG_MULTICAST, vecOrigin[0]);
WriteCoord(MSG_MULTICAST, vecOrigin[1]);
WriteCoord(MSG_MULTICAST, vecOrigin[2]);
WriteCoord(MSG_MULTICAST, vecDir[0]);
WriteCoord(MSG_MULTICAST, vecDir[1]);
WriteCoord(MSG_MULTICAST, vecDir[2]);
WriteFloat(MSG_MULTICAST, flForce);
msg_entity = __NULL__;
multicast(vecOrigin, MULTICAST_PVS);
#else
static void Gib_Remove(void) {
remove(self);
}
static void Gib_Touch(void)
{
if (serverkeyfloat("*bspversion") == BSPVER_HL)
Decals_Place(self.origin, sprintf("{blood%d", floor(random(1,9))));
else {
decal_pickwall(self, self.origin);
pointparticles(DECAL_BLOOD, g_tracedDecal.endpos, g_tracedDecal.normal, 1);
}
}
if (cvar("violence_hgibs") <= 0) {
return;
}
makevectors(vecDir);
vecDir = v_forward;
for (int i = 0; i < 5; i++) {
vector vel = vecDir;
vel += random(-1,1) * v_right;
vel += random(-1,1) * v_up;
vel *= flForce;
vel += [0,0,80];
entity gibb = spawn();
setmodel(gibb, g_hgibs[i]);
setorigin(gibb, vecOrigin);
gibb.movetype = MOVETYPE_BOUNCE;
gibb.solid = SOLID_BBOX;
setsize(gibb, [0,0,0], [0,0,0]);
gibb.velocity = vel;
gibb.avelocity = vectoangles(gibb.velocity);
gibb.think = Gib_Remove;
gibb.touch = Gib_Touch;
gibb.nextthink = time + 5.0f;
gibb.drawmask = MASK_ENGINE;
}
pointsound(vecOrigin, "common/bodysplat.wav", 1, ATTN_NORM);
#endif
}

View File

@ -1,231 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
var int FX_IMPACT_BLACKBITS;
var int FX_IMPACT_SMOKE_BROWN;
var int FX_IMPACT_SMOKE_GREY;
var int FX_IMPACT_SPARK;
var int DECAL_IMPACT_DEFAULT;
var int DECAL_IMPACT_ALIEN;
var int DECAL_IMPACT_FLESH;
var int DECAL_IMPACT_FOLIAGE;
var int DECAL_IMPACT_COMPUTER;
var int DECAL_IMPACT_DIRT;
var int DECAL_IMPACT_VENT;
var int DECAL_IMPACT_GRATE;
var int DECAL_IMPACT_METAL;
var int DECAL_IMPACT_GLASS;
var int DECAL_IMPACT_SAND;
var int DECAL_IMPACT_SLOSH;
var int DECAL_IMPACT_SNOW;
var int DECAL_IMPACT_TILE;
var int DECAL_IMPACT_WOOD;
var int DECAL_IMPACT_CONCRETE;
void
FX_Impact_Init(void)
{
Sound_Precache("sfx_impact.default");
Sound_Precache("sfx_impact.alien");
Sound_Precache("sfx_impact.flesh");
Sound_Precache("sfx_impact.foliage");
Sound_Precache("sfx_impact.computer");
Sound_Precache("sfx_impact.dirt");
Sound_Precache("sfx_impact.vent");
Sound_Precache("sfx_impact.grate");
Sound_Precache("sfx_impact.metal");
Sound_Precache("sfx_impact.glass");
Sound_Precache("sfx_impact.sand");
Sound_Precache("sfx_impact.slosh");
Sound_Precache("sfx_impact.snow");
Sound_Precache("sfx_impact.tile");
Sound_Precache("sfx_impact.wood");
Sound_Precache("sfx_impact.concrete");
FX_IMPACT_BLACKBITS = particleeffectnum("fx_impact.blackbits");
FX_IMPACT_SMOKE_GREY = particleeffectnum("fx_impact.smoke_grey");
FX_IMPACT_SMOKE_BROWN = particleeffectnum("fx_impact.smoke_brown");
FX_IMPACT_SPARK = particleeffectnum("fx_impact.spark");
/* engine-side particle system decals for non HL1 BSP */
DECAL_IMPACT_DEFAULT = particleeffectnum("decal_impact.default");
DECAL_IMPACT_ALIEN = particleeffectnum("decal_impact.alien");
DECAL_IMPACT_FLESH = particleeffectnum("decal_impact.flesh");
DECAL_IMPACT_FOLIAGE = particleeffectnum("decal_impact.foliage");
DECAL_IMPACT_COMPUTER = particleeffectnum("decal_impact.computer");
DECAL_IMPACT_DIRT = particleeffectnum("decal_impact.dirt");
DECAL_IMPACT_VENT = particleeffectnum("decal_impact.vent");
DECAL_IMPACT_GRATE = particleeffectnum("decal_impact.grate");
DECAL_IMPACT_METAL = particleeffectnum("decal_impact.metal");
DECAL_IMPACT_GLASS = particleeffectnum("decal_impact.glass");
DECAL_IMPACT_SAND = particleeffectnum("decal_impact.sand");
DECAL_IMPACT_SLOSH = particleeffectnum("decal_impact.slosh");
DECAL_IMPACT_SNOW = particleeffectnum("decal_impact.snow");
DECAL_IMPACT_TILE = particleeffectnum("decal_impact.tile");
DECAL_IMPACT_WOOD = particleeffectnum("decal_impact.wood");
DECAL_IMPACT_CONCRETE = particleeffectnum("decal_impact.concrete");
precache_model("sprites/wsplash3.spr");
}
#endif
void
FX_Impact(impactType_t iType, vector vecPos, vector vNormal)
{
#ifdef SERVER
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_IMPACT);
WriteByte(MSG_MULTICAST, (float)iType);
WriteCoord(MSG_MULTICAST, vecPos[0]);
WriteCoord(MSG_MULTICAST, vecPos[1]);
WriteCoord(MSG_MULTICAST, vecPos[2]);
WriteCoord(MSG_MULTICAST, vNormal[0]);
WriteCoord(MSG_MULTICAST, vNormal[1]);
WriteCoord(MSG_MULTICAST, vNormal[2]);
msg_entity = self;
multicast(vecPos, MULTICAST_PVS);
#else
/* decals */
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
switch (iType) {
case IMPACT_GLASS:
Decals_Place(vecPos, sprintf("{break%d", floor(random(1,4))));
break;
case IMPACT_MELEE:
Decals_Place(vecPos, sprintf("{shot%d", floor(random(1,6))));
break;
default:
Decals_Place(vecPos, sprintf("{bigshot%d", floor(random(1,6))));
break;
}
} else {
switch (iType) {
case IMPACT_GLASS:
pointparticles(DECAL_IMPACT_GLASS, vecPos, vNormal, 1);
break;
case IMPACT_WOOD:
pointparticles(DECAL_IMPACT_WOOD, vecPos, vNormal, 1);
break;
case IMPACT_METAL:
pointparticles(DECAL_IMPACT_METAL, vecPos, vNormal, 1);
break;
case IMPACT_FLESH:
pointparticles(DECAL_IMPACT_FLESH, vecPos, vNormal, 1);
break;
default:
pointparticles(DECAL_IMPACT_DEFAULT, vecPos, vNormal, 1);
break;
}
}
switch (iType) {
case IMPACT_MELEE:
case IMPACT_EXPLOSION:
break;
case IMPACT_DIRT:
case IMPACT_GLASS:
case IMPACT_FOLIAGE:
case IMPACT_SNOW:
case IMPACT_SAND:
pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1);
break;
case IMPACT_WOOD:
pointparticles(FX_IMPACT_SPARK, vecPos, vNormal, 1);
pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1);
pointparticles(FX_IMPACT_SMOKE_BROWN, vecPos, vNormal, 1);
break;
case IMPACT_GRATE:
case IMPACT_VENT:
case IMPACT_METAL:
pointparticles(FX_IMPACT_SPARK, vecPos, vNormal, 1);
pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1);
break;
case IMPACT_SLOSH:
env_sprite splash = spawn(env_sprite);
setorigin(splash, vecPos + [0,0,24]);
setmodel(splash, "sprites/wsplash3.spr");
splash.SetRenderMode(RM_ADDITIVE);
splash.SetRenderAmt(1.0f);
splash.SetRenderColor([1,1,1]);
splash.drawmask = MASK_ENGINE;
splash.m_iMaxFrame = modelframecount(splash.modelindex);
splash.m_bLoops = 0;
splash.m_flFramerate = 20;
splash.nextthink = time + 0.05f;
break;
case IMPACT_FLESH:
FX_Blood(vecPos, vNormal);
break;
default:
pointparticles(FX_IMPACT_SPARK, vecPos, vNormal, 1);
pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1);
pointparticles(FX_IMPACT_SMOKE_GREY, vecPos, vNormal, 1);
break;
}
switch (iType) {
case IMPACT_ALIEN:
Sound_PlayAt(vecPos, "sfx_impact.alien");
break;
case IMPACT_COMPUTER:
Sound_PlayAt(vecPos, "sfx_impact.computer");
break;
case IMPACT_CONCRETE:
Sound_PlayAt(vecPos, "sfx_impact.concrete");
break;
case IMPACT_DIRT:
Sound_PlayAt(vecPos, "sfx_impact.dirt");
break;
case IMPACT_FLESH:
Sound_PlayAt(vecPos, "sfx_impact.flesh");
break;
case IMPACT_FOLIAGE:
Sound_PlayAt(vecPos, "sfx_impact.foliage");
break;
case IMPACT_GLASS:
Sound_PlayAt(vecPos, "sfx_impact.glass");
break;
case IMPACT_GRATE:
Sound_PlayAt(vecPos, "sfx_impact.grate");
break;
case IMPACT_METAL:
Sound_PlayAt(vecPos, "sfx_impact.metal");
break;
case IMPACT_SLOSH:
Sound_PlayAt(vecPos, "sfx_impact.slosh");
break;
case IMPACT_SNOW:
Sound_PlayAt(vecPos, "sfx_impact.snow");
break;
case IMPACT_TILE:
Sound_PlayAt(vecPos, "sfx_impact.tile");
break;
case IMPACT_VENT:
Sound_PlayAt(vecPos, "sfx_impact.vent");
break;
case IMPACT_WOOD:
Sound_PlayAt(vecPos, "sfx_impact.wood");
break;
default:
Sound_PlayAt(vecPos, "sfx_impact.default");
break;
}
#endif
}

View File

@ -1,39 +1,33 @@
#includelist
entities.h
events.h
flags.h
player.qc
../../../base/src/shared/weapon_common.h
animations.h
animations.qc
pmove.qc
../../../valve/src/shared/entities.h
../../../valve/src/shared/events.h
../../../valve/src/shared/flags.h
../../../valve/src/shared/player.qc
../../../valve/src/shared/weapon_common.h
../../../valve/src/shared/animations.h
../../../valve/src/shared/animations.qc
../../../valve/src/shared/pmove.qc
fx_blood.qc
fx_gaussbeam.qc
fx_breakmodel.qc
fx_explosion.qc
fx_gibhuman.qc
../../../base/src/shared/fx_spark.qc
../../../base/src/shared/fx_corpse.qc
fx_impact.qc
../../../valve/src/shared/fx_blood.qc
../../../valve/src/shared/fx_gaussbeam.qc
../../../valve/src/shared/fx_corpse.qc
items.h
weapons.h
w_crossbow.qc
w_crowbar.qc
w_egon.qc
w_gauss.qc
w_glock.qc
w_handgrenade.qc
w_hornetgun.qc
w_mp5.qc
w_python.qc
w_rpg.qc
w_satchel.qc
w_shotgun.qc
w_snark.qc
w_tripmine.qc
weapons.qc
../../../base/src/shared/weapon_common.qc
input.qc
../../../valve/src/shared/items.h
../../../valve/src/shared/weapons.h
../../../valve/src/shared/w_crossbow.qc
../../../valve/src/shared/w_crowbar.qc
../../../valve/src/shared/w_egon.qc
../../../valve/src/shared/w_gauss.qc
../../../valve/src/shared/w_glock.qc
../../../valve/src/shared/w_handgrenade.qc
../../../valve/src/shared/w_hornetgun.qc
../../../valve/src/shared/w_mp5.qc
../../../valve/src/shared/w_python.qc
../../../valve/src/shared/w_rpg.qc
../../../valve/src/shared/w_satchel.qc
../../../valve/src/shared/w_shotgun.qc
../../../valve/src/shared/w_snark.qc
../../../valve/src/shared/w_tripmine.qc
../../../valve/src/shared/weapons.qc
../../../valve/src/shared/weapon_common.qc
#endlist

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Game_Input(player pl)
{
#ifdef SERVER
CGameRules rules = (CGameRules)g_grMode;
if (rules.m_iIntermission) {
rules.IntermissionEnd();
return;
}
if (input_buttons & INPUT_BUTTON5)
pl.InputUse_Down();
else
pl.InputUse_Up();
if (pl.impulse == 100)
Flashlight_Toggle();
if (cvar("sv_cheats") == 1) {
if (pl.impulse == 101) {
pl.health = 100;
pl.armor = 100;
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_CROWBAR, -1);
Weapons_AddItem(pl, WEAPON_GLOCK, -1);
Weapons_AddItem(pl, WEAPON_PYTHON, -1);
Weapons_AddItem(pl, WEAPON_MP5, -1);
Weapons_AddItem(pl, WEAPON_SHOTGUN, -1);
Weapons_AddItem(pl, WEAPON_CROSSBOW, -1);
Weapons_AddItem(pl, WEAPON_RPG, -1);
Weapons_AddItem(pl, WEAPON_GAUSS, -1);
Weapons_AddItem(pl, WEAPON_EGON, -1);
Weapons_AddItem(pl, WEAPON_HORNETGUN, -1);
Weapons_AddItem(pl, WEAPON_HANDGRENADE, -1);
Weapons_AddItem(pl, WEAPON_SATCHEL, -1);
Weapons_AddItem(pl, WEAPON_TRIPMINE, -1);
Weapons_AddItem(pl, WEAPON_SNARK, -1);
pl.ammo_m203_grenade = 10;
#ifdef GEARBOX
Weapons_AddItem(pl, WEAPON_PIPEWRENCH, -1);
Weapons_AddItem(pl, WEAPON_KNIFE, -1);
Weapons_AddItem(pl, WEAPON_GRAPPLE, -1);
Weapons_AddItem(pl, WEAPON_EAGLE, -1);
Weapons_AddItem(pl, WEAPON_PENGUIN, -1);
Weapons_AddItem(pl, WEAPON_M249, -1);
Weapons_AddItem(pl, WEAPON_DISPLACER, -1);
Weapons_AddItem(pl, WEAPON_SNIPERRIFLE, -1);
Weapons_AddItem(pl, WEAPON_SPORELAUNCHER, -1);
Weapons_AddItem(pl, WEAPON_SHOCKRIFLE, -1);
#endif
}
}
pl.impulse = 0;
#endif
NSVehicle veh = (NSVehicle)pl.vehicle;
bool canfire = true;
if (veh)
if (veh.PreventPlayerFire() == true)
canfire = false;
if (canfire == false)
return;
if (input_buttons & INPUT_BUTTON0)
Weapons_Primary(pl);
else if (input_buttons & INPUT_BUTTON4)
Weapons_Reload(pl);
else if (input_buttons & INPUT_BUTTON3)
Weapons_Secondary(pl);
else
Weapons_Release(pl);
}

View File

@ -14,88 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
/* Here's a list of bone names that we are aware of on HL player models.
Usually we'd use skeletalobjects to share the same skeleton/anim with
another model - but because FTEQW does not support that for HLMDL we
are forced to manually position the bones of our attachnment
by iterating over them and manually setting their position in 3D-space.
*/
string g_pbones[] =
{
"Bip01",
"Bip01 Footsteps",
"Bip01 Pelvis",
"Bip01 L Leg",
"Bip01 L Leg1",
"Bip01 L Foot",
"Bip01 L Toe0",
"Bip01 L Toe01",
"Bip01 L Toe02",
"Dummy16",
"Bip01 R Leg",
"Bip01 R Leg1",
"Bip01 R Foot",
"Bip01 R Toe0",
"Bip01 R Toe01",
"Bip01 R Toe02",
"Dummy11",
"Bip01 Spine",
"Bip01 Spine1",
"Bip01 Spine2",
"Bip01 Spine3",
"Bip01 Neck",
"Bip01 Head",
"Dummy21",
"Dummy08",
"Bone02",
"Bone03",
"Bone04",
"Dummy05",
"Bone09",
"Bone10",
"Dummy04",
"Bone05",
"Bone06",
"Dummy03",
"Bone07",
"Bone08",
"Dummy09",
"Bone11",
"Bone12",
"Dummy10",
"Bone13",
"Bone14",
"Bone15",
"Bip01 L Arm",
"Bip01 L Arm1",
"Bip01 L Arm2",
"Bip01 L Hand",
"Bip01 L Finger0",
"Bip01 L Finger01",
"Bip01 L Finger02",
"Dummy06",
"Bip01 L Finger1",
"Bip01 L Finger11",
"Bip01 L Finger12",
"Dummy07",
"Bip01 R Arm",
"Bip01 R Arm1",
"Bip01 R Arm2",
"Bip01 R Hand",
"Bip01 R Finger0",
"Bip01 R Finger01",
"Bip01 R Finger02",
"Dummy01",
"Bip01 R Finger1",
"Bip01 R Finger11",
"Bip01 R Finger12",
"Dummy02",
"Box02",
"Bone08",
"Bone15"
};
#endif
#include "skeleton.h"
/* all custom SendFlags bits we can possibly send */
enumflags
@ -153,21 +72,51 @@ class player:NSClientPlayer
virtual void UpdatePlayerAnimation(float);
#ifdef CLIENT
////virtual void(void) draw;
//virtual float() predraw;
//virtual void(void) postdraw;
virtual void UpdatePlayerAttachments(bool);
virtual void(float,float) ReceiveEntity;
virtual void(void) PredictPreFrame;
virtual void(void) PredictPostFrame;
virtual void ReceiveEntity(float,float);
virtual void PredictPreFrame(void);
virtual void PredictPostFrame(void);
virtual void UpdateAliveCam(void);
#else
virtual void(void) EvaluateEntity;
virtual float(entity, float) SendEntity;
virtual void(float) Save;
virtual void(string,string) Restore;
virtual void EvaluateEntity(void);
virtual float SendEntity(entity, float);
virtual void Save(float);
virtual void Restore(string,string);
#endif
};
void
player::player(void)
{
anim_top = 0;
anim_top_time = 0;
anim_top_delay = 0;
anim_bottom = 0;
anim_bottom_time = 0;
glock_mag = 0;
mp5_mag = 0;
python_mag = 0;
shotgun_mag = 0;
crossbow_mag = 0;
rpg_mag = 0;
satchel_chg = 0;
ammo_9mm = 0;
ammo_357 = 0;
ammo_buckshot = 0;
ammo_bolt = 0;
ammo_rocket = 0;
ammo_uranium = 0;
ammo_handgrenade = 0;
ammo_satchel = 0;
ammo_tripmine = 0;
ammo_snark = 0;
ammo_hornet = 0;
ammo_m203_grenade = 0;
ammo_gauss_volume = 0;
ammo_rpg_state = 0;
mode_tempstate = 0;
}
void Animation_PlayerUpdate(player);
void Animation_TimerUpdate(player, float);
@ -181,6 +130,39 @@ player::UpdatePlayerAnimation(float timelength)
}
#ifdef CLIENT
void Camera_RunPosBob(vector angles, __inout vector camera_pos);
void Camera_StrafeRoll(__inout vector camera_angle);
void Shake_Update(NSClientPlayer);
void
player::UpdateAliveCam(void)
{
vector cam_pos = GetEyePos();
Camera_RunPosBob(view_angles, cam_pos);
g_view.SetCameraOrigin(cam_pos);
Camera_StrafeRoll(view_angles);
g_view.SetCameraAngle(view_angles);
if (vehicle) {
NSVehicle veh = (NSVehicle)vehicle;
if (veh.UpdateView)
veh.UpdateView();
} else if (health) {
if (autocvar_pm_thirdPerson == TRUE) {
makevectors(view_angles);
vector vStart = [pSeat->m_vecPredictedOrigin[0], pSeat->m_vecPredictedOrigin[1], pSeat->m_vecPredictedOrigin[2] + 16] + (v_right * 4);
vector vEnd = vStart + (v_forward * -48) + [0,0,16] + (v_right * 4);
traceline(vStart, vEnd, FALSE, this);
g_view.SetCameraOrigin(trace_endpos + (v_forward * 5));
}
}
Shake_Update(this);
g_view.AddPunchAngle(punchangle);
}
.string oldmodel;
string Weapons_GetPlayermodel(player, int);
@ -196,7 +178,7 @@ player::UpdatePlayerAttachments(bool visible)
src = origin + view_ofs;
ang = v_angle;
} else {
src = pSeat->m_vecPredictedOrigin + [0,0,-8];
src = pSeat->m_vecPredictedOrigin + view_ofs;
ang = view_angles;
}
@ -204,7 +186,7 @@ player::UpdatePlayerAttachments(bool visible)
traceline(src, src + (v_forward * 8096), MOVE_NORMAL, this);
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]);
dynamiclight_add(trace_endpos + (trace_plane_normal * 4), 128, [1,1,1]);
} else {
float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight");
dynamiclight_set(p, LFIELD_ANGLES, ang);
@ -560,11 +542,11 @@ player::EvaluateEntity(void)
/* the generic client attributes */
NSClientPlayer::EvaluateEntity();
EVALUATE_FIELD(anim_top, PLAYER_TOPFRAME);
EVALUATE_FIELD(anim_top_time, PLAYER_TOPFRAME);
EVALUATE_FIELD(anim_top_delay, PLAYER_TOPFRAME );
EVALUATE_FIELD(anim_bottom, PLAYER_BOTTOMFRAME);
EVALUATE_FIELD(anim_bottom_time, PLAYER_BOTTOMFRAME);
EVALUATE_FIELD(anim_top, PLAYER_TOPFRAME)
EVALUATE_FIELD(anim_top_time, PLAYER_TOPFRAME)
EVALUATE_FIELD(anim_top_delay, PLAYER_TOPFRAME)
EVALUATE_FIELD(anim_bottom, PLAYER_BOTTOMFRAME)
EVALUATE_FIELD(anim_bottom_time, PLAYER_BOTTOMFRAME)
EVALUATE_FIELD(glock_mag, PLAYER_AMMO1)
EVALUATE_FIELD(mp5_mag, PLAYER_AMMO1)
@ -600,6 +582,10 @@ player::SendEntity
float
player::SendEntity(entity ePEnt, float flChanged)
{
/* just-in-case. */
if (classname != "player")
return (0);
/* don't broadcast invisible players */
if (IsFakeSpectator() && ePEnt != this)
return (0);
@ -648,35 +634,3 @@ player::SendEntity(entity ePEnt, float flChanged)
return (1);
}
#endif
void
player::player(void)
{
anim_top = 0;
anim_top_time = 0;
anim_top_delay = 0;
anim_bottom = 0;
anim_bottom_time = 0;
glock_mag = 0;
mp5_mag = 0;
python_mag = 0;
shotgun_mag = 0;
crossbow_mag = 0;
rpg_mag = 0;
satchel_chg = 0;
ammo_9mm = 0;
ammo_357 = 0;
ammo_buckshot = 0;
ammo_bolt = 0;
ammo_rocket = 0;
ammo_uranium = 0;
ammo_handgrenade = 0;
ammo_satchel = 0;
ammo_tripmine = 0;
ammo_snark = 0;
ammo_hornet = 0;
ammo_m203_grenade = 0;
ammo_gauss_volume = 0;
ammo_rpg_state = 0;
mode_tempstate = 0;
}

View File

@ -23,7 +23,7 @@
#define PMOVE_AIRACCELERATE 10
#define PMOVE_WATERACCELERATE 10
#define PMOVE_ACCELERATE 10
#define PMOVE_MAXSPEED 320
#define PMOVE_MAXSPEED 270
#define PMOVE_STEP_WALKSPEED 135
#define PMOVE_STEP_RUNSPEED 220
#define PHY_VIEWPOS [0,0,28]

82
src/shared/skeleton.h Normal file
View File

@ -0,0 +1,82 @@
#ifdef CLIENT
/* Here's a list of bone names that we are aware of on HL player models.
Usually we'd use skeletalobjects to share the same skeleton/anim with
another model - but because FTEQW does not support that for HLMDL we
are forced to manually position the bones of our attachnment
by iterating over them and manually setting their position in 3D-space.
*/
string g_pbones[] =
{
"Bip01",
"Bip01 Footsteps",
"Bip01 Pelvis",
"Bip01 L Leg",
"Bip01 L Leg1",
"Bip01 L Foot",
"Bip01 L Toe0",
"Bip01 L Toe01",
"Bip01 L Toe02",
"Dummy16",
"Bip01 R Leg",
"Bip01 R Leg1",
"Bip01 R Foot",
"Bip01 R Toe0",
"Bip01 R Toe01",
"Bip01 R Toe02",
"Dummy11",
"Bip01 Spine",
"Bip01 Spine1",
"Bip01 Spine2",
"Bip01 Spine3",
"Bip01 Neck",
"Bip01 Head",
"Dummy21",
"Dummy08",
"Bone02",
"Bone03",
"Bone04",
"Dummy05",
"Bone09",
"Bone10",
"Dummy04",
"Bone05",
"Bone06",
"Dummy03",
"Bone07",
"Bone08",
"Dummy09",
"Bone11",
"Bone12",
"Dummy10",
"Bone13",
"Bone14",
"Bone15",
"Bip01 L Arm",
"Bip01 L Arm1",
"Bip01 L Arm2",
"Bip01 L Hand",
"Bip01 L Finger0",
"Bip01 L Finger01",
"Bip01 L Finger02",
"Dummy06",
"Bip01 L Finger1",
"Bip01 L Finger11",
"Bip01 L Finger12",
"Dummy07",
"Bip01 R Arm",
"Bip01 R Arm1",
"Bip01 R Arm2",
"Bip01 R Hand",
"Bip01 R Finger0",
"Bip01 R Finger01",
"Bip01 R Finger02",
"Dummy01",
"Bip01 R Finger1",
"Bip01 R Finger11",
"Bip01 R Finger12",
"Dummy02",
"Box02",
"Bone08",
"Bone15"
};
#endif

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_crossbow (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_crossbow.mdl"
HALF-LIFE (1998) ENTITY
Crossbow Weapon
*/
enum
{
CROSSBOW_IDLE1,
@ -84,13 +75,15 @@ int
w_crossbow_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 5 : startammo;
if (new) {
pl.crossbow_mag = 5;
pl.crossbow_mag = addAmmo;
return (1);
}
if (pl.ammo_bolt < MAX_A_BOLT) {
pl.ammo_bolt = bound(0, pl.ammo_bolt + 5, MAX_A_BOLT);
pl.ammo_bolt = bound(0, pl.ammo_bolt + addAmmo, MAX_A_BOLT);
} else {
if (!new)
return (0);
@ -117,53 +110,6 @@ w_crossbow_holster(player pl)
Weapons_ViewAnimation(pl, CROSSBOW_HOLSTER1);
}
#ifdef SERVER
void Crossbolt_Touch(void) {
/* explode mode, multiplayer */
if (self.weapon) {
float dmg = Skill_GetValue("plr_xbow_bolt_monster", 50);
FX_Explosion(self.origin);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_CROSSBOW);
if (random() < 0.5) {
sound(self, 1, "weapons/explode3.wav", 1.0f, ATTN_NORM);
} else {
sound(self, 1, "weapons/explode4.wav", 1.0f, ATTN_NORM);
}
remove(self);
return;
}
/* walls, etc. */
if (other.takedamage != DAMAGE_YES) {
FX_Spark(self.origin, trace_plane_normal);
Sound_Play(self, 1, "weapon_crossbow.hit");
/* disappear bolt after ~ 10 seconds */
self.velocity = [0,0,0];
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_NOT;
self.think = Util_Destroy;
self.nextthink = time + 15.0f;
makevectors(self.angles);
setorigin(self, self.origin + v_forward * -16);
return;
}
/* anything else that can take damage */
Damage_Apply(other, self.owner, Skill_GetValue("plr_xbow_bolt_monster", 50), WEAPON_CROSSBOW, DMG_BLUNT);
Sound_Play(self, 1, "weapon_crossbow.hitbody");
if (other.iBleeds == FALSE) {
FX_Spark(self.origin, trace_plane_normal);
} else {
FX_Blood(self.origin, [1,0,0]);
}
/* disappear... immediately */
remove(self);
}
#endif
void
w_crossbow_primary(player pl)
{
@ -185,12 +131,12 @@ w_crossbow_primary(player pl)
#ifndef CLIENT
HLGameRules rules = (HLGameRules) g_grMode;
Weapons_MakeVectors(pl);
/* multiplayer uses hitscan when zoomed in */
if (rules.IsMultiplayer() == true && pl.viewzoom < 1.0) {
vector src, dest;
src = pl.origin + pl.view_ofs;
Weapons_MakeVectors(pl);
dest = src + v_forward * 4096;
traceline(src, dest, MOVE_LAGGED, pl);
@ -198,7 +144,7 @@ w_crossbow_primary(player pl)
Damage_Apply(trace_ent, pl, Skill_GetValue("plr_xbow_bolt_monster", 50), WEAPON_CROSSBOW, DMG_BLUNT);
if (other.iBleeds == FALSE)
FX_Spark(trace_endpos, trace_plane_normal);
pointparticles(particleeffectnum("platform.spark"), self.origin, trace_plane_normal, 1);
else
FX_Blood(trace_endpos, [1,0,0]);
@ -215,24 +161,12 @@ w_crossbow_primary(player pl)
bolt_used.nextthink = time + 10.0f;
}
} else {
entity bolt = spawn();
setmodel(bolt, "models/crossbow_bolt.mdl");
setorigin(bolt, Weapons_GetCameraPos(pl) + (v_forward * 16));
bolt.owner = pl;
bolt.velocity = v_forward * 2000;
bolt.movetype = MOVETYPE_FLYMISSILE;
bolt.solid = SOLID_BBOX;
//bolt.flags |= FL_LAGGEDMOVE;
bolt.gravity = 0.5f;
bolt.angles = vectoangles(bolt.velocity);
bolt.avelocity[2] = 10;
bolt.touch = Crossbolt_Touch;
/* zoomed out = explosive */
if (rules.IsMultiplayer() == true)
bolt.weapon = 1;
setsize(bolt, [0,0,0], [0,0,0]);
if (rules.IsMultiplayer() == true) {
NSProjectile_SpawnDef("projectile_arrowExplosive", pl);
} else {
NSProjectile_SpawnDef("projectile_arrow", pl);
}
}
if (pl.crossbow_mag > 0) {
@ -345,33 +279,12 @@ void
w_crossbow_crosshair(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector aicon_pos;
if (pl.viewzoom == 1) {
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[72/128,0],
[0.1875, 0.1875],
[1,1,1],
1,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [72/128,0], [0.1875, 0.1875]);
} else {
cross_pos = g_hudmins + (g_hudres / 2) + [-52,-8];
drawsubpic(
cross_pos,
[104,16],
g_cross_spr,
[24/128,96/128],
[104/128, 16/128],
[1,1,1],
1,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [104,16], [24/128,96/128], [104/128, 16/128]);
}
HUD_DrawAmmo1();
@ -474,12 +387,4 @@ weapon_t w_crossbow =
.isempty = w_crossbow_isempty,
.type = w_crossbow_type,
.hudpic = w_crossbow_hudpic
};
#ifdef SERVER
void
weapon_crossbow(void)
{
Weapons_InitItem(WEAPON_CROSSBOW);
}
#endif
};

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_crowbar (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_crowbar.mdl"
HALF-LIFE (1998) ENTITY
Crowbar Weapon
*/
enum
{
CBAR_IDLE,
@ -139,8 +130,6 @@ w_crowbar_primary(player pl)
/* don't bother with decals, we got squibs */
if (trace_ent.iBleeds) {
FX_Blood(trace_endpos, [1,0,0]);
} else {
FX_Impact(IMPACT_MELEE, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage) {
@ -238,12 +227,3 @@ weapon_t w_crowbar =
.type = w_crowbar_type,
.hudpic = w_crowbar_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_crowbar(void)
{
Weapons_InitItem(WEAPON_CROWBAR);
}
#endif

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_egon (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_egon.mdl"
HALF-LIFE (1998) ENTITY
Egon/Gluon-Gun Weapon
*/
#ifdef CLIENT
var float TRAIL_EGONBEAM;
@ -92,8 +83,10 @@ string w_egon_deathmsg(void)
int w_egon_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 20 : startammo;
if (pl.ammo_uranium < MAX_A_URANIUM) {
pl.ammo_uranium = bound(0, pl.ammo_uranium + 20, MAX_A_URANIUM);
pl.ammo_uranium = bound(0, pl.ammo_uranium + addAmmo, MAX_A_URANIUM);
} else {
if (!new)
return (0);
@ -143,7 +136,7 @@ void w_egon_primary(player pl)
vector src = Weapons_GetCameraPos(pl);
vector endpos = src + v_forward * 1024;
traceline(src, endpos, FALSE, pl);
Damage_Radius(trace_endpos, pl, 14, 64, TRUE, DMG_ELECTRO);
Damage_Radius(trace_endpos, pl, 14, 64, TRUE, WEAPON_EGON);
Client_ShakeOnce(trace_endpos, 128, 0.2, 1.0, 1.0f);
#endif
@ -269,9 +262,8 @@ w_egon_postdraw(player pl, int thirdperson)
void w_egon_crosshair(player pl)
{
#ifdef CLIENT
static vector cross_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(cross_pos, [24,24], g_cross_spr, [72/128,48/128], [0.1875, 0.1875], [1,1,1], 1, DRAWFLAG_NORMAL);
Cross_DrawSub(g_cross_spr, [24,24], [72/128,48/128], [0.1875, 0.1875]);
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,96/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
@ -343,10 +335,4 @@ weapon_t w_egon =
.isempty = w_egon_isempty,
.type = w_egon_type,
.predraw = w_egon_postdraw
};
#ifdef SERVER
void weapon_egon(void) {
Weapons_InitItem(WEAPON_EGON);
}
#endif
};

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_gauss (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_gauss.mdl"
HALF-LIFE (1998) ENTITY
Gauss Weapon
*/
enum
{
GAUSS_IDLE1,
@ -54,13 +45,15 @@ void w_gauss_precache(void)
precache_sound("weapons/electro4.wav");
precache_sound("weapons/electro5.wav");
precache_sound("weapons/electro6.wav");
precache_sound("weapons/gauss2.wav");
Sound_Precache("weapon_gauss.empty");
Sound_Precache("weapon_gauss.fire");
Sound_Precache("weapon_gauss.overcharge");
#else
precache_sound("ambience/pulsemachine.wav");
precache_model("models/v_gauss.mdl");
precache_model("models/p_gauss.mdl");
#endif
precache_sound("ambience/pulsemachine.wav");
}
void w_gauss_updateammo(player pl)
{
@ -82,9 +75,10 @@ string w_gauss_deathmsg(void)
int w_gauss_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 20 : startammo;
if (pl.ammo_uranium < MAX_A_URANIUM) {
pl.ammo_uranium = bound(0, pl.ammo_uranium + 20, MAX_A_URANIUM);
pl.ammo_uranium = bound(0, pl.ammo_uranium + addAmmo, MAX_A_URANIUM);
} else {
if (!new)
return (0);
@ -123,7 +117,7 @@ void w_gauss_fire(player pl, int one)
vecCurPlane = trace_plane_normal;
vecCurPos = trace_endpos;
sound(pl, CHAN_WEAPON, "weapons/gauss2.wav", 1, ATTN_NORM);
pl.StartSoundDef("weapon_gauss.fire", CHAN_WEAPON, true);
int iDamage = one ? 20 : (int)rint((bound(0, pl.ammo_gauss_volume, 10) * 20));
if (serverkeyfloat("*bspversion") == BSPVER_HL)
@ -136,19 +130,6 @@ void w_gauss_fire(player pl, int one)
sound(trace_ent, CHAN_ITEM, sprintf("weapons/electro%d.wav", random(0,3)+4), 1, ATTN_NORM);
}
if (one) {
return;
} else {
int iForce = (int)rint((bound(5, pl.ammo_gauss_volume, 10) * 20));
/* Apply force */
if (pl.flags & FL_ONGROUND) {
pl.velocity += v_forward * (-iForce * 2);
} else {
pl.velocity += v_forward * (-iForce * 4);
}
}
// reflection equation:
Weapons_MakeVectors(pl);
vecDir = v_forward;
@ -186,7 +167,7 @@ void w_gauss_primary(player pl)
/* Ammo check */
if ((pl.ammo_uranium < 2) || (pl.WaterLevel() >= WATERLEVEL_SUBMERGED)) {
#ifdef SERVER
Sound_Play(pl, CHAN_AUTO, "weapon_gauss.empty");
pl.StartSoundDef("weapon_gauss.fire", CHAN_WEAPON, true);
#endif
pl.gflags |= GF_SEMI_TOGGLED;
return;
@ -216,6 +197,23 @@ void w_gauss_release(player pl)
return;
}
/* do nothing if we overcharged */
if (pl.ammo_gauss_volume == 100) {
return;
}
/* if multiplayer then always fling the player
* FIXME need a check for coop */
if (serverkeyfloat("sv_playerslots") > 1) {
if (pl.mode_tempstate != GAUSSTATE_IDLE) {
int iForce = (int)rint((bound(5, pl.ammo_gauss_volume, 10) * 20));
Weapons_MakeVectors(pl);
/* Apply force */
pl.velocity += v_forward * (-iForce * 4);
}
}
if (pl.mode_tempstate == GAUSSTATE_REVVINGUP) {
pl.w_attack_next = 0.0f;
pl.w_idle_next = 0.5f;
@ -264,6 +262,7 @@ void w_gauss_release(player pl)
void w_gauss_secondary(player pl)
{
if (pl.w_attack_next > 0.0)
return;
if (pl.gflags & GF_SEMI_TOGGLED)
@ -280,7 +279,7 @@ void w_gauss_secondary(player pl)
/* regular ammo check */
if ((pl.ammo_uranium <= 0) || (pl.WaterLevel() >= WATERLEVEL_SUBMERGED)) {
#ifdef SERVER
Sound_Play(pl, CHAN_AUTO, "weapon_gauss.empty");
pl.StartSoundDef("weapon_gauss.empty", CHAN_AUTO, true);
#endif
pl.gflags |= GF_SEMI_TOGGLED;
return;
@ -295,23 +294,27 @@ void w_gauss_secondary(player pl)
/* Set pitch sound shift */
pl.ammo_gauss_volume += 1;
/* holding it for too long, damage our owner */
/* holding it for too long, damage our owner (overcharge) */
if (pl.ammo_gauss_volume > 100) {
pl.ammo_gauss_volume = 100;
w_gauss_release(pl);
#ifdef SERVER
Damage_Apply(pl, pl, 10, DMG_ELECTRO, WEAPON_GAUSS);
Damage_Apply(pl, pl, 50, WEAPON_GAUSS, DMG_ELECTRO);
pl.StartSoundDef("weapon_gauss.overcharge", CHAN_AUTO, true);
pl.StopSound(CHAN_WEAPON, true);
#endif
pl.mode_tempstate = GAUSSTATE_IDLE;
pl.w_attack_next = 0.5f;
pl.w_idle_next = 0.5f;
pl.ammo_gauss_volume = 0;
Weapons_ViewAnimation(pl, GAUSS_IDLE1);
return;
}
if (pl.mode_tempstate == GAUSSTATE_REVVINGUP) {
Weapons_ViewAnimation(pl, GAUSS_SPIN);
pl.mode_tempstate = GAUSSTATE_FULL;
pl.w_idle_next = 0.5f;
pl.w_idle_next = 0.0f; // fire immediately if we let go
pl.w_attack_next = 0.5f;
} else if (!pl.mode_tempstate) {
Weapons_ViewAnimation(pl, GAUSS_SPINUP);
@ -319,31 +322,23 @@ void w_gauss_secondary(player pl)
#ifdef SERVER
sound(pl, CHAN_WEAPON, "ambience/pulsemachine.wav", 2, ATTN_NORM);
#endif
pl.w_idle_next = 0.5f;
pl.w_idle_next = 0.5f; // delay if we let go
pl.w_attack_next = 0.5f;
}
}
/* set globals for the overcharge's overlay */
.float overlay_state;
.float overlay_alpha;
void w_gauss_crosshair(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector aicon_pos;
Cross_DrawSub(g_cross_spr, [24,24], [48/128,48/128], [0.1875, 0.1875]);
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[48/128,48/128],
[0.1875, 0.1875],
[1,1,1],
1,
DRAWFLAG_NORMAL
);
drawsubpic(
aicon_pos,
[24,24],
@ -356,6 +351,32 @@ void w_gauss_crosshair(player pl)
);
HUD_DrawAmmo2();
/* overchage flashes the player */
if (pl.ammo_gauss_volume == 100) {
/* check for the state, give a default alpha */
if (pl.overlay_state == 0)
pl.overlay_alpha = 0.8f;
pl.overlay_state = 1;
}
if (pl.overlay_state == 1) {
/* give us a nice fadeout about 3 seconds */
pl.overlay_alpha -= frametime * 0.3;
drawfill(
video_mins,
video_res,
[0.6,0.3,0],
pl.overlay_alpha,
DRAWFLAG_ADDITIVE
);
if (pl.overlay_alpha < 0.1f) {
pl.overlay_state = 0;
}
}
#endif
}
@ -443,9 +464,3 @@ weapon_t w_gauss =
.type = w_gauss_type,
.hudpic = w_gauss_hudpic
};
#ifdef SERVER
void weapon_gauss(void) {
Weapons_InitItem(WEAPON_GAUSS);
}
#endif

View File

@ -14,26 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_9mmhandgun (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_9mmhandgun.mdl"
HALF-LIFE (1998) ENTITY
9mm Handgun/Glock Weapon
Same as weapon_glock
*/
/*QUAKED weapon_glock (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_9mmhandgun.mdl"
HALF-LIFE (1998) ENTITY
9mm Handgun/Glock Weapon
Same as weapon_9mmhandgun
*/
enum
{
GLOCK_IDLE1,
@ -123,13 +103,15 @@ int
w_glock_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 18 : startammo;
if (new) {
pl.glock_mag = 18;
pl.glock_mag = addAmmo;
return (1);
}
if (pl.ammo_9mm < MAX_A_9MM) {
pl.ammo_9mm = bound(0, pl.ammo_9mm + 18, MAX_A_9MM);
pl.ammo_9mm = bound(0, pl.ammo_9mm + addAmmo, MAX_A_9MM);
} else {
if (!new)
return (0);
@ -327,22 +309,11 @@ void
w_glock_hud(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector aicon_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[0.1875,0],
[0.1875, 0.1875],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [0.1875,0], [0.1875, 0.1875]);
HUD_DrawAmmo1();
HUD_DrawAmmo2();
@ -430,18 +401,3 @@ weapon_t w_glock =
.type = w_glock_type,
.hudpic = w_glock_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_9mmhandgun(void)
{
Weapons_InitItem(WEAPON_GLOCK);
}
void
weapon_glock(void)
{
Weapons_InitItem(WEAPON_GLOCK);
}
#endif

View File

@ -14,14 +14,9 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_handgrenade (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_grenade.mdl"
HALF-LIFE (1998) ENTITY
Handgrenade Weapon
*/
#ifdef SERVER
.float nadeCookingTime;
#endif
enum
{
@ -40,6 +35,8 @@ void w_handgrenade_precache(void)
#ifdef SERVER
Sound_Precache("weapon_handgrenade.bounce");
precache_model("models/w_grenade.mdl");
particleeffectnum("fx_explosion.main");
precache_model("sprites/fexplo.spr");
#else
precache_model("models/v_grenade.mdl");
precache_model("models/p_grenade.mdl");
@ -69,9 +66,10 @@ string w_handgrenade_deathmsg(void)
int w_handgrenade_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 1 : startammo;
if (pl.ammo_handgrenade < MAX_A_HANDGRENADE) {
pl.ammo_handgrenade = bound(0, pl.ammo_handgrenade + 1, MAX_A_HANDGRENADE);
pl.ammo_handgrenade = bound(0, pl.ammo_handgrenade + addAmmo, MAX_A_HANDGRENADE);
} else {
if (!new)
return (0);
@ -80,60 +78,6 @@ int w_handgrenade_pickup(player pl, int new, int startammo)
return (1);
}
#ifdef SERVER
void w_handgrenade_throw(player pl)
{
static void WeaponFrag_Throw_Explode(void)
{
float dmg = Skill_GetValue("plr_hand_grenade", 150);
FX_Explosion(self.origin);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_HANDGRENADE);
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
remove(self);
}
static void WeaponFrag_Throw_Touch(void)
{
if (other.takedamage == DAMAGE_YES) {
Damage_Apply(other, self.owner, 15, WEAPON_HANDGRENADE, DMG_BLUNT);
} else {
Sound_Play(self, CHAN_BODY, "weapon_handgrenade.bounce");
}
self.frame = 0;
}
vector vPLAngle = pl.v_angle;
if (vPLAngle[0] < 0) {
vPLAngle[0] = -10 + vPLAngle[0] * ((90 - 10) / 90.0);
} else {
vPLAngle[0] = -10 + vPLAngle[0] * ((90 + 10) / 90.0);
}
float flVel = (90 - vPLAngle[0]) * 5;
if (flVel > 1000) {
flVel = 1000;
}
makevectors(vPLAngle);
vector vecSrc = pl.origin + pl.view_ofs + v_forward * 16;
vector vecThrow = v_forward * flVel + pl.velocity;
entity eGrenade = spawn();
eGrenade.owner = pl;
eGrenade.classname = "remove_me";
eGrenade.solid = SOLID_BBOX;
eGrenade.frame = 1;
eGrenade.velocity = vecThrow;
eGrenade.movetype = MOVETYPE_BOUNCE;
eGrenade.think = WeaponFrag_Throw_Explode;
eGrenade.touch = WeaponFrag_Throw_Touch;
eGrenade.nextthink = time + 4.0f;
setmodel(eGrenade, "models/w_grenade.mdl");
setsize(eGrenade, [0,0,0], [0,0,0]);
setorigin(eGrenade, vecSrc);
}
#endif
void w_handgrenade_draw(player pl)
{
pl.mode_tempstate = 0;
@ -167,6 +111,10 @@ void w_handgrenade_primary(player pl)
pl.mode_tempstate = 1;
pl.w_attack_next = 0.5f;
pl.w_idle_next = 0.5f;
#ifdef SERVER
pl.nadeCookingTime = time;
#endif
}
void w_handgrenade_hud(player pl)
@ -180,7 +128,6 @@ void w_handgrenade_hud(player pl)
void w_handgrenade_release(player pl)
{
if (pl.w_idle_next > 0.0) {
return;
}
@ -188,7 +135,27 @@ void w_handgrenade_release(player pl)
if (pl.mode_tempstate == 1) {
Weapons_ViewAnimation(pl, HANDGRENADE_THROW1);
#ifdef SERVER
w_handgrenade_throw(pl);
vector throwDirection;
float throwingStrength;
NSProjectile nade = (NSProjectile )EntityDef_CreateClassname("projectile_handgrenade");
nade.SetOwner(pl);
throwDirection = pl.v_angle;
throwDirection[0] = -10.0f; /* always aim a bit up */
/* diminish when aiming up */
if (pl.v_angle[0] < 0) {
throwDirection[0] += (pl.v_angle[0] * 0.9f);
} else { /* increase when aiming down */
throwDirection[0] += (pl.v_angle[0] * 1.1f);
}
throwingStrength = bound(0, (90 - throwDirection[0]) * 5.0f, 1000);
nade.Launch(pl.GetEyePos(), pl.v_angle, time - pl.nadeCookingTime, 0.0f, 0.0f);
makevectors(throwDirection);
nade.SetVelocity((v_forward * throwingStrength) + pl.GetVelocity());
#endif
pl.ammo_handgrenade--;
pl.mode_tempstate = 2;
@ -282,10 +249,4 @@ weapon_t w_handgrenade =
.isempty = w_handgrenade_isempty,
.type = w_handgrenade_type,
.hudpic = w_handgrenade_hudpic
};
#ifdef SERVER
void weapon_handgrenade(void) {
Weapons_InitItem(WEAPON_HANDGRENADE);
}
#endif
};

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_hornetgun (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_hgun.mdl"
HALF-LIFE (1998) ENTITY
Hornetgun Weapon
*/
enum
{
HORNETGUN_IDLE,
@ -225,23 +216,11 @@ void
w_hornetgun_crosshair(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector aicon_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
Cross_DrawSub(g_cross_spr, [24,24], [72/128,24/128], [0.1875, 0.1875]);
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[72/128,24/128],
[0.1875, 0.1875],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
HUD_DrawAmmo2();
drawsubpic(
@ -332,12 +311,4 @@ weapon_t w_hornetgun =
.isempty = w_hornetgun_isempty,
.type = w_hornetgun_type,
.hudpic = w_hornetgun_hudpic
};
#ifdef SERVER
void
weapon_hornetgun(void)
{
Weapons_InitItem(WEAPON_HORNETGUN);
}
#endif
};

View File

@ -14,27 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_9mmAR (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_9mmar.mdl"
HALF-LIFE (1998) ENTITY
MP5/9mmAR Weapon
Same as weapon_mp5
*/
/*QUAKED weapon_mp5 (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_9mmar.mdl"
HALF-LIFE (1998) ENTITY
MP5/9mmAR Weapon
Same as weapon_9mmAR
*/
/* Animations */
enum
{
MP5_IDLE1,
@ -103,17 +82,19 @@ int
w_mp5_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
#ifdef GEARBOX
int addAmmo = (startammo == -1) ? 50 : startammo;
#else
int addAmmo = (startammo == -1) ? 25 : startammo;
#endif
if (new) {
#ifdef GEARBOX
pl.mp5_mag = 50;
#else
pl.mp5_mag = 25;
#endif
pl.mp5_mag = addAmmo;
return (1);
}
if (pl.ammo_9mm < MAX_A_9MM) {
pl.ammo_9mm = bound(0, pl.ammo_9mm + 25, MAX_A_9MM);
pl.ammo_9mm = bound(0, pl.ammo_9mm + addAmmo, MAX_A_9MM);
} else {
if (!new)
return (0);
@ -239,33 +220,7 @@ w_mp5_secondary(player pl)
pl.ammo_m203_grenade--;
#ifdef SERVER
static void Grenade_ExplodeTouch(void) {
float dmg = Skill_GetValue("plr_9mmAR_grenade", 100);
FX_Explosion(self.origin);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_HANDGRENADE);
if (random() < 0.5) {
sound(self, 1, "weapons/explode3.wav", 1, ATTN_NORM);
} else {
sound(self, 1, "weapons/explode4.wav", 1, ATTN_NORM);
}
remove(self);
}
Weapons_MakeVectors(pl);
entity gren = spawn();
setmodel(gren, "models/grenade.mdl");
setorigin(gren, Weapons_GetCameraPos(pl) + (v_forward * 16.0f));
gren.owner = pl;
gren.velocity = v_forward * 800.0f;
gren.angles = vectoangles(gren.velocity);
gren.avelocity[0] = random(-100.0f, -500.0f);
gren.gravity = 0.5f;
gren.movetype = MOVETYPE_BOUNCE;
//gren.flags |= FL_LAGGEDMOVE;
gren.solid = SOLID_BBOX;
setsize(gren, [0,0,0], [0,0,0]);
gren.touch = Grenade_ExplodeTouch;
NSProjectile_SpawnDef("projectile_ARgrenade", pl);
Sound_Play(pl, CHAN_WEAPON, "weapon_mp5.gl");
#endif
@ -340,21 +295,9 @@ void
w_mp5_crosshair(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector aicon_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[0,48/128],
[0.1875, 0.1875],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [0,48/128], [0.1875, 0.1875]);
HUD_DrawAmmo1();
HUD_DrawAmmo2();
@ -472,18 +415,4 @@ weapon_t w_mp5 =
.isempty = w_mp5_isempty,
.type = w_mp5_type,
.hudpic = w_mp5_hudpic
};
#ifdef SERVER
void
weapon_9mmAR(void)
{
Weapons_InitItem(WEAPON_MP5);
}
void
weapon_mp5(void)
{
Weapons_InitItem(WEAPON_MP5);
}
#endif
};

View File

@ -14,26 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_357 (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_357.mdl"
HALF-LIFE (1998) ENTITY
357/Python Weapon
Same as weapon_python
*/
/*QUAKED weapon_python (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_357.mdl"
HALF-LIFE (1998) ENTITY
357/Python Weapon
Same as weapon_357
*/
enum
{
PYTHON_IDLE1,
@ -64,14 +44,15 @@ int
w_python_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 6 : startammo;
if (new) {
pl.python_mag = 6;
pl.python_mag = addAmmo;
return (1);
}
if (pl.ammo_357 < MAX_A_357) {
pl.ammo_357 = bound(0, pl.ammo_357 + 6, MAX_A_357);
pl.ammo_357 = bound(0, pl.ammo_357 + addAmmo, MAX_A_357);
} else {
if (!new)
return (0);
@ -265,33 +246,12 @@ void
w_python_crosshair(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector aicon_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
if (pl.viewzoom == 1) {
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[48/128,0],
[0.1875, 0.1875],
[1,1,1],
1,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [48/128,0], [0.1875, 0.1875]);
} else {
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[96/128,0],
[0.1875, 0.1875],
[1,1,1],
1,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [96/128,0], [0.1875, 0.1875]);
}
HUD_DrawAmmo1();
@ -396,19 +356,4 @@ weapon_t w_python =
.isempty = w_python_isempty,
.type = w_python_type,
.hudpic = w_python_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_357(void)
{
Weapons_InitItem(WEAPON_PYTHON);
}
void
weapon_python(void)
{
Weapons_InitItem(WEAPON_PYTHON);
}
#endif
};

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_rpg (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_rpg.mdl"
HALF-LIFE (1998) ENTITY
RPG Weapon
*/
enum
{
RPG_IDLE,
@ -44,6 +35,7 @@ void w_rpg_precache(void)
Sound_Precache("weapon_rpg.empty");
precache_model("models/w_rpg.mdl");
precache_model("models/rpgrocket.mdl");
Sound_Precache("fx.explosion");
#else
precache_model("models/v_rpg.mdl");
precache_model("models/p_rpg.mdl");
@ -71,14 +63,20 @@ string w_rpg_deathmsg(void)
int w_rpg_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 2 : startammo;
if (new) {
pl.rpg_mag = 1;
if (addAmmo > 1) {
pl.rpg_mag = 1;
pl.ammo_rocket = bound(0, pl.ammo_rocket + 1, MAX_A_ROCKET);
} else {
pl.rpg_mag = addAmmo;
}
return (1);
}
if (pl.ammo_rocket < MAX_A_ROCKET) {
pl.ammo_rocket = bound(0, pl.ammo_rocket + 1, MAX_A_ROCKET);
pl.ammo_rocket = bound(0, pl.ammo_rocket + 2, MAX_A_ROCKET);
} else {
if (!new)
return (0);
@ -118,49 +116,12 @@ void w_rpg_primary(player pl)
pl.rpg_mag--;
#ifdef SERVER
static void Rocket_Touch(void) {
float dmg = Skill_GetValue("plr_rpg", 100);
FX_Explosion(self.origin);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_RPG);
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
remove(self);
}
static void Rocket_BuildSpeed(void){
/* Calculate new direction */
if (self.weapon) {
makevectors(self.owner.v_angle);
traceline(self.owner.origin, self.owner.origin + v_forward * 8096, FALSE, self.owner);
self.angles = vectoangles(trace_endpos - self.origin);
}
/* Increase speed towards it */
makevectors(self.angles);
self.velocity += (v_forward * 2000) * frametime;
self.nextthink = time;
}
Weapons_MakeVectors(pl);
entity rocket = spawn();
setmodel(rocket, "models/rpgrocket.mdl");
setorigin(rocket, Weapons_GetCameraPos(pl) + (v_forward * 16));
rocket.owner = pl;
rocket.movetype = MOVETYPE_FLY;
rocket.solid = SOLID_BBOX;
//bolt.flags |= FL_LAGGEDMOVE;
rocket.gravity = 0.5f;
rocket.velocity = (pl.WaterLevel() >= WATERLEVEL_SUBMERGED) ? (v_forward * 100): (v_forward * 250);
rocket.angles = vectoangles(rocket.velocity);
rocket.avelocity[2] = 10;
rocket.touch = Rocket_Touch;
rocket.think = Rocket_BuildSpeed;
rocket.nextthink = time + 0.15f;
rocket.traileffectnum = particleeffectnum("weapon_rpg.trail");
if (pl.ammo_rpg_state > 0) {
rocket.weapon = 1;
NSProjectile_SpawnDef("projectile_rocket_homing", pl);
} else {
NSProjectile_SpawnDef("projectile_rocket", pl);
}
setsize(rocket, [0,0,0], [0,0,0]);
Sound_Play(pl, CHAN_WEAPON, "weapon_rpg.shoot");
#endif
@ -279,7 +240,6 @@ void w_rpg_hudpic(player pl, int selected, vector pos, float a)
void w_rpg_hud(player pl)
{
#ifdef CLIENT
vector cross_pos;
vector laser_pos;
vector aicon_pos;
@ -294,7 +254,6 @@ void w_rpg_hud(player pl)
jitter[0] = (random(0,2) - 2) * (1 - trace_fraction);
jitter[1] = (random(0,2) - 2) * (1 - trace_fraction);
laser_pos = g_hudmins + (g_hudres / 2) + ([-lerp,-lerp] / 2);
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(
laser_pos + jitter,
@ -307,28 +266,9 @@ void w_rpg_hud(player pl)
DRAWFLAG_ADDITIVE
);
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[24/128,48/128],
[0.1875, 0.1875],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
} else {
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(
cross_pos,
[24,24],
g_cross_spr,
[24/128,48/128],
[0.1875, 0.1875],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
}
/* ammo counters */
@ -391,9 +331,3 @@ weapon_t w_rpg =
.type = w_rpg_type,
.hudpic = w_rpg_hudpic
};
#ifdef SERVER
void weapon_rpg(void) {
Weapons_InitItem(WEAPON_RPG);
}
#endif

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_satchel (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_satchel.mdl"
HALF-LIFE (1998) ENTITY
Satchel Weapon
*/
enum
{
SATCHEL_IDLE,
@ -41,45 +32,15 @@ enum
};
#ifdef SERVER
void
s_satchel_drop(entity master, vector src, vector vel)
{
static void s_satchel_touch(void)
{
if (other != world)
return;
Sound_Play(self, CHAN_BODY, "weapon_satchel.bounce");
}
entity satch;
satch = spawn();
satch.owner = master;
satch.classname = "satchel";
satch.movetype = MOVETYPE_BOUNCE;
satch.solid = SOLID_BBOX;
satch.frame = 1;
satch.gravity = 0.5f;
satch.friction = 0.8f;
satch.velocity = vel;
satch.avelocity = [0,400,0];
satch.touch = s_satchel_touch;
setmodel(satch, "models/w_satchel.mdl");
setsize(satch, [-4,-4,-4], [4,4,4]);
setorigin(satch, src);
}
void
s_satchel_detonate(entity master)
{
for (entity b = world; (b = find(b, ::classname, "satchel"));) {
for (entity b = world; (b = find(b, ::classname, "projectile_satchel"));) {
if (b.owner != master)
continue;
float dmg = Skill_GetValue("plr_satchel", 150);
FX_Explosion(b.origin);
Damage_Radius(b.origin, master, dmg, dmg * 2.5f, TRUE, WEAPON_SATCHEL);
sound(b, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
remove(b);
NSEntity satchelEnt = (NSEntity)b;
satchelEnt.Trigger(master, TRIG_TOGGLE);
}
}
#endif
@ -125,9 +86,10 @@ int
w_satchel_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 1 : startammo;
if (pl.ammo_satchel < MAX_A_SATCHEL) {
pl.ammo_satchel = bound(0, pl.ammo_satchel + 1, MAX_A_SATCHEL);
pl.ammo_satchel = bound(0, pl.ammo_satchel + addAmmo, MAX_A_SATCHEL);
} else {
if (!new)
return (0);
@ -176,11 +138,7 @@ w_satchel_primary(player pl)
#ifdef SERVER
/* if we don't have any satchels placed yet, place one */
if (!pl.satchel_chg) {
vector throw;
Weapons_MakeVectors(pl);
throw = pl.velocity + (v_forward * 274);
s_satchel_drop(pl, pl.origin, throw);
NSProjectile_SpawnDef("projectile_satchel", pl);
pl.satchel_chg++;
pl.ammo_satchel--;
pl.mode_tempstate = 1; /* mark us as having deployed something */
@ -231,10 +189,7 @@ w_satchel_secondary(player pl)
Weapons_ViewAnimation(pl, RADIO_DRAW);
#ifdef SERVER
vector throw;
Weapons_MakeVectors(pl);
throw = pl.velocity + (v_forward * 274);
s_satchel_drop(pl, pl.origin, throw);
NSProjectile_SpawnDef("projectile_satchel", pl);
#endif
if (pl.flags & FL_CROUCHING)
@ -351,11 +306,3 @@ weapon_t w_satchel =
.type = w_satchel_type,
.hudpic = w_satchel_hudpic
};
#ifdef SERVER
void
weapon_satchel(void)
{
Weapons_InitItem(WEAPON_SATCHEL);
}
#endif

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_shotgun (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_shotgun.mdl"
HALF-LIFE (1998) ENTITY
Shotgun Weapon
*/
enum
{
SHOTGUN_IDLE1,
@ -56,6 +47,7 @@ void w_shotgun_ejectshell(void)
if (other == world)
Sound_Play(self, CHAN_BODY, "modelevent_shotgunshell.land");
}
entity eShell = spawn();
setmodel(eShell, "models/shotgunshell.mdl");
eShell.solid = SOLID_BBOX;
@ -124,13 +116,15 @@ int
w_shotgun_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
int addAmmo = (startammo == -1) ? 8 : startammo;
if (new) {
pl.shotgun_mag = 8;
pl.shotgun_mag = addAmmo;
return (1);
}
if (pl.ammo_buckshot < MAX_A_BUCKSHOT) {
pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 8, MAX_A_BUCKSHOT);
pl.ammo_buckshot = bound(0, pl.ammo_buckshot + addAmmo, MAX_A_BUCKSHOT);
} else {
if (!new)
return (0);
@ -188,7 +182,7 @@ w_shotgun_primary(player pl)
return;
}
if (pl.w_attack_next) {
if (pl.w_attack_next > 0.0f) {
w_shotgun_release(pl);
return;
}
@ -254,7 +248,7 @@ w_shotgun_secondary(player pl)
return;
}
if (pl.w_attack_next) {
if (pl.w_attack_next > 0.0f) {
w_shotgun_release(pl);
return;
}
@ -317,7 +311,44 @@ w_shotgun_release(player pl)
return;
}
if (pl.mode_tempstate == SHOTTY_IDLE) {
switch (pl.mode_tempstate) {
case SHOTTY_RELOAD_START:
Weapons_ViewAnimation(pl, SHOTGUN_START_RELOAD);
pl.mode_tempstate = SHOTTY_RELOAD;
pl.w_idle_next = 0.65f;
break;
case SHOTTY_RELOAD:
Weapons_ViewAnimation(pl, SHOTGUN_RELOAD);
pl.shotgun_mag++;
pl.ammo_buckshot--;
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.reload");
#endif
if (pl.ammo_buckshot <= 0 || pl.shotgun_mag >= 8) {
pl.mode_tempstate = SHOTTY_RELOAD_END;
}
Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, pl.mode_tempstate);
pl.w_idle_next = 0.5f;
break;
case SHOTTY_RELOAD_END:
Weapons_ViewAnimation(pl, SHOTGUN_PUMP);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.cock");
#endif
pl.mode_tempstate = SHOTTY_IDLE;
pl.w_idle_next = 10.0f;
pl.w_attack_next = 0.5f;
break;
case SHOTTY_COCKSOUND:
#ifdef SERVER
Sound_Play(pl, CHAN_AUTO, "weapon_shotgun.cock");
#endif
pl.mode_tempstate = SHOTTY_IDLE;
pl.w_idle_next = 10.0f;
pl.w_attack_next = 0.5f;
break;
case SHOTTY_IDLE:
default:
int r = floor(pseudorandom() * 3.0f);
switch (r) {
case 1:
@ -333,39 +364,7 @@ w_shotgun_release(player pl)
pl.w_idle_next = 2.222222f;
break;
}
} else if (pl.mode_tempstate == SHOTTY_RELOAD_START) {
Weapons_ViewAnimation(pl, SHOTGUN_START_RELOAD);
pl.mode_tempstate = SHOTTY_RELOAD;
pl.w_idle_next = 0.65f;
} else if (pl.mode_tempstate == SHOTTY_RELOAD) {
Weapons_ViewAnimation(pl, SHOTGUN_RELOAD);
pl.shotgun_mag++;
pl.ammo_buckshot--;
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.reload");
#endif
if (pl.ammo_buckshot <= 0 || pl.shotgun_mag >= 8) {
pl.mode_tempstate = SHOTTY_RELOAD_END;
}
Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, pl.mode_tempstate);
pl.w_idle_next = 0.5f;
} else if (pl.mode_tempstate == SHOTTY_RELOAD_END) {
Weapons_ViewAnimation(pl, SHOTGUN_PUMP);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.cock");
#endif
pl.mode_tempstate = SHOTTY_IDLE;
pl.w_idle_next = 10.0f;
pl.w_attack_next = 0.5f;
} else if (pl.mode_tempstate == SHOTTY_COCKSOUND) {
#ifdef CLIENT
#else
Sound_Play(pl, CHAN_AUTO, "weapon_shotgun.cock");
#endif
pl.mode_tempstate = SHOTTY_IDLE;
pl.w_idle_next = 10.0f;
pl.w_attack_next = 0.5f;
break;
}
}
@ -373,9 +372,7 @@ void
w_shotgun_crosshair(player pl)
{
#ifdef CLIENT
static vector cross_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(cross_pos, [24,24], g_cross_spr, [48/128,24/128], [0.1875, 0.1875], [1,1,1], 1, DRAWFLAG_NORMAL);
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
HUD_DrawAmmo1();
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
@ -449,12 +446,4 @@ weapon_t w_shotgun =
.isempty = w_shotgun_isempty,
.type = w_shotgun_type,
.hudpic = w_shotgun_hudpic
};
#ifdef SERVER
void
weapon_shotgun(void)
{
Weapons_InitItem(WEAPON_SHOTGUN);
}
#endif
};

Some files were not shown because too many files have changed in this diff Show More