Merge branch 'master' into mirceakitsune/multijump
authorMircea Kitsune <sonichedgehog_hyperblast00@yahoo.com>
Mon, 26 Apr 2010 21:38:04 +0000 (00:38 +0300)
committerMircea Kitsune <sonichedgehog_hyperblast00@yahoo.com>
Mon, 26 Apr 2010 21:38:04 +0000 (00:38 +0300)
83 files changed:
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
balance25.cfg
common-spog.pk3 [deleted file]
defaultXonotic.cfg
effectinfo.txt
font-dejavu.pk3dir/font-dejavu.cfg [deleted file]
font-dejavu.pk3dir/fonts/DejaVuSans-Bold.ttf [deleted file]
font-dejavu.pk3dir/fonts/DejaVuSansMono.ttf [deleted file]
models/monsters/zombie.dpm.framegroups
models/turrets/walker_body.md3.framegroups
models/vehicles/raptor.dpm [new file with mode: 0644]
models/vehicles/raptor_bomb.dpm [new file with mode: 0644]
models/vehicles/raptor_cockpit.dpm [new file with mode: 0644]
models/vehicles/raptor_gun.dpm [new file with mode: 0644]
models/vehicles/spiderbot.dpm.framegroups
monster_zombie.cfg
physicsSamual.cfg
qcsrc/client/View.qc
qcsrc/client/projectile.qc
qcsrc/common/constants.qh
qcsrc/menu/anim/keyframe.c
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c
qcsrc/qc-client.cbp [new file with mode: 0644]
qcsrc/qc-common.cbp [new file with mode: 0644]
qcsrc/qc-server.cbp [new file with mode: 0644]
qcsrc/server/cl_client.qc
qcsrc/server/cl_physics.qc
qcsrc/server/cl_player.qc
qcsrc/server/cl_weapons.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/clientcommands.qc
qcsrc/server/defs.qh
qcsrc/server/extensions.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_models.qc
qcsrc/server/gamecommand.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/monsters/monster_zombie.qc
qcsrc/server/mutators/base.qh
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator_dodging.qc [new file with mode: 0644]
qcsrc/server/mutators/mutator_dodging.qh [new file with mode: 0644]
qcsrc/server/mutators/mutator_nix.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/pathlib/debug.qc
qcsrc/server/pathlib/expandnode.qc
qcsrc/server/pathlib/main.qc
qcsrc/server/pathlib/movenode.qc
qcsrc/server/pathlib/path_waypoint.qc [new file with mode: 0644]
qcsrc/server/pathlib/pathlib.qh
qcsrc/server/pathlib/utility.qc
qcsrc/server/progs.src
qcsrc/server/t_items.qc
qcsrc/server/teamplay.qc
qcsrc/server/tturrets/include/turrets_early.qh
qcsrc/server/tturrets/system/system_main.qc
qcsrc/server/tturrets/units/unit_ewheel.qc
qcsrc/server/tturrets/units/unit_walker.qc
qcsrc/server/vehicles/racer.qc
qcsrc/server/vehicles/raptor.qc [new file with mode: 0644]
qcsrc/server/vehicles/spiderbot.qc
qcsrc/server/vehicles/vehicles.qh
qcsrc/server/w_campingrifle.qc
qcsrc/warpzonelib/server.qc
qcsrc/xonotic-gamecode.workspace [new file with mode: 0644]
sync-extensions.sh [new file with mode: 0755]
textures/raptor.jpg [new file with mode: 0644]
textures/raptor_bump.jpg [new file with mode: 0644]
textures/raptor_cockpit.jpg [new file with mode: 0644]
textures/raptor_gloss.jpg [new file with mode: 0644]
textures/raptor_pants.jpg [new file with mode: 0644]
textures/raptor_shirt.jpg [new file with mode: 0644]
textures/sb_shield.tga [new file with mode: 0644]
textures/spiderbot.tga [new file with mode: 0644]
textures/spiderbot_gloss.tga [new file with mode: 0644]
textures/spiderbot_glow.tga [new file with mode: 0644]
textures/spiderbot_norm.tga [new file with mode: 0644]
textures/spiderbot_pants.tga [new file with mode: 0644]
textures/wakazachi.tga [new file with mode: 0644]
textures/wakazachi_gloss.tga [new file with mode: 0644]
textures/wakazachi_norm.tga [new file with mode: 0644]
textures/wakazachi_pants.tga [new file with mode: 0644]

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..fb9e9b1
--- /dev/null
@@ -0,0 +1,179 @@
+*.7z -crlf -diff
+*.aft crlf=input
+*.aliases crlf=input
+all crlf=input
+*.animinfo crlf=input
+*.aps -crlf -diff
+*.ase -crlf
+*.bat -crlf
+*.bgs crlf=input
+*.blend -crlf -diff
+*.bmp -crlf -diff
+branch-manager crlf=input
+BSDmakefile crlf=input
+bsp2ent crlf=input
+*.bsp -crlf -diff
+*.cache -crlf -diff
+*.cbp -crlf
+*.cbp -crlf -diff
+*.c crlf=input
+*.cfg crlf=input
+*.cg crlf=input
+ChangeLog crlf=input
+CHANGES crlf=input
+COMPILING crlf=input
+*.conf crlf=input
+CONTRIBUTORS crlf=input
+COPYING crlf=input
+*.cpp crlf=input
+*.css crlf=input
+Current -crlf -diff
+*.cvsignore crlf=input
+*.cvswrappers crlf=input
+*.db -crlf -diff
+*.default crlf=input
+*.def crlf=input
+*.dem -crlf -diff
+*.dev -crlf
+*.dll -crlf -diff
+DOCS -crlf -diff
+*.dot crlf=input
+DoxyConfig crlf=input
+Doxyfile crlf=input
+*.doxygen crlf=input
+*.dpm -crlf -diff
+*.dsp -crlf
+*.dsw -crlf
+*.dtd crlf=input
+*.dylib -crlf -diff
+*.EncoderPlugin crlf=input
+*.ent -crlf
+*.form crlf=input
+*.framegroups crlf=input
+*.game crlf=input
+gendox crlf=input
+gendoxfunctions crlf=input
+genDoxyfile crlf=input
+*.gif -crlf -diff
+*.gitattributes crlf=input
+git-branch-manager crlf=input
+git-filter-index crlf=input
+git-filter-repository crlf=input
+*.gitignore crlf=input
+git-pullall crlf=input
+git-split-repository crlf=input
+git-svn-checkout crlf=input
+git-svn-update crlf=input
+git-update-octopus crlf=input
+*.glp crlf=input
+*.glsl crlf=input
+GPL crlf=input
+*.hardwired crlf=input
+*.h crlf=input
+*.hs crlf=input
+*.html crlf=input
+*.html-part crlf=input
+*.icns -crlf -diff
+*.ico -crlf -diff
+*.idsoftware crlf=input
+*.inc crlf=input
+*.instantaction crlf=input
+*.java crlf=input
+*.jhm crlf=input
+*.jnlp crlf=input
+*.jpg -crlf -diff
+*.jsmooth crlf=input
+LGPL crlf=input
+LICENSE crlf=input
+*.lmp -crlf -diff
+*.loaders crlf=input
+*.lso -crlf -diff
+makefile crlf=input
+Makefile crlf=input
+*.makespr32 crlf=input
+makespr32 crlf=input
+*.map -crlf
+*.mapinfo crlf=input
+*.m crlf=input
+*.md3 -crlf -diff
+*.md5anim -crlf
+*.md5mesh -crlf
+*.mdl -crlf -diff
+*.med crlf=input
+*.mf crlf=input
+*.mid -crlf -diff
+*.mk crlf=input
+*.mmpz -crlf -diff
+*.modinfo crlf=input
+*.modules crlf=input
+nexuiz-map-compiler crlf=input
+nexuiz-osx-agl crlf=input
+nexuiz-osx-sdl crlf=input
+*.nib -crlf
+*.obj -crlf
+OFFSETS -crlf -diff
+*.ogg -crlf -diff
+*.options crlf=input
+pangorc crlf=input
+*.patch crlf=input
+*.patchsets crlf=input
+*.pcx -crlf -diff
+*.pk3 -crlf -diff
+PkgInfo crlf=input
+*.pl crlf=input
+*.plist crlf=input
+*.pm crlf=input
+*.png -crlf -diff
+POSITIONS -crlf -diff
+*.proj -crlf
+*.properties crlf=input
+*.psd -crlf -diff
+*.py crlf=input
+*.q3map1 crlf=input
+*.qc crlf=input
+*.qdt crlf=input
+*.qh crlf=input
+*.rb crlf=input
+*.rc2 crlf=input
+*.rc -crlf
+*.readme crlf=input
+README crlf=input
+*.rtlights -crlf -diff
+SCHEMA crlf=input
+*.scm crlf=input
+SDL -crlf -diff
+SDLMain.m crlf=input
+*.shader crlf=input
+*.sh crlf=input
+*.skin crlf=input
+*.sln -crlf
+*.sounds crlf=input
+*.sp2 -crlf -diff
+*.spr32 -crlf -diff
+*.spr -crlf -diff
+*.src crlf=input
+*.strings crlf=input
+*.strip crlf=input
+strip crlf=input
+*.svg -crlf -diff
+*.TAB -crlf -diff
+*.tga -crlf -diff
+TMAP -crlf -diff
+todo crlf=input
+TODO crlf=input
+*.ttf -crlf -diff
+*.TTF -crlf -diff
+*.txt crlf=input
+*.TXT crlf=input
+*.vcproj -crlf
+*.wav -crlf -diff
+*.waypoints -crlf -diff
+*.width crlf=input
+*.workspace -crlf
+*.xcf -crlf -diff
+*.xlink crlf=input
+*.xml crlf=input
+*.xpm crlf=input
+*.zip -crlf -diff
+zipdiff crlf=input
+*.zym -crlf -diff
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c3e14d3
--- /dev/null
@@ -0,0 +1,6 @@
+csprogs.dat
+menu.dat
+progs.dat
+qcsrc/client/fteqcc.log
+qcsrc/menu/fteqcc.log
+qcsrc/server/fteqcc.log
index c13ec44..11cc3a4 100644 (file)
@@ -3,6 +3,7 @@
 // use g_start_weapon_* to also replace the on-startup weapons!
 // example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
 // set the cvars to "0" to totally disable a weapon
+set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun"
 set g_weaponreplace_laser ""
 set g_weaponreplace_shotgun ""
 set g_weaponreplace_uzi ""
diff --git a/common-spog.pk3 b/common-spog.pk3
deleted file mode 100644 (file)
index 3696bbb..0000000
Binary files a/common-spog.pk3 and /dev/null differ
index 165c53d..9976b8e 100644 (file)
@@ -319,7 +319,7 @@ set sv_fragmessage_information_typefrag 1 "Enable typefrag display information,
 
 // use default physics
 set sv_friction_on_land 0
-exec physics26.cfg
+exec physicsNoQWBunny.cfg
 
 set sv_player_viewoffset "0 0 35" "view offset of the player model"
 set sv_player_mins "-16 -16 -24" "playermodel mins"
@@ -512,6 +512,19 @@ alias clearmap "disconnect"
 
 set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
 
+set g_dodging 0 "set to 1 to enable dodging in games"
+
+seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable"
+
+set sv_dodging_wall_dodging 0 "set to 1 to allow dodging off walls. 0 to disable"
+set sv_dodging_delay 0.5 "determines how long a player has to wait to be able to dodge again after dodging"
+set sv_dodging_up_speed 200 "the jump velocity of the dodge"
+set sv_dodging_horiz_speed 400 "the horizontal velocity of the dodge"
+set sv_dodging_ramp_time 0.1 "a ramp so that the horizontal part of the dodge is added smoothly (seconds)"
+set sv_dodging_height_threshold 10 "the maximum height above ground where to allow dodging"
+set sv_dodging_wall_distance_threshold 10 "the maximum distance from a wall that still allows dodging"
+set sv_dodging_sound 1 "if 1 dodging makes a sound. if 0 dodging is silent"
+
 set leadlimit 0
 
 // this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF, and Runematch.
@@ -1151,8 +1164,6 @@ set g_chat_flood_lmax_tell 2      "private chat: maximum number of lines per chat mes
 set g_chat_flood_burst_tell 2  "private chat: allow bursts of so many chat lines"
 set g_chat_flood_notify_flooder 1      "when 0, the flooder still can see his own message"
 set g_chat_teamcolors 0        "colorize nicknames in team color for chat"
-set g_voice_flood_spv 4        "normal voices: seconds between voices to not count as flooding"
-set g_voice_flood_spv_team 2   "team voices: seconds between voices to not count as flooding"
 set g_nick_flood_timeout 120 "time after which nick flood protection resets (set to 0 to disable nick flood checking)"
 set g_nick_flood_penalty 0.5 "duration of the nick flood penalty"
 set g_nick_flood_penalty_yellow 3 "number of changes to allow before warning and movement blocking"
@@ -1470,6 +1481,7 @@ seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for
 seta cl_weaponpriority7 "" "use impulse 207 for prev gun from this list, 217 for best gun, 227 for next gun"
 seta cl_weaponpriority8 "" "use impulse 208 for prev gun from this list, 218 for best gun, 228 for next gun"
 seta cl_weaponpriority9 "" "use impulse 209 for prev gun from this list, 219 for best gun, 229 for next gun"
+seta cl_weaponimpulsemode 0 "0: only cycle between currently usable weapons in weapon priority order; 1: cycle between all possible weapons on a key in weapon priority order"
 
 seta sv_status_privacy 1       "hide IP addresses from \"status\" replies shown to clients"
 
@@ -1780,3 +1792,13 @@ seta _cl_userid "" "player ID (e.g. for tournaments)"
 // FIXME workaround for engine bug
 sv_gameplayfix_nudgeoutofsolid 0
 // to div0: remove this once 5b7ac1706712977bbc0297d2d53294e73574c7cd (svn r9537) is in the stable branch of the engine again
+
+// otherwise, antilag breaks
+sv_gameplayfix_consistentplayerprethink 1
+
+// support Q1BSP maps
+mod_q1bsp_polygoncollisions 1
+
+// improve some minor details
+sv_gameplayfix_gravityunaffectedbyticrate 1
+sv_gameplayfix_nogravityonground 1
index 8ab688d..2885afb 100644 (file)
@@ -1348,8 +1348,8 @@ airfriction 12
 
 // electro trail
 // glowing vapor trail
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_XONOTICPLASMA"), from, to)
-effect TR_XONOTICPLASMA
+// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_NEXUIZPLASMA"), from, to)
+effect TR_NEXUIZPLASMA
 trailspacing 1
 type static
 color 0x283880 0x283880
@@ -1362,7 +1362,7 @@ lighttime 0
 lightcolor 1.5 3 6
 velocitymultiplier -0.1
 // bright sparks
-effect TR_XONOTICPLASMA
+effect TR_NEXUIZPLASMA
 trailspacing 6
 count 3
 type snow
diff --git a/font-dejavu.pk3dir/font-dejavu.cfg b/font-dejavu.pk3dir/font-dejavu.cfg
deleted file mode 100644 (file)
index 4b3200f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// must be loaded AFTER config.cfg
-utf8_enable 1
-r_font_disable_freetype 0
-r_font_size_snapping 2
-loadfont console fonts/DejaVuSansMono,gfx/conchars $con_textsize
-loadfont notify fonts/DejaVuSans-Bold,gfx/vera-sans $con_notifysize
-loadfont chat fonts/DejaVuSans-Bold,gfx/vera-sans $con_chatsize
-loadfont centerprint fonts/DejaVuSansMono,gfx/conchars 9
-loadfont infobar fonts/DejaVuSansMono,gfx/conchars 8
-loadfont user0 fonts/DejaVuSans-Bold,gfx/vera-sans 9.6 12 12.8 16
-loadfont user1 fonts/DejaVuSans-Bold,gfx/vera-sans 8 10 14 $sbar_fontsize $scr_centersize // csqc font
-loadfont user2 fonts/DejaVuSans-Bold,gfx/vera-sans 16 24 32 // csqc bigfont
-sbar_columns_set
diff --git a/font-dejavu.pk3dir/fonts/DejaVuSans-Bold.ttf b/font-dejavu.pk3dir/fonts/DejaVuSans-Bold.ttf
deleted file mode 100644 (file)
index b8f6c3e..0000000
Binary files a/font-dejavu.pk3dir/fonts/DejaVuSans-Bold.ttf and /dev/null differ
diff --git a/font-dejavu.pk3dir/fonts/DejaVuSansMono.ttf b/font-dejavu.pk3dir/fonts/DejaVuSansMono.ttf
deleted file mode 100644 (file)
index af80fb7..0000000
Binary files a/font-dejavu.pk3dir/fonts/DejaVuSansMono.ttf and /dev/null differ
index 4bd49bd..3d56cdb 100644 (file)
@@ -1,31 +1,31 @@
-1 56 30 0      // zombie attackleap         1\r
-57 41 60 1     // zombie attackrun1         2\r
-98 41 60 1     // zombie attackrun2         3\r
-139 41 60 1    // zombie attackrun3         4\r
-180 41 30 1    // zombie attackstanding1    5\r
-221 35 30 1    // zombie attackstanding2    6\r
-256 41 30 1    // zombie attackstanding3    7\r
-297 21 60 1    // zombie blockend           8\r
-318 21 60 0    // zombie blockstart         9\r
-339 96 30 0    // zombie deathback1         10\r
-435 67 30 0    // zombie deathback2         11\r
-502 71 30 0    // zombie deathback3         12\r
-573 61 30 0    // zombie deathfront1        13\r
-634 66 30 0    // zombie deathfront2        14\r
-700 96 30 0    // zombie deathfront3        15\r
-796 96 30 0    // zombie deathleft1         16\r
-892 71 30 0    // zombie deathleft2         17\r
-963 66 30 0    // zombie deathright1        18\r
-1029 86  30 0  // zombie deathright2        19\r
-1115 121 10 1  // zombie idle               20\r
-1236 11 30 0   // zombie painback1          21\r
-1247 11 30 0   // zombie painback2          22\r
-1258 11 30 0   // zombie painfront1         23\r
-1269 11 30 0   // zombie painfront2         24\r
-1280 41 60 1   // zombie runbackwards       25\r
-1321 41 60 1   // zombie runbackwardsleft   26\r
-1362 41 60 1   // zombie runbackwardsright  27\r
-1403 41 60 1   // zombie runforward         28\r
-1444 41 60 1   // zombie runforwardleft     29\r
-1485 41 60 1   // zombie runforwardright    30\r
-1526 61 30 0   // zombie spawn              31\r
+1 56 30 0      // zombie attackleap         1
+57 41 60 1     // zombie attackrun1         2
+98 41 60 1     // zombie attackrun2         3
+139 41 60 1    // zombie attackrun3         4
+180 41 30 1    // zombie attackstanding1    5
+221 35 30 1    // zombie attackstanding2    6
+256 41 30 1    // zombie attackstanding3    7
+297 21 60 1    // zombie blockend           8
+318 21 60 0    // zombie blockstart         9
+339 96 30 0    // zombie deathback1         10
+435 67 30 0    // zombie deathback2         11
+502 71 30 0    // zombie deathback3         12
+573 61 30 0    // zombie deathfront1        13
+634 66 30 0    // zombie deathfront2        14
+700 96 30 0    // zombie deathfront3        15
+796 96 30 0    // zombie deathleft1         16
+892 71 30 0    // zombie deathleft2         17
+963 66 30 0    // zombie deathright1        18
+1029 86  30 0  // zombie deathright2        19
+1115 121 10 1  // zombie idle               20
+1236 11 30 0   // zombie painback1          21
+1247 11 30 0   // zombie painback2          22
+1258 11 30 0   // zombie painfront1         23
+1269 11 30 0   // zombie painfront2         24
+1280 41 60 1   // zombie runbackwards       25
+1321 41 60 1   // zombie runbackwardsleft   26
+1362 41 60 1   // zombie runbackwardsright  27
+1403 41 60 1   // zombie runforward         28
+1444 41 60 1   // zombie runforwardleft     29
+1485 41 60 1   // zombie runforwardright    30
+1526 61 30 0   // zombie spawn              31
index 590155e..050d79c 100644 (file)
@@ -1,12 +1,12 @@
-1   1   1  0  // ANIM_NO\r
-35 55 20 1 // ANIM_TURN\r
-5 25 20 1   // ANIM_WALK\r
-5 25 40 1   // ANIM_RUN\r
-35 55 20 1 // ANIM_STRAFE_L\r
-65 85 20 1 // ANIM_STRAFE_R\r
-95 100 20 0 // ANIM_JUMP\r
-100 107 20 0 // ANIM_LAND\r
-90 95 20 0 // ANIM_PAIN\r
-123 140 40 0 // ANIM_MEELE\r
-146 151 20 1 // ANIM_SWIM\r
-5 25 20 1   // ANIM_ROAM\r
+1   1   1  0  // ANIM_NO
+35 55 20 1 // ANIM_TURN
+5 25 20 1   // ANIM_WALK
+5 25 40 1   // ANIM_RUN
+35 55 20 1 // ANIM_STRAFE_L
+65 85 20 1 // ANIM_STRAFE_R
+95 100 20 0 // ANIM_JUMP
+100 107 20 0 // ANIM_LAND
+90 95 20 0 // ANIM_PAIN
+123 140 40 0 // ANIM_MEELE
+146 151 20 1 // ANIM_SWIM
+5 25 20 1   // ANIM_ROAM
diff --git a/models/vehicles/raptor.dpm b/models/vehicles/raptor.dpm
new file mode 100644 (file)
index 0000000..83518c5
Binary files /dev/null and b/models/vehicles/raptor.dpm differ
diff --git a/models/vehicles/raptor_bomb.dpm b/models/vehicles/raptor_bomb.dpm
new file mode 100644 (file)
index 0000000..7fcc713
Binary files /dev/null and b/models/vehicles/raptor_bomb.dpm differ
diff --git a/models/vehicles/raptor_cockpit.dpm b/models/vehicles/raptor_cockpit.dpm
new file mode 100644 (file)
index 0000000..332b2d7
Binary files /dev/null and b/models/vehicles/raptor_cockpit.dpm differ
diff --git a/models/vehicles/raptor_gun.dpm b/models/vehicles/raptor_gun.dpm
new file mode 100644 (file)
index 0000000..fdc2791
Binary files /dev/null and b/models/vehicles/raptor_gun.dpm differ
index 3ea278d..f9db722 100644 (file)
@@ -1,6 +1,6 @@
-1   30  20 1 // forward\r
-32  30  20 1 // backward\r
-63  30  20 1 // left\r
-94  30 20 1 // right\r
-125 30 20 0 // jump\r
-0   1   20 0 // idle\r
+1   30  20 1 // forward
+32  30  20 1 // backward
+63  30  20 1 // left
+94  30 20 1 // right
+125 30 20 0 // jump
+0   1   20 0 // idle
index 89eba2b..65d9e71 100644 (file)
@@ -1,21 +1,21 @@
-set g_monster_zombie_respawntime    2\r
-set g_monster_zombie_movespeed      350\r
-set g_monster_zombie_health         275\r
-set g_monster_zombie_stopspeed      90\r
-set g_monster_zombie_turnspeed      360\r
-set g_monster_zombie_idle_timer_min 5\r
-set g_monster_zombie_idle_timer_max 10\r
-set g_monster_zombie_targetrange    2048\r
-\r
-set g_monster_zombie_attack_run_range    128\r
-set g_monster_zombie_attack_run_hitrange 96\r
-set g_monster_zombie_attack_run_delay    0.35\r
-set g_monster_zombie_attack_run_damage   30\r
-set g_monster_zombie_attack_run_force    300\r
-\r
-set g_monster_zombie_attack_stand_range    64\r
-set g_monster_zombie_attack_stand_hitrange 64\r
-set g_monster_zombie_attack_stand_delay    0.25\r
-set g_monster_zombie_attack_stand_damage   60\r
-set g_monster_zombie_attack_stand_force    250\r
-\r
+set g_monster_zombie_respawntime    2
+set g_monster_zombie_movespeed      350
+set g_monster_zombie_health         275
+set g_monster_zombie_stopspeed      90
+set g_monster_zombie_turnspeed      360
+set g_monster_zombie_idle_timer_min 5
+set g_monster_zombie_idle_timer_max 10
+set g_monster_zombie_targetrange    2048
+
+set g_monster_zombie_attack_run_range    128
+set g_monster_zombie_attack_run_hitrange 96
+set g_monster_zombie_attack_run_delay    0.35
+set g_monster_zombie_attack_run_damage   30
+set g_monster_zombie_attack_run_force    300
+
+set g_monster_zombie_attack_stand_range    64
+set g_monster_zombie_attack_stand_hitrange 64
+set g_monster_zombie_attack_stand_delay    0.25
+set g_monster_zombie_attack_stand_damage   60
+set g_monster_zombie_attack_stand_force    250
+
index f4a1840..ce1d1d8 100644 (file)
@@ -1,27 +1,27 @@
-sv_gravity 880\r
-sv_maxspeed 420\r
-sv_maxairspeed 235\r
-sv_stopspeed 200\r
-sv_accelerate 6\r
-sv_airaccelerate 6\r
-sv_friction 4\r
-edgefriction 0\r
-sv_stepheight 34\r
-sv_jumpvelocity 330\r
-sv_wateraccelerate -1\r
-sv_waterfriction -1\r
-sv_airaccel_sideways_friction 0.3\r
-sv_airaccel_qw 0.93\r
-sv_airstopaccelerate 0\r
-sv_airstrafeaccelerate 0\r
-sv_maxairstrafespeed 0\r
-sv_aircontrol 0\r
-sv_warsowbunny_turnaccel 0\r
-sv_warsowbunny_accel 0.1593\r
-sv_warsowbunny_topspeed 925\r
-sv_warsowbunny_backtosideratio 0.8\r
-sv_friction_on_land 0\r
-sv_doublejump 0\r
+sv_gravity 880
+sv_maxspeed 420
+sv_maxairspeed 235
+sv_stopspeed 200
+sv_accelerate 6
+sv_airaccelerate 6
+sv_friction 4
+edgefriction 0
+sv_stepheight 34
+sv_jumpvelocity 330
+sv_wateraccelerate -1
+sv_waterfriction -1
+sv_airaccel_sideways_friction 0.3
+sv_airaccel_qw 0.93
+sv_airstopaccelerate 0
+sv_airstrafeaccelerate 0
+sv_maxairstrafespeed 0
+sv_aircontrol 0
+sv_warsowbunny_turnaccel 0
+sv_warsowbunny_accel 0.1593
+sv_warsowbunny_topspeed 925
+sv_warsowbunny_backtosideratio 0.8
+sv_friction_on_land 0
+sv_doublejump 0
 sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
index c42512a..9bb7661 100644 (file)
@@ -341,6 +341,8 @@ float view_set;
 float camera_mode;
 string NextFrameCommand;
 void CSQC_SPIDER_HUD();
+void CSQC_RAPTOR_HUD();
+
 void CSQC_UpdateView(float w, float h)
 {
        entity e;
@@ -596,6 +598,8 @@ void CSQC_UpdateView(float w, float h)
        }
        else if(hud == HUD_WAKIZASHI)
         CSQC_WAKIZASHI_HUD();
+    else if(hud == HUD_RAPTOR)
+        CSQC_RAPTOR_HUD();
        else
        {
                if(cvar("r_letterbox") == 0)
@@ -857,13 +861,13 @@ void Sbar_Draw();
 
 void CSQC_SPIDER_HUD()
 {
-       float rockets, reload, heat, hp, shield, i;
+       float rockets, reload, heat, hp, shield;
        vector picsize, hudloc;
 
     // Fetch health & ammo stats
     hp      = bound(0,getstatf(STAT_VEHICLESTAT_HEALTH), 1);
        shield  = bound(0,getstatf(STAT_VEHICLESTAT_SHIELD), 1);
-       heat    = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 1);
+       heat    = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 2);
        rockets =     getstati(STAT_VEHICLESTAT_AMMO2);
        reload  = min(getstatf(STAT_VEHICLESTAT_RELOAD2), 1);
 
@@ -882,10 +886,8 @@ void CSQC_SPIDER_HUD()
     picsize = drawgetimagesize(spider_a2) * 0.5;
     drawpic(hudloc + '120 96  0', spider_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
 
-
     drawstring(hudloc + '145 19  0', strcat(ftos(rint(hp * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL);
     drawstring(hudloc + '175 34  0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL);
-
     drawstring(hudloc + '136 102  0', strcat(ftos(100 - rint(heat * 100)), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL);
 
     picsize = drawgetimagesize(spider_a1) * 0.85;
@@ -964,6 +966,76 @@ void CSQC_SPIDER_HUD()
 
 }
 
+#define raptor_h "gfx/vehicles/hud_bg.tga"
+#define raptor_b "gfx/vehicles/raptor.tga"
+#define raptor_g1 "gfx/vehicles/raptor_guns.tga"
+#define raptor_g2 "gfx/vehicles/raptor_bombs.tga"
+#define raptor_s "gfx/vehicles/shiled.tga"
+
+#define spider_a1 "gfx/hud/sb_rocket.tga"
+#define spider_a2 "gfx/sb_bullets.tga"
+
+void CSQC_RAPTOR_HUD()
+{
+       float rockets, reload, heat, hp, shield, energy;
+       vector picsize, hudloc;
+
+    // Fetch health & ammo stats
+    hp      = bound(0,getstatf(STAT_VEHICLESTAT_HEALTH), 1);
+       shield  = bound(0,getstatf(STAT_VEHICLESTAT_SHIELD), 1);
+       reload  = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 1);
+       energy  = min(getstatf(STAT_VEHICLESTAT_ENERGY),  1);
+
+    // Draw the crosshairs
+    picsize = drawgetimagesize(SPIDER_CROSS);
+    picsize_x *= cvar_or("cl_vehicle_spiderbot_cross_size", 1);
+    picsize_y *= cvar_or("cl_vehicle_spiderbot_cross_size", 1);
+    drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), SPIDER_CROSS, picsize, '1 1 1', cvar_or("cl_vehicle_spiderbot_cross_alpha",0.6), DRAWFLAG_NORMAL);
+
+    hudloc_y =  4;
+    hudloc_x = 4;
+
+    picsize = drawgetimagesize(raptor_h) * 0.5;
+    drawpic(hudloc, raptor_h, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+    picsize = drawgetimagesize(spider_a2) * 0.5;
+    drawpic(hudloc + '120 96  0', spider_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+    drawstring(hudloc + '145 19  0', strcat(ftos(rint(hp * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL);
+    drawstring(hudloc + '175 34  0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL);
+    drawstring(hudloc + '136 102 0', strcat(ftos(rint(energy * 100)), "%"),'15 15 0','0.5 0.5 1', 1, DRAWFLAG_NORMAL);
+
+
+    picsize = drawgetimagesize(spider_a1) * 0.85;
+    if(reload == 1)
+    {
+        drawpic(hudloc + '132 54  0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        drawstring(hudloc + '179 69  0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','0 1 0', 0.5, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + '132 54  0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        drawstring(hudloc + '179 69  0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','0 0 1', 1, DRAWFLAG_NORMAL);
+    }
+
+    picsize = drawgetimagesize(raptor_b) * 0.5;
+    hudloc_y = 10.5;
+    hudloc_x = 10.5;
+
+    drawpic(hudloc, raptor_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
+    drawpic(hudloc, raptor_b, picsize, '0 1 0' * hp + '1 0 0' * (1 - hp), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, raptor_g1, picsize, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, raptor_g2, picsize, '1 1 1' * reload + '1 0 0' *  (1 - reload), 1, DRAWFLAG_NORMAL);
+
+
+       if (sb_showscores)
+       {
+               Sbar_DrawScoreboard();
+               Sbar_DrawCenterPrint();
+       }
+
+}
+
 #define waki_h "gfx/vehicles/hud_bg.tga"
 #define waki_b "gfx/vehicles/waki.tga"
 #define waki_e "gfx/vehicles/waki_e.tga"
index 97debdf..2730a32 100644 (file)
@@ -249,14 +249,14 @@ void Ent_Projectile()
                self.traileffect = 0;
                switch(self.cnt)
                {
-                       case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_XONOTICPLASMA"); break;
+                       case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
                        case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break;
                        case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
                        case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
                        case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break;
                        case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
                        case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
-                       case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_XONOTICPLASMA"); break;
+                       case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
                        case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
                        case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
                        case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
index cdd3a31..92ef984 100644 (file)
@@ -285,6 +285,7 @@ const float STAT_HUD = 50;
 const float HUD_NORMAL = 0;
 const float HUD_SPIDERBOT = 10;
 const float HUD_WAKIZASHI = 11;
+const float HUD_RAPTOR    = 12;
 
 const float STAT_VEHICLESTAT_HEALTH  = 60;
 const float STAT_VEHICLESTAT_SHIELD  = 61;
index 39e1fd8..d32f196 100644 (file)
@@ -1,5 +1,6 @@
 #ifdef INTERFACE
 CLASS(Keyframe) EXTENDS(Animation)
+       METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)))
        METHOD(Keyframe, addAnim, void(entity, entity))
        METHOD(Keyframe, calcValue, float(entity, float, float, float, float))
        ATTRIB(Keyframe, currentChild, entity, NULL)
@@ -8,6 +9,9 @@ CLASS(Keyframe) EXTENDS(Animation)
 ENDCLASS(Animation)
 entity makeHostedKeyframe(entity, void(entity, float), float, float, float);
 entity makeKeyframe(entity, void(entity, float), float, float, float);
+float getNewChildStart(entity);
+float getNewChildDuration(entity, float);
+float getNewChildValue(entity);
 #endif
 
 #ifdef IMPLEMENTATION
@@ -27,6 +31,40 @@ entity makeKeyframe(entity obj, void(entity, float) setter, float duration, floa
        return me;
 }
 
+entity addEasingKeyframe(entity me, float durationTime, float end, float(float, float, float, float) func)
+{
+       entity other;
+       other = makeEasing(me.object, me.setter, func, getNewChildStart(me), getNewChildDuration(me, durationTime), getNewChildValue(me), end);
+       me.addAnim(me, other);
+       return other;
+}
+
+float getNewChildStart(entity me)
+{
+       if (me.lastChild)
+               return (me.lastChild.startTime + me.lastChild.duration);
+       else
+               return 0;
+}
+
+float getNewChildDuration(entity me, float durationTime)
+{
+       float dura, maxDura;
+       maxDura = me.duration;
+       if (me.lastChild) maxDura = maxDura - (me.lastChild.startTime + me.lastChild.duration);
+       dura = durationTime;
+       if (0 >= dura || dura > maxDura) dura = maxDura;
+       return dura;
+}
+
+float getNewChildValue(entity me)
+{
+       if (me.lastChild)
+               return (me.lastChild.startValue + me.lastChild.delta);
+       else
+               return me.startValue;
+}
+
 void addAnimKeyframe(entity me, entity other)
 {
        if(other.parent)
index 68cf5b6..12d7e4f 100644 (file)
@@ -64,6 +64,8 @@ string toStringXonoticMutatorsDialog(entity me)
 {
        string s;
        s = "";
+       if(cvar("g_dodging"))
+               s = strcat(s, ", Dodging");
        if(cvar("g_minstagib"))
                s = strcat(s, ", MinstaGib");
        if(cvar("g_nix"))
@@ -164,6 +166,9 @@ void fillXonoticMutatorsDialog(entity me)
                me.TD(me, 1, 2, makeXonoticTextLabel(0, "Gameplay mutators:"));
        me.TR(me);
                me.TDempty(me, 0.2);
+               me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_dodging", "Dodging"));
+       me.TR(me);
+               me.TDempty(me, 0.2);
                me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_cloaked", "Cloaked"));
        me.TR(me);
                me.TDempty(me, 0.2);
diff --git a/qcsrc/qc-client.cbp b/qcsrc/qc-client.cbp
new file mode 100644 (file)
index 0000000..056b98e
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+       <FileVersion major="1" minor="6" />
+       <Project>
+               <Option title="qc-client" />
+               <Option makefile="client" />
+               <Option makefile_is_custom="1" />
+               <Option pch_mode="2" />
+               <Option compiler="qaukec" />
+               <Build>
+                       <Target title="Debug">
+                               <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj\Debug\" />
+                               <Option type="1" />
+                               <Option compiler="qaukec" />
+                               <Compiler>
+                                       <Add option="-g" />
+                               </Compiler>
+                               <MakeCommands>
+                                       <Build command="$make -src $makefile" />
+                                       <CompileFile command="" />
+                                       <Clean command="" />
+                                       <DistClean command="" />
+                               </MakeCommands>
+                       </Target>
+                       <Target title="Release">
+                               <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj\Release\" />
+                               <Option type="1" />
+                               <Option compiler="qaukec" />
+                               <Compiler>
+                                       <Add option="-O2" />
+                               </Compiler>
+                               <Linker>
+                                       <Add option="-s" />
+                               </Linker>
+                               <MakeCommands>
+                                       <Build command="$make -src $makefile" />
+                                       <CompileFile command="" />
+                                       <Clean command="" />
+                                       <DistClean command="" />
+                               </MakeCommands>
+                       </Target>
+               </Build>
+               <Compiler>
+                       <Add option="-Wall" />
+               </Compiler>
+               <Unit filename="client\Defs.qc" />
+               <Unit filename="client\Main.qc" />
+               <Unit filename="client\View.qc" />
+               <Unit filename="client\autocvars.qh" />
+               <Unit filename="client\bgmscript.qc" />
+               <Unit filename="client\bgmscript.qh" />
+               <Unit filename="client\casings.qc" />
+               <Unit filename="client\csqc_builtins.qc" />
+               <Unit filename="client\csqc_constants.qc" />
+               <Unit filename="client\ctf.qc" />
+               <Unit filename="client\damage.qc" />
+               <Unit filename="client\effects.qc" />
+               <Unit filename="client\gibs.qc" />
+               <Unit filename="client\hook.qc" />
+               <Unit filename="client\interpolate.qc" />
+               <Unit filename="client\interpolate.qh" />
+               <Unit filename="client\laser.qc" />
+               <Unit filename="client\main.qh" />
+               <Unit filename="client\mapvoting.qc" />
+               <Unit filename="client\miscfunctions.qc" />
+               <Unit filename="client\modeleffects.qc" />
+               <Unit filename="client\movetypes.qc" />
+               <Unit filename="client\movetypes.qh" />
+               <Unit filename="client\particles.qc" />
+               <Unit filename="client\prandom.qc" />
+               <Unit filename="client\prandom.qh" />
+               <Unit filename="client\pre.qh" />
+               <Unit filename="client\progs.src" />
+               <Unit filename="client\projectile.qc" />
+               <Unit filename="client\rubble.qc" />
+               <Unit filename="client\sbar.qc" />
+               <Unit filename="client\sortlist.qc" />
+               <Unit filename="client\teamplay.qc" />
+               <Unit filename="client\teamradar.qc" />
+               <Unit filename="client\teamradar.qh" />
+               <Unit filename="client\tuba.qc" />
+               <Unit filename="client\wall.qc" />
+               <Unit filename="client\waypointsprites.qc" />
+               <Unit filename="client\waypointsprites.qh" />
+               <Extensions>
+                       <code_completion />
+                       <debugger />
+               </Extensions>
+       </Project>
+</CodeBlocks_project_file>
diff --git a/qcsrc/qc-common.cbp b/qcsrc/qc-common.cbp
new file mode 100644 (file)
index 0000000..95f1ba8
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+       <FileVersion major="1" minor="6" />
+       <Project>
+               <Option title="qc-common" />
+               <Option makefile="none" />
+               <Option makefile_is_custom="1" />
+               <Option pch_mode="2" />
+               <Option compiler="qaukec" />
+               <Build>
+                       <Target title="Debug">
+                               <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj\Debug\" />
+                               <Option type="1" />
+                               <Option compiler="qaukec" />
+                               <Compiler>
+                                       <Add option="-g" />
+                               </Compiler>
+                               <MakeCommands>
+                                       <Build command="$make -src $makefile" />
+                                       <CompileFile command="" />
+                                       <Clean command="" />
+                                       <DistClean command="" />
+                               </MakeCommands>
+                       </Target>
+                       <Target title="Release">
+                               <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj\Release\" />
+                               <Option type="1" />
+                               <Option compiler="qaukec" />
+                               <Compiler>
+                                       <Add option="-O2" />
+                               </Compiler>
+                               <Linker>
+                                       <Add option="-s" />
+                               </Linker>
+                               <MakeCommands>
+                                       <Build command="$make -src $makefile" />
+                                       <CompileFile command="" />
+                                       <Clean command="" />
+                                       <DistClean command="" />
+                               </MakeCommands>
+                       </Target>
+               </Build>
+               <Compiler>
+                       <Add option="-Wall" />
+               </Compiler>
+               <Unit filename="common\campaign_common.qh" />
+               <Unit filename="common\campaign_file.qc" />
+               <Unit filename="common\campaign_setup.qc" />
+               <Unit filename="common\constants.qh" />
+               <Unit filename="common\gamecommand.qc" />
+               <Unit filename="common\items.qc" />
+               <Unit filename="common\items.qh" />
+               <Unit filename="common\mapinfo.qc" />
+               <Unit filename="common\mapinfo.qh" />
+               <Unit filename="common\util-pre.qh" />
+               <Unit filename="common\util.qc" />
+               <Unit filename="common\util.qh" />
+               <Extensions>
+                       <code_completion />
+                       <debugger />
+               </Extensions>
+       </Project>
+</CodeBlocks_project_file>
diff --git a/qcsrc/qc-server.cbp b/qcsrc/qc-server.cbp
new file mode 100644 (file)
index 0000000..00912be
--- /dev/null
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+       <FileVersion major="1" minor="6" />
+       <Project>
+               <Option title="qc-server" />
+               <Option makefile="server/" />
+               <Option makefile_is_custom="1" />
+               <Option pch_mode="2" />
+               <Option compiler="qaukec" />
+               <Build>
+                       <Target title="Debug">
+                               <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj\Debug\" />
+                               <Option type="1" />
+                               <Option compiler="qaukec" />
+                               <Compiler>
+                                       <Add option="-g" />
+                               </Compiler>
+                               <MakeCommands>
+                                       <Build command="$make -DVEHICLES_ENABLED -DRELEASE -src $makefile" />
+                                       <CompileFile command="" />
+                                       <Clean command="" />
+                                       <DistClean command="" />
+                               </MakeCommands>
+                       </Target>
+                       <Target title="Release">
+                               <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj\Release\" />
+                               <Option type="1" />
+                               <Option compiler="qaukec" />
+                               <Compiler>
+                                       <Add option="-O2" />
+                               </Compiler>
+                               <Linker>
+                                       <Add option="-s" />
+                               </Linker>
+                               <MakeCommands>
+                                       <Build command="$make -DVEHICLES_ENABLED -DRELEASE -src $makefile" />
+                                       <CompileFile command="" />
+                                       <Clean command="" />
+                                       <DistClean command="" />
+                               </MakeCommands>
+                       </Target>
+               </Build>
+               <Compiler>
+                       <Add option="-Wall" />
+               </Compiler>
+               <Unit filename="anticheat.qc" />
+               <Unit filename="anticheat.qh" />
+               <Unit filename="antilag.qc" />
+               <Unit filename="antilag.qh" />
+               <Unit filename="arena.qc" />
+               <Unit filename="assault.qc" />
+               <Unit filename="bot\aim.qc" />
+               <Unit filename="bot\aim.qh" />
+               <Unit filename="bot\bot.qc" />
+               <Unit filename="bot\bot.qh" />
+               <Unit filename="bot\havocbot\havocbot.qc" />
+               <Unit filename="bot\havocbot\havocbot.qh" />
+               <Unit filename="bot\havocbot\role_ctf.qc" />
+               <Unit filename="bot\havocbot\role_keyhunt.qc" />
+               <Unit filename="bot\havocbot\role_onslaught.qc" />
+               <Unit filename="bot\havocbot\roles.qc" />
+               <Unit filename="bot\navigation.qc" />
+               <Unit filename="bot\navigation.qh" />
+               <Unit filename="bot\scripting.qc" />
+               <Unit filename="bot\waypoints.qc" />
+               <Unit filename="bot\waypoints.qh" />
+               <Unit filename="builtins.qh" />
+               <Unit filename="campaign.qc" />
+               <Unit filename="campaign.qh" />
+               <Unit filename="cheats.qc" />
+               <Unit filename="cheats.qh" />
+               <Unit filename="cl_client.qc" />
+               <Unit filename="cl_impulse.qc" />
+               <Unit filename="cl_physics.qc" />
+               <Unit filename="cl_player.qc" />
+               <Unit filename="cl_weapons.qc" />
+               <Unit filename="cl_weaponsystem.qc" />
+               <Unit filename="clientcommands.qc" />
+               <Unit filename="constants.qh" />
+               <Unit filename="csqceffects.qc" />
+               <Unit filename="csqcprojectile.qc" />
+               <Unit filename="csqcprojectile.qh" />
+               <Unit filename="ctf.qc" />
+               <Unit filename="defs.qh" />
+               <Unit filename="domination.qc" />
+               <Unit filename="ent_cs.qc" />
+               <Unit filename="extensions.qh" />
+               <Unit filename="func_breakable.qc" />
+               <Unit filename="g_casings.qc" />
+               <Unit filename="g_damage.qc" />
+               <Unit filename="g_hook.qc" />
+               <Unit filename="g_hook.qh" />
+               <Unit filename="g_lights.qc" />
+               <Unit filename="g_models.qc" />
+               <Unit filename="g_subs.qc" />
+               <Unit filename="g_swamp.qc" />
+               <Unit filename="g_tetris.qc" />
+               <Unit filename="g_triggers.qc" />
+               <Unit filename="g_violence.qc" />
+               <Unit filename="g_world.qc" />
+               <Unit filename="gamecommand.qc" />
+               <Unit filename="ipban.qc" />
+               <Unit filename="ipban.qh" />
+               <Unit filename="miscfunctions.qc" />
+               <Unit filename="mode_onslaught.qc" />
+               <Unit filename="monsters\ai.qc" />
+               <Unit filename="monsters\defs.qc" />
+               <Unit filename="monsters\fight.qc" />
+               <Unit filename="monsters\m_monsters.qc" />
+               <Unit filename="monsters\mode_management.qc" />
+               <Unit filename="monsters\monster_zombie.qc" />
+               <Unit filename="movelib.qc" />
+               <Unit filename="mutators\base.qc" />
+               <Unit filename="mutators\base.qh" />
+               <Unit filename="mutators\gamemode_keyhunt.qc" />
+               <Unit filename="mutators\gamemode_keyhunt.qh" />
+               <Unit filename="mutators\mutator_dodging.qc" />
+               <Unit filename="mutators\mutator_dodging.qh" />
+               <Unit filename="mutators\mutator_nix.qc" />
+               <Unit filename="mutators\mutators.qh" />
+               <Unit filename="nexball.qc" />
+               <Unit filename="pathlib.qc" />
+               <Unit filename="pathlib\costs.qc" />
+               <Unit filename="pathlib\debug.qc" />
+               <Unit filename="pathlib\expandnode.qc" />
+               <Unit filename="pathlib\main.qc" />
+               <Unit filename="pathlib\movenode.qc" />
+               <Unit filename="pathlib\pathlib.qh" />
+               <Unit filename="pathlib\utility.qc" />
+               <Unit filename="playerdemo.qc" />
+               <Unit filename="playerdemo.qh" />
+               <Unit filename="portals.qc" />
+               <Unit filename="portals.qh" />
+               <Unit filename="post-builtins.qh" />
+               <Unit filename="pre-builtins.qh" />
+               <Unit filename="progs.src" />
+               <Unit filename="race.qc" />
+               <Unit filename="race.qh" />
+               <Unit filename="runematch.qc" />
+               <Unit filename="scores.qc" />
+               <Unit filename="scores.qh" />
+               <Unit filename="scores_rules.qc" />
+               <Unit filename="steerlib.qc" />
+               <Unit filename="sv_main.qc" />
+               <Unit filename="sv_stats.qc" />
+               <Unit filename="sys.qh" />
+               <Unit filename="t_halflife.qc" />
+               <Unit filename="t_items.qc" />
+               <Unit filename="t_jumppads.qc" />
+               <Unit filename="t_plats.qc" />
+               <Unit filename="t_quake.qc" />
+               <Unit filename="t_quake3.qc" />
+               <Unit filename="t_swamp.qc" />
+               <Unit filename="t_teleporters.qc" />
+               <Unit filename="target_spawn.qc" />
+               <Unit filename="teamplay.qc" />
+               <Unit filename="tturrets\include\turrets.qh" />
+               <Unit filename="tturrets\include\turrets_early.qh" />
+               <Unit filename="tturrets\system\system_aimprocs.qc" />
+               <Unit filename="tturrets\system\system_damage.qc" />
+               <Unit filename="tturrets\system\system_main.qc" />
+               <Unit filename="tturrets\system\system_misc.qc" />
+               <Unit filename="tturrets\system\system_scoreprocs.qc" />
+               <Unit filename="tturrets\units\unit_checkpoint.qc" />
+               <Unit filename="tturrets\units\unit_common.qc" />
+               <Unit filename="tturrets\units\unit_ewheel.qc" />
+               <Unit filename="tturrets\units\unit_flac.qc" />
+               <Unit filename="tturrets\units\unit_fusionreactor.qc" />
+               <Unit filename="tturrets\units\unit_hellion.qc" />
+               <Unit filename="tturrets\units\unit_hk.qc" />
+               <Unit filename="tturrets\units\unit_machinegun.qc" />
+               <Unit filename="tturrets\units\unit_mlrs.qc" />
+               <Unit filename="tturrets\units\unit_phaser.qc" />
+               <Unit filename="tturrets\units\unit_plasma.qc" />
+               <Unit filename="tturrets\units\unit_targettrigger.qc" />
+               <Unit filename="tturrets\units\unit_tessla.qc" />
+               <Unit filename="tturrets\units\unit_walker.qc" />
+               <Unit filename="vehicles\racer.qc" />
+               <Unit filename="vehicles\raptor.qc" />
+               <Unit filename="vehicles\spiderbot.qc" />
+               <Unit filename="vehicles\vehicles.qc" />
+               <Unit filename="vehicles\vehicles.qh" />
+               <Unit filename="verbstack.qc" />
+               <Unit filename="vote.qc" />
+               <Unit filename="vote.qh" />
+               <Unit filename="w_all.qc" />
+               <Unit filename="w_campingrifle.qc" />
+               <Unit filename="w_common.qc" />
+               <Unit filename="w_crylink.qc" />
+               <Unit filename="w_electro.qc" />
+               <Unit filename="w_fireball.qc" />
+               <Unit filename="w_grenadelauncher.qc" />
+               <Unit filename="w_hagar.qc" />
+               <Unit filename="w_hlac.qc" />
+               <Unit filename="w_hook.qc" />
+               <Unit filename="w_laser.qc" />
+               <Unit filename="w_minstanex.qc" />
+               <Unit filename="w_nex.qc" />
+               <Unit filename="w_porto.qc" />
+               <Unit filename="w_rocketlauncher.qc" />
+               <Unit filename="w_shotgun.qc" />
+               <Unit filename="w_tuba.qc" />
+               <Unit filename="w_uzi.qc" />
+               <Unit filename="waypointsprites.qc" />
+               <Extensions>
+                       <code_completion />
+                       <debugger />
+               </Extensions>
+       </Project>
+</CodeBlocks_project_file>
index 593a0ca..ef83ef6 100644 (file)
@@ -13,10 +13,13 @@ void Announce(string snd) {
 }
 
 void AnnounceTo(entity e, string snd) {
-       msg_entity = e;
-       WriteByte(MSG_ONE, SVC_TEMPENTITY);
-       WriteByte(MSG_ONE, TE_CSQC_ANNOUNCE);
-       WriteString(MSG_ONE, snd);
+       if (clienttype(e) == CLIENTTYPE_REAL)
+       {
+               msg_entity = e;
+               WriteByte(MSG_ONE, SVC_TEMPENTITY);
+               WriteByte(MSG_ONE, TE_CSQC_ANNOUNCE);
+               WriteString(MSG_ONE, snd);
+       }
 }
 
 float ClientData_Send(entity to, float sf)
@@ -405,6 +408,7 @@ string CheckPlayerModel(string plyermodel) {
        {
                if(substring(plyermodel,-4,4) != ".zym")
                if(substring(plyermodel,-4,4) != ".dpm")
+               if(substring(plyermodel,-4,4) != ".iqm")
                if(substring(plyermodel,-4,4) != ".md3")
                if(substring(plyermodel,-4,4) != ".psk")
                        return FallbackPlayerModel;
@@ -2049,6 +2053,7 @@ void SetZoomState(float z)
 }
 
 void GetPressedKeys(void) {
+       MUTATOR_CALLHOOK(GetPressedKeys);
        if (self.movement_x > 0) // get if movement keys are pressed
        {       // forward key pressed
                self.pressedkeys |= KEY_FORWARD;
@@ -2526,8 +2531,7 @@ void PlayerPreThink (void)
 
                if(frametime)
                {
-                       if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                               self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
+                       self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
                        player_powerups();
                }
 
@@ -2847,7 +2851,6 @@ void PlayerPostThink (void)
                        ImpulseCommands();
                if (intermission_running)
                        return;         // intermission or finale
-
                GetPressedKeys();
        } else if (self.classname == "observer") {
                //do nothing
index eef7724..11d0cbf 100644 (file)
@@ -715,6 +715,8 @@ void SV_PlayerPhysics()
                bot_think();
        }
        
+       MUTATOR_CALLHOOK(PlayerPhysics);
+
        self.items &~= IT_USING_JETPACK;
 
        if(self.classname == "player")
index 1911f40..8925f17 100644 (file)
@@ -633,7 +633,11 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                Obituary (attacker, inflictor, self, deathtype);
                race_PreDie();
                DropAllRunes(self);
-               frag_attacker = attacker; MUTATOR_CALLHOOK(PlayerDies);
+
+               frag_attacker = attacker;
+               frag_inflictor = inflictor;
+               MUTATOR_CALLHOOK(PlayerDies);
+
                if(self.flagcarried)
                {
                        if(attacker.classname != "player" && attacker.classname != "gib")
@@ -881,14 +885,20 @@ void UpdateSelectedPlayer()
 }
 
 .float muted; // to be used by prvm_edictset server playernumber muted 1
-void Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
+float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
+// message "": do not say, just test flood control
+// return value:
+//   1 = accept
+//   0 = reject
+//  -1 = fake accept
 {
        string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, privatemsgprefix;
        float flood, privatemsgprefixlen;
        entity head;
+       float ret;
 
        if(Ban_MaybeEnforceBan(source))
-               return;
+               return 0;
 
        if(!teamsay && !privatesay)
                if(substring(msgin, 0, 1) == " ")
@@ -896,9 +906,6 @@ void Say(entity source, float teamsay, entity privatesay, string msgin, float fl
 
        msgin = formatmessage(msgin);
 
-       if(msgin == "")
-               return;
-
        if(source.classname != "player")
                colorstr = "^0"; // black for spectators
        else if(teams_matter)
@@ -909,9 +916,8 @@ void Say(entity source, float teamsay, entity privatesay, string msgin, float fl
        if(intermission_running)
                teamsay = FALSE;
 
-       msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
-       if(msgin == "")
-               return;
+       if(msgin != "")
+               msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
 
        /*
         * using bprint solves this... me stupid
@@ -929,29 +935,36 @@ void Say(entity source, float teamsay, entity privatesay, string msgin, float fl
        else
                namestr = source.netname;
 
-       if(privatesay)
+       if(msgin != "")
        {
-               msgstr = strcat("\{1}\{13}* ^3", namestr, "^3 tells you: ^7");
-               privatemsgprefixlen = strlen(msgstr);
-               msgstr = strcat(msgstr, msgin);
-               cmsgstr = strcat(colorstr, "^3", namestr, "^3 tells you:\n^7", msgin);
-               if(cvar("g_chat_teamcolors"))
-                       privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay), ": ^7");
+               if(privatesay)
+               {
+                       msgstr = strcat("\{1}\{13}* ^3", namestr, "^3 tells you: ^7");
+                       privatemsgprefixlen = strlen(msgstr);
+                       msgstr = strcat(msgstr, msgin);
+                       cmsgstr = strcat(colorstr, "^3", namestr, "^3 tells you:\n^7", msgin);
+                       if(cvar("g_chat_teamcolors"))
+                               privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay), ": ^7");
+                       else
+                               privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", privatesay.netname, ": ^7");
+               }
+               else if(teamsay)
+               {
+                       msgstr = strcat("\{1}\{13}", colorstr, "(^3", namestr, colorstr, ") ^7", msgin);
+                       cmsgstr = strcat(colorstr, "(^3", namestr, colorstr, ")\n^7", msgin);
+               }
                else
-                       privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", privatesay.netname, ": ^7");
-       }
-       else if(teamsay)
-       {
-               msgstr = strcat("\{1}\{13}", colorstr, "(^3", namestr, colorstr, ") ^7", msgin);
-               cmsgstr = strcat(colorstr, "(^3", namestr, colorstr, ")\n^7", msgin);
+               {
+                       msgstr = strcat("\{1}", namestr, "^7: ", msgin);
+                       cmsgstr = "";
+               }
+               msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
        }
        else
        {
-               msgstr = strcat("\{1}", namestr, "^7: ", msgin);
-               cmsgstr = "";
+               msgstr = cmsgstr = "";
        }
 
-       msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
        fullmsgstr = msgstr;
        fullcmsgstr = cmsgstr;
 
@@ -989,37 +1002,47 @@ void Say(entity source, float teamsay, entity privatesay, string msgin, float fl
                // to match explanation in default.cfg, a value of 3 must allow three-line bursts and not four!
 
                // do flood control for the default line size
-               getWrappedLine_remaining = msgstr;
-               msgstr = "";
-               lines = 0;
-               while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
+               if(msgstr != "")
                {
-                       msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
-                       ++lines;
-               }
-               msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
+                       getWrappedLine_remaining = msgstr;
+                       msgstr = "";
+                       lines = 0;
+                       while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
+                       {
+                               msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
+                               ++lines;
+                       }
+                       msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
 
-               if(getWrappedLine_remaining != "")
-               {
-                       msgstr = strcat(msgstr, "\n");
-                       flood = 2;
-               }
+                       if(getWrappedLine_remaining != "")
+                       {
+                               msgstr = strcat(msgstr, "\n");
+                               flood = 2;
+                       }
 
-               if(time >= source.flood_field)
-               {
-                       source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + lines * flood_spl;
+                       if(time >= source.flood_field)
+                       {
+                               source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + lines * flood_spl;
+                       }
+                       else
+                       {
+                               flood = 1;
+                               msgstr = fullmsgstr;
+                       }
                }
                else
                {
-                       flood = 1;
-                       msgstr = fullmsgstr;
+                       if(time >= source.flood_field)
+                               source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + flood_spl;
+                       else
+                               flood = 1;
                }
        }
 
        if (timeoutStatus == 2) //when game is paused, no flood protection
                source.flood_field = flood = 0;
 
-       if(flood == 2)
+       if(flood == 2) // cannot happen for empty msgstr
        {
                if(cvar("g_chat_flood_notify_flooder"))
                {
@@ -1056,57 +1079,70 @@ void Say(entity source, float teamsay, entity privatesay, string msgin, float fl
        if(source.muted)
        {
                // always fake the message
-               sprint(source, sourcemsgstr);
-               if(cmsgstr != "" && !privatesay)
-                       centerprint(source, sourcecmsgstr);
+               ret = -1;
        }
        else if(flood == 1)
        {
                if(cvar("g_chat_flood_notify_flooder"))
-                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n"));
-               else
                {
-                       sprint(source, sourcemsgstr);
-                       if(cmsgstr != "" && !privatesay)
-                               centerprint(source, sourcecmsgstr);
+                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n"));
+                       ret = 0;
                }
+               else
+                       ret = -1;
        }
-       else if(privatesay)
-       {
-               sprint(source, sourcemsgstr);
-               sprint(privatesay, msgstr);
-               if(cmsgstr != "")
-                       centerprint(privatesay, cmsgstr);
-       }
-       else if(teamsay > 0)
-       {
-               sprint(source, sourcemsgstr);
-               if(sourcecmsgstr != "")
-                       centerprint(source, sourcecmsgstr);
-               FOR_EACH_REALPLAYER(head) if(head.team == source.team)
-                       if(head != source)
-                       {
-                               sprint(head, msgstr);
-                               if(cmsgstr != "")
-                                       centerprint(head, cmsgstr);
-                       }
-       }
-       else if(teamsay < 0)
+       else
        {
-               sprint(source, sourcemsgstr);
-               FOR_EACH_REALCLIENT(head) if(head.classname != "player")
-                       if(head != source)
-                               sprint(head, msgstr);
+               ret = 1;
        }
-       else if(sourcemsgstr != msgstr)
+
+       if(sourcemsgstr != "" && ret != 0)
        {
-               sprint(source, sourcemsgstr);
-               FOR_EACH_REALCLIENT(head)
-                       if(head != source)
-                               sprint(head, msgstr);
+               if(ret < 0) // fake
+               {
+                       sprint(source, sourcemsgstr);
+                       if(sourcecmsgstr != "" && !privatesay)
+                               centerprint(source, sourcecmsgstr);
+               }
+               else if(privatesay)
+               {
+                       sprint(source, sourcemsgstr);
+                       sprint(privatesay, msgstr);
+                       if(cmsgstr != "")
+                               centerprint(privatesay, cmsgstr);
+               }
+               else if(teamsay > 0)
+               {
+                       sprint(source, sourcemsgstr);
+                       if(sourcecmsgstr != "")
+                               centerprint(source, sourcecmsgstr);
+                       FOR_EACH_REALPLAYER(head) if(head.team == source.team)
+                               if(head != source)
+                               {
+                                       sprint(head, msgstr);
+                                       if(cmsgstr != "")
+                                               centerprint(head, cmsgstr);
+                               }
+               }
+               else if(teamsay < 0)
+               {
+                       sprint(source, sourcemsgstr);
+                       FOR_EACH_REALCLIENT(head) if(head.classname != "player")
+                               if(head != source)
+                                       sprint(head, msgstr);
+               }
+               else if(sourcemsgstr != msgstr)
+               {
+                       sprint(source, sourcemsgstr);
+                       FOR_EACH_REALCLIENT(head)
+                               if(head != source)
+                                       sprint(head, msgstr);
+               }
+               else
+                       bprint(msgstr);
        }
-       else
-               bprint(msgstr);
+
+       return ret;
 }
 
 float GetVoiceMessageVoiceType(string type)
@@ -1238,6 +1274,81 @@ void UpdatePlayerSounds()
        LoadPlayerSounds(strcat(self.model, ".sounds"), 0);
 }
 
+void FakeGlobalSound(string sample, float chan, float voicetype)
+{
+       float n;
+       float tauntrand;
+
+       if(sample == "")
+               return;
+
+       tokenize_console(sample);
+       n = stof(argv(1));
+       if(n > 0)
+               sample = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
+       else
+               sample = strcat(argv(0), ".wav"); // randomization
+
+       switch(voicetype)
+       {
+               case VOICETYPE_LASTATTACKER_ONLY:
+                       break;
+               case VOICETYPE_LASTATTACKER:
+                       if(self.pusher)
+                       {
+                               msg_entity = self;
+                               if(clienttype(msg_entity) == CLIENTTYPE_REAL)
+                                       soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);
+                       }
+                       break;
+               case VOICETYPE_TEAMRADIO:
+                       msg_entity = self;
+                       if(msg_entity.cvar_cl_voice_directional == 1)
+                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
+                       else
+                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
+                       break;
+               case VOICETYPE_AUTOTAUNT:
+                       if(!sv_autotaunt)
+                               break;
+                       if(!sv_taunt)
+                               break;
+                       if(sv_gentle)
+                               break;
+                       tauntrand = random();
+                       msg_entity = self;
+                       if (tauntrand < msg_entity.cvar_cl_autotaunt)
+                       {
+                               if (msg_entity.cvar_cl_voice_directional >= 1)
+                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));
+                               else
+                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
+                       }
+                       break;
+               case VOICETYPE_TAUNT:
+                       if(self.classname == "player")
+                               if(self.deadflag == DEAD_NO)
+                                       setanim(self, self.anim_taunt, FALSE, TRUE, TRUE);
+                       if(!sv_taunt)
+                               break;
+                       if(sv_gentle)
+                               break;
+                       msg_entity = self;
+                       if (msg_entity.cvar_cl_voice_directional >= 1)
+                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));
+                       else
+                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
+                       break;
+               case VOICETYPE_PLAYERSOUND:
+                       msg_entity = self;
+                       soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NORM);
+                       break;
+               default:
+                       backtrace("Invalid voice type!");
+                       break;
+       }
+}
+
 void GlobalSound(string sample, float chan, float voicetype)
 {
        float n;
@@ -1257,34 +1368,32 @@ void GlobalSound(string sample, float chan, float voicetype)
        {
                case VOICETYPE_LASTATTACKER_ONLY:
                        if(self.pusher)
-                               if(self.pusher.team == self.team)
+                       {
+                               msg_entity = self.pusher;
+                               if(clienttype(msg_entity) == CLIENTTYPE_REAL)
                                {
-                                       msg_entity = self.pusher;
-                                       if(clienttype(msg_entity) == CLIENTTYPE_REAL)
-                                       {
-                                               if(msg_entity.cvar_cl_voice_directional == 1)
-                                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
-                                               else
-                                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
-                                       }
+                                       if(msg_entity.cvar_cl_voice_directional == 1)
+                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
+                                       else
+                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
                                }
+                       }
                        break;
                case VOICETYPE_LASTATTACKER:
                        if(self.pusher)
-                               if(self.pusher.team == self.team)
+                       {
+                               msg_entity = self.pusher;
+                               if(clienttype(msg_entity) == CLIENTTYPE_REAL)
                                {
-                                       msg_entity = self.pusher;
-                                       if(clienttype(msg_entity) == CLIENTTYPE_REAL)
-                                       {
-                                               if(msg_entity.cvar_cl_voice_directional == 1)
-                                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
-                                               else
-                                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
-                                       }
-                                       msg_entity = self;
-                                       if(clienttype(msg_entity) == CLIENTTYPE_REAL)
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);
+                                       if(msg_entity.cvar_cl_voice_directional == 1)
+                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
+                                       else
+                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
                                }
+                               msg_entity = self;
+                               if(clienttype(msg_entity) == CLIENTTYPE_REAL)
+                                       soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);
+                       }
                        break;
                case VOICETYPE_TEAMRADIO:
                        FOR_EACH_REALCLIENT(msg_entity)
@@ -1328,6 +1437,7 @@ void GlobalSound(string sample, float chan, float voicetype)
                                else
                                        soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
                        }
+                       break;
                case VOICETYPE_PLAYERSOUND:
                        sound(self, chan, sample, VOL_BASE, ATTN_NORM);
                        break;
@@ -1339,15 +1449,14 @@ void GlobalSound(string sample, float chan, float voicetype)
 
 void PlayerSound(.string samplefield, float chan, float voicetype)
 {
-       string sample;
-       sample = self.samplefield;
-       GlobalSound(sample, chan, voicetype);
+       GlobalSound(self.samplefield, chan, voicetype);
 }
 
 void VoiceMessage(string type, string msg)
 {
        var .string sample;
-       var float voicetype, ownteam;
+       float voicetype, ownteam;
+       float flood;
        sample = GetVoiceMessageSampleField(type);
 
        if(GetPlayerSoundSampleField_notFound)
@@ -1359,35 +1468,12 @@ void VoiceMessage(string type, string msg)
        voicetype = GetVoiceMessageVoiceType(type);
        ownteam = (voicetype == VOICETYPE_TEAMRADIO);
 
-       float flood;
-       float flood_spv;
-       var .float flood_field;
-
-       flood = 0;
-       if(ownteam)
-       {
-               flood_spv = cvar("g_voice_flood_spv_team");
-               flood_field = floodcontrol_voiceteam;
-       }
-       else
-       {
-               flood_spv = cvar("g_voice_flood_spv");
-               flood_field = floodcontrol_voice;
-       }
-
-       if(time >= self.flood_field)
-               self.flood_field = max(time, self.flood_field) + flood_spv;
-       else
-               flood = 1;
-
-       if (timeoutStatus == 2) //when game is paused, no flood protection
-               self.flood_field = flood = 0;
-
-       if (msg != "")
-               Say(self, ownteam, world, msg, 0);
+       flood = Say(self, ownteam, world, msg, 1);
 
-       if (!flood)
-               PlayerSound(sample, CHAN_VOICE, voicetype);
+       if (flood > 0)
+               GlobalSound(self.sample, CHAN_VOICE, voicetype);
+       else if (flood < 0)
+               FakeGlobalSound(self.sample, CHAN_VOICE, voicetype);
 }
 
 void MoveToTeam(entity client, float team_colour, float type, float show_message)
index 788a67e..b5e245d 100644 (file)
@@ -12,6 +12,8 @@ void W_SwitchWeapon(float imp)
        {
                if (client_hasweapon(self, imp, TRUE, TRUE))
                        W_SwitchWeapon_Force(self, imp);
+               else
+                       self.selectweapon = imp; // update selectweapon ANYWAY
        }
        else
        {
@@ -20,7 +22,7 @@ void W_SwitchWeapon(float imp)
 };
 
 .float weaponcomplainindex;
-float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain)
+float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
 {
        // We cannot tokenize in this function, as GiveItems calls this
        // function. Thus we must use car/cdr.
@@ -28,6 +30,12 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
        string rest;
        switchtonext = switchtolast = 0;
        first_valid = prev_valid = 0;
+       float weaponcur;
+
+       if(skipmissing || pl.selectweapon == 0)
+               weaponcur = pl.switchweapon;
+       else
+               weaponcur = pl.selectweapon;
 
        if(dir == 0)
                switchtonext = 1;
@@ -44,13 +52,13 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
 
                ++c;
 
-               if(client_hasweapon(pl, weaponwant, TRUE, FALSE))
+               if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE))
                {
                        if(switchtonext)
                                return weaponwant;
                        if(!first_valid)
                                first_valid = weaponwant;
-                       if(weaponwant == pl.switchweapon)
+                       if(weaponwant == weaponcur)
                        {
                                if(dir >= 0)
                                        switchtonext = 1;
@@ -96,7 +104,7 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
 void W_CycleWeapon(string weaponorder, float dir)
 {
        float w;
-       w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1);
+       w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE);
        if(w > 0)
                W_SwitchWeapon(w);
 }
@@ -104,7 +112,7 @@ void W_CycleWeapon(string weaponorder, float dir)
 void W_NextWeaponOnImpulse(float imp)
 {
        float w;
-       w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1);
+       w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
        if(w > 0)
                W_SwitchWeapon(w);
 }
@@ -145,7 +153,7 @@ string W_FixWeaponOrder_ForceComplete(string order)
 
 float w_getbestweapon(entity e)
 {
-       return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, 0);
+       return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE);
 };
 
 // generic weapons table
index e7bfc69..f1e9bf7 100644 (file)
@@ -36,6 +36,7 @@ void W_SwitchWeapon_Force(entity e, float w)
 {
        e.cnt = e.switchweapon;
        e.switchweapon = w;
+       e.selectweapon = w;
 }
 
 .float antilag_debug;
index d272d69..ff5794d 100644 (file)
@@ -225,7 +225,6 @@ void SV_ParseClientCommand(string s) {
                                DropFlag(self.flagcarried, world, world);
                        if(self.ballcarried)
                                DropBall(self.ballcarried, self.origin, self.velocity);
-                       MUTATOR_CALLHOOK(MakePlayerSpectator);
                        WaypointSprite_PlayerDead();
                        self.classname = "observer";
                        if(g_ca)
index e80025a..b487e3d 100644 (file)
@@ -505,6 +505,7 @@ void UpdatePlayerSounds();
 void ClearPlayerSounds();
 void PlayerSound(.string samplefield, float channel, float voicetype);
 void GlobalSound(string samplestring, float channel, float voicetype);
+void FakeGlobalSound(string samplestring, float channel, float voicetype);
 void VoiceMessage(string type, string message);
 
 // autotaunt system
@@ -637,3 +638,6 @@ string deathmessage;
 
 .float cvar_cl_accuracy_data_share;
 .float cvar_cl_accuracy_data_receive;
+
+.float cvar_cl_weaponimpulsemode;
+.float selectweapon; // last selected weapon of the player
index f73259c..e5df457 100644 (file)
@@ -177,7 +177,7 @@ float   EF_RED          = 128;
 
 //DP_EF_RESTARTANIM_BIT
 //idea: id software
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
 //effects bit:
 float   EF_RESTARTANIM_BIT = 1048576;
 //description:
@@ -195,7 +195,7 @@ float   EF_STARDUST     = 2048;
 
 //DP_EF_TELEPORT_BIT
 //idea: id software
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
 //effects bit:
 float   EF_TELEPORT_BIT = 2097152;
 //description:
@@ -517,7 +517,7 @@ void(entity e, entity tagentity, string tagname) setattachment = #443; // attach
 
 //DP_NULL_MODEL
 //idea: Chris
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
 //definitions:
 //string dp_null_model = "null";
 //description:
@@ -561,8 +561,8 @@ float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(
 //note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
 
 //DP_QC_AUTOCVARS
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //description:
 //allows QC variables to be bound to cvars
 //(works for float, string, vector types)
@@ -615,8 +615,8 @@ string(string s) cvar_defstring = #482;
 //returns the default value of a cvar, as a tempstring.
 
 //DP_QC_CVAR_DESCRIPTION
-//idea: div0
-//DarkPlaces implementation: div0
+//idea: divVerent
+//DarkPlaces implementation: divVerent
 //builtin definitions:
 string(string name) cvar_description = #518;
 //description:
@@ -631,8 +631,8 @@ string(string s) cvar_string = #448;
 //returns the value of a cvar, as a tempstring.
 
 //DP_QC_CVAR_TYPE
-//idea: div0
-//DarkPlaces implementation: div0
+//idea: divVerent
+//DarkPlaces implementation: divVerent
 //builtin definitions:
 float(string name) cvar_type = #495;
 float CVAR_TYPEFLAG_EXISTS = 1;
@@ -694,8 +694,8 @@ string(entity ent) etos = #65;
 //prints "entity 1" or similar into a string. (this was a Q2 builtin)
 
 //DP_QC_EXTRESPONSEPACKET
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 string(void) getextresponse = #624;
 //description:
@@ -713,8 +713,8 @@ entity(.string fld, string match) findchain = #402;
 //similar to find() but returns a chain of entities like findradius.
 
 //DP_QC_FINDCHAIN_TOFIELD
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 entity(.string fld, float match, .entity tofield) findradius_tofield = #22;
 entity(.string fld, string match, .entity tofield) findchain_tofield = #402;
@@ -806,12 +806,13 @@ float SPA_LIGHTMAP0_TEXCOORDS = 5;
 float SPA_LIGHTMAP0_COLOR = 6;
 //builtin definitions:
 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+
 //description:
 //function to query extended information about a point on a certain surface
 
 //DP_QC_GETSURFACETRIANGLE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 float(entity e, float s) getsurfacenumtriangles = #628;
 vector(entity e, float s, float n) getsurfacetriangle = #629;
@@ -830,7 +831,7 @@ vector(entity ent, float tagindex) gettaginfo = #452;
 
 //DP_QC_GETTAGINFO_BONEPROPERTIES
 //idea: daemon
-//DarkPlaces implementation: div0
+//DarkPlaces implementation: divVerent
 //global definitions:
 float gettaginfo_parent;
 string gettaginfo_name;
@@ -846,7 +847,7 @@ vector gettaginfo_up;
 
 //DP_QC_GETTIME
 //idea: tZork
-//darkplaces implementation: tZork, div0
+//darkplaces implementation: tZork, divVerent
 //constant definitions:
 float GETTIME_FRAMESTART = 0; // time of start of frame
 float GETTIME_REALTIME = 1; // current time (may be OS specific)
@@ -858,15 +859,15 @@ float(float tmr) gettime = #519;
 //some timers to query...
 
 //DP_QC_GETTIME_CDTRACK
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //constant definitions:
 float GETTIME_CDTRACK = 4;
 //description:
 //returns the playing time of the current cdtrack when passed to gettime()
 
 //DP_QC_LOG
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
 //builtin definitions:
 float log(float f) = #532;
 //description:
@@ -937,8 +938,8 @@ float(float a, float b) pow = #97;
 //useful math functions, sine of val, cosine of val, square root of val, and raise a to power b, respectively.
 
 //DP_QC_SPRINTF
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 string(string format, ...) sprintf = #627;
 //description:
@@ -955,6 +956,7 @@ string(string format, ...) sprintf = #627;
 //    ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int
 //    eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double
 //    s takes a string
+//    vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space
 //    For conversions s and c, the flag # makes precision and width interpreted
 //      as byte count, by default it is interpreted as character count in UTF-8
 //      enabled engines. No other conversions can create wide characters, and #
@@ -1011,8 +1013,8 @@ float(string s, string separator1, ...) tokenizebyseparator = #479;
 //possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000")
 
 //DP_QC_TOKENIZE_CONSOLE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 float(string s) tokenize_console = #514;
 float(float i) argv_start_index = #515;
@@ -1055,7 +1057,7 @@ float MOVE_WORLDONLY = 3;
 //allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions
 
 //DP_QC_UNLIMITEDTEMPSTRINGS
-//idea: div0
+//idea: divVerent
 //darkplaces implementation: LordHavoc
 //description:
 //this extension alters Quake behavior such that instead of reusing a single
@@ -1097,23 +1099,23 @@ void(vector dir) vectorvectors = #432;
 //creates v_forward, v_right, and v_up vectors given a forward vector, similar to makevectors except it takes a forward direction vector instead of angles.
 
 //DP_QC_WHICHPACK
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 string(string filename) whichpack = #503;
 //description:
 //returns the name of the pak/pk3/whatever containing the given file, in the same path space as FRIK_FILE functions use (that is, possibly with a path name prefix)
 
 //DP_QC_URI_ESCAPE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //URI::Escape's functionality
 string(string in) uri_escape = #510;
 string(string in) uri_unescape = #511;
 
 //DP_QC_URI_GET
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //loads text from an URL into a string
 //returns 1 on success of initiation, 0 if there are too many concurrent
 //connections already or if the URL is invalid
@@ -1133,8 +1135,8 @@ float(string url, float id) uri_get = #513;
 //this extension indicates that FTE_CSQC_SKELETONOBJECTS functionality is available in server QC (as well as CSQC).
 
 //DP_SV_SPAWNFUNC_PREFIX
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities.
 //Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A).
 //Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix.
@@ -1372,8 +1374,8 @@ void(vector origin, string sample, float volume, float attenuation) pointsound =
 // To mimic the engine's default behavior, simply call remove(self).
 
 //DP_SV_ONENTITYPREPOSTSPAWNFUNCTION
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //engine-called QC prototypes:
 //void() SV_OnEntityPreSpawnFunction;
 //void() SV_OnEntityPostSpawnFunction;
@@ -1494,8 +1496,8 @@ void(string s, ...) print = #339; // same number as in EXT_CSQC
 //this extension allows precache_model and precache_sound (and any variants) to be used during the game (with automatic messages to clients to precache the new model/sound indices), also setmodel/sound/ambientsound can be called without precaching first (they will cause an automatic precache).
 
 //DP_SV_QCSTATUS
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //1. A global variable
 string worldstatus;
 //Its content is set as "qcstatus" field in the rules.
@@ -1535,8 +1537,8 @@ void(entity ent, float colors) setcolor = #401;
 //range is 0 to infinite, recommended values to try are 0.1 (very slow, 10% speed), 1 (normal speed), 5 (500% speed).
 
 //DP_SV_WRITEPICTURE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //builtin definitions:
 void(float to, string s, float sz) WritePicture = #501;
 //description:
@@ -1865,12 +1867,14 @@ float FILE_WRITE = 2;
 //idea: Spike, LordHavoc
 //darkplaces implementation: LordHavoc
 //builtin definitions:
-float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure  (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
+// all skeleton numbers are 1-based (0 being no skeleton)
+// all bone numbers are 1-based (0 being invalid)
+float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton
-string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring)
-float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, -1 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
+float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
+string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
+float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
+float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
 vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
 vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
 void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
@@ -2070,8 +2074,8 @@ string(float n) argv = #442;
 //description:
 //when a savegame is loaded, this function is called
 
-//XONOTIC_PLAYERMODEL
-//idea: Xonotic
+//NEXUIZ_PLAYERMODEL
+//idea: Nexuiz
 //darkplaces implementation: Black
 //console commands:
 //playermodel <name> - FIXME: EXAMPLE NEEDED
@@ -2080,7 +2084,7 @@ string(float n) argv = #442;
 .string playermodel; // name of player model sent by client
 .string playerskin; // name of player skin sent by client
 //description:
-//these client properties are used by Xonotic.
+//these client properties are used by Nexuiz.
 
 //NXQ_GFX_LETTERBOX
 //idea: nxQuake
@@ -2140,7 +2144,7 @@ float PFLAGS_FULLDYNAMIC = 128; // light enable (without this set no light is pr
 
 //FTE_QC_CHECKPVS
 //idea: Urre
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
 //builtin definitions:
 float checkpvs(vector viewpos, entity viewee) = #240;
 //description:
@@ -2177,7 +2181,7 @@ float(string s1, string s2, float len) strncasecmp = #230; // same as strcasecmp
 
 //DP_CON_BESTWEAPON
 //idea: many
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
 //description:
 //allows QC to register weapon properties for use by the bestweapon command, for mods that change required ammo count or type for the weapons
 //it is done using console commands sent via stuffcmd:
@@ -2212,8 +2216,8 @@ float(float bufhandle, string str, float order) bufstr_add = #468;
 void(float bufhandle, float string_index) bufstr_free = #469;
 
 //DP_QC_STRINGBUFFERS_CVARLIST
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //functions to list cvars and store their names into a stringbuffer
 //cvars that start with pattern but not with antipattern will be stored into the buffer
 void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
@@ -2229,15 +2233,15 @@ string(string search, string replace, string subject) strireplace = #485;
 //strireplace does the same but uses case-insensitive matching of the 'search' term
 //
 //DP_QC_CRC16
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
 //When caseinsensitive is set, the CRC is calculated of the lower cased string.
 float(float caseinsensitive, string s, ...) crc16 = #494;
 
 //DP_SV_SHUTDOWN
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
 //A function that gets called just before progs exit. To save persistent data from.
 //It is not called on a crash or error.
 //void SV_Shutdown();
@@ -2263,17 +2267,24 @@ void(float pause) setpause = #531;
 
 
 
-
-
+// EXPERIMENTAL (not finalized) EXTENSIONS:
 
 //DP_PHYSICS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc, divVerent
+//constant definitions:
 float SOLID_PHYSICS_BOX = 32;
 float SOLID_PHYSICS_SPHERE = 33;
 float SOLID_PHYSICS_CAPSULE = 34;
 float MOVETYPE_PHYSICS = 32;
+float JOINTTYPE_POINT = 1; // point; uses origin (anchor)
+float JOINTTYPE_HINGE = 2; // hinge; uses origin (anchor) and angles (axis)
+float JOINTTYPE_SLIDER = 3; // slider; uses angles (axis)
+float JOINTTYPE_UNIVERSAL = 4; // universal; uses origin (anchor) and angles (forward is axis1, up is axis2)
+float JOINTTYPE_HINGE2 = 5; // hinge2; uses origin (anchor), angles (axis1), velocity (axis2)
+//field definitions:
 .float mass;
-
-.float jointtype;
+.float jointtype; // see JOINTTYPE_ definitions above
 // common joint properties:
 // .entity aiment, enemy; // connected objects
 // .vector movedir;
@@ -2286,28 +2297,6 @@ float MOVETYPE_PHYSICS = 32;
 //     movedir_y = -1 * max motor force to use
 //     movedir_z = stop position (+/-), set to 0 for no stop
 //   note that ODE does not support both in one anyway
-//   motor properties only make sense for hinge and slider!
-
-float JOINTTYPE_POINT = 1;
-// .vector origin; // point anchor
-
-float JOINTTYPE_HINGE = 2;
-// .vector origin; // hinge anchor
-// .vector angles; // hinge axis
-
-float JOINTTYPE_SLIDER = 3;
-// .vector angles; // slider axis
-
-float JOINTTYPE_UNIVERSAL = 4;
-// .vector origin; // universal anchor
-// .vector angles; // universal axis1 and axis2 (axis1 is forward, axis2 is up)
-
-float JOINTTYPE_HINGE2 = 5;
-// .vector origin; // hinge2 anchor
-// .vector angles; // hinge2 first axis (as angles)
-// .vector velocity; // hinge2 second axis (as vector)
-
-
-
-
-
+//description:
+//various physics properties can be defined in an entity and are executed via
+//ODE
index 936b5f6..338204c 100644 (file)
@@ -146,37 +146,44 @@ void GiveFrags (entity attacker, entity targ, float f)
        }
 
        // FIXME fix the mess this is (we have REAL points now!)
-       frag_attacker = attacker;
+       entity oldself;
+       oldself = self;
+       self = attacker;
        frag_target = targ;
        frag_score = f;
        if(MUTATOR_CALLHOOK(GiveFragsForKill))
        {
                f = frag_score;
+               self = oldself;
        }
-       else if(g_runematch)
-       {
-               f = RunematchHandleFrags(attacker, targ, f);
-       }
-       else if(g_lms)
+       else
        {
-               // remove a life
-               float tl;
-               tl = PlayerScore_Add(targ, SP_LMS_LIVES, -1);
-               if(tl < lms_lowest_lives)
-                       lms_lowest_lives = tl;
-               if(tl <= 0)
+               self = oldself;
+               if(g_runematch)
                {
-                       if(!lms_next_place)
-                               lms_next_place = player_count;
-                       PlayerScore_Add(targ, SP_LMS_RANK, lms_next_place); // won't ever spawn again
-                       --lms_next_place;
+                       f = RunematchHandleFrags(attacker, targ, f);
                }
-               f = 0;
-       }
-       else if(g_ctf)
-       {
-               if(g_ctf_ignore_frags)
+               else if(g_lms)
+               {
+                       // remove a life
+                       float tl;
+                       tl = PlayerScore_Add(targ, SP_LMS_LIVES, -1);
+                       if(tl < lms_lowest_lives)
+                               lms_lowest_lives = tl;
+                       if(tl <= 0)
+                       {
+                               if(!lms_next_place)
+                                       lms_next_place = player_count;
+                               PlayerScore_Add(targ, SP_LMS_RANK, lms_next_place); // won't ever spawn again
+                               --lms_next_place;
+                       }
                        f = 0;
+               }
+               else if(g_ctf)
+               {
+                       if(g_ctf_ignore_frags)
+                               f = 0;
+               }
        }
 
        attacker.totalfrags += f;
index e09b03b..8a38048 100644 (file)
@@ -133,9 +133,9 @@ float g_clientmodel_genericsendentity (entity to, float sf)
        Net_LinkEntity(self, TRUE, 0, g_clientmodel_genericsendentity);
 
 // non-solid model entities:
-void spawnfunc_misc_gamemodel()         { G_MODEL_INIT      (SOLID_NOT) } // model entity
-void spawnfunc_misc_clientmodel()       { G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
-void spawnfunc_misc_models()            { G_MODEL_INIT      (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
+void spawnfunc_misc_gamemodel()         { self.angles_x = -self.angles_x; G_MODEL_INIT      (SOLID_NOT) } // model entity
+void spawnfunc_misc_clientmodel()       { self.angles_x = -self.angles_x; G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
+void spawnfunc_misc_models()            { self.angles_x = -self.angles_x; G_MODEL_INIT      (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
 
 // non-solid brush entities:
 void spawnfunc_func_illusionary()       { G_MODEL_INIT      (SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
index af03b83..39b2665 100644 (file)
@@ -588,7 +588,7 @@ void EffectIndexDump()
        db_put(d, "TR_KNIGHTSPIKE", "1"); print("effect TR_KNIGHTSPIKE is ", ftos(particleeffectnum("TR_KNIGHTSPIKE")), "\n");
        db_put(d, "TR_VORESPIKE", "1"); print("effect TR_VORESPIKE is ", ftos(particleeffectnum("TR_VORESPIKE")), "\n");
        db_put(d, "TR_NEHAHRASMOKE", "1"); print("effect TR_NEHAHRASMOKE is ", ftos(particleeffectnum("TR_NEHAHRASMOKE")), "\n");
-       db_put(d, "TR_XONOTICPLASMA", "1"); print("effect TR_XONOTICPLASMA is ", ftos(particleeffectnum("TR_XONOTICPLASMA")), "\n");
+       db_put(d, "TR_NEXUIZPLASMA", "1"); print("effect TR_NEXUIZPLASMA is ", ftos(particleeffectnum("TR_NEXUIZPLASMA")), "\n");
        db_put(d, "TR_GLOWTRAIL", "1"); print("effect TR_GLOWTRAIL is ", ftos(particleeffectnum("TR_GLOWTRAIL")), "\n");
        db_put(d, "SVC_PARTICLE", "1"); print("effect SVC_PARTICLE is ", ftos(particleeffectnum("SVC_PARTICLE")), "\n");
 
@@ -1333,6 +1333,17 @@ void GameCommand(string command)
                return;
        }
 
+       if(argv(0) == "showtraceline")
+       {
+               vector src, dst;
+               src = stov(argv(1));
+               dst = stov(argv(2));
+               traceline(src, dst, MOVE_NORMAL, world);
+               trailparticles(world, particleeffectnum("TR_NEXUIZPLASMA"), src, trace_endpos);
+               trailparticles(world, particleeffectnum("TR_CRYLINKPLASMA"), trace_endpos, dst);
+               return;
+       }
+
        print("Invalid command. For a list of supported commands, try sv_cmd help.\n");
 }
 
index d9c5ca6..7aa9166 100644 (file)
@@ -593,8 +593,13 @@ float w_getbestweapon(entity e);
 void GetCvars(float f)
 {
        string s;
+
        if (f > 0)
                s = strcat1(argv(f));
+
+       get_cvars_f = f;
+       get_cvars_s = s;
+       MUTATOR_CALLHOOK(GetCvars);
        GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
        GetCvars_handleFloat(s, f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction");
        GetCvars_handleFloat(s, f, cvar_scr_centertime, "scr_centertime");
@@ -612,6 +617,7 @@ void GetCvars(float f)
        GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[7], "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
        GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
        GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleFloat(s, f, cvar_cl_weaponimpulsemode, "cl_weaponimpulsemode");
        GetCvars_handleFloat(s, f, cvar_cl_autotaunt, "cl_autotaunt");
        GetCvars_handleFloat(s, f, cvar_cl_noantilag, "cl_noantilag");
        GetCvars_handleFloat(s, f, cvar_cl_voice_directional, "cl_voice_directional");
index 0d43660..9b7ad54 100644 (file)
-//#define MONSTES_ENABLED\r
-#ifdef MONSTES_ENABLED\r
-\r
-#define zombie_anim_attackleap         0\r
-#define zombie_anim_attackrun1         1\r
-#define zombie_anim_attackrun2         2\r
-#define zombie_anim_attackrun3         3\r
-#define zombie_anim_attackstanding1    4\r
-#define zombie_anim_attackstanding2    5\r
-#define zombie_anim_attackstanding3    6\r
-#define zombie_anim_blockend           7\r
-#define zombie_anim_blockstart         8\r
-#define zombie_anim_deathback1         9\r
-#define zombie_anim_deathback2         10\r
-#define zombie_anim_deathback3         11\r
-#define zombie_anim_deathfront1        12\r
-#define zombie_anim_deathfront2        13\r
-#define zombie_anim_deathfront3        14\r
-#define zombie_anim_deathleft1         15\r
-#define zombie_anim_deathleft2         16\r
-#define zombie_anim_deathright1        17\r
-#define zombie_anim_deathright2        18\r
-#define zombie_anim_idle               19\r
-#define zombie_anim_painback1          20\r
-#define zombie_anim_painback2          21\r
-#define zombie_anim_painfront1         22\r
-#define zombie_anim_painfront2         23\r
-#define zombie_anim_runbackwards       24\r
-#define zombie_anim_runbackwardsleft   25\r
-#define zombie_anim_runbackwardsright  26\r
-#define zombie_anim_runforward         27\r
-#define zombie_anim_runforwardleft     28\r
-#define zombie_anim_runforwardright    29\r
-#define zombie_anim_spawn              30\r
-\r
-#define ZOMBIE_MIN                                      '-18 -18 -25'\r
-#define ZOMBIE_MAX                                      '18 18 47'\r
-\r
-#define ZV_IDLE     10\r
-\r
-#define ZV_PATH     100\r
-#define ZV_HUNT     200\r
-\r
-#define ZV_ATTACK_FIND  10\r
-#define ZV_ATTACK_RUN   20\r
-#define ZV_ATTACK_STAND 30\r
-\r
-#define ZV_PATH2 10000\r
-\r
-//.entity verbs_idle;\r
-//.entity verbs_attack;\r
-//.entity verbs_move;\r
-\r
-//.float  state_timeout;\r
-//.void() monster_state;\r
-#define MONSTERFLAG_NORESPAWN 2\r
-\r
-void zombie_spawn();\r
-\r
-float zombie_scoretarget(entity trg)\r
-{\r
-    float  tmp;\r
-    vector ang1;\r
-\r
-    if (trg.takedamage == DAMAGE_AIM)\r
-    if not (trg.flags & FL_NOTARGET)\r
-    if (trg.deadflag == DEAD_NO)\r
-    if (trg.team != self.team)\r
-    {\r
-        if((self.origin_z - trg.origin_z) < 128)\r
-        {\r
-            ang1 = normalize(self.origin - trg.origin);\r
-            tmp = vlen(ang1 - v_forward);\r
-            if(tmp > 1.5)\r
-            {\r
-                traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);\r
-                if(trace_ent != trg)\r
-                    return 0;\r
-\r
-                return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;\r
-            }\r
-            else if(self.enemy == trg)\r
-                return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;\r
-        }\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
-{\r
-    //dprint("zombie_corpse_damage\n");\r
-    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);\r
-\r
-    self.health -= damage;\r
-\r
-    if(self.health < 0)\r
-    {\r
-        Violence_GibSplash(self, 1, 1, attacker);\r
-        remove(self);\r
-    }\r
-}\r
-\r
-void zombie_die(vector dir)\r
-{\r
-    vector v;\r
-    float f;\r
-\r
-    entity dummy;\r
-\r
-    dummy = spawn();\r
-    setmodel(dummy,"models/monsters/zombie.dpm");\r
-    setorigin(dummy, self.origin);\r
-    dummy.velocity  = self.velocity;\r
-    dummy.movetype  = MOVETYPE_BOUNCE;\r
-    dummy.think     = SUB_Remove;\r
-    dummy.nextthink = time + 3;\r
-    dummy.health    = 50;\r
-    dummy.takedamage = DAMAGE_YES;\r
-    dummy.event_damage = zombie_corpse_damage;\r
-    dummy.solid      = SOLID_CORPSE;\r
-    setsize(dummy,self.mins,self.maxs);\r
-\r
-    SUB_SetFade(dummy,time + 5,2);\r
-\r
-\r
-    v = normalize(self.origin - dir);\r
-    f = vlen(v_forward - v) - 1;\r
-    if(f > 0.5)\r
-        dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);\r
-    else if(f < 0.5)\r
-        dummy.frame = zombie_anim_deathback1 + rint(random() * 2);\r
-    else\r
-    {\r
-        f = vlen(v_right - v) - 1;\r
-        if(f > 0.5)\r
-            dummy.frame = zombie_anim_deathright1 + rint(random() * 2);\r
-        else if(f < 0.5)\r
-            dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);\r
-    }\r
-\r
-\r
-    if(self.spawnflags & MONSTERFLAG_NORESPAWN)\r
-    {\r
-        self.think = SUB_Remove;\r
-        self.nextthink = time;\r
-        return;\r
-    }\r
-\r
-    setmodel(self,"");\r
-    self.solid          = SOLID_NOT;\r
-    self.takedamage     = DAMAGE_NO;\r
-    self.event_damage   = SUB_Null;\r
-    self.enemy          = world;\r
-    self.think          = zombie_spawn;\r
-    self.nextthink      = time + cvar("g_monster_zombie_respawntime");\r
-    self.pain_finished  = self.nextthink;\r
-}\r
-\r
-void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
-{\r
-\r
-    vector v;\r
-    float f;\r
-\r
-    v = normalize(self.origin - hitloc);\r
-    f = vlen(v_forward - v) - 1;\r
-\r
-\r
-    self.health -= damage;\r
-    self.velocity = self.velocity + force;\r
-    if(self.health <= 0)\r
-    {\r
-        zombie_die(hitloc);\r
-        return;\r
-    }\r
-\r
-    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);\r
-\r
-       if (damage > 50)\r
-               Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);\r
-       if (damage > 100)\r
-               Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);\r
-\r
-    if (time > self.pain_finished)\r
-    {\r
-        if(f < 0.5)\r
-        {\r
-            if(random() < 0.5)\r
-                self.frame = zombie_anim_painback1;\r
-            else\r
-                self.frame = zombie_anim_painback2;\r
-        }\r
-        else\r
-        {\r
-            if(random() < 0.5)\r
-                self.frame = zombie_anim_painfront1;\r
-            else\r
-                self.frame = zombie_anim_painfront2;\r
-        }\r
-\r
-        self.pain_finished = time + 0.36;\r
-    }\r
-}\r
-\r
-.vector bvec;\r
-.float bvec_time;\r
-\r
-void zombie_move()\r
-{\r
-    vector real_angle;\r
-    float vz, tdiff, tspeed;\r
-\r
-    tdiff = time - self.zoomstate;\r
-    tspeed = tdiff * cvar("g_monster_zombie_turnspeed");\r
-    vz = self.velocity_z;\r
-    self.zoomstate = time;\r
-\r
-    if(self.bvec_time < time)\r
-    {\r
-        self.bvec_time = time + 0.2;\r
-        self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);\r
-    }\r
-\r
-    if(self.enemy)\r
-        self.moveto = self.enemy.origin;\r
-    else\r
-        self.moveto = self.origin + v_forward;\r
-\r
-    self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);\r
-\r
-    self.angles_y = safeangle(self.angles_y);\r
-    real_angle = vectoangles(self.steerto) - self.angles;\r
-    self.angles_y += bound(-10, real_angle_y, 10);\r
-\r
-    if(vlen(self.origin - self.moveto) > 64)\r
-    {\r
-        movelib_move_simple(v_forward ,cvar("g_monster_zombie_movespeed"),0.6);\r
-        if(time > self.pain_finished)\r
-            if(self.attack_finished_single < time)\r
-                self.frame = zombie_anim_runforward;\r
-    }\r
-    else\r
-    {\r
-        movelib_beak_simple(cvar("g_monster_zombie_stopspeed"));\r
-        if(time > self.pain_finished)\r
-            if(self.attack_finished_single < time)\r
-                self.frame = zombie_anim_idle;\r
-    }\r
-\r
-    self.velocity_z = vz;\r
-    self.steerto = self.origin;\r
-}\r
-\r
-float zombie_verb_idle_roam(float eval)\r
-{\r
-    switch (eval)\r
-    {\r
-    case VCM_EVAL:\r
-\r
-        if(self.enemy)\r
-            return VS_CALL_NO;\r
-\r
-        return verb.verb_static_value;\r
-\r
-    case VCM_DO:\r
-\r
-        self.moveto = v_forward * 128;\r
-        self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);\r
-\r
-        return VS_CALL_YES_DOING;\r
-    }\r
-\r
-    return VS_CALL_YES_DONE;\r
-}\r
-\r
-float zombie_verb_idle_stand(float eval)\r
-{\r
-    switch (eval)\r
-    {\r
-    case VCM_EVAL:\r
-\r
-        if(self.enemy)\r
-            return VS_CALL_NO;\r
-\r
-        return verb.verb_static_value;\r
-\r
-    case VCM_DO:\r
-\r
-        self.moveto   = self.origin;\r
-        self.frame    = zombie_anim_idle;\r
-        self.velocity = '0 0 0';\r
-\r
-        return VS_CALL_YES_DOING;\r
-    }\r
-\r
-    return VS_CALL_YES_DONE;\r
-}\r
-\r
-float zombie_verb_idle(float eval)\r
-{\r
-    switch (eval)\r
-    {\r
-    case VCM_EVAL:\r
-\r
-        if(self.enemy)\r
-            return VS_CALL_NO;\r
-\r
-        return verb.verb_static_value;\r
-\r
-    case VCM_DO:\r
-        float t;\r
-\r
-        t = cvar("g_monster_zombie_idle_timer_max") -  cvar("g_monster_zombie_idle_timer_min");\r
-        t = cvar("g_monster_zombie_idle_timer_min") + (random() * t);\r
-\r
-        if(random() < 0.5)\r
-            verbstack_push(self.verbs_idle, zombie_verb_idle_roam,  ZV_IDLE + 1, t, self);\r
-        else\r
-            verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);\r
-\r
-        return VS_CALL_YES_DOING;\r
-    }\r
-\r
-    return VS_CALL_YES_DONE;\r
-}\r
-\r
-float zombie_verb_attack_findtarget(float eval)\r
-{\r
-    switch (eval)\r
-    {\r
-    case VCM_EVAL:\r
-        if(self.enemy)\r
-            return VS_CALL_NO;\r
-\r
-        return verb.verb_static_value;\r
-\r
-    case VCM_DO:\r
-\r
-        entity trg, best_trg;\r
-        float trg_score, best_trg_score;\r
-\r
-        trg = findradius(self.origin,cvar("g_monster_zombie_targetrange"));\r
-        while(trg)\r
-        {\r
-            trg_score = zombie_scoretarget(trg);\r
-            if(trg_score > best_trg_score)\r
-            {\r
-                best_trg = trg;\r
-                best_trg_score = trg_score;\r
-            }\r
-\r
-            trg = trg.chain;\r
-        }\r
-\r
-        if(best_trg)\r
-        {\r
-            self.enemy = best_trg;\r
-            dprint("Selected: ",best_trg.netname, " as target.\n");\r
-        }\r
-\r
-        return VS_CALL_YES_DOING;\r
-    }\r
-\r
-    return VS_CALL_YES_DONE;\r
-}\r
-\r
-void zombie_runattack_damage()\r
-{\r
-    entity oldself;\r
-    oldself = self;\r
-    self = self.owner;\r
-\r
-    if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_hitrange"))\r
-        return;\r
-\r
-    if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)\r
-        return;\r
-\r
-    Damage(self.enemy, self, self, cvar("g_monster_zombie_attack_run_damage"), DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin)  * cvar("g_monster_zombie_attack_run_force"));\r
-\r
-    self = oldself;\r
-    self.think = SUB_Remove;\r
-    self.nextthink = time;\r
-}\r
-\r
-float zombie_verb_attack_run(float eval)\r
-{\r
-    switch (eval)\r
-    {\r
-    case VCM_EVAL:\r
-        if not (self.enemy)\r
-            return VS_CALL_NO;\r
-\r
-        if(self.attack_finished_single > time)\r
-            return VS_CALL_NO;\r
-\r
-        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_range"))\r
-            return VS_CALL_NO;\r
-\r
-        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)\r
-            return VS_CALL_NO;\r
-\r
-        return verb.verb_static_value;\r
-\r
-    case VCM_DO:\r
-        entity pain;\r
-        pain = spawn();\r
-        pain.owner = self;\r
-        pain.think = zombie_runattack_damage;\r
-        pain.nextthink = time + cvar("g_monster_zombie_attack_run_delay");\r
-\r
-        self.attack_finished_single = time + 0.7;\r
-        self.frame = zombie_anim_attackrun1 + rint(random() * 2);\r
-\r
-        return VS_CALL_YES_DOING;\r
-    }\r
-\r
-    return VS_CALL_YES_DONE;\r
-}\r
-\r
-void zombie_standattack_damage()\r
-{\r
-    //entity oldself;\r
-    //oldself = self;\r
-    //self = self.owner;\r
-\r
-    setorigin(self,self.owner.origin + v_forward * 32);\r
-    RadiusDamage(self, self.owner, cvar("g_monster_zombie_attack_stand_damage"),cvar("g_monster_zombie_attack_stand_damage"),16,self, cvar("g_monster_zombie_attack_stand_force"),DEATH_TURRET,world);\r
-    //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)\r
-\r
-\r
-    //self = oldself;\r
-    self.think = SUB_Remove;\r
-    self.nextthink = time;\r
-}\r
-\r
-float zombie_verb_attack_stand(float eval)\r
-{\r
-    switch (eval)\r
-    {\r
-    case VCM_EVAL:\r
-        if not (self.enemy)\r
-            return VS_CALL_NO;\r
-\r
-        if(self.attack_finished_single > time)\r
-            return VS_CALL_NO;\r
-\r
-        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_stand_range"))\r
-            return VS_CALL_NO;\r
-\r
-        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)\r
-            return VS_CALL_NO;\r
-\r
-        return verb.verb_static_value;\r
-\r
-    case VCM_DO:\r
-        entity pain;\r
-        pain = spawn();\r
-        pain.owner = self;\r
-        pain.think = zombie_runattack_damage;\r
-        pain.nextthink = time + cvar("g_monster_zombie_attack_stand_delay");\r
-\r
-        self.attack_finished_single = time + 0.7;\r
-        self.frame = zombie_anim_attackstanding1 + rint(random() * 1);\r
-        dprint("frame:",ftos(self.frame),"\n");\r
-\r
-        return VS_CALL_YES_DOING;\r
-    }\r
-\r
-    return VS_CALL_YES_DONE;\r
-}\r
-\r
-void zombie_think()\r
-{\r
-    self.angles_x *= -1;\r
-    makevectors(self.angles);\r
-    self.angles_x *= -1;\r
-\r
-    if (zombie_scoretarget(self.enemy) == 0)\r
-        self.enemy = world;\r
-\r
-    verbstack_pop(self.verbs_attack);\r
-    //verbstack_pop(self.verbs_move);\r
-\r
-    if not (self.enemy)\r
-        verbstack_pop(self.verbs_idle);\r
-\r
-    zombie_move();\r
-\r
-    if(self.enemy)\r
-        self.nextthink = time;\r
-    else\r
-        self.nextthink = time + 0.2;\r
-}\r
-\r
-void zombie_spawn()\r
-{\r
-    setmodel(self,"models/monsters/zombie.dpm");\r
-\r
-    self.solid          = SOLID_BBOX;\r
-    self.takedamage     = DAMAGE_AIM;\r
-    self.event_damage   = zombie_damage;\r
-    self.enemy          = world;\r
-    self.frame          = zombie_anim_spawn;\r
-    self.think          = zombie_think;\r
-    self.nextthink      = time + 2.1;\r
-    self.pain_finished  = self.nextthink;\r
-    self.movetype       = MOVETYPE_WALK;\r
-    self.health         = cvar("g_monster_zombie_health");\r
-    self.velocity       = '0 0 0';\r
-    self.angles         = self.pos2;\r
-    self.moveto         = self.origin;\r
-    self.flags          = FL_MONSTER;\r
-\r
-    setorigin(self,self.pos1);\r
-    setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);\r
-}\r
-\r
-\r
-void spawnfunc_monster_zombie()\r
-{\r
-    if not(cvar("g_monsters"))\r
-    {\r
-        remove(self);\r
-        return;\r
-    }\r
-\r
-    precache_model("models/monsters/zombie.dpm");\r
-\r
-\r
-    self.verbs_idle   = spawn();\r
-    self.verbs_attack = spawn();\r
-\r
-    self.verbs_idle.owner = self;\r
-    self.verbs_attack.owner = self;\r
-\r
-    self.think      = zombie_spawn;\r
-    self.nextthink  = time + 2;\r
-\r
-    traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);\r
-\r
-    self.pos1 = trace_endpos;\r
-    self.pos2 = self.angles;\r
-    self.team = MAX_SHOT_DISTANCE -1;\r
-\r
-    verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);\r
-\r
-    verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);\r
-    verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);\r
-    verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);\r
-\r
-}\r
-\r
-#endif // MONSTES_ENABLED\r
+//#define MONSTES_ENABLED
+#ifdef MONSTES_ENABLED
+
+#define zombie_anim_attackleap         0
+#define zombie_anim_attackrun1         1
+#define zombie_anim_attackrun2         2
+#define zombie_anim_attackrun3         3
+#define zombie_anim_attackstanding1    4
+#define zombie_anim_attackstanding2    5
+#define zombie_anim_attackstanding3    6
+#define zombie_anim_blockend           7
+#define zombie_anim_blockstart         8
+#define zombie_anim_deathback1         9
+#define zombie_anim_deathback2         10
+#define zombie_anim_deathback3         11
+#define zombie_anim_deathfront1        12
+#define zombie_anim_deathfront2        13
+#define zombie_anim_deathfront3        14
+#define zombie_anim_deathleft1         15
+#define zombie_anim_deathleft2         16
+#define zombie_anim_deathright1        17
+#define zombie_anim_deathright2        18
+#define zombie_anim_idle               19
+#define zombie_anim_painback1          20
+#define zombie_anim_painback2          21
+#define zombie_anim_painfront1         22
+#define zombie_anim_painfront2         23
+#define zombie_anim_runbackwards       24
+#define zombie_anim_runbackwardsleft   25
+#define zombie_anim_runbackwardsright  26
+#define zombie_anim_runforward         27
+#define zombie_anim_runforwardleft     28
+#define zombie_anim_runforwardright    29
+#define zombie_anim_spawn              30
+
+#define ZOMBIE_MIN                                      '-18 -18 -25'
+#define ZOMBIE_MAX                                      '18 18 47'
+
+#define ZV_IDLE     10
+
+#define ZV_PATH     100
+#define ZV_HUNT     200
+
+#define ZV_ATTACK_FIND  10
+#define ZV_ATTACK_RUN   20
+#define ZV_ATTACK_STAND 30
+
+#define ZV_PATH2 10000
+
+//.entity verbs_idle;
+//.entity verbs_attack;
+//.entity verbs_move;
+
+//.float  state_timeout;
+//.void() monster_state;
+#define MONSTERFLAG_NORESPAWN 2
+
+void zombie_spawn();
+
+float zombie_scoretarget(entity trg)
+{
+    float  tmp;
+    vector ang1;
+
+    if (trg.takedamage == DAMAGE_AIM)
+    if not (trg.flags & FL_NOTARGET)
+    if (trg.deadflag == DEAD_NO)
+    if (trg.team != self.team)
+    {
+        if((self.origin_z - trg.origin_z) < 128)
+        {
+            ang1 = normalize(self.origin - trg.origin);
+            tmp = vlen(ang1 - v_forward);
+            if(tmp > 1.5)
+            {
+                traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);
+                if(trace_ent != trg)
+                    return 0;
+
+                return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;
+            }
+            else if(self.enemy == trg)
+                return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;
+        }
+    }
+
+    return 0;
+}
+
+void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+    //dprint("zombie_corpse_damage\n");
+    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+    self.health -= damage;
+
+    if(self.health < 0)
+    {
+        Violence_GibSplash(self, 1, 1, attacker);
+        remove(self);
+    }
+}
+
+void zombie_die(vector dir)
+{
+    vector v;
+    float f;
+
+    entity dummy;
+
+    dummy = spawn();
+    setmodel(dummy,"models/monsters/zombie.dpm");
+    setorigin(dummy, self.origin);
+    dummy.velocity  = self.velocity;
+    dummy.movetype  = MOVETYPE_BOUNCE;
+    dummy.think     = SUB_Remove;
+    dummy.nextthink = time + 3;
+    dummy.health    = 50;
+    dummy.takedamage = DAMAGE_YES;
+    dummy.event_damage = zombie_corpse_damage;
+    dummy.solid      = SOLID_CORPSE;
+    setsize(dummy,self.mins,self.maxs);
+
+    SUB_SetFade(dummy,time + 5,2);
+
+
+    v = normalize(self.origin - dir);
+    f = vlen(v_forward - v) - 1;
+    if(f > 0.5)
+        dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);
+    else if(f < 0.5)
+        dummy.frame = zombie_anim_deathback1 + rint(random() * 2);
+    else
+    {
+        f = vlen(v_right - v) - 1;
+        if(f > 0.5)
+            dummy.frame = zombie_anim_deathright1 + rint(random() * 2);
+        else if(f < 0.5)
+            dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);
+    }
+
+
+    if(self.spawnflags & MONSTERFLAG_NORESPAWN)
+    {
+        self.think = SUB_Remove;
+        self.nextthink = time;
+        return;
+    }
+
+    setmodel(self,"");
+    self.solid          = SOLID_NOT;
+    self.takedamage     = DAMAGE_NO;
+    self.event_damage   = SUB_Null;
+    self.enemy          = world;
+    self.think          = zombie_spawn;
+    self.nextthink      = time + cvar("g_monster_zombie_respawntime");
+    self.pain_finished  = self.nextthink;
+}
+
+void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+
+    vector v;
+    float f;
+
+    v = normalize(self.origin - hitloc);
+    f = vlen(v_forward - v) - 1;
+
+
+    self.health -= damage;
+    self.velocity = self.velocity + force;
+    if(self.health <= 0)
+    {
+        zombie_die(hitloc);
+        return;
+    }
+
+    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+       if (damage > 50)
+               Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
+       if (damage > 100)
+               Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
+
+    if (time > self.pain_finished)
+    {
+        if(f < 0.5)
+        {
+            if(random() < 0.5)
+                self.frame = zombie_anim_painback1;
+            else
+                self.frame = zombie_anim_painback2;
+        }
+        else
+        {
+            if(random() < 0.5)
+                self.frame = zombie_anim_painfront1;
+            else
+                self.frame = zombie_anim_painfront2;
+        }
+
+        self.pain_finished = time + 0.36;
+    }
+}
+
+.vector bvec;
+.float bvec_time;
+
+void zombie_move()
+{
+    vector real_angle;
+    float vz, tdiff, tspeed;
+
+    tdiff = time - self.zoomstate;
+    tspeed = tdiff * cvar("g_monster_zombie_turnspeed");
+    vz = self.velocity_z;
+    self.zoomstate = time;
+
+    if(self.bvec_time < time)
+    {
+        self.bvec_time = time + 0.2;
+        self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
+    }
+
+    if(self.enemy)
+        self.moveto = self.enemy.origin;
+    else
+        self.moveto = self.origin + v_forward;
+
+    self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);
+
+    self.angles_y = safeangle(self.angles_y);
+    real_angle = vectoangles(self.steerto) - self.angles;
+    self.angles_y += bound(-10, real_angle_y, 10);
+
+    if(vlen(self.origin - self.moveto) > 64)
+    {
+        movelib_move_simple(v_forward ,cvar("g_monster_zombie_movespeed"),0.6);
+        if(time > self.pain_finished)
+            if(self.attack_finished_single < time)
+                self.frame = zombie_anim_runforward;
+    }
+    else
+    {
+        movelib_beak_simple(cvar("g_monster_zombie_stopspeed"));
+        if(time > self.pain_finished)
+            if(self.attack_finished_single < time)
+                self.frame = zombie_anim_idle;
+    }
+
+    self.velocity_z = vz;
+    self.steerto = self.origin;
+}
+
+float zombie_verb_idle_roam(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+
+        self.moveto = v_forward * 128;
+        self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle_stand(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+
+        self.moveto   = self.origin;
+        self.frame    = zombie_anim_idle;
+        self.velocity = '0 0 0';
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+        float t;
+
+        t = cvar("g_monster_zombie_idle_timer_max") -  cvar("g_monster_zombie_idle_timer_min");
+        t = cvar("g_monster_zombie_idle_timer_min") + (random() * t);
+
+        if(random() < 0.5)
+            verbstack_push(self.verbs_idle, zombie_verb_idle_roam,  ZV_IDLE + 1, t, self);
+        else
+            verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_attack_findtarget(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+
+        entity trg, best_trg;
+        float trg_score, best_trg_score;
+
+        trg = findradius(self.origin,cvar("g_monster_zombie_targetrange"));
+        while(trg)
+        {
+            trg_score = zombie_scoretarget(trg);
+            if(trg_score > best_trg_score)
+            {
+                best_trg = trg;
+                best_trg_score = trg_score;
+            }
+
+            trg = trg.chain;
+        }
+
+        if(best_trg)
+        {
+            self.enemy = best_trg;
+            dprint("Selected: ",best_trg.netname, " as target.\n");
+        }
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+void zombie_runattack_damage()
+{
+    entity oldself;
+    oldself = self;
+    self = self.owner;
+
+    if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_hitrange"))
+        return;
+
+    if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+        return;
+
+    Damage(self.enemy, self, self, cvar("g_monster_zombie_attack_run_damage"), DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin)  * cvar("g_monster_zombie_attack_run_force"));
+
+    self = oldself;
+    self.think = SUB_Remove;
+    self.nextthink = time;
+}
+
+float zombie_verb_attack_run(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+        if not (self.enemy)
+            return VS_CALL_NO;
+
+        if(self.attack_finished_single > time)
+            return VS_CALL_NO;
+
+        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_range"))
+            return VS_CALL_NO;
+
+        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+        entity pain;
+        pain = spawn();
+        pain.owner = self;
+        pain.think = zombie_runattack_damage;
+        pain.nextthink = time + cvar("g_monster_zombie_attack_run_delay");
+
+        self.attack_finished_single = time + 0.7;
+        self.frame = zombie_anim_attackrun1 + rint(random() * 2);
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+void zombie_standattack_damage()
+{
+    //entity oldself;
+    //oldself = self;
+    //self = self.owner;
+
+    setorigin(self,self.owner.origin + v_forward * 32);
+    RadiusDamage(self, self.owner, cvar("g_monster_zombie_attack_stand_damage"),cvar("g_monster_zombie_attack_stand_damage"),16,self, cvar("g_monster_zombie_attack_stand_force"),DEATH_TURRET,world);
+    //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+
+
+    //self = oldself;
+    self.think = SUB_Remove;
+    self.nextthink = time;
+}
+
+float zombie_verb_attack_stand(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+        if not (self.enemy)
+            return VS_CALL_NO;
+
+        if(self.attack_finished_single > time)
+            return VS_CALL_NO;
+
+        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_stand_range"))
+            return VS_CALL_NO;
+
+        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+        entity pain;
+        pain = spawn();
+        pain.owner = self;
+        pain.think = zombie_runattack_damage;
+        pain.nextthink = time + cvar("g_monster_zombie_attack_stand_delay");
+
+        self.attack_finished_single = time + 0.7;
+        self.frame = zombie_anim_attackstanding1 + rint(random() * 1);
+        dprint("frame:",ftos(self.frame),"\n");
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+void zombie_think()
+{
+    self.angles_x *= -1;
+    makevectors(self.angles);
+    self.angles_x *= -1;
+
+    if (zombie_scoretarget(self.enemy) == 0)
+        self.enemy = world;
+
+    verbstack_pop(self.verbs_attack);
+    //verbstack_pop(self.verbs_move);
+
+    if not (self.enemy)
+        verbstack_pop(self.verbs_idle);
+
+    zombie_move();
+
+    if(self.enemy)
+        self.nextthink = time;
+    else
+        self.nextthink = time + 0.2;
+}
+
+void zombie_spawn()
+{
+    setmodel(self,"models/monsters/zombie.dpm");
+
+    self.solid          = SOLID_BBOX;
+    self.takedamage     = DAMAGE_AIM;
+    self.event_damage   = zombie_damage;
+    self.enemy          = world;
+    self.frame          = zombie_anim_spawn;
+    self.think          = zombie_think;
+    self.nextthink      = time + 2.1;
+    self.pain_finished  = self.nextthink;
+    self.movetype       = MOVETYPE_WALK;
+    self.health         = cvar("g_monster_zombie_health");
+    self.velocity       = '0 0 0';
+    self.angles         = self.pos2;
+    self.moveto         = self.origin;
+    self.flags          = FL_MONSTER;
+
+    setorigin(self,self.pos1);
+    setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);
+}
+
+
+void spawnfunc_monster_zombie()
+{
+    if not(cvar("g_monsters"))
+    {
+        remove(self);
+        return;
+    }
+
+    precache_model("models/monsters/zombie.dpm");
+
+
+    self.verbs_idle   = spawn();
+    self.verbs_attack = spawn();
+
+    self.verbs_idle.owner = self;
+    self.verbs_attack.owner = self;
+
+    self.think      = zombie_spawn;
+    self.nextthink  = time + 2;
+
+    traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);
+
+    self.pos1 = trace_endpos;
+    self.pos2 = self.angles;
+    self.team = MAX_SHOT_DISTANCE -1;
+
+    verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);
+
+    verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);
+    verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);
+    verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);
+
+}
+
+#endif // MONSTES_ENABLED
index 11ea2f6..9ed316e 100644 (file)
@@ -36,19 +36,77 @@ void Mutator_Remove(float(float) func); // calls error() on fail
 
 
 // register all possible hooks here
+
 MUTATOR_HOOKABLE(MakePlayerObserver);
-MUTATOR_HOOKABLE(MakePlayerSpectator);
+       // called when a player becomes observer, after shared setup
+
 MUTATOR_HOOKABLE(PlayerSpawn);
+       // called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
+
 MUTATOR_HOOKABLE(ClientDisconnect);
-MUTATOR_HOOKABLE(PlayerDies); entity other; entity frag_attacker;
-MUTATOR_HOOKABLE(GiveFragsForKill); entity frag_attacker, frag_target; float frag_score;
+       // called when a player disconnects
+
+MUTATOR_HOOKABLE(PlayerDies);
+       // called when a player dies to e.g. remove stuff he was carrying.
+       // INPUT:
+               entity frag_inflictor;
+               entity frag_attacker;
+
+MUTATOR_HOOKABLE(GiveFragsForKill);
+       // called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill
+       // INPUT:
+               entity frag_target;
+       // INPUT, OUTPUT:
+               float frag_score;
+
 MUTATOR_HOOKABLE(MatchEnd);
-MUTATOR_HOOKABLE(GetTeamCount); float ret_float;
-MUTATOR_HOOKABLE(SpectateCopy); entity other;
+       // called when the match ends
+
+MUTATOR_HOOKABLE(GetTeamCount);
+       // should adjust ret_float to contain the team count
+       // INPUT, OUTPUT:
+               float ret_float;
+
+MUTATOR_HOOKABLE(SpectateCopy);
+       // copies variables for spectating "other" to "self"
+       // INPUT:
+               entity other;
+
 MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon);
+       // returns 1 if throwing the current weapon shall not be allowed
+
 MUTATOR_HOOKABLE(SetStartItems);
-MUTATOR_HOOKABLE(BuildMutatorsString); string ret_string;
-MUTATOR_HOOKABLE(BuildMutatorsPrettyString); string ret_string;
-MUTATOR_HOOKABLE(FilterItem); // return error to request removal, or change self.items or self.weapons
-MUTATOR_HOOKABLE(OnEntityPreSpawn); // return error to prevent entity spawn, or modify the entity
+       // adjusts {warmup_}start_{items,weapons,ammo_{cells,rockets,nails,shells,fuel}}
+
+MUTATOR_HOOKABLE(BuildMutatorsString);
+       // appends ":mutatorname" to ret_string for logging
+       // INPUT, OUTPUT:
+               string ret_string;
+
+MUTATOR_HOOKABLE(BuildMutatorsPrettyString);
+       // appends ", Mutator name" to ret_string for display
+       // INPUT, OUTPUT:
+               string ret_string;
+
+MUTATOR_HOOKABLE(FilterItem);
+       // checks if the current item may be spawned (self.items and self.weapons may be read and written to, as well as the ammo_ fields)
+       // return error to request removal
+
+MUTATOR_HOOKABLE(OnEntityPreSpawn);
+       // return error to prevent entity spawn, or modify the entity
+
 MUTATOR_HOOKABLE(PlayerPreThink);
+       // runs in the event loop for players; is called for ALL player entities, also bots, also the dead, or spectators
+
+MUTATOR_HOOKABLE(GetPressedKeys);
+       // TODO change this into a general PlayerPostThink hook?
+
+MUTATOR_HOOKABLE(PlayerPhysics);
+       // called before any player physics, may adjust variables for movement,
+       // is run AFTER bot code and idle checking
+
+MUTATOR_HOOKABLE(GetCvars);
+       // is meant to call GetCvars_handle*(get_cvars_s, get_cvars_f, cvarfield, "cvarname") for cvars this mutator needs from the client
+       // INPUT:
+               float get_cvars_f;
+               string get_cvars_s;
index f207426..cdc4a07 100644 (file)
@@ -1064,10 +1064,9 @@ MUTATOR_HOOKFUNCTION(kh_SpectateCopy)
 MUTATOR_DEFINITION(gamemode_keyhunt)
 {
        MUTATOR_HOOK(MakePlayerObserver, kh_Key_DropAll, CBC_ORDER_ANY);
-       MUTATOR_HOOK(MakePlayerSpectator, kh_Key_DropAll, CBC_ORDER_ANY);
        MUTATOR_HOOK(ClientDisconnect, kh_Key_DropAll, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerDies, kh_PlayerDies, CBC_ORDER_ANY);
-       MUTATOR_HOOK(GiveFragsForKill, kh_GiveFragsForKill, CBC_ORDER_EXCLUSIVE);
+       MUTATOR_HOOK(GiveFragsForKill, kh_GiveFragsForKill, CBC_ORDER_FIRST);
        MUTATOR_HOOK(MatchEnd, kh_finalize, CBC_ORDER_ANY);
        MUTATOR_HOOK(GetTeamCount, kh_GetTeamCount, CBC_ORDER_EXCLUSIVE);
        MUTATOR_HOOK(SpectateCopy, kh_SpectateCopy, CBC_ORDER_ANY);
diff --git a/qcsrc/server/mutators/mutator_dodging.qc b/qcsrc/server/mutators/mutator_dodging.qc
new file mode 100644 (file)
index 0000000..d3b8e6d
--- /dev/null
@@ -0,0 +1,295 @@
+
+.float cvar_cl_dodging_timeout;
+
+
+// these are used to store the last key press time for each of the keys..
+.float last_FORWARD_KEY_time;
+.float last_BACKWARD_KEY_time;
+.float last_LEFT_KEY_time;
+.float last_RIGHT_KEY_time;
+
+// these store the movement direction at the time of the dodge action happening.
+.float dodging_direction_x;
+.float dodging_direction_y;
+
+// this indicates the last time a dodge was executed. used to check if another one is allowed
+// and to ramp up the dodge acceleration in the physics hook.
+.float last_dodging_time;
+
+// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
+.float dodging_action;
+
+// This is the velocity gain to be added over the ramp time.
+// It will decrease from frame to frame during dodging_action = 1
+// until it's 0.
+.float dodging_velocity_gain;
+
+// the jump part of the dodge cannot be ramped
+.float dodging_single_action;
+
+void dodging_Initialize() {
+       // print("dodging_Initialize\n");
+
+       self.last_FORWARD_KEY_time = 0;
+       self.last_BACKWARD_KEY_time = 0;
+       self.last_RIGHT_KEY_time = 0;
+       self.last_LEFT_KEY_time = 0;
+       self.last_dodging_time = 0;
+       self.dodging_action = 0;
+       self.dodging_velocity_gain = 0;
+       self.dodging_single_action = 0;
+       self.dodging_direction_x = 0;
+       self.dodging_direction_y = 0;
+}
+
+MUTATOR_HOOKFUNCTION(dodging_GetCvars) {
+       GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
+       // print("dodging_PlayerPhysics\n");
+
+       float common_factor;
+       float new_velocity_gain;
+       float velocity_difference;
+       float clean_up_and_do_nothing;
+
+       new_velocity_gain = 0;
+       clean_up_and_do_nothing = 0;
+
+       if (g_dodging == 0)
+               clean_up_and_do_nothing = 1;
+
+       // when swimming, no dodging allowed..
+       if (self.waterlevel >= WATERLEVEL_SWIMMING)
+               clean_up_and_do_nothing = 1;
+
+       if (clean_up_and_do_nothing != 0) {
+               self.dodging_action = 0;
+               self.dodging_direction_x = 0;
+               self.dodging_direction_y = 0;
+               return 0;
+       }
+
+       // make sure v_up, v_right and v_forward are sane
+       makevectors(self.angles);
+
+       // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code 
+       // will be called ramp_time/frametime times = 2 times. so, we need to 
+       // add 0.5 * the total speed each frame until the dodge action is done..
+       common_factor = sys_frametime / cvar("sv_dodging_ramp_time");
+
+       // if ramp time is smaller than frametime we get problems ;D
+       if (common_factor > 1) 
+               common_factor = 1;
+
+       new_velocity_gain = self.dodging_velocity_gain - (common_factor * cvar("sv_dodging_horiz_speed"));
+       if (new_velocity_gain < 0)
+               new_velocity_gain = 0;
+
+       velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
+
+       // ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
+       if (self.dodging_action == 1) {
+               //disable jump key during dodge accel phase
+               if (self.movement_z > 0) self.movement_z = 0;
+
+               self.velocity = 
+                         self.velocity 
+                       + ((self.dodging_direction_y * velocity_difference) * v_right)
+                       + ((self.dodging_direction_x * velocity_difference) * v_forward);
+
+               self.dodging_velocity_gain = self.dodging_velocity_gain - velocity_difference;
+       }
+
+       // the up part of the dodge is a single shot action
+       if (self.dodging_single_action == 1) {
+               self.flags &~= FL_ONGROUND;
+
+               self.velocity = 
+                         self.velocity 
+                       + (cvar("sv_dodging_up_speed") * v_up);
+
+               if (cvar("sv_dodging_sound") == 1)
+                       PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
+
+               setanim(self, self.anim_jump, TRUE, FALSE, TRUE);
+
+               self.dodging_single_action = 0;
+       }
+
+       // are we done with the dodging ramp yet?
+       if((self.dodging_action == 1) && ((time - self.last_dodging_time) > cvar("sv_dodging_ramp_time")))
+       {
+               // reset state so next dodge can be done correctly
+               self.dodging_action = 0;
+               self.dodging_direction_x = 0;
+               self.dodging_direction_y = 0;
+       }
+
+       return 0;
+}
+
+
+// returns 1 if the player is close to a wall
+float check_close_to_wall(float threshold) {
+       if (cvar("sv_dodging_wall_dodging") == 0)
+               return 0;
+
+       vector trace_start;
+       vector trace_end;
+
+       trace_start = self.origin;
+
+       trace_end = self.origin + (1000*v_right);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       trace_end = self.origin - (1000*v_right);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       trace_end = self.origin + (1000*v_forward);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       trace_end = self.origin - (1000*v_forward);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       return 0;
+}
+
+float check_close_to_ground(float threshold) {
+       if (self.flags & FL_ONGROUND)
+               return 1;
+
+       return 0;
+}
+
+
+MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
+       // print("dodging_PlayerPhysics\n");
+
+       float length;
+       float tap_direction_x;
+       float tap_direction_y;
+
+       tap_direction_x = 0;
+       tap_direction_y = 0;
+
+       float dodge_detected;
+       if (g_dodging == 0)
+               return 0;
+
+       dodge_detected = 0;
+
+       // first check if the last dodge is far enough back in time so we can dodge again
+       if ((time - self.last_dodging_time) < cvar("sv_dodging_delay"))
+               return 0;
+
+       if (check_close_to_ground(cvar("sv_dodging_height_threshold")) != 1 
+               && check_close_to_wall(cvar("sv_dodging_wall_distance_threshold")) != 1)
+               return 0;
+
+       if (self.movement_x > 0) {
+               // is this a state change?
+               if (!(self.pressedkeys & KEY_FORWARD)) {
+                       if ((time - self.last_FORWARD_KEY_time) < self.cvar_cl_dodging_timeout) { 
+                               tap_direction_x = 1.0;
+                               dodge_detected = 1;
+                       }
+                       self.last_FORWARD_KEY_time = time;
+               }
+       }
+
+       if (self.movement_x < 0) {
+               // is this a state change?
+               if (!(self.pressedkeys & KEY_BACKWARD)) {
+                       tap_direction_x = -1.0;
+                       if ((time - self.last_BACKWARD_KEY_time) < self.cvar_cl_dodging_timeout)        { 
+                               dodge_detected = 1;
+                       }
+                       self.last_BACKWARD_KEY_time = time;
+               }
+       }
+
+       if (self.movement_y > 0) {
+               // is this a state change?
+               if (!(self.pressedkeys & KEY_RIGHT)) {
+                       tap_direction_y = 1.0;
+                       if ((time - self.last_RIGHT_KEY_time) < self.cvar_cl_dodging_timeout)   { 
+                               dodge_detected = 1;
+                       }
+                       self.last_RIGHT_KEY_time = time;
+               }
+       }
+
+       if (self.movement_y < 0) {
+               // is this a state change?
+               if (!(self.pressedkeys & KEY_LEFT)) {
+                       tap_direction_y = -1.0;
+                       if ((time - self.last_LEFT_KEY_time) < self.cvar_cl_dodging_timeout)    { 
+                               dodge_detected = 1;
+                       }
+                       self.last_LEFT_KEY_time = time;
+               }
+       }
+
+
+
+       if (dodge_detected == 1) {
+               self.last_dodging_time = time;
+
+               self.dodging_action = 1;
+               self.dodging_single_action = 1;
+
+               self.dodging_velocity_gain = cvar("sv_dodging_horiz_speed");
+
+               self.dodging_direction_x = tap_direction_x;
+               self.dodging_direction_y = tap_direction_y;
+
+               // normalize the dodging_direction vector.. (unlike UT99) XD
+               length = length + self.dodging_direction_x * self.dodging_direction_x;
+               length = length + self.dodging_direction_y * self.dodging_direction_y;
+               length = sqrt(length);
+
+               self.dodging_direction_x = self.dodging_direction_x * 1.0/length;
+               self.dodging_direction_y = self.dodging_direction_y * 1.0/length;
+       }
+
+       return 0;
+}
+
+MUTATOR_DEFINITION(dodging)
+{
+       // we need to be called before GetPressedKey does its thing so we can
+       // detect state changes and therefore dodging actions..
+       MUTATOR_HOOK(GetPressedKeys, dodging_GetPressedKeys, CBC_ORDER_ANY);
+
+       // in the physics hook we actually implement the dodge..
+       MUTATOR_HOOK(PlayerPhysics, dodging_PlayerPhysics, CBC_ORDER_ANY);
+
+       // get timeout information from the client, so the client can configure it..
+       MUTATOR_HOOK(GetCvars, dodging_GetCvars, CBC_ORDER_ANY);
+
+       // this just turns on the cvar.
+       MUTATOR_ONADD
+       {
+               g_dodging = 1;
+               dodging_Initialize();
+       }
+
+       // this just turns off the cvar.
+       MUTATOR_ONREMOVE
+       {        
+               g_dodging = 0;
+       }
+
+       return 0;
+}
diff --git a/qcsrc/server/mutators/mutator_dodging.qh b/qcsrc/server/mutators/mutator_dodging.qh
new file mode 100644 (file)
index 0000000..8e8be25
--- /dev/null
@@ -0,0 +1,2 @@
+float g_dodging;
+
index dc1794c..cc3d563 100644 (file)
@@ -1,4 +1,4 @@
-float g_nix, g_nix_with_laser;
+float g_nix_with_laser;
 
 float nix_weapon;
 float nix_weapon_ammo;
@@ -9,6 +9,13 @@ float nix_nextweapon_ammo;
 .float nix_lastinfotime;
 .float nix_nextincr;
 
+.float nix_save_cells;
+.float nix_save_shells;
+.float nix_save_nails;
+.float nix_save_rockets;
+.float nix_save_fuel;
+.float nix_save_weapons;
+
 float NIX_CanChooseWeapon(float wpn)
 {
        entity e;
@@ -207,6 +214,8 @@ MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
 
 MUTATOR_DEFINITION(mutator_nix)
 {
+       entity e;
+
        MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
        MUTATOR_HOOK(SetStartItems, nix_SetStartItems, CBC_ORDER_EXCLUSIVE);
        MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
@@ -218,19 +227,51 @@ MUTATOR_DEFINITION(mutator_nix)
 
        MUTATOR_ONADD
        {
-               g_nix = 1;
                g_nix_with_laser = cvar("g_nix_with_laser");
 
                nix_nextchange = time;
                nix_nextweapon = 0;
 
                NIX_precache();
+
+               FOR_EACH_PLAYER(e)
+               {
+                       if(e.deadflag == DEAD_NO)
+                       {
+                               e.nix_save_cells = e.ammo_cells;
+                               e.nix_save_shells = e.ammo_shells;
+                               e.nix_save_nails = e.ammo_nails;
+                               e.nix_save_rockets = e.ammo_rockets;
+                               e.nix_save_fuel = e.ammo_fuel;
+                               e.nix_save_weapons = e.weapons;
+                       }
+                       else
+                       {
+                               e.nix_save_cells = 0;
+                               e.nix_save_shells = 0;
+                               e.nix_save_nails = 0;
+                               e.nix_save_rockets = 0;
+                               e.nix_save_fuel = 0;
+                               e.nix_save_weapons = 0;
+                       }
+               }
        }
 
        MUTATOR_ONREMOVE
        {
-               g_nix = 0;
                // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
+
+               FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
+               {
+                       e.ammo_cells = max(start_ammo_cells, e.nix_save_cells);
+                       e.ammo_shells = max(start_ammo_shells, e.nix_save_shells);
+                       e.ammo_nails = max(start_ammo_nails, e.nix_save_nails);
+                       e.ammo_rockets = max(start_ammo_rockets, e.nix_save_rockets);
+                       e.ammo_fuel = max(start_ammo_fuel, e.nix_save_fuel);
+                       e.weapons = (start_weapons | e.nix_save_weapons);
+                       if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
+                               e.switchweapon = w_getbestweapon(self);
+               }
        }
 
        return 0;
index bbaad86..da14483 100644 (file)
@@ -1,3 +1,5 @@
 MUTATOR_DECLARATION(gamemode_keyhunt);
 
 MUTATOR_DECLARATION(mutator_nix);
+
+MUTATOR_DECLARATION(dodging);
index ac6249f..bad8516 100644 (file)
@@ -56,7 +56,7 @@ void pathlib_showsquare2(entity node ,vector ncolor,float align)
 
     if(align)
     {
-        traceline(node.origin + '0 0 32',node.origin - '0 0 128',MOVE_WORLDONLY,node);
+        traceline(node.origin + '0 0 32', node.origin - '0 0 128', MOVE_WORLDONLY, node);
         node.angles = vectoangles(trace_plane_normal);
         node.angles_x -= 90;
     }
index 81c0cd1..4647fea 100644 (file)
@@ -40,7 +40,7 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
     for(i=0;i < 8; ++i)
     {
         t = plib_points[i];
-        fc  = pathlib_heuristic(t,goal) + pathlib_cost(node,t,pathlib_gridsize);
+        fc  = pathlib_heuristic(t,goal) + pathlib_cost(node, t, pathlib_gridsize);
         plib_fvals[i] = fc;
 
     }
@@ -77,11 +77,11 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
         */
     }
 
-    pathlib_makenode(node,start,bp,goal,pathlib_gridsize);
+    pathlib_makenode(node, start, bp, goal, pathlib_gridsize);
 
     for(i = 0; i < 3; ++i)
     {
-        pathlib_makenode(node,start,plib_points2[i],goal,pathlib_gridsize);
+        pathlib_makenode(node, start, plib_points2[i], goal, pathlib_gridsize);
     }
 
     return pathlib_open_cnt;
@@ -89,44 +89,79 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
 
 float pathlib_expandnode_star(entity node, vector start, vector goal)
 {
-    vector point,where,f,r;
+    vector point, where, f, r;
 
     where = node.origin;
 
     f = PLIB_FORWARD * pathlib_gridsize;
     r = PLIB_RIGHT   * pathlib_gridsize;
 
+    if (node.pathlib_node_edgeflags == pathlib_node_edgeflag_unknown)
+        node.pathlib_node_edgeflags = tile_check_plus2(node.origin);
+
+    if(node.pathlib_node_edgeflags == pathlib_node_edgeflag_none)
+    {
+        dprint("Node at ", vtos(node.origin), " not expanable");
+        return pathlib_open_cnt;
+    }
+
     // Forward
-    point = where + f;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_forward)
+    {
+        point = where + f;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost);
+    }
 
     // Back
-    point = where - f;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_back)
+    {
+        point = where - f;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost);
+    }
 
     // Right
-    point = where + r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+        if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_right)
+    {
+        point = where + r;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost);
+    }
 
     // Left
-    point = where - r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_left)
+    {
+        point = where - r;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost);
+
+    }
 
     // Forward-right
-    point = where + f + r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_forwardright)
+    {
+        point = where + f + r;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+    }
 
     // Forward-left
-    point = where + f - r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_forwardleft)
+    {
+        point = where + f - r;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+
+    }
 
     // Back-right
-    point = where - f + r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_backright)
+    {
+        point = where - f + r;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+    }
 
     // Back-left
-    point = where - f - r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+    if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_backleft)
+    {
+        point = where - f - r;
+        pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+    }
 
     return pathlib_open_cnt;
 }
@@ -142,40 +177,40 @@ float pathlib_expandnode_octagon(entity node, vector start, vector goal)
 
     // Forward
     point = where + f;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
     // Back
     point = where - f;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
     // Right
     point = where + r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
     // Left
     point = where - r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
     f = PLIB_FORWARD * pathlib_gridsize * 0.5;
     r = PLIB_RIGHT   * pathlib_gridsize * 0.5;
 
     // Forward-right
     point = where + f + r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
 
     // Forward-left
     point = where + f - r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
 
     // Back-right
     point = where - f + r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
     // Back-left
     point = where - f - r;
-    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+    pathlib_makenode(node, start, point, goal, pathlib_movecost);
 
     return pathlib_open_cnt;
 }
index 6d5a785..fbff82e 100644 (file)
@@ -28,7 +28,7 @@ entity pathlib_mknode(vector where,entity parent)
     node = pathlib_nodeatpoint(where);
     if(node)
     {
-        mark_error(where,60);
+        mark_error(where, 60);
         return node;
     }
 
@@ -40,19 +40,12 @@ entity pathlib_mknode(vector where,entity parent)
     node.owner        = openlist;
     node.path_prev    = parent;
 
-    setmodel(node,"models/pathlib/square.md3");
-    setsize(node,'0 0 0','0 0 0');
-    node.colormod = randomvec() * 2;
-    node.alpha = 0.25;
-    node.scale     = pathlib_gridsize / 512.001;
 
-    //pathlib_showsquare2(node,'1 1 1',0);//(node.medium & CONTENT_EMPTY));
+    setsize(node, '0 0 0', '0 0 0');
+
     setorigin(node, where);
     node.medium = pointcontents(where);
-
-    mark_info(where,60);
-    //pathlib_showsquare(where,1,30);
-
+    pathlib_showsquare(where, 1 ,15);
 
     ++pathlib_made_cnt;
     ++pathlib_open_cnt;
@@ -70,6 +63,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
 
     if(inwater(parent.origin))
     {
+        dprint("FromWater\n");
         pathlib_expandnode = pathlib_expandnode_box;
         pathlib_movenode   = pathlib_swimnode;
     }
@@ -77,11 +71,13 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     {
         if(inwater(to))
         {
+            dprint("ToWater\n");
             pathlib_expandnode = pathlib_expandnode_box;
             pathlib_movenode   = pathlib_walknode;
         }
         else
         {
+            dprint("LandToLoand\n");
             //if(edge_check(parent.origin))
             //    return 0;
 
@@ -94,6 +90,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     node = pathlib_nodeatpoint(to);
     if(node)
     {
+        dprint("NodeAtPoint\n");
         ++pathlib_merge_cnt;
 
         if(node.owner == openlist)
@@ -120,9 +117,17 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
         return 1;
     }
 
-    where = pathlib_movenode(parent.origin,to,0);
+    where = pathlib_movenode(parent.origin, to, 0);
+
     if not(pathlib_movenode_goodnode)
+    {
+        //pathlib_showsquare(where, 0 ,30);
+        //pathlib_showsquare(parent.origin, 1 ,30);
+        dprint("pathlib_movenode_goodnode = 0\n");
         return 0;
+    }
+
+    //pathlib_showsquare(where, 1 ,30);
 
     if(pathlib_nodeatpoint(where))
     {
@@ -132,15 +137,20 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
         return 0;
     }
 
+
     if(doedge)
         if not (tile_check(where))
+        {
+            dprint("tile_check fail\n");
+            pathlib_showsquare(where, 0 ,30);
             return 0;
+        }
+
 
     h = pathlib_heuristic(where,goal);
     g = pathlib_cost(parent,where,cost);
     f = g + h;
 
-
     /*
     node = findradius(where,pathlib_gridsize * 0.5);
     while(node)
@@ -175,7 +185,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     }
     */
 
-    node = pathlib_mknode(where,parent);
+    node = pathlib_mknode(where, parent);
     node.pathlib_node_h = h;
     node.pathlib_node_g = g;
     node.pathlib_node_f = f;
@@ -317,6 +327,11 @@ float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
     return 0;
 }
 
+float buildpath_nodefilter_none(vector n,vector c,vector p)
+{
+    return 0;
+}
+
 entity path_build(entity next, vector where, entity prev, entity start)
 {
     entity path;
@@ -358,17 +373,23 @@ entity pathlib_astar(vector from,vector to)
 
     // Select water<->land capable node make/link
     pathlib_makenode     = pathlib_makenode_adaptive;
+
     // Select XYZ cost estimate
     //pathlib_heuristic    = pathlib_h_diagonal3;
     pathlib_heuristic    = pathlib_h_diagonal;
+
     // Select distance + waterfactor cost
     pathlib_cost         = pathlib_g_euclidean_water;
+
     // Select star expander
     pathlib_expandnode   = pathlib_expandnode_star;
+
     // Select walk simulation movement test
     pathlib_movenode     = pathlib_walknode;
+
     // Filter final nodes by direction
     buildpath_nodefilter = buildpath_nodefilter_directional;
+
     // Filter tiles with cross pattern
     tile_check = tile_check_cross;
 
@@ -400,31 +421,37 @@ entity pathlib_astar(vector from,vector to)
     pathlib_gridsize       = 128;
     pathlib_movecost       = pathlib_gridsize;
     pathlib_movecost_diag  = vlen(('1 1 0' * pathlib_gridsize));
-    pathlib_movecost_waterfactor = 1;
+    pathlib_movecost_waterfactor = 25000000;
     pathlib_foundgoal      = 0;
 
-    movenode_boxmax   = self.maxs * 1.25;
-    movenode_boxmin   = self.mins * 1.25;
+    movenode_boxmax   = self.maxs * 1.1;
+    movenode_boxmin   = self.mins * 1.1;
 
-    movenode_stepsize = 32;
+    movenode_stepsize = pathlib_gridsize * 0.25;
 
-    tile_check_size = 65;
+    tile_check_size = pathlib_gridsize * 0.5;
+    tile_check_up   = '0 0 2' * pathlib_gridsize;
     tile_check_up   = '0 0 128';
-    tile_check_down = '0 0 128';
+    tile_check_down = '0 0 3' * pathlib_gridsize;
+    tile_check_down = '0 0 256';
 
+    //movenode_stepup   = '0 0 128';
     movenode_stepup   = '0 0 36';
-    movenode_maxdrop  = '0 0 128';
+    movenode_maxdrop  = '0 0 512';
+    //movenode_maxdrop  = '0 0 512';
     movenode_boxup    = '0 0 72';
 
-    from_x = fsnap(from_x,pathlib_gridsize);
-    from_y = fsnap(from_y,pathlib_gridsize);
+    from_x = fsnap(from_x, pathlib_gridsize);
+    from_y = fsnap(from_y, pathlib_gridsize);
+    //from_z += 32;
 
-    to_x = fsnap(to_x,pathlib_gridsize);
-    to_y = fsnap(to_y,pathlib_gridsize);
+    to_x = fsnap(to_x, pathlib_gridsize);
+    to_y = fsnap(to_y, pathlib_gridsize);
+    //to_z += 32;
 
     dprint("AStar init\n");
-    path = pathlib_mknode(from,world);
-    pathlib_close_node(path,to);
+    path = pathlib_mknode(from, world);
+    pathlib_close_node(path, to);
     if(pathlib_foundgoal)
     {
         dprint("AStar: Goal found on first node!\n");
@@ -439,7 +466,7 @@ entity pathlib_astar(vector from,vector to)
         return open;
     }
 
-    if(pathlib_expandnode(path,from,to) <= 0)
+    if(pathlib_expandnode(path, from, to) <= 0)
     {
         dprint("AStar path fail.\n");
         pathlib_cleanup();
@@ -449,11 +476,11 @@ entity pathlib_astar(vector from,vector to)
 
     best_open_node = pathlib_getbestopen();
     n = best_open_node;
-    pathlib_close_node(best_open_node,to);
+    pathlib_close_node(best_open_node, to);
     if(inwater(n.origin))
-        pathlib_expandnode_box(n,from,to);
+        pathlib_expandnode_box(n, from, to);
     else
-        pathlib_expandnode_star(n,from,to);
+        pathlib_expandnode_star(n, from, to);
 
     while(pathlib_open_cnt)
     {
index 59973b0..9369fb4 100644 (file)
@@ -66,11 +66,22 @@ vector pathlib_flynode(vector start,vector end)
     return end;
 }
 
+void a_think()
+{
+    te_lightning1(self,self.origin, self.pos1);
+    if(self.cnt < time)
+        remove(self);
+    else
+        self.nextthink = time + 0.2;
+}
+
 vector pathlib_walknode(vector start,vector end,float doedge)
 {
     vector direction,point,last_point,s,e;
     float steps, distance, i;
 
+    dprint("Walking node from ", vtos(start), " to ", vtos(end), "\n");
+
     pathlib_movenode_goodnode = 0;
 
     end_x = fsnap(end_x,pathlib_gridsize);
@@ -79,9 +90,21 @@ vector pathlib_walknode(vector start,vector end,float doedge)
     start_y = fsnap(start_y,pathlib_gridsize);
 
     // Find the floor
-    traceline(start + movenode_stepup, start - movenode_maxdrop,MOVE_WORLDONLY,self);
+    traceline(start + movenode_stepup, start - movenode_maxdrop, MOVE_WORLDONLY, self);
     if(trace_fraction == 1.0)
+    {
+        entity a;
+        a = spawn();
+        a.think = a_think;
+        a.nextthink = time;
+        setorigin(a,start + movenode_stepup);
+        a.pos1 = trace_endpos;
+        //start - movenode_maxdrop
+        a.cnt = time + 10;
+
+        dprint("I cant walk on air!\n");
         return trace_endpos;
+    }
 
     start = trace_endpos;
 
diff --git a/qcsrc/server/pathlib/path_waypoint.qc b/qcsrc/server/pathlib/path_waypoint.qc
new file mode 100644 (file)
index 0000000..73b4155
--- /dev/null
@@ -0,0 +1,245 @@
+var float pathlib_wpp_open(entity wp, entity child, float cost);
+
+void pathlib_wpp_close(entity wp)
+{
+    --pathlib_open_cnt;
+    ++pathlib_closed_cnt;
+
+    wp.pathlib_list = closedlist;
+
+    if(wp == best_open_node)
+        best_open_node = world;
+
+    if(wp == goal_node)
+        pathlib_foundgoal = TRUE;
+}
+
+float pathlib_wpp_opencb(entity wp, entity child, float cost)
+{
+
+    if(child.pathlib_list == closedlist)
+        return FALSE;
+
+       // FIXME! wp.wp##mincost is NOT distance. Make it distance or add a field for distance to be used here (for better speed)
+       cost = vlen(child.origin - wp.origin);
+       
+    child.path_prev     = wp;
+    child.pathlib_list   = openlist;
+    child.pathlib_node_g = wp.pathlib_node_g + cost;
+    child.pathlib_node_h = pathlib_heuristic(child.origin, goal_node.origin);
+    child.pathlib_node_c = pathlib_wpp_waypointcallback(child, wp);
+    child.pathlib_node_f = child.pathlib_node_g + child.pathlib_node_h + child.pathlib_node_c;
+    
+
+    if(child == goal_node)
+        pathlib_foundgoal = TRUE;
+
+    ++pathlib_open_cnt;
+
+    if(best_open_node.pathlib_node_f > child.pathlib_node_f)
+        best_open_node = child;
+
+    return TRUE;
+}
+
+float pathlib_wpp_openncb(entity wp, entity child, float cost)
+{
+
+    if(child.pathlib_list == closedlist)
+        return FALSE;
+
+       // FIXME! wp.wp##mincost is NOT distance. Make it distance or add a field for distance to be used here (for better speed)
+       cost = vlen(child.origin - wp.origin);
+       
+    child.path_prev     = wp;
+    child.pathlib_list   = openlist;
+    child.pathlib_node_g = wp.pathlib_node_g + cost;
+    child.pathlib_node_h = pathlib_heuristic(child.origin, goal_node.origin); 
+    child.pathlib_node_f = child.pathlib_node_g + child.pathlib_node_h;
+
+    if(child == goal_node)
+        pathlib_foundgoal = TRUE;
+
+    ++pathlib_open_cnt;
+
+    if(best_open_node.pathlib_node_f > child.pathlib_node_f)
+        best_open_node = child;
+
+    return TRUE;
+}
+
+float pathlib_wpp_expand(entity wp)
+{
+    if(wp.wp00) pathlib_wpp_open(wp,wp.wp00,wp.wp00mincost); else return 0;
+    if(wp.wp01) pathlib_wpp_open(wp,wp.wp01,wp.wp01mincost); else return 1;
+    if(wp.wp02) pathlib_wpp_open(wp,wp.wp02,wp.wp02mincost); else return 2;
+    if(wp.wp03) pathlib_wpp_open(wp,wp.wp03,wp.wp03mincost); else return 3;
+    if(wp.wp04) pathlib_wpp_open(wp,wp.wp04,wp.wp04mincost); else return 4;
+    if(wp.wp05) pathlib_wpp_open(wp,wp.wp05,wp.wp05mincost); else return 5;
+    if(wp.wp06) pathlib_wpp_open(wp,wp.wp06,wp.wp06mincost); else return 6;
+    if(wp.wp07) pathlib_wpp_open(wp,wp.wp07,wp.wp07mincost); else return 7;
+    if(wp.wp08) pathlib_wpp_open(wp,wp.wp08,wp.wp08mincost); else return 8;
+    if(wp.wp09) pathlib_wpp_open(wp,wp.wp09,wp.wp09mincost); else return 9;
+    if(wp.wp10) pathlib_wpp_open(wp,wp.wp10,wp.wp10mincost); else return 10;
+    if(wp.wp11) pathlib_wpp_open(wp,wp.wp11,wp.wp11mincost); else return 11;
+    if(wp.wp12) pathlib_wpp_open(wp,wp.wp12,wp.wp12mincost); else return 12;
+    if(wp.wp13) pathlib_wpp_open(wp,wp.wp13,wp.wp13mincost); else return 13;
+    if(wp.wp14) pathlib_wpp_open(wp,wp.wp14,wp.wp14mincost); else return 14;
+    if(wp.wp15) pathlib_wpp_open(wp,wp.wp15,wp.wp15mincost); else return 15;
+    if(wp.wp16) pathlib_wpp_open(wp,wp.wp16,wp.wp16mincost); else return 16;
+    if(wp.wp17) pathlib_wpp_open(wp,wp.wp17,wp.wp17mincost); else return 17;
+    if(wp.wp18) pathlib_wpp_open(wp,wp.wp18,wp.wp18mincost); else return 18;
+    if(wp.wp19) pathlib_wpp_open(wp,wp.wp19,wp.wp19mincost); else return 19;
+    if(wp.wp20) pathlib_wpp_open(wp,wp.wp20,wp.wp20mincost); else return 20;
+    if(wp.wp21) pathlib_wpp_open(wp,wp.wp21,wp.wp21mincost); else return 21;
+    if(wp.wp22) pathlib_wpp_open(wp,wp.wp22,wp.wp22mincost); else return 22;
+    if(wp.wp23) pathlib_wpp_open(wp,wp.wp23,wp.wp23mincost); else return 23;
+    if(wp.wp24) pathlib_wpp_open(wp,wp.wp24,wp.wp24mincost); else return 24;
+    if(wp.wp25) pathlib_wpp_open(wp,wp.wp25,wp.wp25mincost); else return 25;
+    if(wp.wp26) pathlib_wpp_open(wp,wp.wp26,wp.wp26mincost); else return 26;
+    if(wp.wp27) pathlib_wpp_open(wp,wp.wp27,wp.wp27mincost); else return 27;
+    if(wp.wp28) pathlib_wpp_open(wp,wp.wp28,wp.wp28mincost); else return 28;
+    if(wp.wp29) pathlib_wpp_open(wp,wp.wp29,wp.wp29mincost); else return 29;
+    if(wp.wp30) pathlib_wpp_open(wp,wp.wp30,wp.wp30mincost); else return 30;
+    if(wp.wp31) pathlib_wpp_open(wp,wp.wp31,wp.wp31mincost); else return 31;
+    
+    return 32;
+}
+
+entity pathlib_wpp_bestopen()
+{
+    entity n, best;
+
+    if(best_open_node)
+        return best_open_node;
+
+    n = findchainentity(pathlib_list, openlist);
+    best = n;
+    while(n)
+    {
+        if(n.pathlib_node_f < best.pathlib_node_f)
+            best = n;
+
+        n = n.chain;
+    }
+
+    return best;
+
+}
+
+entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback)
+{
+    entity n;
+    float ptime;
+
+    ptime                                      = gettime(GETTIME_REALTIME);
+    pathlib_starttime          = ptime;        
+       pathlib_movecost                = 300;
+       pathlib_movecost_diag   = vlen('1 1 0' * pathlib_movecost);
+       
+       if not (pathlib_wpp_waypointcallback) 
+               callback = FALSE;
+               
+       if (callback)
+               pathlib_wpp_open = pathlib_wpp_opencb;
+       else
+               pathlib_wpp_open = pathlib_wpp_openncb;
+       
+       pathlib_heuristic = pathlib_h_none;
+       
+    if not(openlist)
+        openlist       = spawn();
+
+    if not(closedlist)
+        closedlist     = spawn();
+
+    pathlib_closed_cnt       = 0;
+    pathlib_open_cnt         = 0;
+    pathlib_searched_cnt     = 0;
+    pathlib_foundgoal      = FALSE;
+
+    dprint("pathlib_waypointpath init\n");
+
+    // Initialize waypoint grid
+    // FIXME! presisted chain for better preformance
+    for(n = findchain(classname, "waypoint"); n; n = n.chain)
+    {
+        n.pathlib_list = world;
+        n.pathlib_node_g = 0;
+        n.pathlib_node_f = 0;
+        n.pathlib_node_h = 0;
+        
+        //setmodel(n, "models/runematch/rune.mdl");
+        //n.effects = EF_LOWPRECISION;
+        //n.colormod = '0 0 0';
+        //n.scale = 1;
+        
+    }
+
+    goal_node  = wp_to;
+    start_node = wp_from;
+
+    start_node.pathlib_list = closedlist;
+    dprint("Expanding ",ftos(pathlib_wpp_expand(start_node))," links\n");
+    if(pathlib_open_cnt <= 0)
+    {
+        dprint("pathlib_waypointpath: Start waypoint not linked! aborting.\n");
+        return world;
+    }
+
+    return world;
+}
+
+entity pathlib_waypointpath_step()
+{
+    entity n;
+
+    n = pathlib_wpp_bestopen();
+    if(!n)
+    {
+        dprint("Cannot find best open node, abort.\n");
+        return world;
+    }
+    pathlib_wpp_close(n);
+       dprint("Expanding ",ftos(pathlib_wpp_expand(n))," links\n");
+       
+    if(pathlib_foundgoal)
+    {
+        entity start, end, open, ln;
+        
+        dprint("Target found. Rebuilding and filtering path...\n");
+        
+               buildpath_nodefilter = buildpath_nodefilter_none;
+               start = path_build(world, start_node.origin, world, world);
+               end   = path_build(world, goal_node.origin, world, start);
+               ln    = end;
+               
+               for(open = goal_node; open.path_prev != start_node; open = open.path_prev)
+               {
+                       n    = path_build(ln,open.origin,open.path_prev,start);
+                       ln.path_prev = n;
+                       ln = n;
+               }
+               start.path_next = n;
+               n.path_prev = start;            
+               
+        return start;
+    }
+
+    return world;
+}
+void plas_think()
+{
+    pathlib_waypointpath_step();
+    if(pathlib_foundgoal)
+        return;
+    self.nextthink = time + 0.1;
+}
+
+void pathlib_waypointpath_autostep()
+{
+    entity n;
+    n = spawn();
+    n.think = plas_think;
+    n.nextthink = time + 0.1;
+}
index 19f6ef0..2616a77 100644 (file)
@@ -1,3 +1,4 @@
+.entity pathlib_list;
 .entity path_next;
 .entity path_prev;
 
@@ -17,12 +18,28 @@ void pathlib_showpath2(entity path);
 
 entity openlist;
 entity closedlist;
+entity edgelist;
+
 entity goal_node;
+entity start_node;
 
 .float is_path_node;
 .float pathlib_node_g;
 .float pathlib_node_h;
 .float pathlib_node_f;
+.float pathlib_node_c;
+
+#define pathlib_node_edgeflag_unknown        0
+#define pathlib_node_edgeflag_left           2
+#define pathlib_node_edgeflag_right          4
+#define pathlib_node_edgeflag_forward        8
+#define pathlib_node_edgeflag_back           16
+#define pathlib_node_edgeflag_backleft       32
+#define pathlib_node_edgeflag_backright      64
+#define pathlib_node_edgeflag_forwardleft    128
+#define pathlib_node_edgeflag_forwardright   256
+#define pathlib_node_edgeflag_none           512
+.float pathlib_node_edgeflags;
 
 float pathlib_open_cnt;
 float pathlib_closed_cnt;
@@ -39,17 +56,17 @@ float pathlib_movecost_waterfactor;
 float pathlib_foundgoal;
 
 float pathlib_starttime;
-#define pathlib_maxtime 5
+#define pathlib_maxtime 60
 
 entity best_open_node;
 
 vector tile_check_up;
 vector tile_check_down;
 float  tile_check_size;
-float      tile_check_cross(vector where);
-float      tile_check_plus(vector where);
-float      tile_check_star(vector where);
-var float  tile_check(vector where);
+float     tile_check_cross(vector where);
+float     tile_check_plus(vector where);
+float     tile_check_star(vector where);
+var float tile_check(vector where);
 
 float  movenode_stepsize;
 vector movenode_stepup;
@@ -82,14 +99,17 @@ float      pathlib_h_euclidean(vector a,vector b);
 float      pathlib_h_diagonal2(vector a, vector b);
 float      pathlib_h_diagonal3(vector a, vector b);
 float      pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end);
+float      pathlib_h_none(vector preprev, vector prev) { return 0; }
 var float  pathlib_heuristic(vector from, vector to);
 
 var float  pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
 var float  buildpath_nodefilter(vector n,vector c,vector p);
 
+var float  pathlib_wpp_waypointcallback(entity wp, entity wp_prev);
+var const float pathlib_wpp_wpcb_null();
 
 #ifdef DEBUGPATHING
-#include "debug.qc"
+       #include "debug.qc"
 #endif
 
 #include "utility.qc"
@@ -97,3 +117,4 @@ var float  buildpath_nodefilter(vector n,vector c,vector p);
 #include "costs.qc"
 #include "expandnode.qc"
 #include "main.qc"
+#include "path_waypoint.qc"
index 81d06b2..5d9fc3d 100644 (file)
@@ -90,28 +90,29 @@ float tile_check_cross(vector where)
     f = PLIB_FORWARD * tile_check_size;
     r = PLIB_RIGHT   * tile_check_size;
 
+
     // forward-right
     p = where + f + r;
-    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
-    if not (location_isok(trace_endpos,1,0))
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if not (location_isok(trace_endpos, 1, 0))
         return 0;
 
     // Forward-left
     p = where + f - r;
-    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
-    if not (location_isok(trace_endpos,1,0))
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if not (location_isok(trace_endpos, 1, 0))
         return 0;
 
     // Back-right
     p = where - f + r;
-    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
-    if not (location_isok(trace_endpos,1,0))
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if not (location_isok(trace_endpos, 1 ,0))
         return 0;
 
     //Back-left
     p = where - f - r;
-    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
-    if not (location_isok(trace_endpos,1,0))
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if not (location_isok(trace_endpos, 1, 0))
         return 0;
 
     return 1;
@@ -130,13 +131,13 @@ float tile_check_plus(vector where)
     if not (location_isok(trace_endpos,1,0))
         return 0;
 
+
     //left
     p = where - r;
     traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
     if not (location_isok(trace_endpos,1,0))
         return 0;
 
-
     // Right
     p = where + r;
     traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
@@ -152,6 +153,100 @@ float tile_check_plus(vector where)
     return 1;
 }
 
+float tile_check_plus2(vector where)
+{
+    vector p,f,r;
+    float i,e;
+
+    f = PLIB_FORWARD * pathlib_gridsize;
+    r = PLIB_RIGHT   * pathlib_gridsize;
+
+//#define pathlib_node_edgeflag_left    2
+//#define pathlib_node_edgeflag_right   4
+//#define pathlib_node_edgeflag_forward 8
+//#define pathlib_node_edgeflag_back    16
+
+    // forward
+    p = where + f;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if (location_isok(trace_endpos,1,0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_forward;
+    }
+
+
+    //left
+    p = where - r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if (location_isok(trace_endpos,1,0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_left;
+    }
+
+
+    // Right
+    p = where + r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if (location_isok(trace_endpos,1,0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_right;
+    }
+
+    //Back
+    p = where - f;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if (location_isok(trace_endpos,1,0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_back;
+    }
+
+    // forward-right
+    p = where + f + r;
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if (location_isok(trace_endpos, 1, 0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_forwardright;
+    }
+
+    // Forward-left
+    p = where + f - r;
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if (location_isok(trace_endpos, 1, 0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_forwardleft;
+    }
+
+    // Back-right
+    p = where - f + r;
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if (location_isok(trace_endpos, 1 ,0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_backright;
+    }
+
+    //Back-left
+    p = where - f - r;
+    traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+    if (location_isok(trace_endpos, 1, 0))
+    {
+       ++i;
+       e |= pathlib_node_edgeflag_backleft;
+    }
+
+
+    if(i == 0)
+        e = pathlib_node_edgeflag_none;
+
+    return e;
+}
+
 float tile_check_star(vector where)
 {
     if(tile_check_plus(where))
index 8b90140..b325251 100644 (file)
@@ -23,6 +23,7 @@ defs.qh               // Should rename this, it has fields and globals
 mutators/base.qh
 mutators/mutators.qh
 mutators/gamemode_keyhunt.qh // TODO fix this
+mutators/mutator_dodging.qh
 
 //// tZork Turrets ////
 tturrets/include/turrets_early.qh
@@ -173,6 +174,7 @@ cheats.qc
 mutators/base.qc
 mutators/gamemode_keyhunt.qc
 mutators/mutator_nix.qc
+mutators/mutator_dodging.qc
 
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/mathlib.qc
index 6025578..9d32f32 100644 (file)
@@ -48,8 +48,7 @@ float Item_Customize()
        if(self.weapons != (self.weapons & other.weapons))
        {
                self.colormod = '0 0 0';
-               if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                       self.glowmod = self.colormod;
+               self.glowmod = self.colormod;
                self.alpha = 0.5 + 0.5 * g_ghost_items; // halfway more alpha
                return TRUE;
        }
@@ -58,8 +57,7 @@ float Item_Customize()
                if(g_ghost_items)
                {
                        self.colormod = stov(cvar_string("g_ghost_items_color"));
-                       if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                               self.glowmod = self.colormod;
+                       self.glowmod = self.colormod;
                        self.alpha = g_ghost_items;
                        return TRUE;
                }
@@ -77,8 +75,7 @@ void Item_Show (entity e, float mode)
                e.model = e.mdl;
                e.solid = SOLID_TRIGGER;
                e.colormod = '0 0 0';
-               if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                       self.glowmod = self.colormod;
+               self.glowmod = self.colormod;
                e.alpha = 0;
                e.customizeentityforclient = func_null;
 
@@ -90,8 +87,7 @@ void Item_Show (entity e, float mode)
                e.model = string_null;
                e.solid = SOLID_NOT;
                e.colormod = '0 0 0';
-               if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                       self.glowmod = self.colormod;
+               self.glowmod = self.colormod;
                e.alpha = 0;
                e.customizeentityforclient = func_null;
 
@@ -103,8 +99,7 @@ void Item_Show (entity e, float mode)
                e.model = e.mdl;
                e.solid = SOLID_TRIGGER; // can STILL be picked up!
                e.colormod = '0 0 0';
-               if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                       self.glowmod = self.colormod;
+               self.glowmod = self.colormod;
                e.effects |= EF_STARDUST;
                e.customizeentityforclient = Item_Customize;
 
@@ -116,8 +111,7 @@ void Item_Show (entity e, float mode)
                e.model = e.mdl;
                e.solid = SOLID_NOT;
                e.colormod = stov(cvar_string("g_ghost_items_color"));
-               if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                       self.glowmod = self.colormod;
+               self.glowmod = self.colormod;
                e.alpha = g_ghost_items;
                e.customizeentityforclient = func_null;
 
@@ -129,8 +123,7 @@ void Item_Show (entity e, float mode)
                e.model = string_null;
                e.solid = SOLID_NOT;
                e.colormod = stov(cvar_string("g_ghost_items_color"));
-               if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
-                       self.glowmod = self.colormod;
+               self.glowmod = self.colormod;
                e.alpha = 0;
                e.customizeentityforclient = func_null;
 
index 4e1c167..0798b29 100644 (file)
@@ -208,6 +208,9 @@ void InitGameplayMode()
        fraglimit_override = cvar("fraglimit_override");
        leadlimit_override = cvar("leadlimit_override");
 
+       if(cvar("g_dodging"))
+               MUTATOR_ADD(dodging);
+       
        if(g_dm)
        {
                game = GAME_DEATHMATCH;
@@ -622,7 +625,11 @@ void CheckAllowedTeams (entity for_whom)
        c1 = c2 = c3 = c4 = -1;
        cb1 = cb2 = cb3 = cb4 = 0;
 
-       if(g_onslaught)
+       if(cvar("g_campaign") && for_whom && clienttype(for_whom) == CLIENTTYPE_REAL)
+       {
+               c1 = 0; // only allow RED team for player joining
+       }
+       else if(g_onslaught)
        {
                // onslaught is special
                head = findchain(classname, "onslaught_generator");
@@ -797,7 +804,9 @@ float FindSmallestTeam(entity pl, float ignore_pl)
 
        if(totalteams <= 1)
        {
-               if(g_domination)
+               if(cvar("g_campaign") && pl && clienttype(pl) == CLIENTTYPE_REAL)
+                       return 1; // special case for campaign and player joining
+               else if(g_domination)
                        error("Too few teams available for domination\n");
                else if(g_ctf)
                        error("Too few teams available for ctf\n");
@@ -844,9 +853,9 @@ float FindSmallestTeam(entity pl, float ignore_pl)
        {
                // 1: use team count, if equal prefer own team
                if(c1 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM1) / 512.0);
-               if(c2 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM2) / 512.0);
-               if(c3 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM3) / 512.0);
-               if(c4 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM4) / 512.0);
+               if(c2 >= 0) RandomSelection_Add(world, 2, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM2) / 512.0);
+               if(c3 >= 0) RandomSelection_Add(world, 3, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM3) / 512.0);
+               if(c4 >= 0) RandomSelection_Add(world, 4, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM4) / 512.0);
        }
        else if(balance_type == 3)
        {
index 25cba99..fa07f86 100644 (file)
@@ -28,6 +28,7 @@ vector real_origin(entity ent);
 .string cvar_basename;
 
 //.float spawnflags
+#define TSF_SUSPENDED     1
 /// Spawn a pillar model under the turret to make it look ok on uneven ground surfaces
 #define TSF_TERRAINBASE   2
 /// Disable builtin ammo regeneration
index 6ee0849..afddaef 100644 (file)
@@ -567,7 +567,8 @@ float turret_validate_target(entity e_turret,entity e_target,float validate_flag
     if (validate_flags & TFL_TARGETSELECT_LOS)
     {
         v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5);
-        traceline(e_turret.tur_shotorg,v_tmp,0,e_turret);
+
+        traceline(e_turret.tur_shotorg, v_tmp, 0, e_turret);
 
         if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos))
             return -19;
@@ -926,8 +927,8 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
         v = gettaginfo(e,gettagindex(e,"tag_fire"));
         if(v == '0 0 0')
         {
-            objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway.");
-            crash();
+            //objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway.");
+            //crash();
         }
         setmodel(e,"");
 
@@ -942,6 +943,9 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
         csqc_shared = 0;
     }
 
+    if not (self.spawnflags & TSF_SUSPENDED)
+        droptofloor_builtin();
+
     // Terrainbase spawnflag. This puts a enlongated model
     // under the turret, so it looks ok on uneaven surfaces.
     if (self.spawnflags & TSF_TERRAINBASE)
index 3f7acda..3d84386 100644 (file)
@@ -171,6 +171,13 @@ void ewheel_postthink()
     float vz;
     vector wish_angle,real_angle;
 
+    /*
+    if(self.enemy)
+        dprint("enemy!\n");
+    else
+        dprint("nothign =(!\n");
+    */
+
     vz = self.velocity_z;
 
     self.angles_x = anglemods(self.angles_x);
@@ -190,7 +197,8 @@ void ewheel_postthink()
     self.angles_y = (self.angles_y + real_angle_y);
 
     // Simulate banking
-    self.angles_z = bound(-45,real_angle_y * -2.5,45);
+    self.angles_z -= self.angles_z * frametime * 2;
+    self.angles_z = bound(-45,self.angles_z  + ((real_angle_y * -25) * frametime),45);
 
     if(self.enemy)
         ewheel_move_enemy();
@@ -207,7 +215,10 @@ void ewheel_respawnhook()
 {
     entity e;
 
-    setorigin(self,self.pos1);
+    self.velocity = '0 0 0';
+    self.enemy = world;
+
+    setorigin(self, self.pos1);
 
     if (self.target != "")
     {
@@ -230,23 +241,14 @@ void ewheel_respawnhook()
 
 void ewheel_diehook()
 {
-    turret_trowgib2(self.origin,self.velocity + '0 0 400', '-0.6 -0.2 -02', self, 3 + time + random() * 2);
-
     self.velocity = '0 0 0';
 
+    turret_trowgib2(self.origin, self.velocity + '0 0 400', '-0.6 -0.2 -02', self, 3 + time + random() * 2);
+
     if (self.pathcurrent)
         pathlib_deletepath(self.pathcurrent.owner);
 
     self.pathcurrent = world;
-
-    /*
-    if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
-    {
-        verbstack_flush(self.verbs_move);
-        remove(self.verbs_move);
-    }
-    */
-
 }
 
 void turret_ewheel_dinit()
@@ -291,12 +293,11 @@ void turret_ewheel_dinit()
     self.solid      = SOLID_SLIDEBOX;
     self.takedamage = DAMAGE_AIM;
 
-    setsize(self,'-32 -32 0', '32 32 48');
+    setsize(self, '-32 -32 0', '32 32 48');
+    self.idle_aim = '0 0 0';
 
     self.pos1 = self.origin;
 
-    self.idle_aim = '0 0 0';
-
     // Our fire routine
     self.turret_firefunc  = ewheel_attack;
     self.turret_postthink = ewheel_postthink;
@@ -306,6 +307,10 @@ void turret_ewheel_dinit()
     self.tur_head.aim_speed = cvar("g_turrets_unit_ewheel_turnrate");
     self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
 
+    if (!turret_tag_setup())
+        dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+    //setorigin(self,self.origin + '0 0 128');
     if (self.target != "")
     {
         e = find(world,targetname,self.target);
@@ -319,7 +324,7 @@ void turret_ewheel_dinit()
             dprint("Warning: not a turrret path\n");
         else
         {
-            self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+            self.pathcurrent = WALKER_PATH(self.origin, e.origin);
             self.pathgoal = e;
         }
     }
@@ -332,6 +337,10 @@ void spawnfunc_turret_ewheel()
     precache_model ("models/turrets/ewheel-base2.md3");
     precache_model ("models/turrets/ewheel-gun1.md3");
 
+    precache_model ("models/pathlib/goodsquare.md3");
+    precache_model ("models/pathlib/badsquare.md3");
+    precache_model ("models/pathlib/square.md3");
+
     turret_ewheel_loadcvars();
 
     self.think = turret_ewheel_dinit;
index 14dd163..e1341b4 100644 (file)
@@ -718,6 +718,9 @@ void turret_walker_dinit()
         return;
     }
 
+    if (!turret_tag_setup())
+        dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
     self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
     self.target_select_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
index 3e36dc8..b929c42 100644 (file)
@@ -22,6 +22,8 @@ float racer_turnroll;
 float racer_speed_forward;
 float racer_speed_strafe;
 
+float racer_afterburn_cost;
+
 float  jetfromtag_power;
 float  jetfromtag_normpower;
 vector jetfromtag_origin;
@@ -41,6 +43,8 @@ void racer_loadsettings()
     racer_speed_forward     = cvar("g_vehicle_racer_speed_forward");
     racer_speed_strafe      = cvar("g_vehicle_racer_speed_strafe");
 
+    racer_afterburn_cost    = cvar("g_vehicle_racer_afterburn_cost");
+
     racer_healthmax = cvar("g_vehicle_racer_health");
     racer_shieldmax = cvar("g_vehicle_racer_shield");
     racer_energymax = cvar("g_vehicle_racer_energy");
@@ -203,7 +207,6 @@ void racer_fire_cannon(string tagname)
        // FIXME this uses prydon cursor
     v = normalize(self.owner.cursor_trace_endpos - bolt.origin);
     v_forward_z = v_z * 0.5;
-    //v_forward_z *= 0.5;
 
     bolt.velocity = v_forward * cvar("g_vehicle_racer_laser_speed");
 
@@ -355,7 +358,6 @@ float racer_pplug()
     float ftmp, ftmp2;
     vector df;
 
-
     if(cvar("g_vehicle_racer_reload"))
     {
         racer_loadsettings();
@@ -395,13 +397,13 @@ float racer_pplug()
     ftmp = racer_turnspeed * sys_frametime;
     ftmp2 = ftmp * -1;
 
-    ftmp = bound(ftmp2,shortangle_f(player.v_angle_y - racer.angles_y,racer.angles_y),ftmp);
+    ftmp = bound(ftmp2, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
     ftmp2 = safeangle(racer.angles_y + ftmp);
 
     // Roll
-    ftmp = bound(-45,shortangle_f(player.v_angle_z + ((racer.angles_y - ftmp2) * racer_turnroll), racer.angles_z),45);
+    ftmp = bound(-45, shortangle_f(player.v_angle_z + ((racer.angles_y - ftmp2) * racer_turnroll), racer.angles_z), 45);
     ftmp = safeangle(racer.angles_z + ftmp);
-    racer.angles_z = bound(-85,ftmp,85);
+    racer.angles_z = bound(-85, ftmp, 85);
 
     // Turn
     racer.angles_y = ftmp2;
@@ -414,7 +416,7 @@ float racer_pplug()
     racer.angles_x = safeangle(racer.angles_x + ftmp);
     racer.angles_x *= -1;
 
-    df = racer.velocity * -1;
+    df = racer.velocity * -0.5;
 
     if(player.movement_x != 0)
     {
@@ -438,12 +440,11 @@ float racer_pplug()
 
 
     // Afterburn
-    //if (jetfromtag_groundcontact)
     if (player.BUTTON_JUMP)
-    if(racer.vehicle_energy >= (cvar("g_vehicle_racer_speed_afterburn_cost") * frametime))
+    if(racer.vehicle_energy >= (racer_afterburn_cost * frametime))
     {
         racer.wait = time + cvar("g_vehicle_racer_energy_usepause");
-        racer.vehicle_energy -= cvar("g_vehicle_racer_speed_afterburn_cost") * frametime;
+        racer.vehicle_energy -= racer_afterburn_cost * frametime;
         df += (v_forward * cvar("g_vehicle_racer_speed_afterburn"));
     }
 
@@ -494,8 +495,6 @@ float racer_pplug()
     }
 
     player.vehicle_reload1 = (time - racer.lip) / (racer.delay-racer.lip);
-    //player.vehicle_energy = racer.vehicle_energy;
-
     vehicle_stdproc_shiledregen(racer_shieldmax, frametime);
     vehicle_stdproc_healthregen(racer_healthmax, frametime);
 
@@ -715,16 +714,6 @@ void racer_touch()
     racer_enter();
 }
 
-/*
-float racer_customizeentityforclient()
-{
-    if(self.deadflag == DEAD_DEAD)
-        return FALSE;
-
-    return TRUE;
-}
-*/
-
 void racer_spawn()
 {
     self.think = racer_spawnthink;
diff --git a/qcsrc/server/vehicles/raptor.qc b/qcsrc/server/vehicles/raptor.qc
new file mode 100644 (file)
index 0000000..d7f4de6
--- /dev/null
@@ -0,0 +1,892 @@
+#define RAPTOR_MIN '-40 -40 0'
+#define RAPTOR_MAX '40 40 40'
+
+float raptor_movestyle;
+float raptor_turnspeed;
+float raptor_turnroll;
+float raptor_pitchspeed;
+float raptor_speed_forward;
+float raptor_speed_strafe;
+float raptor_speed_up;
+float raptor_speed_down;
+
+float raptor_bomblet_waves;
+float raptor_bomblet_wavefirst;
+float raptor_bomblet_wavenext;
+float raptor_bomblet_wawespread;
+float raptor_bomblets;
+float raptor_bomblet_damage;
+float raptor_bomblet_edgedamage;
+float raptor_bomblet_radius;
+float raptor_bomblet_force;
+float raptor_bombs_refire;
+
+float raptor_beam_dps;
+float raptor_beam_fops;
+float raptor_beam_aps;
+float raptor_beam_size;
+float raptor_beam_leangth;
+float raptor_beam_refire;
+
+float raptor_shield_max;
+float raptor_shield_regen;
+
+float raptor_health_max;
+float raptor_health_regen;
+
+float raptor_energy_max;
+float raptor_energy_regen;
+
+void raptor_spawn();
+void raptor_return();
+float raptor_pplug();
+float raptor_takeoff();
+float raptor_land();
+
+.entity bomb1;
+.entity bomb2;
+
+float raptor_altitude(float amax)
+{
+       tracebox(self.origin, self.mins, self.maxs, '0 0 -1' * amax, TRUE, self);
+       if(trace_fraction == 1)
+        return amax+1;
+    else
+        return vlen(self.origin - trace_endpos);
+}
+
+void raptor_loadsettings()
+{
+    raptor_movestyle     = CCVAR("_movestyle");
+    raptor_turnspeed     = CCVAR("_turnspeed");
+    raptor_turnroll      = CCVAR("_turnroll");
+    raptor_pitchspeed    = CCVAR("_pitchspeed");
+    raptor_speed_forward = CCVAR("_speed_forward");
+    raptor_speed_strafe  = CCVAR("_speed_strafe");
+    raptor_speed_up      = CCVAR("_speed_up");
+    raptor_speed_down    = CCVAR("_speed_down");
+
+    raptor_bomblet_waves      = CCVAR("_bomblet_waves ");
+    raptor_bomblet_wavefirst  = CCVAR("_bomblet_wavefirst");
+    raptor_bomblet_wavenext   = CCVAR("_bomblet_wavenext");
+    raptor_bomblet_wawespread = CCVAR("_bomblet_wawespread");
+    raptor_bomblets           = CCVAR("_bomblets");
+    raptor_bomblet_damage     = CCVAR("_bomblet_damage");
+    raptor_bomblet_edgedamage = CCVAR("_bomblet_edgedamage");
+    raptor_bomblet_radius     = CCVAR("_bomblet_radius");
+    raptor_bomblet_force      = CCVAR("_bomblet_force ");
+    raptor_bombs_refire       = CCVAR("_bombs_refire");
+
+    raptor_beam_dps     = CCVAR("_beam_dps");
+    raptor_beam_fops    = CCVAR("_beam_fops");
+    raptor_beam_aps     = CCVAR("_beam_aps");
+    raptor_beam_size    = CCVAR("_beam_size");
+    raptor_beam_leangth = CCVAR("_beam_length");
+    raptor_beam_refire  = CCVAR("_beam_refire");
+
+    raptor_shield_max    = CCVAR("_shield_max");
+    raptor_shield_regen  = CCVAR("_shield_regen");
+
+    raptor_health_max    = CCVAR("_health_max");
+    raptor_health_regen  = CCVAR("_health_regen");
+
+    raptor_energy_max    = CCVAR("_energy_max");
+    raptor_energy_regen  = CCVAR("_energy_regen");
+}
+
+void raptor_bombs_return()
+{
+    self.owner.bomb1.alpha = 1;
+    self.owner.bomb2.alpha = 1;
+    remove(self);
+}
+
+void raptor_bomblet_boom()
+{
+    if(other.enemy == self.enemy)
+        return;
+
+    pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+    RadiusDamage (self, self.enemy, raptor_bomblet_damage, raptor_bomblet_edgedamage, raptor_bomblet_radius, world, raptor_bomblet_force, DEATH_SBROCKET, world);
+    remove(self);
+}
+
+void raptor_bomb_burst()
+{
+    self.angles = vectoangles(self.velocity);
+
+    if(self.cnt < time)
+    {
+        entity bomblet;
+        float i,v;
+        vector d;
+
+        makevectors(self.angles);
+        v = vlen(self.velocity) + random();
+        d = normalize(self.velocity);
+        pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+        for(i = 0; i < raptor_bomblets; ++i)
+        {
+
+            bomblet = spawn();
+            setorigin(bomblet,self.origin);
+
+            setmodel(bomblet,"models/vehicles/raptor_bomb.dpm");
+            bomblet.scale = 0.5;
+
+            bomblet.owner = self.owner;
+            bomblet.enemy = self.enemy;
+
+            bomblet.solid = SOLID_TRIGGER;
+            bomblet.movetype    = MOVETYPE_BOUNCE;
+            bomblet.touch = raptor_bomblet_boom;
+
+            bomblet.think = raptor_bomblet_boom;
+            bomblet.nextthink = time + 5;
+
+            //bomblet.modelflags = MF_ROCKET;
+            bomblet.modelflags = MF_GRENADE;
+
+            bomblet.velocity =  normalize(d + randomvec() * raptor_bomblet_wawespread) * v;
+
+            bomblet.angles = vectoangles(bomblet.velocity);
+        }
+
+        self.wait -= 1;
+        if(self.wait <= 0)
+        {
+            remove(self);
+            return;
+        }
+
+        self.cnt = time + raptor_bomblet_wavenext;
+    }
+
+    self.nextthink = time;
+}
+
+void raptor_bomb_touch()
+{
+    raptor_bomb_burst();
+}
+
+void raptor_bombdrop()
+{
+    entity bomb_1, bomb_2;
+
+    self.bomb1.alpha = 0.25;
+    self.bomb2.alpha = 0.25;
+
+    bomb_1 = spawn();
+    bomb_2 = spawn();
+
+    setmodel(bomb_1,"models/vehicles/raptor_bomb.dpm");
+    setmodel(bomb_2,"models/vehicles/raptor_bomb.dpm");
+
+    setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
+    setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
+
+    bomb_1.movetype  = bomb_2.movetype    = MOVETYPE_TOSS;
+    bomb_1.velocity  = bomb_2.velocity    = self.velocity;
+    bomb_1.touch     = bomb_2.touch       = raptor_bomb_touch;
+    bomb_1.think     = bomb_2.think       = raptor_bomb_burst;
+    bomb_1.nextthink = bomb_2.nextthink   = time;
+    bomb_1.cnt       = bomb_2.cnt         = time + raptor_bomblet_wavefirst;
+    bomb_1.wait       = bomb_2.wait       = raptor_bomblet_waves;
+
+    bomb_1.avelocity = bomb_2.avelocity   = '0 0 180';
+    bomb_1.owner     = bomb_2.owner       = self;
+    bomb_1.enemy     = bomb_2.enemy       = self.owner;
+    bomb_1.angles    = bomb_2.angles      = self.angles;
+    bomb_1.solid     = bomb_2.solid      = SOLID_BBOX;
+
+    bomb_1 = spawn();
+    bomb_1.owner = self;
+    bomb_1.think = raptor_bombs_return;
+    bomb_1.nextthink = time + raptor_bombs_refire;
+}
+
+void raptor_animator_think()
+{
+    self.owner.frame += 1;
+    if(self.owner.frame == self.cnt)
+        remove(self);
+    else
+        self.nextthink = time + self.wait;
+}
+
+void raptor_setanim(float start, float end, float length)
+{
+    entity ani;
+    if(self.tur_head.enemy)
+        ani = self.tur_head.enemy;
+    else
+        ani = spawn();
+
+    self.tur_head.enemy = ani;
+    ani.owner = self;
+    self.frame = start;
+    ani.cnt = end;
+    ani.wait = sys_frametime / length;
+    ani.think = raptor_animator_think;
+    ani.nextthink = time + ani.wait;
+}
+
+void raptor_beam (vector start, vector end, vector smin, vector smax, float bforce, float f_dmg, float deathtype)
+
+{
+    vector hitloc, force, endpoint, dir;
+    entity ent;
+
+    dir = normalize(end - start);
+    force = dir * bforce;
+
+    // go a little bit into the wall because we need to hit this wall later
+    end = end + dir;
+
+    // trace multiple times until we hit a wall, each obstacle will be made unsolid.
+    // note down which entities were hit so we can damage them later
+    while (1)
+    {
+        tracebox(start, smin, smax, end, FALSE, world);
+
+        // if it is world we can't hurt it so stop now
+        if (trace_ent == world || trace_fraction == 1)
+            break;
+
+        if (trace_ent.solid == SOLID_BSP)
+            break;
+
+        // make the entity non-solid so we can hit the next one
+        trace_ent.railgunhit = TRUE;
+        trace_ent.railgunhitloc = end;
+        trace_ent.railgunhitsolidbackup = trace_ent.solid;
+
+        // make the entity non-solid
+        trace_ent.solid = SOLID_NOT;
+    }
+
+    endpoint = trace_endpos;
+
+    // find all the entities the railgun hit and hurt them
+    ent = findchainfloat(railgunhit, TRUE);
+    while (ent)
+    {
+        // get the details we need to call the damage function
+        ent.solid = ent.railgunhitsolidbackup;
+        hitloc = ent.railgunhitloc;
+        ent.railgunhitloc = '0 0 0';
+        ent.railgunhitsolidbackup = SOLID_NOT;
+        ent.railgunhit = FALSE;
+
+        // apply the damage
+        if (ent.takedamage)
+            Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
+
+        ent = ent.chain;
+    }
+    trace_endpos = endpoint;
+}
+
+
+void raptor_enter()
+{
+    // Remove this when bots know how to use vehicles
+    if (clienttype(other) != CLIENTTYPE_REAL)
+        return;
+
+    if(teamplay)
+        if(self.team)
+            if(self.team != other.team)
+                return;
+
+    self.owner = other;
+    self.switchweapon = other.switchweapon;
+
+    self.event_damage          = vehicle_stdproc_damage;
+    self.colormap              = self.owner.colormap;
+    self.vehicle_hudmodel.viewmodelforclient = self.owner;
+    self.nextthink             = 0;
+    self.owner.angles          = self.angles;
+    self.owner.takedamage      = DAMAGE_NO;
+    self.owner.solid           = SOLID_NOT;
+    self.owner.movetype        = MOVETYPE_NOCLIP;
+    self.owner.alpha           = -1;
+    self.owner.PlayerPhysplug  = raptor_takeoff;
+    self.owner.vehicle         = self;
+    self.owner.event_damage    = SUB_Null;
+    self.owner.hud             = HUD_RAPTOR;
+    self.owner.vehicle_health  = self.vehicle_health / raptor_health_max;
+    self.owner.vehicle_shield  = self.vehicle_shield / raptor_shield_max;
+    self.owner.view_ofs        = '0 0 1';
+    self.owner.vehicle_ammo1   = self.vehicle_ammo1;
+    self.owner.vehicle_ammo2   = self.vehicle_ammo2;
+    self.owner.vehicle_reload1 = self.vehicle_reload1;
+    self.owner.vehicle_reload2 = self.vehicle_reload2;
+
+    other.flags &~= FL_ONGROUND;
+    self.flags &~= FL_ONGROUND;
+
+    self.frame = 0;
+    raptor_setanim(0, 25, 1);
+
+    self.team                 = self.owner.team;
+    self.flags               -= FL_NOTARGET;
+
+    self.velocity = '0 0 1';
+
+    setorigin(other,self.origin + '0 0 32');
+    other.velocity = self.velocity;
+
+    other.flags &~= FL_ONGROUND;
+    msg_entity = other;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.vehicle_viewport);
+
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);     // 10 = SVC_SETVIEWANGLES
+    WriteAngle(MSG_ONE,  self.angles_x * -1);   // tilt
+    WriteAngle(MSG_ONE,  self.angles_y);        // yaw
+    WriteAngle(MSG_ONE,  0);                    // roll
+}
+
+void raptor_exit(float eject)
+{
+       self.colormap   = 1024;
+       self.flags      = FL_NOTARGET;
+
+    if not (self.owner)
+        return;
+
+    msg_entity = self.owner;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.owner);
+
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);    // 10 = SVC_SETVIEWANGLES
+    WriteAngle(MSG_ONE,  0);                   // tilt
+    WriteAngle(MSG_ONE,  self.angles_y); // yaw
+    WriteAngle(MSG_ONE,  0);                   // roll
+
+    if (self.deadflag == DEAD_NO)
+    {
+        //self.think = racer_exitthink;
+        self.nextthink = time;
+    }
+
+    self.owner.takedamage     = DAMAGE_AIM;
+    self.owner.solid          = SOLID_SLIDEBOX;
+    self.owner.movetype       = MOVETYPE_WALK;
+
+    setsize(self.owner,PL_MIN,PL_MAX);
+
+    self.owner.effects        &~= EF_NODRAW;
+    self.owner.alpha          = 1;
+    self.owner.PlayerPhysplug = SUB_Null;
+    self.owner.vehicle        = world;
+       self.owner.view_ofs       = PL_VIEW_OFS;
+       self.owner.event_damage   = PlayerDamage;
+       self.owner.hud            = HUD_NORMAL;
+       //self.exteriormodeltoclient = self;
+
+    self.vehicle_hudmodel.viewmodelforclient = self;
+
+       if(eject)
+       {
+           makevectors(self.angles);
+           setorigin(self.owner,self.origin + v_forward * 100);
+           self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+       }
+       else
+       {
+           self.owner.velocity = (v_forward) * -150;
+        setorigin(self.owner,self.origin - v_forward * 128);
+       }
+
+    self.owner = world;
+
+    if (self.deadflag != DEAD_NO)
+    {
+        entity ret;
+        ret = spawn();
+        ret.enemy = self;
+        ret.think = raptor_return;
+        ret.nextthink = time + cvar("g_vehicle_racer_respawntime");
+    }
+}
+
+
+float raptor_pplug()
+{
+    entity player, vhic;
+    float ftmp, ftmp2, energy_used;
+    vector df;
+
+
+    if(cvar("g_vehicle_raptor_reload"))
+    {
+        raptor_loadsettings();
+        cvar_set("g_vehicle_raptor_reload","0");
+    }
+
+    player = self;
+    vhic   = self.vehicle;
+    self    = vhic;
+
+    if(player.BUTTON_USE)
+    {
+        self = vhic;
+        raptor_exit(0);
+        self = player;
+        return 0;
+    }
+
+    if(vhic.deadflag != DEAD_NO)
+    {
+        self = player;
+        player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+        return 1;
+    }
+
+    vhic.angles_x *= -1;
+    // Rotate Body
+    ftmp = raptor_turnspeed * sys_frametime;
+
+    ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - vhic.angles_y, vhic.angles_y), ftmp);
+
+    // Roll
+    //ftmp = bound(-90,shortangle_f(player.v_angle_z + ((vhic.angles_y - ftmp2) * raptor_turnroll), vhic.angles_z),90);
+    //ftmp = safeangle(vhic.angles_z + ftmp);
+    //vhic.angles_z = ftmp;
+
+    // Turn
+    vhic.angles_y = safeangle(vhic.angles_y + ftmp);
+
+    // Pitch Body
+    ftmp = raptor_pitchspeed  * sys_frametime;
+
+    ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - vhic.angles_x,vhic.angles_x), ftmp);
+
+    vhic.angles_x = bound(-60,safeangle(vhic.angles_x + ftmp),60);
+    vhic.angles_x *= -1;
+
+    if(raptor_movestyle == 1)
+    {
+        ftmp = vhic.angles_z;
+        vhic.angles_z = 0;
+        ftmp2 = vhic.angles_x;
+        vhic.angles_x = 0;
+        fixedmakevectors(vhic.angles);
+        vhic.angles_z = ftmp;
+        vhic.angles_x = ftmp2;
+    }
+    else
+        fixedmakevectors(vhic.angles);
+
+    df = vhic.velocity * -1;
+
+    if(player.movement_x != 0)
+    {
+        if(player.movement_x > 0)
+            df += v_forward  * raptor_speed_forward;
+        else if(player.movement_x < 0)
+            df -= v_forward  * raptor_speed_forward;
+    }
+
+    if(player.movement_y != 0)
+    {
+        if(player.movement_y < 0)
+            df -= v_right * raptor_speed_strafe;
+        else if(player.movement_y > 0)
+            df += v_right * raptor_speed_strafe;
+
+        vhic.angles_z = bound(-30,vhic.angles_z + (player.movement_y / raptor_speed_strafe),30);
+    }
+    else
+    {
+        vhic.angles_z *= 0.95;
+        if(vhic.angles_z >= -1 && vhic.angles_z <= -1)
+            vhic.angles_z = 0;
+    }
+
+    if(player.BUTTON_CROUCH)
+        df -=   v_up * raptor_speed_down;
+    else if (player.BUTTON_JUMP)
+        df +=  v_up * raptor_speed_up;
+    //else
+        //df_z = vhic.velocity_z * -1;
+
+    vhic.velocity  += df * frametime;
+    player.velocity = player.movement  = vhic.velocity;
+    setorigin(player,vhic.origin + '0 0 32');
+
+    // Aim the gunz
+    vector target_angle, move_angle, org1, org2, targ;
+
+    makevectors(player.v_angle);
+
+    //targ = (vhic.origin + player.view_ofs) + v_forward * MAX_SHOT_DISTANCE;
+    targ = player.cursor_trace_endpos;
+
+    org1 = gettaginfo(vhic.gun1,gettagindex(vhic.gun1, "fire1"));
+    org2 = gettaginfo(vhic.gun2,gettagindex(vhic.gun2, "fire1"));
+
+    traceline(vhic.origin + player.view_ofs, targ, FALSE, vhic);
+    targ = trace_endpos;
+
+    // Find the direction
+    target_angle = vectoangles(normalize(targ - org1)); // And make a angle
+
+    // Find the diffrence between where we currently aim and where we want to aim
+    move_angle = target_angle - (vhic.angles + vhic.gun1.angles);
+    move_angle = shortangle_vxy(move_angle,(vhic.angles + vhic.gun1.angles));
+    vhic.gun1.angles_x = bound(-10, move_angle_x + vhic.gun1.angles_x, 10);
+    vhic.gun1.angles_y = bound(-15, move_angle_y + vhic.gun1.angles_y, 15);
+
+    // Find the direction
+    target_angle = vectoangles(normalize(targ - org2)); // And make a angle
+
+    move_angle = target_angle - (vhic.angles + vhic.gun2.angles);
+    move_angle = shortangle_vxy(move_angle,(vhic.angles + vhic.gun2.angles));
+    vhic.gun2.angles_x = bound(-15,move_angle_x + vhic.gun2.angles_x,15);
+    vhic.gun2.angles_y = bound(-20,move_angle_y + vhic.gun2.angles_y,20);
+
+    if(player.BUTTON_ATCK)
+    if(vhic.vehicle_energy > (raptor_beam_aps * sys_frametime))
+    {
+        vector start;
+        self = player;
+
+        start = gettaginfo(vhic.gun1, gettagindex(vhic.gun1, "fire1"));
+        traceline(start, start + v_forward * MAX_SHOT_DISTANCE, TRUE, player);
+        te_lightning1(vhic.gun1, start, trace_endpos);
+        raptor_beam(start, trace_endpos, '-1 -1 -1' * raptor_beam_size, '1 1 1' * raptor_beam_size, raptor_beam_fops * sys_frametime, raptor_beam_dps * sys_frametime, DEATH_SBROCKET);
+
+
+        start = gettaginfo(vhic.gun2, gettagindex(vhic.gun2, "fire1"));
+        traceline(start, start + v_forward * MAX_SHOT_DISTANCE, TRUE, player);
+        te_lightning1(vhic.gun2, start, trace_endpos);
+        raptor_beam(start, trace_endpos, '-1 -1 -1' * raptor_beam_size, '1 1 1' * raptor_beam_size, raptor_beam_fops * sys_frametime, raptor_beam_dps * sys_frametime, DEATH_SBROCKET);
+
+        self = vhic;
+
+        vhic.vehicle_energy -= raptor_beam_aps * sys_frametime;
+        vhic.cnt = time + 1;
+    }
+
+    if(vhic.cnt < time)
+        vhic.vehicle_energy = min(vhic.vehicle_energy += raptor_energy_regen * frametime, raptor_energy_max);
+
+    player.vehicle_energy = vhic.vehicle_energy / raptor_energy_max;
+
+
+    if(player.BUTTON_ATCK2)
+    if(time > vhic.delay)
+    {
+        raptor_bombdrop();
+        vhic.delay = time + raptor_bombs_refire;
+    }
+
+    player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+    vehicle_stdproc_shiledregen(raptor_shield_max, frametime);
+    vehicle_stdproc_healthregen(raptor_health_max, frametime);
+
+    self = player;
+
+    return 1;
+}
+
+float raptor_takeoff()
+{
+    entity player, vhic;
+
+    if(self.vehicle.frame < 25)
+        return 1;
+
+    player = self;
+    vhic   = self.vehicle;
+    self    = vhic;
+
+    if(raptor_altitude(512) <= 256)
+    {
+        vhic.velocity_z = min(vhic.velocity_z * 1.5, 256);
+    }
+    else
+    {
+        player.PlayerPhysplug = raptor_pplug;
+    }
+
+    player.BUTTON_CROUCH = player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+    self = player;
+
+    return 1;
+}
+
+float raptor_land()
+{
+    return 0;
+}
+
+void raptor_return()
+{
+    pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1);
+    self.enemy.think = raptor_spawn;
+    self.enemy.nextthink = time;
+    remove(self);
+}
+
+void raptor_think()
+{
+}
+
+void raptor_touch()
+{
+    if(self.owner)
+    {
+        if(vlen(self.velocity) == 0)
+            return;
+
+        if(other.classname != "player")
+            return;
+
+        return;
+    }
+
+    if(other.classname != "player")
+        return;
+
+    if(other.deadflag != DEAD_NO)
+        return;
+
+    if(other.vehicle != world)
+        return;
+
+    raptor_enter();
+}
+
+void raptor_die()
+{
+    self.health       = 0;
+    self.event_damage = SUB_Null;
+    self.iscreature   = FALSE;
+    self.solid        = SOLID_NOT;
+    self.takedamage   = DAMAGE_NO;
+    //self.touch        = racer_dietouch;
+    self.deadflag     = DEAD_DYING;
+    self.movetype     = MOVETYPE_BOUNCE;
+    self.wait = time;
+
+    pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
+
+    self.velocity     += '0 0 128';
+
+    if(random() < 0.5)
+        self.avelocity_z  = 45;
+    else
+        self.avelocity_z  = -45;
+
+    self.colormod = '-0.5 -0.5 -0.5';
+
+       self.think     = raptor_spawn;
+       self.nextthink = time + 5;
+}
+
+void raptor_spawn()
+{
+    self.flags     = FL_NOTARGET;
+    self.effects   = 0;
+
+    self.vehicle_health = raptor_health_max;
+    self.vehicle_shield = raptor_shield_max;
+
+    self.event_damage = vehicle_stdproc_damage;
+    self.touch      = raptor_touch;
+
+    self.iscreature = TRUE;
+    self.movetype   = MOVETYPE_FLY;
+    self.solid      = SOLID_SLIDEBOX;
+    self.takedamage = DAMAGE_AIM;
+
+    self.alpha = 1;
+       self.colormap = 1024;
+       self.deadflag    = DEAD_NO;
+    self.bot_attack = TRUE;
+
+    self.colormod = '1 1 1';
+    self.avelocity = '0 0 0';
+    self.velocity = '0 0 0';
+
+    self.vehicle_energy = 1;
+    self.vehicle_hudmodel.viewmodelforclient = self;
+
+    setorigin(self, self.pos1);
+    self.angles = self.pos2;
+
+    setsize(self,RAPTOR_MIN ,RAPTOR_MAX );
+    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
+    self.delay = time;
+}
+
+float raptor_customizeentityforclient()
+{
+    if(self.deadflag == DEAD_DEAD)
+        return FALSE;
+
+    /*
+    if(other == self.owner)
+        self.alpha = -1;
+    else
+        self.alpha = 1;
+    */
+
+    return TRUE;
+}
+
+void raptor_dinit()
+{
+
+    if (self.netname == "")
+        self.netname     = "Raptor";
+
+    setorigin(self, self.origin);
+
+    self.frame = 0;
+
+    setmodel(self,"models/vehicles/raptor.dpm");
+
+    self.bomb1 = spawn();
+    self.bomb2 = spawn();
+
+    setmodel(self.bomb1,"models/vehicles/raptor_bomb.dpm");
+    setmodel(self.bomb2,"models/vehicles/raptor_bomb.dpm");
+
+    setattachment(self.bomb1, self,"bombmount_left");
+    setattachment(self.bomb2, self,"bombmount_right");
+
+
+    if not (self.vehicle_hudmodel)
+    {
+        self.vehicle_hudmodel   = spawn();
+        setmodel(self.vehicle_hudmodel, "models/vehicles/raptor_cockpit.dpm");
+        //setattachment(self.vehicle_hudmodel, self, "tag_viewport");
+        setattachment(self.vehicle_hudmodel, self, "tag_hud");
+    }
+
+    if not (self.vehicle_viewport)
+    {
+        self.vehicle_viewport   = spawn();
+        setmodel (self.vehicle_viewport, "null");
+        setattachment(self.vehicle_viewport, self.vehicle_hudmodel, "tag_camera");
+    }
+
+    if not (self.gun1)
+    {
+        self.gun1   = spawn();
+        setmodel(self.gun1, "models/vehicles/raptor_gun.dpm");
+        setattachment(self.gun1, self, "gunmount_left");
+    }
+
+    if not (self.gun2)
+    {
+        self.gun2   = spawn();
+        setmodel(self.gun2, "models/vehicles/raptor_gun.dpm");
+        setattachment(self.gun2, self, "gunmount_right");
+    }
+
+    self.tur_head     = spawn();
+    self.pos1         = self.origin;
+    self.pos2         = self.angles;
+
+    self.vehicle_hudmodel.viewmodelforclient = self;
+    self.customizeentityforclient            = raptor_customizeentityforclient;
+
+    self.vehicle_die  = raptor_die;
+    self.vehicle_exit = raptor_exit;
+
+
+    entity spinner;
+    spinner = spawn();
+    spinner.owner = self;
+    setmodel(spinner,"models/vehicles/spinner.dpm");
+    setattachment(spinner, self, "engine_left");
+    spinner.movetype = MOVETYPE_NOCLIP;
+    spinner.avelocity = '0 90 0';
+
+    spinner = spawn();
+    spinner.owner = self;
+    setmodel(spinner,"models/vehicles/spinner.dpm");
+    setattachment(spinner, self, "engine_right");
+    spinner.movetype = MOVETYPE_NOCLIP;
+    spinner.avelocity = '0 -90 0';
+
+    addstat(STAT_HUD, AS_INT,  hud);
+       addstat(STAT_VEHICLESTAT_HEALTH,  AS_FLOAT, vehicle_health);
+       addstat(STAT_VEHICLESTAT_SHIELD,  AS_FLOAT, vehicle_shield);
+       addstat(STAT_VEHICLESTAT_ENERGY,  AS_FLOAT, vehicle_energy);
+
+       addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT,   vehicle_ammo1);
+       addstat(STAT_VEHICLESTAT_RELOAD1, AS_FLOAT, vehicle_reload1);
+
+       addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT,   vehicle_ammo2);
+       addstat(STAT_VEHICLESTAT_RELOAD2, AS_FLOAT, vehicle_reload2);
+
+    raptor_spawn();
+}
+
+void spawnfunc_vehicle_raptor2()
+{
+    self.cvar_basename      = "g_vehicle_raptor";
+    raptor_loadsettings();
+
+    self.vehicle_flags      = VHF_HASSHIELD | VHF_SHIELDREGEN;
+
+    traceline(self.origin, self.origin - '0 0 2048', MOVE_WORLDONLY, self);
+    if(trace_startsolid)
+    {
+        dprint("WARNING: vehicle_raptor placed in solid\n");
+        traceline(self.origin + '0 0 512' ,self.origin - '0 0 2048',MOVE_WORLDONLY,self);
+        if(trace_startsolid || trace_fraction == 1.0)
+        {
+            dprint("ERROR: vehicle_raptor placed in more then 512 units into solid\n");
+            remove(self);
+            return;
+        }
+    }
+
+    if(trace_fraction != 1.0)
+        setorigin(self,trace_endpos + '0 0 8');
+    else
+        dprint("WARNING: vehicle_racer placed more then 2048 units above ground.\n");
+
+    precache_model ("models/vehicles/raptor.dpm");
+    precache_model ("models/vehicles/raptor_gun.dpm");
+    precache_model ("models/vehicles/spinner.dpm");
+    precache_model ("models/vehicles/raptor_cockpit.dpm");
+    precache_model ("models/vehicles/raptor_bomb.dpm");
+
+
+    self.think = raptor_dinit;
+    self.nextthink = time + 1;
+}
+
+
+void spawnfunc_vehicle_raptor()
+{
+    entity iqm,dpm,md3;
+
+    precache_model ("models/vehicles/test.iqm");
+    precache_model ("models/vehicles/test.dpm");
+    precache_model ("models/vehicles/test.md3");
+
+    iqm = spawn();
+    dpm = spawn();
+    md3 = spawn();
+    iqm.scale = md3.scale = dpm.scale = 10;
+
+    //setmodel(iqm,"models/vehicles/test.iqm");
+    //setmodel(dpm,"models/vehicles/test.dpm");
+    setmodel(md3,"models/vehicles/test.md3");
+
+    setorigin(iqm, self.origin + '0 0 16');
+    setorigin(dpm, self.origin + '0 20 32');
+    setorigin(iqm, self.origin + '0 40 48');
+}
index 56caf6f..32049c8 100644 (file)
@@ -50,55 +50,43 @@ void spiderbot_rocket_touch()
     spiderbot_rocket_explode();
 }
 
-void spiderbot_rocket_guided()
+void spiderbot_rocket_unguided()
 {
     vector newdir,olddir;
 
     self.nextthink  = time;
-    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
-    {
-        spiderbot_rocket_explode();
-        return;
-    }
 
-    if not (self.owner.vehicle)
-    {
-        UpdateCSQCProjectile(self);
-        return;
-    }
 
     olddir = normalize(self.velocity);
-    crosshair_trace(self.owner);
-    newdir = normalize(trace_endpos - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
+    newdir = normalize(self.pos1 - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
     self.velocity = normalize(olddir + newdir * cvar("g_vehicle_spiderbot_rocket_turnrate")) * cvar("g_vehicle_spiderbot_rocket_speed");
 
     UpdateCSQCProjectile(self);
+
+    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+        spiderbot_rocket_explode();
+
 }
 
-void spiderbot_rocket_unguided()
+void spiderbot_rocket_guided()
 {
-    vector newdir,olddir;
+    vector newdir, olddir;
 
     self.nextthink  = time;
-    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
-    {
-        spiderbot_rocket_explode();
-        return;
-    }
 
     if not (self.owner.vehicle)
-    {
-        UpdateCSQCProjectile(self);
-        return;
-    }
+        self.think = spiderbot_rocket_unguided;
 
+    crosshair_trace(self.owner);
     olddir = normalize(self.velocity);
-    newdir = normalize(self.pos1 - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
+    newdir = normalize(trace_endpos - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
     self.velocity = normalize(olddir + newdir * cvar("g_vehicle_spiderbot_rocket_turnrate")) * cvar("g_vehicle_spiderbot_rocket_speed");
 
     UpdateCSQCProjectile(self);
-}
 
+    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+        spiderbot_rocket_explode();
+}
 
 void spiderbot_rocket_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
@@ -311,13 +299,6 @@ void spiderbot_miniguns_do()
         return;
     }
 }
-#define SBS_IDLE  0
-#define SBS_JUMP  1
-#define SBS_WALK  2
-#define SBS_BACK  3
-#define SBS_LEFT  4
-#define SBS_RIGHT 5
-.float state;
 
 float spiderbot_pplug()
 {
@@ -325,6 +306,10 @@ float spiderbot_pplug()
     entity player,spider;
     float ftmp;
 
+    if not (self.owner)
+    {
+    }
+
     player = self;
     spider = self.vehicle;
 
@@ -366,8 +351,9 @@ float spiderbot_pplug()
     self = spider;
     if(spider.flags & FL_ONGROUND)
     {
-        if(player.BUTTON_JUMP)
+        if(player.BUTTON_JUMP && self.tur_head.wait < time)
         {
+            self.tur_head.wait = time + 2;
             player.BUTTON_JUMP = 0;
             spider.velocity   = v_forward * 700 + v_up * 600;
             spider.frame = 4;
@@ -432,7 +418,6 @@ float spiderbot_pplug()
     else
         player.vehicle_reload2 = 1 - ((spider.gun2.cnt - time) / spider.attack_finished_single);
 
-    //setorigin(spider,spider.origin);
     setorigin(player,spider.origin + '0 0 64');
     player.velocity = spider.velocity;
 
@@ -444,10 +429,7 @@ float spiderbot_pplug()
 void spiderbot_think()
 {
     if(self.flags & FL_ONGROUND)
-    {
         movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
-        //movelib_groundalign4point(300,100);
-    }
 
     self.nextthink = time;
 }
@@ -648,6 +630,7 @@ void spiderbot_spawn()
 
     setsize(self,spiderbot_MIN,spiderbot_MAX);
 
+    self.owner = world;
     self.velocity = '0 0 0';
     self.vehicle_health = CCVAR("_health");
     self.vehicle_shield = CCVAR("_shield");
index ea2d440..192d83f 100644 (file)
@@ -36,8 +36,8 @@ float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80
 .entity vehicle_viewport;
 .entity vehicle_hudmodel;
 
-.float anim_start;
-.float anim_end;
+//.float anim_start;
+//.float anim_end;
 
 .float dmg_time;
 
@@ -51,7 +51,9 @@ var .void() vehicle_spawn;
 //var .float(float message) vehicle_message;
 
 #include "vehicles.qc"
+
 #include "spiderbot.qc"
 #include "racer.qc"
+#include "raptor.qc"
 
 #endif
index 39e2718..e831376 100644 (file)
@@ -239,84 +239,3 @@ float w_campingrifle(float req)
        return TRUE;
 };
 #endif
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Ç[\7f\90Kg|º^fÆ,9Þ@ª  w_deathtypestring = "sniped themself somehow";
-       }
-       else if (req == WR_KILLMESSAGE)
-       {
-               if(w_deathtype & HITTYPE_SECONDARY)
-               {
-                       if(w_deathtype & HITTYPE_BOUNCE)
-                               w_deathtypestring = "failed to hide from #'s bullet hail";
-                       else
-                               w_deathtypestring = "died in #'s bullet hail";
-               }
-               else
-               {
-                       if(w_deathtype & HITTYPE_BOUNCE)
-                       {
-                               // TODO special headshot message here too?
-                               w_deathtypestring = "failed to hide from #'s rifle";
-                       }
-                       else
-                       {
-                               if(w_deathtype & HITTYPE_HEADSHOT)
-                                       w_deathtypestring = "got hit in the head by #";
-                               else
-                                       w_deathtypestring = "was sniped by #";
-                       }
-               }
-       }
-       else if (req == WR_RELOAD)
-       {
-               W_CampingRifle_Reload();
-       }
-       else if (req == WR_RESETPLAYER)
-       {
-               self.campingrifle_accumulator = time - cvar("g_balance_campingrifle_bursttime");
-        &nbs