]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/mrbougo/killspree_bugfix'
authorJakob MG <jakob_mg@hotmail.com>
Thu, 23 Aug 2012 18:17:15 +0000 (20:17 +0200)
committerJakob MG <jakob_mg@hotmail.com>
Thu, 23 Aug 2012 18:17:15 +0000 (20:17 +0200)
256 files changed:
_hud_descriptions.cfg
balance25.cfg
balanceFruitieX.cfg
balanceXPM.cfg
balanceXonotic.cfg
commands.cfg
defaultXonotic.cfg
effectinfo.txt
effects-ultra.cfg
gfx/hud/default/key_atck.tga [new file with mode: 0644]
gfx/hud/default/key_atck2.tga [new file with mode: 0644]
gfx/hud/default/key_atck2_inv.tga [new file with mode: 0644]
gfx/hud/default/key_atck_inv.tga [new file with mode: 0644]
gfx/vehicles/axh-rings.tga [new file with mode: 0644]
gfx/vehicles/bumb.tga [new file with mode: 0644]
gfx/vehicles/bumb_lgun.tga [new file with mode: 0644]
gfx/vehicles/bumb_rgun.tga [new file with mode: 0644]
gfx/vehicles/bumb_side.tga [new file with mode: 0644]
gfx/vehicles/bumb_side_gun.tga [new file with mode: 0644]
gfx/vehicles/energy.tga [new file with mode: 0644]
gfx/vehicles/vth-mover.tga [new file with mode: 0644]
gfx/vehicles/vth-stationary.tga [new file with mode: 0644]
hud_luminos.cfg
hud_luminos_minimal.cfg
hud_luminos_minimal_xhair.cfg
hud_luminos_old.cfg
hud_nexuiz.cfg
models/items/a_bullets_simple.iqm [new file with mode: 0644]
models/items/a_bullets_simple.iqm_0.skin [new file with mode: 0644]
models/items/a_bullets_simple.tga [new file with mode: 0644]
models/items/a_cells_simple.iqm [new file with mode: 0644]
models/items/a_cells_simple.iqm_0.skin [new file with mode: 0644]
models/items/a_cells_simple.tga [new file with mode: 0644]
models/items/a_rockets_simple.iqm [new file with mode: 0644]
models/items/a_rockets_simple.iqm_0.skin [new file with mode: 0644]
models/items/a_rockets_simple.tga [new file with mode: 0644]
models/items/a_shells_simple.iqm [new file with mode: 0644]
models/items/a_shells_simple.iqm_0.skin [new file with mode: 0644]
models/items/a_shells_simple.tga [new file with mode: 0644]
models/items/g_h100_simple.iqm [new file with mode: 0644]
models/items/g_h100_simple.iqm_0.skin [new file with mode: 0644]
models/items/g_h100_simple.tga [new file with mode: 0644]
models/items/g_h1_simple.iqm [new file with mode: 0644]
models/items/g_h1_simple.iqm_0.skin [new file with mode: 0644]
models/items/g_h1_simple.tga [new file with mode: 0644]
models/items/g_h25_simple.iqm [new file with mode: 0644]
models/items/g_h25_simple.iqm_0.skin [new file with mode: 0644]
models/items/g_h25_simple.tga [new file with mode: 0644]
models/items/g_h50_simple.iqm [new file with mode: 0644]
models/items/g_h50_simple.iqm_0.skin [new file with mode: 0644]
models/items/g_h50_simple.tga [new file with mode: 0644]
models/items/g_invincible_simple.iqm [new file with mode: 0644]
models/items/g_invincible_simple.iqm_0.skin [new file with mode: 0644]
models/items/g_invincible_simple.tga [new file with mode: 0644]
models/items/g_strength_simple.iqm [new file with mode: 0644]
models/items/g_strength_simple.iqm_0.skin [new file with mode: 0644]
models/items/g_strength_simple.tga [new file with mode: 0644]
models/items/item_armor_big_simple.iqm [new file with mode: 0644]
models/items/item_armor_big_simple.iqm_0.skin [new file with mode: 0644]
models/items/item_armor_big_simple.tga [new file with mode: 0644]
models/items/item_armor_large_simple.iqm [new file with mode: 0644]
models/items/item_armor_large_simple.iqm_0.skin [new file with mode: 0644]
models/items/item_armor_large_simple.tga [new file with mode: 0644]
models/items/item_armor_medium_simple.iqm [new file with mode: 0644]
models/items/item_armor_medium_simple.iqm_0.skin [new file with mode: 0644]
models/items/item_armor_medium_simple.tga [new file with mode: 0644]
models/items/item_armor_small_simple.iqm [new file with mode: 0644]
models/items/item_armor_small_simple.iqm_0.skin [new file with mode: 0644]
models/items/item_armor_small_simple.tga [new file with mode: 0644]
models/vehicles/bumblebee_body.dpm
models/vehicles/bumblebee_plasma_left.dpm
models/vehicles/bumblebee_plasma_right.dpm
models/vehicles/bumblebee_ray.dpm
models/weapons/crylink_simple.tga [new file with mode: 0644]
models/weapons/g_crylink_simple.iqm [new file with mode: 0644]
models/weapons/g_crylink_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_crylink_simple.obj [new file with mode: 0644]
models/weapons/g_crylink_simple.tga [new file with mode: 0644]
models/weapons/g_electro_simple.iqm [new file with mode: 0644]
models/weapons/g_electro_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_electro_simple.tga [new file with mode: 0644]
models/weapons/g_gl_simple.iqm [new file with mode: 0644]
models/weapons/g_gl_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_gl_simple.tga [new file with mode: 0644]
models/weapons/g_hagar_simple.iqm [new file with mode: 0644]
models/weapons/g_hagar_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_hagar_simple.tga [new file with mode: 0644]
models/weapons/g_nex_simple.iqm [new file with mode: 0644]
models/weapons/g_nex_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_nex_simple.tga [new file with mode: 0644]
models/weapons/g_rl_simple.iqm [new file with mode: 0644]
models/weapons/g_rl_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_rl_simple.tga [new file with mode: 0644]
models/weapons/g_shotgun_simple.iqm [new file with mode: 0644]
models/weapons/g_shotgun_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_shotgun_simple.tga [new file with mode: 0644]
models/weapons/g_uzi_simple.iqm [new file with mode: 0644]
models/weapons/g_uzi_simple.iqm_0.skin [new file with mode: 0644]
models/weapons/g_uzi_simple.tga [new file with mode: 0644]
qcsrc/Makefile
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/autocvars.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/damage.qc
qcsrc/client/hud.qc
qcsrc/client/hud_config.qc
qcsrc/client/mapvoting.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/progs.src
qcsrc/client/projectile.qc
qcsrc/client/scoreboard.qc
qcsrc/client/tturrets.qc
qcsrc/client/vehicles/vehicles.qc
qcsrc/client/waypointsprites.qc
qcsrc/common/campaign_file.qc
qcsrc/common/command/generic.qc
qcsrc/common/command/markup.qc
qcsrc/common/command/rpn.qc
qcsrc/common/constants.qh
qcsrc/common/items.qc
qcsrc/common/items.qh
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/csqcmodellib/sv_model.qc
qcsrc/dpdefs/dpextensions.qc
qcsrc/fteqcc-bugs.qc [new file with mode: 0644]
qcsrc/menu/anim/animhost.c
qcsrc/menu/anim/keyframe.c
qcsrc/menu/draw.qc
qcsrc/menu/draw.qh
qcsrc/menu/item/borderimage.c
qcsrc/menu/item/container.c
qcsrc/menu/item/dialog.c
qcsrc/menu/item/inputbox.c
qcsrc/menu/item/inputcontainer.c
qcsrc/menu/item/label.c
qcsrc/menu/item/listbox.c
qcsrc/menu/item/modalcontroller.c
qcsrc/menu/item/nexposee.c
qcsrc/menu/menu.qc
qcsrc/menu/xonotic/colorbutton.c
qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c
qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c
qcsrc/menu/xonotic/dialog_settings_audio.c
qcsrc/menu/xonotic/languagelist.c
qcsrc/menu/xonotic/playermodel.c
qcsrc/menu/xonotic/serverlist.c
qcsrc/menu/xonotic/util.qc
qcsrc/server/antilag.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/bot.qc
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/bot/havocbot/role_ctf.qc
qcsrc/server/bot/havocbot/role_onslaught.qc
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/scripting.qc
qcsrc/server/campaign.qc
qcsrc/server/cheats.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/cl_weapons.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/command/banning.qh
qcsrc/server/command/cmd.qc
qcsrc/server/command/common.qc
qcsrc/server/command/getreplies.qc
qcsrc/server/command/radarmap.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/csqcprojectile.qc
qcsrc/server/defs.qh
qcsrc/server/domination.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_subs.qc
qcsrc/server/g_triggers.qc
qcsrc/server/g_world.qc
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mode_onslaught.qc [deleted file]
qcsrc/server/movelib.qc
qcsrc/server/mutators/base.qc
qcsrc/server/mutators/gamemode_freezetag.qc
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/gamemode_onslaught.qc [new file with mode: 0644]
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/mutators/mutator_superspec.qc [new file with mode: 0644]
qcsrc/server/mutators/mutators.qh
qcsrc/server/mutators/sandbox.qc
qcsrc/server/pathlib.qc
qcsrc/server/pathlib/expandnode.qc
qcsrc/server/pathlib/utility.qc
qcsrc/server/playerstats.qc
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/runematch.qc
qcsrc/server/scores.qc
qcsrc/server/steerlib.qc
qcsrc/server/sv_main.qc
qcsrc/server/t_items.qc
qcsrc/server/t_jumppads.qc
qcsrc/server/t_teleporters.qc
qcsrc/server/teamplay.qc
qcsrc/server/tturrets/system/system_main.qc
qcsrc/server/tturrets/system/system_misc.qc
qcsrc/server/tturrets/units/unit_ewheel.qc
qcsrc/server/tturrets/units/unit_flac.qc
qcsrc/server/tturrets/units/unit_hellion.qc
qcsrc/server/tturrets/units/unit_hk.qc
qcsrc/server/tturrets/units/unit_mlrs.qc
qcsrc/server/tturrets/units/unit_plasma.qc
qcsrc/server/tturrets/units/unit_tessla.qc
qcsrc/server/tturrets/units/unit_walker.qc
qcsrc/server/vehicles/bumblebee.qc [new file with mode: 0644]
qcsrc/server/vehicles/racer.qc
qcsrc/server/vehicles/raptor.qc
qcsrc/server/vehicles/spiderbot.qc
qcsrc/server/vehicles/vehicles.qc
qcsrc/server/vehicles/vehicles.qh
qcsrc/server/vehicles/vehicles_def.qh
qcsrc/server/w_common.qc
qcsrc/server/w_crylink.qc
qcsrc/server/w_electro.qc
qcsrc/server/w_fireball.qc
qcsrc/server/w_grenadelauncher.qc
qcsrc/server/w_hagar.qc
qcsrc/server/w_hlac.qc
qcsrc/server/w_hook.qc
qcsrc/server/w_laser.qc
qcsrc/server/w_minelayer.qc
qcsrc/server/w_porto.qc
qcsrc/server/w_rocketlauncher.qc
qcsrc/server/w_seeker.qc
qcsrc/server/w_tuba.qc
qcsrc/warpzonelib/common.qc
qcsrc/warpzonelib/server.qc
scripts/simpleitems.shader [new file with mode: 0644]
scripts/weapons.shader
sound/vehicles/missile_alarm.wav [new file with mode: 0644]
textures/raptor.tga
textures/raptor_pants.jpg [deleted file]
textures/raptor_shirt.jpg [deleted file]
textures/raptor_shirt.tga [new file with mode: 0644]
vehicle_bumblebee.cfg
vehicle_racer.cfg
vehicle_raptor.cfg
vehicle_spiderbot.cfg
vehicles.cfg
xonotic-credits.txt

index 372a6af3e146f635154231a39a71b730efd96fc0..cb95f968132ba7145549310b491ec98885459a7a 100644 (file)
@@ -206,6 +206,7 @@ seta hud_panel_pressedkeys_bg_alpha "" "if set to something else than \"\" = ove
 seta hud_panel_pressedkeys_bg_border "" "if set to something else than \"\" = override default size of border around the background"
 seta hud_panel_pressedkeys_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
 seta hud_panel_pressedkeys_aspect "" "forced aspect on panel"
+seta hud_panel_pressedkeys_attack "" "show attack buttons too"
 
 seta hud_panel_chat "" "enable/disable this panel"
 seta hud_panel_chat_pos "" "position of this base of the panel"
index 9783f5e8b348e55260ea256c9b589e9d4ac75ea3..aafb163b441941ea73ad9a0ba736837fcc0bc25f 100644 (file)
@@ -162,13 +162,12 @@ set g_projectiles_damage 2
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 2
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
 // 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
 // 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
 set g_projectiles_newton_style_2_minfactor 0.7
 set g_projectiles_newton_style_2_maxfactor 5
 set g_projectiles_spread_style 0
index 54e232dc4dc44277909ef7831592d7aa9d83446b..1bb8989120df04a0f5f3b7864c66c23ab0df2f57 100644 (file)
@@ -162,13 +162,12 @@ set g_projectiles_damage 2
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 2
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
 // 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
 // 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
 set g_projectiles_newton_style_2_minfactor 0.7
 set g_projectiles_newton_style_2_maxfactor 5
 set g_projectiles_spread_style 7
index ea933d2725c56b78ac7459e2f1705c09719d822e..759551d8d2357a4a2e53f7f1125d229659802fe7 100644 (file)
@@ -162,13 +162,12 @@ set g_projectiles_damage 1
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 0
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
 // 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
 // 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
 set g_projectiles_newton_style_2_minfactor 0.8
 set g_projectiles_newton_style_2_maxfactor 1.5
 set g_projectiles_spread_style 7
index 2f1d16d82e3a9a11b62fc8cb19ffbc36921c0756..52c8a74d84cecfe381db5adbb156bc778f7da233 100644 (file)
@@ -162,13 +162,12 @@ set g_projectiles_damage 2
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 2
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
 // 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
 // 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
 set g_projectiles_newton_style_2_minfactor 0.8
 set g_projectiles_newton_style_2_maxfactor 1.5
 set g_projectiles_spread_style 7
index 174a458347b8b76e827f4ca670412c5e29f51059..35d9e39b91947d5d17210434c6c047a6f8512131 100644 (file)
@@ -239,6 +239,47 @@ alias unban                "qc_cmd_sv     unban                ${* ?}" // Remove
 // other aliases for ban commands
 alias bans "banlist"
 
+// character classes (intersected with 32..126 minus ", $, ;, ^, \ - if you
+// want these, include them explicitly)
+// note that QC code always forbids $ and ; in VoteCommand_checknasty
+set _iscntrl ""
+set _isblank " "
+set _ispunct "!#%&'()*+,-./:<=>?@[]_`{|}~"
+set _isdigit "0123456789"
+set _isupper "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+set _islower "abcdefghijklmnopqrstuvwxyz"
+set _isxdigit "0123456789abcdefABCDEF"
+
+// derived character classes
+set _isalpha "$_isupper$_islower"
+set _isalnum "$_isalpha$_isdigit"
+set _isgraph "$_ispunct$_isalnum"
+set _isascii "$_isgraph$_isblank"
+set _isprint "$_isgraph$_isblank"
+set _isspace "$_isblank"
+
+// restriction is specified as <minargs> followed by <maxargs> instances of ';'
+// and the optional character class to verify the argument by (no checking if
+// empty)
+// set cvar to empty string to not check the command at all
+// if cvar is not set there will be a warning
+set sv_vote_command_restriction_restart "0"
+set sv_vote_command_restriction_fraglimit "1;$_isdigit"
+set sv_vote_command_restriction_chmap "1;$_isgraph"
+set sv_vote_command_restriction_gotomap "1;$_isgraph"
+set sv_vote_command_restriction_nextmap "1;$_isgraph"
+set sv_vote_command_restriction_endmatch "0"
+set sv_vote_command_restriction_reducematchtime "0"
+set sv_vote_command_restriction_extendmatchtime "0"
+set sv_vote_command_restriction_allready "0"
+set sv_vote_command_restriction_kick "1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" // enough space for ban reason
+set sv_vote_command_restriction_kickban "1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" // enough space for ban reason
+set sv_vote_command_restriction_cointoss "0"
+set sv_vote_command_restriction_movetoauto "1;"
+set sv_vote_command_restriction_movetored "1;"
+set sv_vote_command_restriction_movetoblue "1;"
+set sv_vote_command_restriction_movetoyellow "1;"
+set sv_vote_command_restriction_movetopink "1;"
 
 // =================================
 //  voting - server/command/vote.qc
index 0c399bb183cde7a50c4ff80e690bd59764527ffc..96908168944b2472402f5b3776b357a1246f04cd 100644 (file)
@@ -57,7 +57,7 @@ bind f6 team_auto
 mod_q3bsp_lightmapmergepower 4
 
 // player defaults
-_cl_color 112
+_cl_color "112.211" // same effect as 112, but menuqc can detect this as the default and not intentionally set
 _cl_name Player
 _cl_playermodel models/player/erebus.iqm
 _cl_playerskin 0
@@ -574,9 +574,9 @@ seta g_friendlyfire_virtual_force 1 "for teamplay 4: apply force even though dam
 seta g_teamdamage_threshold 40 "for teamplay 4: threshold over which to apply mirror damage"
 seta g_teamdamage_resetspeed 20        "for teamplay 4: how fast player's teamdamage count decreases"
 
-seta g_balance_teams 0 "automatically balance out players entering instead of asking them for their preferred team"
-seta g_balance_teams_force 0   "automatically balance out teams when players move or disconnect"
-seta g_balance_teams_prevent_imbalance 0       "prevent players from changing to larger teams"
+seta g_balance_teams 1 "automatically balance out players entering instead of asking them for their preferred team"
+seta g_balance_teams_prevent_imbalance 1       "prevent players from changing to larger teams"
+set g_balance_teams_scorefactor 0.34 "at the end of the game, take score into account instead of team size by this amount (beware: values over 0.5 mean that a x:0 score imbalance will cause ALL new players to prefer the losing team at the end, despite numbers)"
 set g_tdm_teams 2 "how many teams are in team deathmatch (set by mapinfo)"
 seta g_tdm_teams_override 0    "how many teams are in team deathmatch"
 set g_tdm_team_spawns 0 "when 1, a map can define team spawnpoints for TDM"
@@ -812,6 +812,7 @@ set g_throughfloor_max_steps_other 10 "Maximum number of steps for splash damage
 
 // effects
 r_glsl_vertextextureblend_usebothalphas 1 // allows to abuse texture blending as detail texture
+mod_q3shader_force_terrain_alphaflag 1 // supposedly now required for r_glsl_vertextextureblend_usebothalphas to work
 r_glsl_postprocess 0 // but note, hud_postprocessing enables this
 r_picmipsprites 0 // Xonotic uses sprites that should never be picmipped (team mate, typing, waypoints)
 r_picmipworld 1
@@ -1645,6 +1646,9 @@ seta cl_casings_maxcount 100 "maximum amount of shell casings (must be at least
 seta cl_gibs_maxcount 100 "maximum amount of gibs (must be at least 1)"
 seta cl_vehicle_spiderbot_cross_alpha 0.6
 seta cl_vehicle_spiderbot_cross_size 1
+seta cl_vehicles_hudscale 0.5 
+seta cl_vehicles_hudalpha 0.75
+seta cl_vehicles_hud_tactical 1
 
 //cl_gunalign calculator
 seta menu_cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only"
@@ -1667,9 +1671,6 @@ set g_triggerimpulse_directional_multiplier 1 "trigger_impulse directional field
 set g_triggerimpulse_radial_multiplier 1 "trigger_impulse radial field multiplier"
 set the_goggles "they do nothing" "but the googles, they do"
 
-set g_ghost_items 1 "enable ghosted items (when between 0 and 1, overrides the alpha value)"
-set g_ghost_items_color "-1 -1 -1" "color of ghosted items, 0 0 0 leaves the color unchanged"
-
 set sv_weaponstats_file "" "when set to a file name, per-weapon stats get written to that file"
 
 seta cl_noantilag 0 "turn this on if you believe antilag is bad"
@@ -1702,7 +1703,7 @@ set g_debug_defaultsounds 0 "always use default sounds"
 set sv_use_csqc_players 1 "set to 0 to disable CSQC players for better Xonotic 0.5 compat"
 set cl_precacheplayermodels 0 "TODO please check if this needs to be 1 or if precaching a model the server already requested is fast enough to do it at runtime"
 seta cl_forceplayermodels 0 "make everyone look like your own model (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0)"
-seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0, and is ignored in teamplay)"
+seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0, and is ignored in teamplay with more than two teams)"
 seta cl_forcemyplayermodel "" "set to the model file name you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)"
 seta cl_forcemyplayerskin 0 "set to the skin number you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)"
 seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_color) for your own player model (requires server to have sv_use_csqc_players 1, and is ignored in teamplay; does not affect how enemies look with cl_forceplayermodels)"
@@ -1956,3 +1957,13 @@ alias menu_sync "menu_cmd sync"
 
 set sv_join_notices ""
 set sv_join_notices_time 15
+
+set cl_ghost_items 0.45 "enable ghosted items (when between 0 and 1, overrides the alpha value)"
+set cl_ghost_items_color "-1 -1 -1" "color of ghosted items, 0 0 0 leaves the color unchanged"
+set sv_simple_items 1 "allow or forbid client use of simple items"
+set cl_simple_items 0 "enable simple items (if server allows)"
+set cl_fullbright_items 0 "enable fullbright items (if server allows, controled by g_fullbrightitems)"
+set cl_weapon_stay_color "2 0.5 0.5" "Color of picked up weapons when g_weapon_stay > 0"
+set cl_weapon_stay_alpha 0.75 "Alpha of picked up weapons when g_weapon_stay > 0"
+
+seta g_superspectate 0 "server side, allows extended spectator functions through the cmd interface. followpowerup, followstrength, followstshield or followfc [red|blue] will transfer spectation to the relevent player, if any"
\ No newline at end of file
index 05c249b976d02cb746dbaa95451bd6c6f16fe9ba..38413d3c622aa32af70926abdb2e1b8649458327 100644 (file)
@@ -7409,4 +7409,231 @@ velocityjitter 64 64 64
 //lightradius 50
 //lightradiusfade 50
 //lightcolor 1 0.9 0.7
-//lightshadow 1
\ No newline at end of file
+//lightshadow 1
+
+// heal ray muzzleflash
+
+effect healray_muzzleflash
+countabsolute 1
+type smoke
+color 0x283880 0x283880 // 0x202020 0x404040
+tex 65 65
+size 20 20
+alpha 256 256 512
+originjitter 1.5 1.5 1.5
+velocityjitter 6 6 6
+sizeincrease -10
+velocitymultiplier 0.01
+lightradius 200
+lightradiusfade 2000
+lightcolor 1.5 3 6
+
+effect healray_muzzleflash
+count 22
+type spark
+tex 71 73
+color 0xD9FDFF 0x00f0ff
+size 1 15
+sizeincrease 3
+alpha 50 150 1924
+originjitter 1 1 1
+velocityjitter 150 150 150
+velocitymultiplier 0.4
+airfriction 5
+stretchfactor 3.9
+
+effect healray_muzzleflash
+count 4
+type spark
+tex 70 70
+color 0xD9FDFF 0x00f0ff
+size 1 1
+alpha 110 228 4024
+originjitter 1 1 1
+velocityjitter 650 650 650
+velocitymultiplier 1.1
+stretchfactor 0.2
+
+
+
+//healray impact
+
+effect healray_impact
+countabsolute 1
+type decal
+tex 59 59
+size 32 32
+alpha 256 256 0
+color 0xd800ff 0xd800ff
+originjitter 17 17 17
+lightradius 125
+lightradiusfade 450
+lightcolor 0 4.375 0
+// shockwave
+effect healray_impact
+type smoke
+countabsolute 1
+tex 33 33
+size 32 32
+sizeincrease 1400
+color 0x00ff00 0x84c52f
+alpha 40 40 350
+velocitymultiplier 44
+// cloud of bouncing sparks
+effect healray_impact
+count 30
+type spark
+tex 70 70
+color 0x00ff00 0x84c52f
+size 1 2
+alpha 156 300 1024
+gravity 2
+airfriction 6
+originjitter 1 1 1
+velocityjitter 1112 1112 1112
+// inner cloud of smoke
+effect healray_impact
+count 15
+type smoke
+color 0x00ff00 0x84c52f
+tex 40 40
+size 2 3 
+alpha 200 456 512
+airfriction 3
+gravity -2
+velocityjitter 120 120 420
+rotate -180 180 -90 90
+
+
+
+
+// big plasma muzzle flash
+
+effect bigplasma_muzzleflash
+countabsolute 1
+type smoke
+color 0x283880 0x283880 // 0x202020 0x404040
+tex 65 65
+size 50 50
+alpha 256 256 812
+originjitter 1.5 1.5 1.5
+velocityjitter 6 6 6
+sizeincrease -10
+velocitymultiplier 0.01
+lightradius 200
+lightradiusfade 2000
+lightcolor 1.5 3 6
+
+effect bigplasma_muzzleflash
+countabsolute 1
+type smoke
+color 0x00f0ff 0x00f0ff
+tex 74 74
+size 20 20
+alpha 56 56 1112
+sizeincrease 300
+
+effect bigplasma_muzzleflash
+count 14
+type spark
+tex 51 55
+color 0xD9FDFF 0x00f0ff
+size 5 10
+sizeincrease 135
+alpha 50 150 1924
+originjitter 1 1 1
+velocityjitter 350 350 350
+velocitymultiplier 0.4
+airfriction 5
+stretchfactor 1.9
+
+effect bigplasma_muzzleflash
+count 4
+type spark
+tex 70 70
+color 0xD9FDFF 0x00f0ff
+size 20 20
+alpha 110 228 4024
+originjitter 1 1 1
+velocityjitter 650 650 650
+velocitymultiplier 1.1
+stretchfactor 0.2
+
+
+// big plasma impact
+
+effect bigplasma_impact
+countabsolute 1
+type decal
+tex 59 59
+size 32 32
+alpha 256 256 0
+originjitter 17 17 17
+lightradius 125
+lightradiusfade 450
+lightcolor 3.125 4.375 10
+// shockwave
+effect bigplasma_impact
+type smoke
+countabsolute 1
+tex 33 33
+size 32 32
+sizeincrease 1400
+color 0x80C0FF 0x80C0FF
+alpha 40 40 350
+velocitymultiplier 44
+// cloud of bouncing sparks
+effect bigplasma_impact
+count 30
+type spark
+tex 70 70
+color 0x629dff 0x0018ff
+size 1 2
+alpha 156 300 1024
+gravity 2
+airfriction 6
+originjitter 1 1 1
+velocityjitter 1512 1512 1512
+// inner cloud of smoke
+effect bigplasma_impact
+count 15
+type smoke
+color 0x629dff 0x0018ff
+tex 48 55
+size 20 24
+sizeincrease 555
+alpha 200 456 1512
+airfriction 30
+originjitter 20 20 20
+velocityjitter 320 320 320
+rotate -180 180 -9 9
+// smoke
+effect bigplasma_impact
+type smoke
+count 16
+blend alpha
+tex 0 7
+size 60 30
+color 0x222222 0x000000
+alpha 128 328 390
+rotate -180 180 2 -2
+velocityjitter 100 100 200
+velocityoffset 0 0 180
+originjitter 80 80 10
+sizeincrease 30
+airfriction 0.04
+gravity 0.4
+// smoke in the middle
+effect bigplasma_impact
+type alphastatic
+count 10
+tex 0 7
+size 60 70
+color 0x222222 0x000000
+alpha 128 328 310
+rotate -180 180 20 -20
+velocityjitter 10 10 10
+originjitter 80 80 80
+sizeincrease -10
+airfriction 0.04
+gravity -0.2
\ No newline at end of file
index 4c4c09baff0321867c5d99be8f2d7eb933121c51..f92230f16f04f10ecf7df6656e7aedad21a08536 100644 (file)
@@ -1,5 +1,5 @@
 cl_decals 1
-cl_decals_models 1
+cl_decals_models 0
 cl_decals_time 10
 cl_particles_quality 1
 cl_damageeffect 1
diff --git a/gfx/hud/default/key_atck.tga b/gfx/hud/default/key_atck.tga
new file mode 100644 (file)
index 0000000..40a12dc
Binary files /dev/null and b/gfx/hud/default/key_atck.tga differ
diff --git a/gfx/hud/default/key_atck2.tga b/gfx/hud/default/key_atck2.tga
new file mode 100644 (file)
index 0000000..40a12dc
Binary files /dev/null and b/gfx/hud/default/key_atck2.tga differ
diff --git a/gfx/hud/default/key_atck2_inv.tga b/gfx/hud/default/key_atck2_inv.tga
new file mode 100644 (file)
index 0000000..c1f6e42
Binary files /dev/null and b/gfx/hud/default/key_atck2_inv.tga differ
diff --git a/gfx/hud/default/key_atck_inv.tga b/gfx/hud/default/key_atck_inv.tga
new file mode 100644 (file)
index 0000000..c1f6e42
Binary files /dev/null and b/gfx/hud/default/key_atck_inv.tga differ
diff --git a/gfx/vehicles/axh-rings.tga b/gfx/vehicles/axh-rings.tga
new file mode 100644 (file)
index 0000000..da68ff8
Binary files /dev/null and b/gfx/vehicles/axh-rings.tga differ
diff --git a/gfx/vehicles/bumb.tga b/gfx/vehicles/bumb.tga
new file mode 100644 (file)
index 0000000..22883f4
Binary files /dev/null and b/gfx/vehicles/bumb.tga differ
diff --git a/gfx/vehicles/bumb_lgun.tga b/gfx/vehicles/bumb_lgun.tga
new file mode 100644 (file)
index 0000000..23db1da
Binary files /dev/null and b/gfx/vehicles/bumb_lgun.tga differ
diff --git a/gfx/vehicles/bumb_rgun.tga b/gfx/vehicles/bumb_rgun.tga
new file mode 100644 (file)
index 0000000..f755681
Binary files /dev/null and b/gfx/vehicles/bumb_rgun.tga differ
diff --git a/gfx/vehicles/bumb_side.tga b/gfx/vehicles/bumb_side.tga
new file mode 100644 (file)
index 0000000..69fa4d8
Binary files /dev/null and b/gfx/vehicles/bumb_side.tga differ
diff --git a/gfx/vehicles/bumb_side_gun.tga b/gfx/vehicles/bumb_side_gun.tga
new file mode 100644 (file)
index 0000000..c8fc817
Binary files /dev/null and b/gfx/vehicles/bumb_side_gun.tga differ
diff --git a/gfx/vehicles/energy.tga b/gfx/vehicles/energy.tga
new file mode 100644 (file)
index 0000000..de06ecc
Binary files /dev/null and b/gfx/vehicles/energy.tga differ
diff --git a/gfx/vehicles/vth-mover.tga b/gfx/vehicles/vth-mover.tga
new file mode 100644 (file)
index 0000000..d831896
Binary files /dev/null and b/gfx/vehicles/vth-mover.tga differ
diff --git a/gfx/vehicles/vth-stationary.tga b/gfx/vehicles/vth-stationary.tga
new file mode 100644 (file)
index 0000000..31703bc
Binary files /dev/null and b/gfx/vehicles/vth-stationary.tga differ
index df836368301076d984407568c470f5bdc6efef96..6472a257963fad8c9526546031d3d6e7c716779f 100644 (file)
@@ -204,6 +204,7 @@ seta hud_panel_pressedkeys_bg_alpha ""
 seta hud_panel_pressedkeys_bg_border ""
 seta hud_panel_pressedkeys_bg_padding ""
 seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
 
 seta hud_panel_chat 1
 seta hud_panel_chat_pos "0.010000 0.700000"
index eef7aed2955353d6205e49a9598b218d4cc6f8d6..bb7e0662e32e3bcbce1060385a3f0d42a6961549 100644 (file)
@@ -204,6 +204,7 @@ seta hud_panel_pressedkeys_bg_alpha ""
 seta hud_panel_pressedkeys_bg_border ""
 seta hud_panel_pressedkeys_bg_padding ""
 seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
 
 seta hud_panel_chat 1
 seta hud_panel_chat_pos "0 0.775000"
index 0a77fba082b0c8e590bd4ff58c1bb0c5b8e0f756..e0921ad35337d272f8e0c91a0032864349981cac 100644 (file)
@@ -204,6 +204,7 @@ seta hud_panel_pressedkeys_bg_alpha ""
 seta hud_panel_pressedkeys_bg_border ""
 seta hud_panel_pressedkeys_bg_padding ""
 seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
 
 seta hud_panel_chat 1
 seta hud_panel_chat_pos "0 0.775000"
index cd4b1ba711a264fb5c2068a1cf0cc2ed09fcd2d7..119f7b18f6f8cd3f163e7e6ac172db53ed4516ad 100644 (file)
@@ -204,6 +204,7 @@ seta hud_panel_pressedkeys_bg_alpha ""
 seta hud_panel_pressedkeys_bg_border ""
 seta hud_panel_pressedkeys_bg_padding ""
 seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
 
 seta hud_panel_chat 1
 seta hud_panel_chat_pos "0.020000 0.780000"
index 67bbde531da8e03e03a4c2e7fb3c8e8ef9f119f8..3cf0feb753e5e08b748ce408a03f42affc78393d 100644 (file)
@@ -204,6 +204,7 @@ seta hud_panel_pressedkeys_bg_alpha ""
 seta hud_panel_pressedkeys_bg_border ""
 seta hud_panel_pressedkeys_bg_padding ""
 seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
 
 seta hud_panel_chat 1
 seta hud_panel_chat_pos "0 0.760000"
diff --git a/models/items/a_bullets_simple.iqm b/models/items/a_bullets_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/a_bullets_simple.iqm differ
diff --git a/models/items/a_bullets_simple.iqm_0.skin b/models/items/a_bullets_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..4757695
--- /dev/null
@@ -0,0 +1 @@
+Plane,a_bullets_simple
\ No newline at end of file
diff --git a/models/items/a_bullets_simple.tga b/models/items/a_bullets_simple.tga
new file mode 100644 (file)
index 0000000..111a32a
Binary files /dev/null and b/models/items/a_bullets_simple.tga differ
diff --git a/models/items/a_cells_simple.iqm b/models/items/a_cells_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/a_cells_simple.iqm differ
diff --git a/models/items/a_cells_simple.iqm_0.skin b/models/items/a_cells_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..1651991
--- /dev/null
@@ -0,0 +1 @@
+Plane,a_cells_simple
\ No newline at end of file
diff --git a/models/items/a_cells_simple.tga b/models/items/a_cells_simple.tga
new file mode 100644 (file)
index 0000000..0f7f1df
Binary files /dev/null and b/models/items/a_cells_simple.tga differ
diff --git a/models/items/a_rockets_simple.iqm b/models/items/a_rockets_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/a_rockets_simple.iqm differ
diff --git a/models/items/a_rockets_simple.iqm_0.skin b/models/items/a_rockets_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..5b2333c
--- /dev/null
@@ -0,0 +1 @@
+Plane,a_rockets_simple
\ No newline at end of file
diff --git a/models/items/a_rockets_simple.tga b/models/items/a_rockets_simple.tga
new file mode 100644 (file)
index 0000000..3d8646b
Binary files /dev/null and b/models/items/a_rockets_simple.tga differ
diff --git a/models/items/a_shells_simple.iqm b/models/items/a_shells_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/a_shells_simple.iqm differ
diff --git a/models/items/a_shells_simple.iqm_0.skin b/models/items/a_shells_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..e3dc44f
--- /dev/null
@@ -0,0 +1 @@
+Plane,a_shells_simple
\ No newline at end of file
diff --git a/models/items/a_shells_simple.tga b/models/items/a_shells_simple.tga
new file mode 100644 (file)
index 0000000..a357f50
Binary files /dev/null and b/models/items/a_shells_simple.tga differ
diff --git a/models/items/g_h100_simple.iqm b/models/items/g_h100_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/g_h100_simple.iqm differ
diff --git a/models/items/g_h100_simple.iqm_0.skin b/models/items/g_h100_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..f8acadd
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_h100_simple
\ No newline at end of file
diff --git a/models/items/g_h100_simple.tga b/models/items/g_h100_simple.tga
new file mode 100644 (file)
index 0000000..08b780a
Binary files /dev/null and b/models/items/g_h100_simple.tga differ
diff --git a/models/items/g_h1_simple.iqm b/models/items/g_h1_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/g_h1_simple.iqm differ
diff --git a/models/items/g_h1_simple.iqm_0.skin b/models/items/g_h1_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..9532805
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_h1_simple
\ No newline at end of file
diff --git a/models/items/g_h1_simple.tga b/models/items/g_h1_simple.tga
new file mode 100644 (file)
index 0000000..d8bbbc7
Binary files /dev/null and b/models/items/g_h1_simple.tga differ
diff --git a/models/items/g_h25_simple.iqm b/models/items/g_h25_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/g_h25_simple.iqm differ
diff --git a/models/items/g_h25_simple.iqm_0.skin b/models/items/g_h25_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..0f33bc7
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_h25_simple
\ No newline at end of file
diff --git a/models/items/g_h25_simple.tga b/models/items/g_h25_simple.tga
new file mode 100644 (file)
index 0000000..63593cc
Binary files /dev/null and b/models/items/g_h25_simple.tga differ
diff --git a/models/items/g_h50_simple.iqm b/models/items/g_h50_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/g_h50_simple.iqm differ
diff --git a/models/items/g_h50_simple.iqm_0.skin b/models/items/g_h50_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..b830541
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_h50_simple
\ No newline at end of file
diff --git a/models/items/g_h50_simple.tga b/models/items/g_h50_simple.tga
new file mode 100644 (file)
index 0000000..a8cbad9
Binary files /dev/null and b/models/items/g_h50_simple.tga differ
diff --git a/models/items/g_invincible_simple.iqm b/models/items/g_invincible_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/g_invincible_simple.iqm differ
diff --git a/models/items/g_invincible_simple.iqm_0.skin b/models/items/g_invincible_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..6522c88
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_invincible_simple
\ No newline at end of file
diff --git a/models/items/g_invincible_simple.tga b/models/items/g_invincible_simple.tga
new file mode 100644 (file)
index 0000000..76cb414
Binary files /dev/null and b/models/items/g_invincible_simple.tga differ
diff --git a/models/items/g_strength_simple.iqm b/models/items/g_strength_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/g_strength_simple.iqm differ
diff --git a/models/items/g_strength_simple.iqm_0.skin b/models/items/g_strength_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..bcdad79
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_strength_simple
\ No newline at end of file
diff --git a/models/items/g_strength_simple.tga b/models/items/g_strength_simple.tga
new file mode 100644 (file)
index 0000000..09aa45c
Binary files /dev/null and b/models/items/g_strength_simple.tga differ
diff --git a/models/items/item_armor_big_simple.iqm b/models/items/item_armor_big_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/item_armor_big_simple.iqm differ
diff --git a/models/items/item_armor_big_simple.iqm_0.skin b/models/items/item_armor_big_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..ab88a06
--- /dev/null
@@ -0,0 +1 @@
+Plane,item_armor_big_simple
\ No newline at end of file
diff --git a/models/items/item_armor_big_simple.tga b/models/items/item_armor_big_simple.tga
new file mode 100644 (file)
index 0000000..7bbd5b4
Binary files /dev/null and b/models/items/item_armor_big_simple.tga differ
diff --git a/models/items/item_armor_large_simple.iqm b/models/items/item_armor_large_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/item_armor_large_simple.iqm differ
diff --git a/models/items/item_armor_large_simple.iqm_0.skin b/models/items/item_armor_large_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..4ae65f3
--- /dev/null
@@ -0,0 +1 @@
+Plane,item_armor_large_simple
\ No newline at end of file
diff --git a/models/items/item_armor_large_simple.tga b/models/items/item_armor_large_simple.tga
new file mode 100644 (file)
index 0000000..80db5ab
Binary files /dev/null and b/models/items/item_armor_large_simple.tga differ
diff --git a/models/items/item_armor_medium_simple.iqm b/models/items/item_armor_medium_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/item_armor_medium_simple.iqm differ
diff --git a/models/items/item_armor_medium_simple.iqm_0.skin b/models/items/item_armor_medium_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..8f258c1
--- /dev/null
@@ -0,0 +1 @@
+Plane,item_armor_medium_simple
\ No newline at end of file
diff --git a/models/items/item_armor_medium_simple.tga b/models/items/item_armor_medium_simple.tga
new file mode 100644 (file)
index 0000000..ed3ce1f
Binary files /dev/null and b/models/items/item_armor_medium_simple.tga differ
diff --git a/models/items/item_armor_small_simple.iqm b/models/items/item_armor_small_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/items/item_armor_small_simple.iqm differ
diff --git a/models/items/item_armor_small_simple.iqm_0.skin b/models/items/item_armor_small_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..50bbb53
--- /dev/null
@@ -0,0 +1 @@
+Plane,item_armor_small_simple
\ No newline at end of file
diff --git a/models/items/item_armor_small_simple.tga b/models/items/item_armor_small_simple.tga
new file mode 100644 (file)
index 0000000..d8a0f91
Binary files /dev/null and b/models/items/item_armor_small_simple.tga differ
index 9962dd764ab3c886953c3c7c90809073dd0ac310..016b6343d8e2672f5bfc30d254f8940f883b2ca4 100644 (file)
Binary files a/models/vehicles/bumblebee_body.dpm and b/models/vehicles/bumblebee_body.dpm differ
index 57df41a2580020bf34d40c37775e40a81e1aa9a0..785699909cce5bbf4a5d1c7acba72b767a119c1e 100644 (file)
Binary files a/models/vehicles/bumblebee_plasma_left.dpm and b/models/vehicles/bumblebee_plasma_left.dpm differ
index 1689979fcf6ff85b4f4e4f5dd9e70048b8f1d1fb..86cf3ddfc9b88d5987c591e6fe5c2aa028e218dc 100644 (file)
Binary files a/models/vehicles/bumblebee_plasma_right.dpm and b/models/vehicles/bumblebee_plasma_right.dpm differ
index 2e36eb5345eb55a75521408d2f75b65ab1748464..d6014b9c8f1be1d1b2f476217462ab7dab3d3833 100644 (file)
Binary files a/models/vehicles/bumblebee_ray.dpm and b/models/vehicles/bumblebee_ray.dpm differ
diff --git a/models/weapons/crylink_simple.tga b/models/weapons/crylink_simple.tga
new file mode 100644 (file)
index 0000000..4dfe24e
Binary files /dev/null and b/models/weapons/crylink_simple.tga differ
diff --git a/models/weapons/g_crylink_simple.iqm b/models/weapons/g_crylink_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_crylink_simple.iqm differ
diff --git a/models/weapons/g_crylink_simple.iqm_0.skin b/models/weapons/g_crylink_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..e86b8b2
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_crylink_simple
\ No newline at end of file
diff --git a/models/weapons/g_crylink_simple.obj b/models/weapons/g_crylink_simple.obj
new file mode 100644 (file)
index 0000000..3bd17fc
--- /dev/null
@@ -0,0 +1,14 @@
+# Blender3D v249 OBJ File: crylink_simple.blend\r
+# www.blender3d.org\r
+mtllib g_crylink_simple.mtl\r
+v 0.000000 40.000000 14.999998\r
+v 0.000000 10.000001 15.000000\r
+v 0.000000 9.999999 -15.000000\r
+v 0.000000 40.000000 -15.000002\r
+vt 1.000000 1.000000\r
+vt 0.000000 1.000000\r
+vt 0.000000 0.000000\r
+vt 1.000000 0.000000\r
+usemtl crylink_simple\r
+s off\r
+f 1/1 4/2 3/3 2/4\r
diff --git a/models/weapons/g_crylink_simple.tga b/models/weapons/g_crylink_simple.tga
new file mode 100644 (file)
index 0000000..f4054b7
Binary files /dev/null and b/models/weapons/g_crylink_simple.tga differ
diff --git a/models/weapons/g_electro_simple.iqm b/models/weapons/g_electro_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_electro_simple.iqm differ
diff --git a/models/weapons/g_electro_simple.iqm_0.skin b/models/weapons/g_electro_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..0ae8f4a
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_electro_simple
\ No newline at end of file
diff --git a/models/weapons/g_electro_simple.tga b/models/weapons/g_electro_simple.tga
new file mode 100644 (file)
index 0000000..b523c72
Binary files /dev/null and b/models/weapons/g_electro_simple.tga differ
diff --git a/models/weapons/g_gl_simple.iqm b/models/weapons/g_gl_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_gl_simple.iqm differ
diff --git a/models/weapons/g_gl_simple.iqm_0.skin b/models/weapons/g_gl_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..cbb574d
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_gl_simple
\ No newline at end of file
diff --git a/models/weapons/g_gl_simple.tga b/models/weapons/g_gl_simple.tga
new file mode 100644 (file)
index 0000000..e138aa4
Binary files /dev/null and b/models/weapons/g_gl_simple.tga differ
diff --git a/models/weapons/g_hagar_simple.iqm b/models/weapons/g_hagar_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_hagar_simple.iqm differ
diff --git a/models/weapons/g_hagar_simple.iqm_0.skin b/models/weapons/g_hagar_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..2eb9f30
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_hagar_simple
\ No newline at end of file
diff --git a/models/weapons/g_hagar_simple.tga b/models/weapons/g_hagar_simple.tga
new file mode 100644 (file)
index 0000000..4c82e4b
Binary files /dev/null and b/models/weapons/g_hagar_simple.tga differ
diff --git a/models/weapons/g_nex_simple.iqm b/models/weapons/g_nex_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_nex_simple.iqm differ
diff --git a/models/weapons/g_nex_simple.iqm_0.skin b/models/weapons/g_nex_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..55a8cc4
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_nex_simple
\ No newline at end of file
diff --git a/models/weapons/g_nex_simple.tga b/models/weapons/g_nex_simple.tga
new file mode 100644 (file)
index 0000000..27c984f
Binary files /dev/null and b/models/weapons/g_nex_simple.tga differ
diff --git a/models/weapons/g_rl_simple.iqm b/models/weapons/g_rl_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_rl_simple.iqm differ
diff --git a/models/weapons/g_rl_simple.iqm_0.skin b/models/weapons/g_rl_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..bcb054e
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_rl_simple
\ No newline at end of file
diff --git a/models/weapons/g_rl_simple.tga b/models/weapons/g_rl_simple.tga
new file mode 100644 (file)
index 0000000..d65fa87
Binary files /dev/null and b/models/weapons/g_rl_simple.tga differ
diff --git a/models/weapons/g_shotgun_simple.iqm b/models/weapons/g_shotgun_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_shotgun_simple.iqm differ
diff --git a/models/weapons/g_shotgun_simple.iqm_0.skin b/models/weapons/g_shotgun_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..3721ffc
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_shotgun_simple
\ No newline at end of file
diff --git a/models/weapons/g_shotgun_simple.tga b/models/weapons/g_shotgun_simple.tga
new file mode 100644 (file)
index 0000000..37da2f8
Binary files /dev/null and b/models/weapons/g_shotgun_simple.tga differ
diff --git a/models/weapons/g_uzi_simple.iqm b/models/weapons/g_uzi_simple.iqm
new file mode 100644 (file)
index 0000000..a5cc3e6
Binary files /dev/null and b/models/weapons/g_uzi_simple.iqm differ
diff --git a/models/weapons/g_uzi_simple.iqm_0.skin b/models/weapons/g_uzi_simple.iqm_0.skin
new file mode 100644 (file)
index 0000000..043974b
--- /dev/null
@@ -0,0 +1 @@
+Plane,g_uzi_simple
\ No newline at end of file
diff --git a/models/weapons/g_uzi_simple.tga b/models/weapons/g_uzi_simple.tga
new file mode 100644 (file)
index 0000000..d9b5df4
Binary files /dev/null and b/models/weapons/g_uzi_simple.tga differ
index 618e3ad4e234fc465e927bd80493429d9d5bcc16..27f6fc993aa0c12c1e372a7b36c25922fcce7995 100644 (file)
@@ -3,7 +3,7 @@ FTEQCC ?= fteqcc
 PERL ?= perl
 
 FTEQCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"' -DCVAR_POPCON
-FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -fno-fastarrays $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK)
+FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-return_only -fno-fastarrays $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK)
 FTEQCCFLAGS_PROGS ?=
 FTEQCCFLAGS_MENU ?=
 
index 6072652cd92b845b9d91ddaec16aed26cca39251..1ecc14516228995e4e5111ca10911ad3feb92477 100644 (file)
@@ -87,7 +87,7 @@ void ConsoleCommand_macro_init();
 void CSQC_Init(void)
 {
        prvm_language = cvar_string("prvm_language");
-
+    cl_simple_items = autocvar_cl_simple_items;
 #ifdef USE_FTE
 #pragma target ID
        __engine_check = checkextension("DP_SV_WRITEPICTURE");
@@ -118,7 +118,7 @@ void CSQC_Init(void)
        ClientProgsDB = db_load("client.db");
        compressShortVector_init();
 
-       drawfont = FONT_USER+1;
+       draw_endBoldFont();
        menu_visible = FALSE;
        menu_show = menu_show_error;
        menu_action = menu_sub_null;
@@ -178,7 +178,7 @@ void CSQC_Init(void)
        DamageInfo_Precache();
        Vehicles_Precache();
        turrets_precache();
-  Announcer_Precache();
+    Announcer_Precache();
        Tuba_Precache();
        
        if(autocvar_cl_reticle)
@@ -766,7 +766,9 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
                case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
                case ENT_CLIENT_TURRET: ent_turret(); break; 
-               case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break; 
+               case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
+               case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;  
+               case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;  
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
                        error(sprintf(_("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n"), self.enttype, num_for_edict(self), self.classname));
index 66d7dd31c4b1ae258043002bc381a81109d9ddfc..0dd898aad6039407543f36e1e20c11d00024a2dd 100644 (file)
@@ -1468,6 +1468,8 @@ void CSQC_UpdateView(float w, float h)
             CSQC_RAPTOR_HUD();
         else if(hud == HUD_BUMBLEBEE)
             CSQC_BUMBLE_HUD();
+        else if(hud == HUD_BUMBLEBEE_GUN)
+            CSQC_BUMBLE_GUN_HUD();
     }
        
        cl_notice_run();
index 43dd0dd1834bd76fea1b760fefca9489d4c75f8a..dd482a8f252a73de57d9a51ee3976df07e4a5662 100644 (file)
@@ -67,6 +67,7 @@ float autocvar_cl_reticle_stretch;
 float autocvar_cl_stripcolorcodes;
 var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
 var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
+var float autocvar_cl_vehicles_hud_tactical = 1;
 float autocvar_cl_velocityzoom;
 var float autocvar_cl_velocityzoom_type = 3;
 float autocvar_cl_velocityzoom_speed;
@@ -279,6 +280,7 @@ string autocvar_hud_panel_powerups_progressbar_superweapons;
 float autocvar_hud_panel_powerups_text;
 float autocvar_hud_panel_pressedkeys;
 float autocvar_hud_panel_pressedkeys_aspect;
+float autocvar_hud_panel_pressedkeys_attack;
 float autocvar_hud_panel_racetimer;
 float autocvar_hud_panel_radar;
 float autocvar_hud_panel_radar_foreground_alpha;
@@ -394,6 +396,7 @@ float autocvar_cl_forceplayercolors;
 string autocvar_cl_forcemyplayermodel;
 float autocvar_cl_forcemyplayerskin;
 float autocvar_cl_forcemyplayercolors;
+float autocvar__cl_color;
 float autocvar__cl_playerskin;
 string autocvar__cl_playermodel;
 float autocvar_cl_precacheplayermodels;
index 152ecbe82e998e398d35fcd0a8a1f0cbc37a811b..9c87d13addf9949c671a4319da1e5c91f2f69b45 100644 (file)
@@ -133,12 +133,15 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
        {
                if(islocalplayer)
                {
-                       // trust server's idea of "own player model"
-                       forceplayermodels_modelisgoodmodel = self.forceplayermodels_isgoodmodel;
-                       forceplayermodels_model = self.forceplayermodels_savemodel;
-                       forceplayermodels_modelindex = self.forceplayermodels_savemodelindex;
-                       forceplayermodels_skin = self.forceplayermodels_saveskin;
-                       forceplayermodels_attempted = 1;
+                       if(!isdemo()) // this is mainly cheat protection; not needed for demos
+                       {
+                               // trust server's idea of "own player model"
+                               forceplayermodels_modelisgoodmodel = self.forceplayermodels_isgoodmodel;
+                               forceplayermodels_model = self.forceplayermodels_savemodel;
+                               forceplayermodels_modelindex = self.forceplayermodels_savemodelindex;
+                               forceplayermodels_skin = self.forceplayermodels_saveskin;
+                               forceplayermodels_attempted = 1;
+                       }
                }
        }
 
@@ -170,7 +173,17 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
        }
 
        // apply it
-       if(autocvar_cl_forcemyplayermodel != "" && forceplayermodels_myisgoodmodel && islocalplayer)
+       float isfriend;
+       float cm;
+       cm = self.forceplayermodels_savecolormap;
+       cm = (cm >= 1024) ? cm : (stof(getplayerkeyvalue(self.colormap - 1, "colors")) + 1024);
+
+       if(teamplay)
+               isfriend = (cm == 1024 + 17 * myteam);
+       else
+               isfriend = islocalplayer;
+
+       if(autocvar_cl_forcemyplayermodel != "" && forceplayermodels_myisgoodmodel && isfriend)
        {
                self.model = forceplayermodels_mymodel;
                self.modelindex = forceplayermodels_mymodelindex;
@@ -196,7 +209,56 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
        }
 
        // forceplayercolors too
-       if(!teamplay)
+       if(teamplay)
+       {
+               // own team's color is never forced
+               float forcecolor_friend = 0;
+               float forcecolor_enemy = 0;
+               float teams_count = 0;
+               entity tm;
+
+               for(tm = teams.sort_next; tm; tm = tm.sort_next)
+                       if(tm.team != COLOR_SPECTATOR)
+                               ++teams_count;
+
+               if(autocvar_cl_forcemyplayercolors)
+                       forcecolor_friend = 1024 + autocvar_cl_forcemyplayercolors;
+               if(autocvar_cl_forceplayercolors && teams_count == 2)
+                       forcecolor_enemy = 1024 + autocvar__cl_color;
+
+               if(forcecolor_enemy && !forcecolor_friend)
+               {
+                       // only enemy color is forced?
+                       // verify it is not equal to the friend color
+                       if(forcecolor_enemy == 1024 + 17 * myteam)
+                               forcecolor_enemy = 0;
+               }
+
+               if(forcecolor_friend && !forcecolor_enemy)
+               {
+                       // only friend color is forced?
+                       // verify it is not equal to the enemy color
+                       for(tm = teams.sort_next; tm; tm = tm.sort_next)
+                               // note: we even compare against our own team.
+                               // if we rejected because we matched our OWN team color,
+                               // this is not bad; we then simply keep our color as is
+                               // anyway.
+                               if(forcecolor_friend == 1024 + 17 * tm.team)
+                                       forcecolor_friend = 0;
+               }
+
+               if(cm == 1024 + 17 * myteam)
+               {
+                       if(forcecolor_friend)
+                               self.colormap = forcecolor_friend;
+               }
+               else
+               {
+                       if(forcecolor_enemy)
+                               self.colormap = forcecolor_enemy;
+               }
+       }
+       else
        {
                if(autocvar_cl_forcemyplayercolors && islocalplayer)
                        self.colormap = 1024 + autocvar_cl_forcemyplayercolors;
index fc8b83b5b6c8666a11efe0961ebe8af011cfcbfb..ae83d45eea011d890b8b3fd0430866d2b17312ca 100644 (file)
@@ -229,7 +229,7 @@ void Ent_DamageInfo(float isNew)
                                sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN);
                                pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
                                break;
-                               
+            
                        case DEATH_WAKIGUN:
                                sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
                                pointparticles(particleeffectnum("wakizashi_gun_impact"), self.origin, w_backoff * 1000, 1);
@@ -267,6 +267,10 @@ void Ent_DamageInfo(float isNew)
                                sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN);
                                pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
                                break;
+                       case DEATH_BUMB_GUN:
+                               sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTN_NORM);
+                               pointparticles(particleeffectnum("bigplasma_impact"), self.origin, w_backoff * 1000, 1);
+                               break;
                }
        }
        
index ffd95f4feff69a5896f1fab4ef85e62ce9cd6082..2e3607ff4ffd37baab05b269befe4af27de28418 100644 (file)
@@ -476,6 +476,8 @@ void HUD_Weapons(void)
        HUD_Panel_UpdateCvars(weapons);
        HUD_Panel_ApplyFadeAlpha();
 
+       draw_beginBoldFont();
+
        // calculate fading effect to weapon images for when the panel is idle
        if(autocvar_hud_panel_weapons_fade)
        {
@@ -808,6 +810,8 @@ void HUD_Weapons(void)
                        ++column;
                }
        }
+
+       draw_endBoldFont();
 }
 
 // Ammo (#1)
@@ -908,6 +912,9 @@ void HUD_Ammo(void)
 
        HUD_Panel_UpdateCvars(ammo);
        HUD_Panel_ApplyFadeAlpha();
+
+       draw_beginBoldFont();
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -958,35 +965,40 @@ void HUD_Ammo(void)
                if(autocvar__hud_configure)
                {
                        DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets
-                       return;
                }
+               else
+               {
+                       stat_items = getstati(STAT_ITEMS, 0, 24);
+                       if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
+                               infinite_ammo = TRUE;
+                       for (i = 0; i < AMMO_COUNT; ++i) {
+                               currently_selected = stat_items & GetAmmoItemCode(i);
+                               if (currently_selected)
+                               {
+                                       DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
+                                       break;
+                               }
+                       }
+               }
+       }
+       else
+       {
                stat_items = getstati(STAT_ITEMS, 0, 24);
                if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
                        infinite_ammo = TRUE;
                for (i = 0; i < AMMO_COUNT; ++i) {
                        currently_selected = stat_items & GetAmmoItemCode(i);
-                       if (currently_selected)
+                       DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
+                       ++row;
+                       if(row >= rows)
                        {
-                               DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
-                               return;
+                               row = 0;
+                               column = column + 1;
                        }
                }
-               return; // nothing to display
        }
 
-       stat_items = getstati(STAT_ITEMS, 0, 24);
-       if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
-               infinite_ammo = TRUE;
-       for (i = 0; i < AMMO_COUNT; ++i) {
-               currently_selected = stat_items & GetAmmoItemCode(i);
-               DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
-               ++row;
-               if(row >= rows)
-               {
-                       row = 0;
-                       column = column + 1;
-               }
-       }
+       draw_endBoldFont();
 }
 
 void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha, float fadelerp)
@@ -1107,6 +1119,9 @@ void HUD_Powerups(void)
 
        HUD_Panel_UpdateCvars(powerups);
        HUD_Panel_ApplyFadeAlpha();
+
+       draw_beginBoldFont();
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -1273,6 +1288,8 @@ void HUD_Powerups(void)
                                DrawNumIcon_expanding(pos + superweapons_offset, mySize, superweapons, "superweapons", is_vertical, superweapons_iconalign, '1 1 1', 1, bound(0, (superweapons - superweapons_time) / 0.5, 1));
                }
        }
+
+       draw_endBoldFont();
 }
 
 // Health/armor (#3)
@@ -1745,11 +1762,15 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s
                } else if(type == DEATH_SBBLOWUP) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
-                               print (sprintf(_("^1%s^1 got caught in the destruction of %s^1's vehicle\n"), s2, s1));
+                               print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1));
                } else if(type == DEATH_WAKIGUN) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
                                print (sprintf(_("^1%s^1 was bolted down by %s\n"), s2, s1));
+               } else if(type == DEATH_BUMB_GUN) {
+                       HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print (sprintf(_("^1%s^1 saw %s's preddy lights.\n"), s2, s1));
                } else if(type == DEATH_WAKIROCKET) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
@@ -1757,7 +1778,7 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s
                } else if(type == DEATH_WAKIBLOWUP) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
-                               print (sprintf(_("^1%s^1 dies when %s^1's wakizashi dies.\n"), s2, s1));
+                               print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1));
                } else if(type == DEATH_RAPTOR_CANNON) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
@@ -1769,7 +1790,7 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s
                } else if(type == DEATH_RAPTOR_DEATH) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
-                               print (sprintf(_("^1%s^1 dies when %s^1's raptor dies.\n"), s2, s1));
+                               print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1));
                } else if(type == DEATH_TURRET) {
                        HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
                        if(alsoprint)
@@ -2436,6 +2457,9 @@ void HUD_Timer(void)
 
        HUD_Panel_UpdateCvars(timer);
        HUD_Panel_ApplyFadeAlpha();
+
+       draw_beginBoldFont();
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -2478,6 +2502,8 @@ void HUD_Timer(void)
        }
 
        drawstring_aspect(pos, timer, mySize, timer_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+       draw_endBoldFont();
 }
 
 // Radar (#6)
@@ -2802,6 +2828,7 @@ void HUD_Score(void)
                score = me.(scores[ps_primary]);
                timer = TIME_ENCODED_TOSTRING(score);
 
+               draw_beginBoldFont();
                if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
                        // distribution display
                        distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
@@ -2822,6 +2849,7 @@ void HUD_Score(void)
                if (distribution <= 0)
                        HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                drawstring_aspect(pos, timer, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
        } else if (!teamplay) { // non-teamgames
                if ((spectatee_status == -1 && !autocvar__hud_configure) || autocvar_hud_panel_score_rankings)
                {
@@ -2855,6 +2883,7 @@ void HUD_Score(void)
 
                string distribution_str;
                distribution_str = ftos(distribution);
+               draw_beginBoldFont();
                if (distribution >= 0)
                {
                        if (distribution > 0)
@@ -2863,6 +2892,7 @@ void HUD_Score(void)
                }
                drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                drawstring_aspect(pos + eX * 0.75 * mySize_x, distribution_str, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
        } else { // teamgames
                float scores_count, row, column, rows, columns;
                local noref vector offset; // fteqcc sucks
@@ -2905,6 +2935,7 @@ void HUD_Score(void)
 
                float max_fragcount;
                max_fragcount = -99;
+               draw_beginBoldFont();
                for(tm = teams.sort_next; tm; tm = tm.sort_next) {
                        if(tm.team == COLOR_SPECTATOR)
                                continue;
@@ -2939,6 +2970,7 @@ void HUD_Score(void)
                                ++rows;
                        }
                }
+               draw_endBoldFont();
        }
 }
 
@@ -2957,6 +2989,9 @@ void HUD_RaceTimer (void)
 
        HUD_Panel_UpdateCvars(racetimer);
        HUD_Panel_ApplyFadeAlpha();
+
+       draw_beginBoldFont();
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -3085,6 +3120,8 @@ void HUD_RaceTimer (void)
                        }
                }
        }
+
+       draw_endBoldFont();
 }
 
 // Vote window (#9)
@@ -3907,6 +3944,9 @@ void HUD_ModIcons(void)
 
        HUD_Panel_UpdateCvars(modicons);
        HUD_Panel_ApplyFadeAlpha();
+
+       draw_beginBoldFont();
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -3945,6 +3985,8 @@ void HUD_ModIcons(void)
                HUD_Mod_Dom(pos, mySize);
        else if(gametype == MAPINFO_TYPE_KEEPAWAY)
                HUD_Mod_Keepaway(pos, mySize);
+
+       draw_endBoldFont();
 }
 
 // Draw pressed keys (#11)
@@ -3996,10 +4038,17 @@ void HUD_DrawPressedKeys(void)
        }
 
        vector keysize;
-       keysize = eX * mySize_x * (1/3) + eY * mySize_y * 0.5;
+       keysize = eX * mySize_x * (1/3.0) + eY * mySize_y * (1/(3.0 - !autocvar_hud_panel_pressedkeys_attack));
        float pressedkeys;
        pressedkeys = getstatf(STAT_PRESSED_KEYS);
 
+       if(autocvar_hud_panel_pressedkeys_attack)
+       {
+               drawpic_aspect_skin(pos + eX * keysize_x * 0.5, ((pressedkeys & KEY_ATCK) ? "key_atck_inv.tga" : "key_atck.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawpic_aspect_skin(pos + eX * keysize_x * 1.5, ((pressedkeys & KEY_ATCK2) ? "key_atck_inv.tga" : "key_atck.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               pos_y += keysize_y;
+       }
+
        drawpic_aspect_skin(pos, ((pressedkeys & KEY_CROUCH) ? "key_crouch_inv.tga" : "key_crouch.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
        drawpic_aspect_skin(pos + eX * keysize_x, ((pressedkeys & KEY_FORWARD) ? "key_forward_inv.tga" : "key_forward.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
        drawpic_aspect_skin(pos + eX * keysize_x * 2, ((pressedkeys & KEY_JUMP) ? "key_jump_inv.tga" : "key_jump.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
@@ -4360,6 +4409,8 @@ void HUD_Physics(void)
        HUD_Panel_UpdateCvars(physics);
        HUD_Panel_ApplyFadeAlpha();
 
+       draw_beginBoldFont();
+
        HUD_Panel_DrawBg(1);
        if(panel_bg_padding)
        {
@@ -4612,6 +4663,8 @@ void HUD_Physics(void)
        tmp_offset_y = (panel_size_y - tmp_size_y) / 2;
        if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
                drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(acceleration, 2), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+       draw_endBoldFont();
 }
 
 // CenterPrint (#16)
index a53112bbd4b0495fe21483484b7818ebfd93c31c..0f990c69410d2646ccb0f8dca6a2281d6f46e3be 100644 (file)
@@ -138,6 +138,7 @@ void HUD_Panel_ExportCfg(string cfgname)
                                        HUD_Write_PanelCvar_q("_dom_layout");
                                        break;
                                case HUD_PANEL_PRESSEDKEYS:
+                                       HUD_Write_PanelCvar_q("_attack");
                                        HUD_Write_PanelCvar_q("_aspect");
                                        break;
                                case HUD_PANEL_ENGINEINFO:
index 4cb8dad05fff509e7a905ffc6627a850df8459fb..750bd2a75309d8774aea219b774ed1a9875c9f5d 100644 (file)
@@ -194,6 +194,7 @@ void MapVote_Draw()
        pos_y = ymin;
        pos_z = 0;
 
+       draw_beginBoldFont();
        map = _("Vote for a map");
        pos_x = center - stringwidth(map, false, '12 0 0');
        drawstring(pos, map, '24 24 0', '1 1 1', 1, DRAWFLAG_NORMAL);
@@ -205,6 +206,7 @@ void MapVote_Draw()
        drawstring(pos, map, '16 16 0', '0 1 0', 1, DRAWFLAG_NORMAL);
        pos_y += 22;
        pos_x = xmin;
+       draw_endBoldFont();
 
        // base for multi-column stuff...
        ymin = pos_y;
index 070096fbf4d6db912bb50d7f9c88f0eaa4e8de9c..72bb9c5c40a66ec0932bc1dbed0d3b2d00e8a292 100644 (file)
@@ -627,3 +627,13 @@ void URI_Get_Callback(float id, float status, string data)
                print(sprintf(_("Received HTTP request data for an invalid id %d.\n"), id));
        }
 }
+
+void draw_beginBoldFont()
+{
+       drawfont = FONT_USER+2;
+}
+
+void draw_endBoldFont()
+{
+       drawfont = FONT_USER+1;
+}
index d3a3a07d811e95d7ad75847cdbf056ecdb9a51d3..0922433eebdecd2d6c3c229636162e1475c6e56b 100644 (file)
@@ -53,6 +53,7 @@ projectile.qh
 sortlist.qc
 miscfunctions.qc
 teamplay.qc
+../server/t_items.qc
 
 teamradar.qc
 hud_config.qc
@@ -79,6 +80,7 @@ tuba.qc
 target_music.qc
 
 vehicles/vehicles.qc
+../server/vehicles/bumblebee.qc
 shownames.qh
 shownames.qc
 
index 85d5aedcb5f0bd7f638ff4517342c4bfa6bf30a6..4081bd8d1800c147a4867d2a6b6321bb11ed5e39 100644 (file)
@@ -303,6 +303,10 @@ void Ent_Projectile()
                        case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break;
                        case PROJECTILE_WAKIROCKET:   setmodel(self, "models/vehicles/rocket01.md3");  self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break;
                        case PROJECTILE_WAKICANNON:   setmodel(self, "models/laser.mdl");  self.traileffect = particleeffectnum(""); break;
+
+                       case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+                       case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+
                        default:
                                error("Received invalid CSQC projectile, can't work with this!");
                                break;
@@ -406,9 +410,21 @@ void Ent_Projectile()
                                break;
             case PROJECTILE_WAKIROCKET:
                 loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM);
-                               break;
+                               break;            
+            /*
             case PROJECTILE_WAKICANNON:
                                break;
+                       case PROJECTILE_BUMBLE_GUN:
+                               // only new engines support sound moving with object
+                               loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM);
+                               self.mins = '0 0 -4';
+                               self.maxs = '0 0 -4';
+                               self.move_movetype = MOVETYPE_BOUNCE;
+                               self.move_touch = SUB_Null;
+                               self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
+                               self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
+                               break;
+                       */
                        default:
                                break;
                }
index 935a0277a85abdf98ce2f4d24bbbeb002eedf76e..69a296796108022624ef2b5a7bb65c4fb9a9634d 100644 (file)
@@ -341,6 +341,7 @@ void Cmd_HUD_SetFields(float argc)
 
        hud_fontsize = HUD_GetFontsize("hud_fontsize"); 
 
+       draw_beginBoldFont();
        for(i = 0; i < argc - 1; ++i)
        {
                float nocomplain;
@@ -477,6 +478,7 @@ void Cmd_HUD_SetFields(float argc)
        }
 
        hud_field[hud_num_fields] = SP_END;
+       draw_endBoldFont();
 }
 
 // MOVEUP::
@@ -840,6 +842,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
        }
 
        // print the strings of the columns headers and draw the columns
+       draw_beginBoldFont();
        for(i = 0; i < hud_num_fields; ++i)
        {
                if(hud_field[i] == SP_SEPARATOR)
@@ -882,6 +885,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
                        pos_x -= hud_fontsize_x;
                }
        }
+       draw_endBoldFont();
 
        pos_x = xmin;
        pos_y += 1.25 * hud_fontsize_y; // skip the header
@@ -1220,7 +1224,9 @@ void HUD_DrawScoreboard()
        // Heading
        vector sb_heading_fontsize;
        sb_heading_fontsize = hud_fontsize * 2;
+       draw_beginBoldFont();
        drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+       draw_endBoldFont();
 
        pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
 
@@ -1236,6 +1242,7 @@ void HUD_DrawScoreboard()
                        if(tm.team == COLOR_SPECTATOR)
                                continue;
 
+                       draw_beginBoldFont();
                        rgb = GetTeamRGB(tm.team);
                        str = ftos(tm.(teamscores[ts_primary]));
                        drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
@@ -1245,6 +1252,8 @@ void HUD_DrawScoreboard()
                                str = ftos(tm.(teamscores[ts_secondary]));
                                drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize) + eY * hud_fontsize_y * 1.5, str, hud_fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
                        }
+                       draw_endBoldFont();
+
                        pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
                }
        }
@@ -1302,7 +1311,9 @@ void HUD_DrawScoreboard()
 
        if(specs)
        {
+               draw_beginBoldFont();
                drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
                pos_y += 1.25 * hud_fontsize_y;
        }
 
index 2b9ec0297b2ef63411d210cc8a8597bc8438691f..3aa3c3b2bbe6074ccfffc0588921abf688e8b56b 100644 (file)
@@ -235,36 +235,46 @@ void turret_draw2d()
         return; 
 
        float dist = vlen(self.origin - view_origin);
+    float t = (GetPlayerColor(player_localnum) + 1);   
+
        vector o;
-       /*
-       // TODO: Vehicle tactical hud
-       o = project_3d_to_2d(self.origin + '0 0 32');
-       if(o_z < 0 
-       || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) 
-       || o_y < (vid_conheight * waypointsprite_edgeoffset_top) 
-       || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))  
-       || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
-           return; // Dont draw wp's for turrets out of view
-    o_z = 0;
-    if(hud != HUD_NORMAL)
-    {        
-        switch(hud)
-        {
-            case HUD_SPIDERBOT:
-            case HUD_WAKIZASHI:
-            case HUD_RAPTOR:
-                vector pz = drawgetimagesize("gfx/vehicles/axh-bracket.tga") * 0.25;
-                drawpic(o - pz * 0.5 , "gfx/vehicles/axh-bracket.tga", pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
-                break;
+       string txt;
+       
+       if(autocvar_cl_vehicles_hud_tactical)
+       if(dist < 10240 && t != self.team)
+       {
+        // TODO: Vehicle tactical hud
+        o = project_3d_to_2d(self.origin + '0 0 32');
+        if(o_z < 0 
+        || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) 
+        || o_y < (vid_conheight * waypointsprite_edgeoffset_top) 
+        || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))  
+        || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+            return; // Dont draw wp's for turrets out of view
+        o_z = 0;
+        if(hud != HUD_NORMAL)
+        {        
+            switch(hud)
+            {
+                case HUD_SPIDERBOT:
+                case HUD_WAKIZASHI:
+                case HUD_RAPTOR:
+                    if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
+                        txt = "gfx/vehicles/vth-mover.tga";
+                    else
+                        txt = "gfx/vehicles/vth-stationary.tga";
+                        
+                    vector pz = drawgetimagesize(txt) * 0.25;
+                    drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
+                    break;
+            }
         }
-    }
-    */
+       }
     
        if(dist > self.maxdistance)
         return;
 
        string spriteimage = self.netname;
-       float t = (GetPlayerColor(player_localnum) + 1);        
        float a = self.alpha * autocvar_hud_panel_fg_alpha;
        vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
 
@@ -280,7 +290,7 @@ void turret_draw2d()
                print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage)); 
        }
 
-       string txt = self.netname;
+       txt = self.netname;
        if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
                txt = _("Spam");
        else
@@ -378,7 +388,7 @@ void turret_walker_draw()
         return;
     
     fixedmakevectors(self.angles);
-    movelib_groundalign4point(300, 100, 0.25);
+    movelib_groundalign4point(300, 100, 0.25, 45);
     setorigin(self, self.origin + self.velocity * dt);
     self.tur_head.angles += dt * self.tur_head.move_avelocity;
     self.angles_y = self.move_angles_y;
@@ -540,37 +550,38 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo
 
 void turret_die()
 {    
-    entity headgib;
     
     sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
     pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
     turret_tid2info(self.turret_type);
-    
-    // Base
-    if(self.turret_type == TID_EWHEEL)
-        turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', TRUE);
-    else if (self.turret_type == TID_WALKER)
-        turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', TRUE);
-    else if (self.turret_type == TID_TESLA)
-        turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', FALSE);
-    else
-    {        
-        if (random() > 0.5)
-        {            
-            turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
-            turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
-            turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
-        }
+    if (!autocvar_cl_nogibs)
+    {
+        // Base
+        if(self.turret_type == TID_EWHEEL)
+            turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', TRUE);
+        else if (self.turret_type == TID_WALKER)
+            turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', TRUE);
+        else if (self.turret_type == TID_TESLA)
+            turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', FALSE);
         else
-            turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE);
-
-        headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
-        if(headgib)
-        {
-            headgib.angles = headgib.move_angles = self.tur_head.angles;
-            headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
-            headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
-            headgib.gravity = 0.5;        
+        {        
+            if (random() > 0.5)
+            {            
+                turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+                turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+                turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+            }
+            else
+                turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE);
+
+            entity headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
+            if(headgib)
+            {
+                headgib.angles = headgib.move_angles = self.tur_head.angles;
+                headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
+                headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
+                headgib.gravity = 0.5;        
+            }
         }
     }
     
index ccb9cff58363374f82761aa58899984b800b86f8..3a4597ab2e4be241d5b16d7dc8ec35a8f788dd38 100644 (file)
 #define hud_ammo1_ico "gfx/vehicles/bullets.tga"
 #define hud_ammo2_bar "gfx/vehicles/bar_dwn_right.tga"
 #define hud_ammo2_ico "gfx/vehicles/rocket.tga"
+#define hud_energy "gfx/vehicles/energy.tga"
+
+#define SBRM_FIRST 1
+#define SBRM_VOLLY 1
+#define SBRM_GUIDE 2
+#define SBRM_ARTILLERY 3
+#define SBRM_LAST 3
+
+#define RSM_FIRST 1
+#define RSM_BOMB 1
+#define RSM_FLARE 2
+#define RSM_LAST 2
 
 entity dropmark;
-float autocvar_cl_vehicles_hudscale;
-float autocvar_cl_vehicles_hudalpha;
+var float autocvar_cl_vehicles_hudscale = 0.5;
+var float autocvar_cl_vehicles_hudalpha = 0.75;
 
+#define raptor_ico  "gfx/vehicles/raptor.tga"
+#define raptor_gun  "gfx/vehicles/raptor_guns.tga"
+#define raptor_bomb "gfx/vehicles/raptor_bombs.tga"
+#define raptor_drop "gfx/vehicles/axh-dropcross.tga"
+string raptor_xhair;
 
 void CSQC_WAKIZASHI_HUD();
 void CSQC_SPIDER_HUD();
 void CSQC_RAPTOR_HUD();
 void CSQC_BUMBLE_HUD();
+void CSQC_BUMBLE_GUN_HUD();
 
 #define MAX_AXH 4
 entity AuxiliaryXhair[MAX_AXH];
@@ -30,12 +48,34 @@ const var void Draw_Not();
 .float  axh_drawflag;
 .float  axh_scale;
 
+#define bumb_ico  "gfx/vehicles/bumb.tga"
+#define bumb_lgun  "gfx/vehicles/bumb_lgun.tga"
+#define bumb_rgun  "gfx/vehicles/bumb_rgun.tga"
+
+#define bumb_gun_ico  "gfx/vehicles/bumb_side.tga"
+#define bumb_gun_gun  "gfx/vehicles/bumb_side_gun.tga"
+
+#define spider_ico  "gfx/vehicles/sbot.tga"
+#define spider_rkt  "gfx/vehicles/sbot_rpods.tga"
+#define spider_mgun "gfx/vehicles/sbot_mguns.tga"
+string spider_xhair; // = "gfx/vehicles/axh-special1.tga";
+
+#define waki_ico "gfx/vehicles/waki.tga"
+#define waki_eng "gfx/vehicles/waki_e.tga"
+#define waki_gun "gfx/vehicles/waki_guns.tga"
+#define waki_rkt "gfx/vehicles/waki_rockets.tga"
+#define waki_xhair "gfx/vehicles/axh-special1.tga"
+
+float alarm1time;
+float alarm2time;
+float weapon2mode;
+
 void AuxiliaryXhair_Draw2D()
 {
     vector loc, psize;
 
     psize = self.axh_scale * draw_getimagesize(self.axh_image);
-    loc = project_3d_to_2d(self.origin) - 0.5 * psize;
+    loc = project_3d_to_2d(self.move_origin) - 0.5 * psize;
     if not (loc_z < 0 || loc_x < 0 || loc_y < 0 || loc_x > vid_conwidth || loc_y > vid_conheight)
     {
         loc_z = 0;
@@ -49,54 +89,55 @@ void AuxiliaryXhair_Draw2D()
 
 void Net_AuXair2(float bIsNew)
 {
-    float axh_id;
-    entity axh;
-
-    axh_id = bound(0, ReadByte(), MAX_AXH);
-    axh = AuxiliaryXhair[axh_id];
+    float axh_id       = bound(0, ReadByte(), MAX_AXH);
+    entity axh                 = AuxiliaryXhair[axh_id];
 
     if(axh == world || wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
     {
-        axh               = spawn();
-               axh.draw2d        = Draw_Not;
-               axh.drawmask      = MASK_NORMAL;
-               axh.axh_drawflag  = DRAWFLAG_ADDITIVE;
-               axh.axh_fadetime  = 0.1;
-               axh.axh_image     = "gfx/vehicles/axh-ring.tga";
-               axh.axh_scale     = 1;
-        axh.alpha         = 1;
+        axh                                    = spawn();
+               axh.draw2d                      = Draw_Not;
+               axh.drawmask            = MASK_NORMAL;
+               axh.axh_drawflag        = DRAWFLAG_ADDITIVE;
+               axh.axh_fadetime        = 0.1;
+               axh.axh_image           = "gfx/vehicles/axh-ring.tga";
+               axh.axh_scale           = 1;
+        axh.alpha                      = 1;
                AuxiliaryXhair[axh_id] = axh;
     }
-
-    axh.draw2d   = AuxiliaryXhair_Draw2D;
-
-       axh.origin_x = ReadCoord();
-       axh.origin_y = ReadCoord();
-       axh.origin_z = ReadCoord();
-
-       axh.colormod_x = ReadByte() / 255;
-       axh.colormod_y = ReadByte() / 255;
-       axh.colormod_z = ReadByte() / 255;
-    axh.cnt = time;
+    
+       axh.move_origin_x       = ReadCoord();
+       axh.move_origin_y       = ReadCoord();
+       axh.move_origin_z       = ReadCoord();
+       axh.colormod_x          = ReadByte() / 255;
+       axh.colormod_y          = ReadByte() / 255;
+       axh.colormod_z          = ReadByte() / 255;
+    axh.cnt                    = time;
+    axh.draw2d                 = AuxiliaryXhair_Draw2D;        
 }
 
 void Net_VehicleSetup()
 {
 
-    float hud_id, i;
+    float i;
     
-    hud_id = ReadByte();
+    float hud_id = ReadByte();
+    
+    // Weapon update?
+    if(hud_id > HUD_VEHICLE_LAST)
+    {
+        weapon2mode = hud_id - HUD_VEHICLE_LAST;
+        return;
+    }
     
     // hud_id == 0 means we exited a vehicle, so stop alarm sound/s
     if(hud_id == 0)
     {
         sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE);
         sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE);    
-            
         return;
     }
     
-    hud_id  = bound(HUD_SPIDERBOT, hud_id, HUD_RAPTOR);
+    hud_id  = bound(HUD_VEHICLE_FIRST, hud_id, HUD_VEHICLE_LAST);
 
     // Init auxiliary crosshairs
     entity axh;
@@ -106,15 +147,15 @@ void Net_VehicleSetup()
         if(axh != world && !wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
             remove(axh);
 
-        axh               = spawn();
-               axh.draw2d        = Draw_Not;
-               axh.drawmask      = MASK_NORMAL;
-               axh.axh_drawflag  = DRAWFLAG_NORMAL;
-               axh.axh_fadetime  = 0.1;
-               axh.axh_image     = "gfx/vehicles/axh-ring.tga";
-               axh.axh_scale     = 1;
-        axh.alpha         = 1;
-               AuxiliaryXhair[i] = axh;
+        axh                                    = spawn();
+               axh.draw2d                      = Draw_Not;
+               axh.drawmask            = MASK_NORMAL;
+               axh.axh_drawflag        = DRAWFLAG_NORMAL;
+               axh.axh_fadetime        = 0.1;
+               axh.axh_image           = "gfx/vehicles/axh-ring.tga";
+               axh.axh_scale           = 1;
+        axh.alpha                      = 1;
+               AuxiliaryXhair[i]       = axh;
     }
 
     switch(hud_id)
@@ -148,11 +189,24 @@ void Net_VehicleSetup()
             break;
 
         case HUD_BUMBLEBEE:
+            // Raygun-locked
+            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
+            AuxiliaryXhair[0].axh_scale   = 0.5;
+            
+            // Gunner1
+            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-target.tga";
+            AuxiliaryXhair[1].axh_scale   = 0.75;
+            
+            // Gunner2
+            AuxiliaryXhair[2].axh_image   = "gfx/vehicles/axh-target.tga";
+            AuxiliaryXhair[2].axh_scale   = 0.75;
+            break;        
+        case HUD_BUMBLEBEE_GUN:
             // Plasma cannons
-            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-ring.tga";
+            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
             AuxiliaryXhair[0].axh_scale   = 0.25;
             // Raygun
-            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-special1.tga";
+            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-bracket.tga";
             AuxiliaryXhair[1].axh_scale   = 0.25;
             break;
     }
@@ -168,15 +222,281 @@ void Net_VehicleSetup()
 
 void CSQC_BUMBLE_HUD()
 {
+/*
+    drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0'  * (1 - health), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_r, picsize, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0'  * (1 - energy), 1, DRAWFLAG_NORMAL);
+*/
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc, pic2size, picloc;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc_y = vid_conheight - picsize_y;
+    hudloc_x = vid_conwidth * 0.5 - picsize_x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    energy  *= 0.01;
+    reload1 *= 0.01;
+
+    pic2size = draw_getimagesize(bumb_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+    
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, bumb_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, bumb_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+    
+    drawpic(hudloc + picloc, bumb_lgun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, bumb_lgun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTN_NONE);
+        }
+        
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }        
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE);
+            alarm1time = 0;
+        }        
+    }
+
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {            
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE);
+            alarm2time = 0;
+        }
+    }
+    
+       ammo1 *= 0.01;
+       ammo2 *= 0.01;
+       
+// Gunner1 bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x, picloc_y, picsize_x * ammo1, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+
+// Right gunner slot occupied?
+       if(AuxiliaryXhair[1].draw2d == Draw_Not)
+       {
+               shield = (picsize_x * 0.5) - (0.5 * stringwidth(_("No right gunner!"), FALSE, '1 0 0' * picsize_y + '0 1 0' * picsize_y));                              
+               drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
+               drawstring(hudloc + picloc + '1 0 0' * shield, _("No right gunner!"), '1 0 0' * picsize_y + '0 1 0' * picsize_y, '1 0 0' + '0 1 1' * sin(time * 10), 1, DRAWFLAG_NORMAL);
+       }
+       
+// ..  and icon
+    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(ammo1 < 0.2)
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+       
+// Gunner2 bar
+    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x, picloc_y, picsize_x * ammo2, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// Left gunner slot occupied?
+       if(AuxiliaryXhair[2].draw2d == Draw_Not)
+       {
+               shield = (picsize_x * 0.5) - (0.5 * stringwidth(_("No left gunner!"), FALSE, '1 0 0' * picsize_y + '0 1 0' * picsize_y));                               
+               drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
+               drawstring(hudloc + picloc + '1 0 0' * shield, _("No left gunner!"), '1 0 0' * picsize_y + '0 1 0' * picsize_y, '1 0 0' + '0 1 1' * sin(time * 10), 1, DRAWFLAG_NORMAL);
+       }
+
+// ..  and icon
+    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
+    if(ammo2 < 0.2)
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    else
+    {
+        picsize = draw_getimagesize(waki_xhair);
+        picsize_x *= 0.5;
+        picsize_y *= 0.5;
+        drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    }
+    
+}
+
+void CSQC_BUMBLE_GUN_HUD()
+{
+
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc, pic2size, picloc;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc_y = vid_conheight - picsize_y;
+    hudloc_x = vid_conwidth * 0.5 - picsize_x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    energy  *= 0.01;
+    reload1 *= 0.01;
+
+    pic2size = draw_getimagesize(bumb_gun_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+    
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, bumb_gun_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, bumb_gun_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+    
+    drawpic(hudloc + picloc, bumb_gun_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTN_NONE);
+        }
+        
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }        
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE);
+            alarm1time = 0;
+        }        
+    }
+
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {            
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE);
+            alarm2time = 0;
+        }
+    }
+    
+// Gun bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc_x + picloc_x, picloc_y, picsize_x * energy, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+    
+// ..  and icon
+    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(energy < 0.2)
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    /*
+    else
+    {
+        picsize = draw_getimagesize(waki_xhair);
+        picsize_x *= 0.5;
+        picsize_y *= 0.5;
+
+
+        drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    }
+    */
 }
 
 
-#define spider_ico  "gfx/vehicles/sbot.tga"
-#define spider_rkt  "gfx/vehicles/sbot_rpods.tga"
-#define spider_mgun "gfx/vehicles/sbot_mguns.tga"
-#define spider_xhair "gfx/vehicles/axh-special1.tga"
-float alarm1time;
-float alarm2time;
 
 void CSQC_SPIDER_HUD()
 {
@@ -195,11 +515,6 @@ void CSQC_SPIDER_HUD()
 
     drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
 
-    //drawstring(hudloc + '145 19  0', strcat(ftos(vh_health), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL);
-    //drawstring(hudloc + '175 34  0', strcat(ftos(shield), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL);
-    //drawstring(hudloc + '136 102  0', strcat(ftos(ammo1), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL);
-    //drawstring(hudloc + '179 69  0', strcat(ftos(9 - ammo2), " / 8"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL);
-
     ammo1   *= 0.01;
     shield  *= 0.01;
     vh_health  *= 0.01;
@@ -269,7 +584,6 @@ void CSQC_SPIDER_HUD()
             alarm2time = 0;
         }
     }
-    
 
 // Minigun bar
     picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
@@ -324,6 +638,21 @@ void CSQC_SPIDER_HUD()
                HUD_DrawScoreboard();
     else
     {
+        switch(weapon2mode)
+        {
+            case SBRM_VOLLY:
+                spider_xhair = "gfx/vehicles/axh-bracket.tga";
+                break;
+            case SBRM_GUIDE:
+                spider_xhair = "gfx/vehicles/axh-cross.tga";
+                break;
+            case SBRM_ARTILLERY:
+                spider_xhair = "gfx/vehicles/axh-tag.tga";
+                break;
+            default:
+                spider_xhair= "gfx/vehicles/axh-tag.tga";
+        }
+
         picsize = draw_getimagesize(spider_xhair);
         picsize_x *= autocvar_cl_vehicle_spiderbot_cross_size;
         picsize_y *= autocvar_cl_vehicle_spiderbot_cross_size;
@@ -332,11 +661,6 @@ void CSQC_SPIDER_HUD()
     }
 }
 
-#define raptor_ico  "gfx/vehicles/raptor.tga"
-#define raptor_gun  "gfx/vehicles/raptor_guns.tga"
-#define raptor_bomb "gfx/vehicles/raptor_bombs.tga"
-#define raptor_drop "gfx/vehicles/axh-dropcross.tga"
-#define raptor_xhair "gfx/vehicles/axh-ring.tga"
 void CSQC_RAPTOR_HUD()
 {
        if(autocvar_r_letterbox)
@@ -455,55 +779,64 @@ void CSQC_RAPTOR_HUD()
         drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
     else
         drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-// Bombing crosshair
-    if(!dropmark)
+    
+    if(weapon2mode == RSM_FLARE)
     {
-        dropmark = spawn();
-        dropmark.owner = self;
-        dropmark.gravity = 1;
+        raptor_xhair =  "gfx/vehicles/axh-bracket.tga";
     }
-
-    if(reload2 == 100)
+    else
     {
-        vector where;
+        raptor_xhair =  "gfx/vehicles/axh-ring.tga";
+        
+        // Bombing crosshair
+        if(!dropmark)
+        {
+            dropmark = spawn();
+            dropmark.owner = self;
+            dropmark.gravity = 1;
+        }
 
-        setorigin(dropmark, pmove_org);
-        dropmark.velocity = pmove_vel;
-        tracetoss(dropmark, self);
+        if(reload2 == 100)
+        {
+            vector where;
 
-        where = project_3d_to_2d(trace_endpos);
+            setorigin(dropmark, pmove_org);
+            dropmark.velocity = pmove_vel;
+            tracetoss(dropmark, self);
 
-        setorigin(dropmark, trace_endpos);
-        picsize = draw_getimagesize(raptor_drop) * 0.2;
+            where = project_3d_to_2d(trace_endpos);
 
-        if not (where_z < 0 || where_x < 0 || where_y < 0 || where_x > vid_conwidth || where_y > vid_conheight)
-        {
-            where_x -= picsize_x * 0.5;
-            where_y -= picsize_y * 0.5;
-            where_z = 0;
-            drawpic(where, raptor_drop, picsize, '0 2 0', 1, DRAWFLAG_ADDITIVE);
-        }
-        dropmark.cnt = time + 5;
-    }
-    else
-    {
-        vector where;
-        if(dropmark.cnt > time)
-        {
-            where = project_3d_to_2d(dropmark.origin);
-            picsize = draw_getimagesize(raptor_drop) * 0.25;
+            setorigin(dropmark, trace_endpos);
+            picsize = draw_getimagesize(raptor_drop) * 0.2;
 
             if not (where_z < 0 || where_x < 0 || where_y < 0 || where_x > vid_conwidth || where_y > vid_conheight)
             {
                 where_x -= picsize_x * 0.5;
                 where_y -= picsize_y * 0.5;
                 where_z = 0;
-                drawpic(where, raptor_drop, picsize, '2 0 0', 1, DRAWFLAG_ADDITIVE);
+                drawpic(where, raptor_drop, picsize, '0 2 0', 1, DRAWFLAG_ADDITIVE);
+            }
+            dropmark.cnt = time + 5;
+        }
+        else
+        {
+            vector where;
+            if(dropmark.cnt > time)
+            {
+                where = project_3d_to_2d(dropmark.origin);
+                picsize = draw_getimagesize(raptor_drop) * 0.25;
+
+                if not (where_z < 0 || where_x < 0 || where_y < 0 || where_x > vid_conwidth || where_y > vid_conheight)
+                {
+                    where_x -= picsize_x * 0.5;
+                    where_y -= picsize_y * 0.5;
+                    where_z = 0;
+                    drawpic(where, raptor_drop, picsize, '2 0 0', 1, DRAWFLAG_ADDITIVE);
+                }
             }
         }
     }
-
+    
        if (scoreboard_showscores)
                HUD_DrawScoreboard();
     else
@@ -516,11 +849,6 @@ void CSQC_RAPTOR_HUD()
     }
 }
 
-#define waki_ico "gfx/vehicles/waki.tga"
-#define waki_eng "gfx/vehicles/waki_e.tga"
-#define waki_gun "gfx/vehicles/waki_guns.tga"
-#define waki_rkt "gfx/vehicles/waki_rockets.tga"
-#define waki_xhair "gfx/vehicles/axh-special1.tga"
 void CSQC_WAKIZASHI_HUD()
 {
 /*
@@ -660,13 +988,6 @@ void CSQC_WAKIZASHI_HUD()
 
 void Vehicles_Precache()
 {
-// fixme: HAAAAKKKZZZ!!!!!!!!!!!! (this belongs as a setting in default.cfg)
-    autocvar_cl_vehicles_hudscale = 0.5;
-    autocvar_cl_vehicles_hudalpha = 0.75;
-
-
-       precache_model("models/vehicles/wakizashi.dpm");
-
        precache_model("models/vehicles/bomblet.md3");
        precache_model("models/vehicles/clusterbomb.md3");
        precache_model("models/vehicles/clusterbomb_fragment.md3");
@@ -679,15 +1000,15 @@ void Vehicles_Precache()
 
 void RaptorCBShellfragDraw()
 {
-       
-       Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
        if(wasfreed(self))
-               return;     
-
+               return;   
+               
+       Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
        self.move_avelocity += randomvec() * 15;
        self.renderflags = 0;
+       
        if(self.cnt < time)
-       self.alpha = bound(0, self.nextthink - time, 1);
+               self.alpha = bound(0, self.nextthink - time, 1);
 
        if(self.alpha < ALPHA_MIN_VISIBLE)
         remove(self);
index 78ddc8b793c22f4b080100ace1df2a94538979be..513c66eb8b9ca96623a1eb7c55ccab0de2e38103 100644 (file)
@@ -595,6 +595,7 @@ void Draw_WaypointSprite()
        if(autocvar_g_waypointsprite_uppercase)
                txt = strtoupper(txt);
 
+       draw_beginBoldFont();
        if(self.health >= 0)
        {
                o = drawspritetext(o, ang, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
@@ -630,6 +631,7 @@ void Draw_WaypointSprite()
        {
                o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
        }
+       draw_endBoldFont();
 }
 
 void Ent_RemoveWaypointSprite()
index 067cd8054de6f311d562bf427190fd806ef1de79..5ab3da67cff47e58a34f3731b1d330d256bb3526 100644 (file)
@@ -38,13 +38,12 @@ float CampaignFile_Load(float offset, float n)
                        {
                                entlen = tokenize(l); // using insane tokenizer for CSV
 
-#define CAMPAIGN_GETARG0                  if(i >= entlen)
-#define CAMPAIGN_GETARG1 CAMPAIGN_GETARG0     error("syntax error in campaign file: line has not enough fields");
-#define CAMPAIGN_GETARG2 CAMPAIGN_GETARG1 a = argv(++i);
-#define CAMPAIGN_GETARG3 CAMPAIGN_GETARG2 if(a == ",")
-#define CAMPAIGN_GETARG4 CAMPAIGN_GETARG3     a = "";
-#define CAMPAIGN_GETARG5 CAMPAIGN_GETARG4 else
-#define CAMPAIGN_GETARG  CAMPAIGN_GETARG5     ++i
+#define CAMPAIGN_GETARG \
+       a = argv(++i); \
+       if(a == ",") \
+               a = ""; \
+       else \
+               ++i
 // What you're seeing here is what people will do when your compiler supports
 // C-style macros but no line continuations.
 
@@ -58,6 +57,10 @@ float CampaignFile_Load(float offset, float n)
                                CAMPAIGN_GETARG; campaign_mutators[campaign_entries] = strzone(a);
                                CAMPAIGN_GETARG; campaign_shortdesc[campaign_entries] = strzone(a);
                                CAMPAIGN_GETARG; campaign_longdesc[campaign_entries] = strzone(strreplace("\\n", "\n", a));
+
+                               if(i > entlen)
+                                       error("syntax error in campaign file: line has not enough fields");
+
                                campaign_entries = campaign_entries + 1;
 
                                if(campaign_entries >= n)                               
index 73fe45c406ab789e195718107e801a4ac5f91a6f..b7b8da0e9f407f64da0bab06bc3dae90c7d4c528 100644 (file)
@@ -263,6 +263,7 @@ void GenericCommand_maplist(float request, float argc)
                                        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
                                        argc = tokenizebyseparator(cvar_string("g_maplist"), " ");
                                        
+                                       tmp_string = "";
                                        for(i = 0; i < argc; ++i)
                                                if(MapInfo_CheckMap(argv(i)))
                                                        tmp_string = strcat(tmp_string, " ", argv(i));
@@ -279,6 +280,7 @@ void GenericCommand_maplist(float request, float argc)
                                        {
                                                argc = tokenizebyseparator(cvar_string("g_maplist"), " ");
                                                
+                                               tmp_string = "";
                                                for(i = 0; i < argc; ++i)
                                                        if(argv(i) != argv(2))
                                                                tmp_string = strcat(tmp_string, " ", argv(i));
@@ -349,6 +351,7 @@ void GenericCommand_removefromlist(float request, float argc)
                                
                                argc = tokenizebyseparator(cvar_string(original_cvar), " ");
                                
+                               tmp_string = "";
                                for(i = 0; i < argc; ++i)
                                        if(argv(i) != removal)
                                                tmp_string = strcat(tmp_string, " ", argv(i));
index cb1a8cc37144eb23c069b6b1294ccb5510073520..d1562aaac4222c1ebf8eedbbfdf60f7d22ffc001 100644 (file)
@@ -51,6 +51,7 @@ void GenericCommand_markup_init()
        markup_from[i] = "&.."; markup_to[i] = "\x9e"; ++i;
        markup_from[i] = "&.)"; markup_to[i] = "\x9f"; ++i;
        markup_from[i] = "&<|"; markup_to[i] = "\xff"; ++i;
+       unused_float = i;
 }
 
 string GenericCommand_markup(string s2)
index c15a8d26ef79f0094de66fb91b95d2e8dc11798d..5cca2db1ce666145fb7f339925daacaf3ce8f756 100644 (file)
@@ -236,9 +236,9 @@ void GenericCommand_rpn(float request, float argc, string command)
                                                        i = stof(db_get(rpn_db, "stack.pointer"));
                                                        db_put(rpn_db, "stack.pointer", ftos(i+1));
                                                        db_put(rpn_db, strcat("stack.", ftos(i)), s);
+                                                       if(!i)
+                                                               db_put(rpn_db, "stack.pos", "0");
                                                }
-                                               if(!i)
-                                                       db_put(rpn_db, "stack.pos", "0");
                                        } else if(rpncmd == "dbpop") {
                                                i = stof(db_get(rpn_db, "stack.pointer"));
                                                if(i)
@@ -556,4 +556,4 @@ void GenericCommand_rpn(float request, float argc, string command)
                        return;
                }
        }
-}
\ No newline at end of file
+}
index e70a83c391d7b992ce0091e91efc89504fa31c4d..9717905b6e0f61c5d8a863a0467b9ae4826446eb 100644 (file)
@@ -97,6 +97,8 @@ const float ENT_CLIENT_ACCURACY = 30;
 const float ENT_CLIENT_SHOWNAMES = 31;
 const float ENT_CLIENT_WARPZONE_TELEPORTED = 32;
 const float ENT_CLIENT_MODEL = 33;
+const float ENT_CLIENT_ITEM = 34;
+const float ENT_CLIENT_BUMBLE_RAYGUN = 35;
 
 const float ENT_CLIENT_TURRET = 40;
 const float ENT_CLIENT_AUXILIARYXHAIR = 50;
@@ -127,6 +129,8 @@ const float KEY_LEFT                =       4;
 const float KEY_RIGHT          =       8;
 const float KEY_JUMP           =       16;
 const float KEY_CROUCH         =       32;
+const float KEY_ATCK           =       64;
+const float KEY_ATCK2          =       128;
 
 ///////////////////////////
 // cvar constants
@@ -180,7 +184,8 @@ const float HUD_SPIDERBOT       = 10;
 const float HUD_WAKIZASHI       = 11;
 const float HUD_RAPTOR          = 12;
 const float HUD_BUMBLEBEE       = 13;
-const float HUD_VEHICLE_LAST    = 13;
+const float HUD_BUMBLEBEE_GUN   = 14;
+const float HUD_VEHICLE_LAST    = 14;
 
 const vector eX = '1 0 0';
 const vector eY = '0 1 0';
@@ -346,6 +351,9 @@ float PROJECTILE_SPIDERROCKET   = 27;
 float PROJECTILE_WAKIROCKET     = 28;
 float PROJECTILE_WAKICANNON     = 29;
 
+float PROJECTILE_BUMBLE_GUN     = 30;
+float PROJECTILE_BUMBLE_BEAM    = 31;
+
 float SPECIES_HUMAN        =  0;
 float SPECIES_ROBOT_SOLID  =  1;
 float SPECIES_ALIEN        =  2;
@@ -388,8 +396,12 @@ float  DEATH_WAKIBLOWUP    = 10036;
 float  DEATH_RAPTOR_CANNON = 10037;
 float  DEATH_RAPTOR_BOMB   = 10038;
 float  DEATH_RAPTOR_BOMB_SPLIT = 10039;
-float  DEATH_RAPTOR_DEATH  = 10040;
-float  DEATH_VHLAST        = 10040;
+float  DEATH_RAPTOR_DEATH   = 10040;
+float  DEATH_BUMB_GUN       = 10041;
+float  DEATH_BUMB_RAY       = 10042;
+float  DEATH_BUMB_RAY_HEAL  = 10043;
+float  DEATH_BUMB_DEATH     = 10044;
+float  DEATH_VHLAST         = 10044;
 #define DEATH_ISVEHICLE(t)  ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST)
 
 float DEATH_GENERIC = 10050;
index 1282d428af96e139049298a6bd2630cf9437d5e8..0aebde0af256b3a4a63d8a260030a9df429202c4 100644 (file)
@@ -43,7 +43,7 @@ void register_weapons_done()
        dummy_weapon_info.weapon = 0; // you can recognize dummies by this
        WEPSET_CLEAR_E(dummy_weapon_info);
        dummy_weapon_info.netname = "";
-       dummy_weapon_info.message = "@!#%'n Tuba";
+       dummy_weapon_info.message = "AOL CD Thrower";
        dummy_weapon_info.items = 0;
        dummy_weapon_info.weapon_func = w_null;
        dummy_weapon_info.mdl = "";
index 5a39d2148c045b1d155250cf8ae71432adbab85a..33fa21f7eeef5fb96bb0986971ce5223f27d0979 100644 (file)
@@ -101,11 +101,16 @@ float WEP_LAST;
 # define WEPSET_BIT(a)                  power2of((a) - WEP_FIRST)
 # define WEPSET_DECLARE_A(a)            float _WS_##a
 # define WEPSET_CLEAR_E(e)              ((e)._WS_weapons = 0)
-# define WEPSET_CLEAR_A(a)              ((_WS_##a) = 0)
+# define WEPSET_CLEAR_A(a)              (_WS_##a = 0)
 # define WEPSET_EMPTY_E(e)              ((e)._WS_weapons == 0)
-# define WEPSET_EMPTY_A(a)              ((_WS_##a) == 0)
-# define WEPSET_COPY_AS(a)              ((_WS_##a) = getstati(STAT_WEAPONS))
+# define WEPSET_EMPTY_A(a)              (_WS_##a == 0)
+# define WEPSET_COPY_AS(a)              (_WS_##a = getstati(STAT_WEAPONS))
 # define WEPSET_ADDSTAT()               addstat(STAT_WEAPONS, AS_INT, _WS_weapons)
+# define WEPSET_WRITE_E(dest,a)         WriteInt24_t(dest, (a)._WS_weapons)
+# define WEPSET_WRITE_A(dest,a)         WriteInt24_t(dest, _WS_##a)
+# define WEPSET_WRITE_W(dest,a)         WriteInt24_t(dest, WEPSET_BIT(a))
+# define WEPSET_READ_E(a)               (a)._WS_weapons = ReadInt24_t()
+# define WEPSET_READ_A(a)               (_WS_##a) = ReadInt24_t()
 # define WEPSET_OP1_EE(a,b,mergeop,x)   ((a)._WS_weapons x (b)._WS_weapons)
 # define WEPSET_OP2_EE(a,b,mergeop,x,y) ((a)._WS_weapons x (b)._WS_weapons y (a)._WS_weapons)
 # define WEPSET_OP1_EA(a,b,mergeop,x)   ((a)._WS_weapons x _WS_##b)
@@ -132,6 +137,11 @@ float WEP_LAST;
 # define WEPSET_EMPTY_A(a)              ((_WS1_##a) == 0 && (_WS2_##a) == 0)
 # define WEPSET_COPY_AS(a)              ((_WS1_##a) = getstati(STAT_WEAPONS), (_WS2_##a) = getstati(STAT_WEAPONS2))
 # define WEPSET_ADDSTAT()               addstat(STAT_WEAPONS, AS_INT, _WS1_weapons); addstat(STAT_WEAPONS2, AS_INT, _WS2_weapons)
+# define WEPSET_WRITE_E(dest,a)         WriteInt24_t(dest, (a)._WS1_weapons); WriteInt24_t(dest, (a)._WS2_weapons)
+# define WEPSET_WRITE_A(dest,a)         WriteInt24_t(dest, _WS1_##a); WriteInt24_t(dest, _WS2_##a)
+# define WEPSET_WRITE_W(dest,a)         WriteInt24_t(dest, WEPSET_BIT1(a)); WriteInt24_t(dest, WEPSET_BIT2(a))
+# define WEPSET_READ_E(a)               (a)._WS1_weapons = ReadInt24_t(); (a)._WS2_weapons = ReadInt24_t()
+# define WEPSET_READ_A(a)               (_WS1_##a) = ReadInt24_t(); (_WS2_##a) = ReadInt24_t()
 # define WEPSET_OP1_EE(a,b,mergeop,x)   (((a)._WS1_weapons x (b)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons))
 # define WEPSET_OP2_EE(a,b,mergeop,x,y) (((a)._WS1_weapons x (b)._WS1_weapons y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons y (a)._WS2_weapons))
 # define WEPSET_OP1_EA(a,b,mergeop,x)   (((a)._WS1_weapons x _WS1_##b) mergeop ((a)._WS2_weapons x _WS2_##b))
index 166acac675b08c52bf38988e23ea46bc534a7f19..05c93865dbcceed7c2606d9cb567b727e3fe8ad7 100644 (file)
@@ -242,6 +242,8 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
        spawnpoints = 0;
        spawnplaces = 0;
        _MapInfo_Map_worldspawn_music = "";
+       mapMins = '0 0 0';
+       mapMaxs = '0 0 0';
 
        for(;;)
        {
@@ -943,7 +945,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, float pAllowGenerate, flo
                        MapInfo_Map_author = s;
                else if(t == "has")
                {
-                       t = car(s); s = cdr(s);
+                       t = car(s); // s = cdr(s);
                        if     (t == "weapons") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_WEAPONS;
                        else if(t == "turrets") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_TURRETS;
                        else if(t == "vehicles") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_VEHICLES;
index 698bd7e40ace811727cf2588b1c62e92ee4213e9..bd67f67a825104abcd3108d8096d501fa8a27762 100644 (file)
@@ -1,4 +1,4 @@
-var float MAPINFO_TYPE_ALL = 0;
+float MAPINFO_TYPE_ALL;
 entity MapInfo_Type_first;
 entity MapInfo_Type_last;
 .entity enemy; // internal next pointer
index 582777647c9fcd2e2798baa4c695ecea269d3969..6e534ffc19464a92777b956353b926f48ddd578e 100644 (file)
@@ -859,6 +859,8 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
 {
        float created_saved_value;
        entity e;
+
+       created_saved_value = FALSE;
        
        if not(tmp_cvar || tmp_value)
        {
@@ -1578,6 +1580,109 @@ vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0
        return v;
 }
 
+vector solve_shotdirection(vector myorg, vector myvel, vector eorg, vector evel, float spd, float newton_style)
+{
+       vector ret;
+
+       // make origin and speed relative
+       eorg -= myorg;
+       if(newton_style)
+               evel -= myvel;
+
+       // now solve for ret, ret normalized:
+       //   eorg + t * evel == t * ret * spd
+       // or, rather, solve for t:
+       //   |eorg + t * evel| == t * spd
+       //   eorg^2 + t^2 * evel^2 + 2 * t * (eorg * evel) == t^2 * spd^2
+       //   t^2 * (evel^2 - spd^2) + t * (2 * (eorg * evel)) + eorg^2 == 0
+       vector solution = solve_quadratic(evel * evel - spd * spd, 2 * (eorg * evel), eorg * eorg);
+       // p = 2 * (eorg * evel) / (evel * evel - spd * spd)
+       // q = (eorg * eorg) / (evel * evel - spd * spd)
+       if(!solution_z) // no real solution
+       {
+               // happens if D < 0
+               // (eorg * evel)^2 < (evel^2 - spd^2) * eorg^2
+               // (eorg * evel)^2 / eorg^2 < evel^2 - spd^2
+               // spd^2 < ((evel^2 * eorg^2) - (eorg * evel)^2) / eorg^2
+               // spd^2 < evel^2 * (1 - cos^2 angle(evel, eorg))
+               // spd^2 < evel^2 * sin^2 angle(evel, eorg)
+               // spd < |evel| * sin angle(evel, eorg)
+               return '0 0 0';
+       }
+       else if(solution_x > 0)
+       {
+               // both solutions > 0: take the smaller one
+               // happens if p < 0 and q > 0
+               ret = normalize(eorg + solution_x * evel);
+       }
+       else if(solution_y > 0)
+       {
+               // one solution > 0: take the larger one
+               // happens if q < 0 or q == 0 and p < 0
+               ret = normalize(eorg + solution_y * evel);
+       }
+       else
+       {
+               // no solution > 0: reject
+               // happens if p > 0 and q >= 0
+               // 2 * (eorg * evel) / (evel * evel - spd * spd) > 0
+               // (eorg * eorg) / (evel * evel - spd * spd) >= 0
+               //
+               // |evel| >= spd
+               // eorg * evel > 0
+               //
+               // "Enemy is moving away from me at more than spd"
+               return '0 0 0';
+       }
+
+       // NOTE: we always got a solution if spd > |evel|
+
+       if(newton_style == 2)
+               ret = normalize(ret * spd + myvel);
+
+       return ret;
+}
+
+vector get_shotvelocity(vector myvel, vector mydir, float spd, float newton_style, float mi, float ma)
+{
+       if(!newton_style)
+               return spd * mydir;
+
+       if(newton_style == 2)
+       {
+               // true Newtonian projectiles with automatic aim adjustment
+               //
+               // solve: |outspeed * mydir - myvel| = spd
+               // outspeed^2 - 2 * outspeed * (mydir * myvel) + myvel^2 - spd^2 = 0
+               // outspeed = (mydir * myvel) +- sqrt((mydir * myvel)^2 - myvel^2 + spd^2)
+               // PLUS SIGN!
+               // not defined?
+               // then...
+               // myvel^2 - (mydir * myvel)^2 > spd^2
+               // velocity without mydir component > spd
+               // fire at smallest possible spd that works?
+               // |(mydir * myvel) * myvel - myvel| = spd
+
+               vector solution = solve_quadratic(1, -2 * (mydir * myvel), myvel * myvel - spd * spd);
+
+               float outspeed;
+               if(solution_z)
+                       outspeed = solution_y; // the larger one
+               else
+               {
+                       //outspeed = 0; // slowest possible shot
+                       outspeed = solution_x; // the real part (that is, the average!)
+                       //dprint("impossible shot, adjusting\n");
+               }
+
+               outspeed = bound(spd * mi, outspeed, spd * ma);
+               return mydir * outspeed;
+       }
+
+       // real Newtonian
+       return myvel + spd * mydir;
+}
+
 void check_unacceptable_compiler_bugs()
 {
        if(cvar("_allow_unacceptable_compiler_bugs"))
@@ -1825,6 +1930,7 @@ float matchacl(string acl, string str)
        while(acl)
        {
                t = car(acl); acl = cdr(acl);
+
                d = 1;
                if(substring(t, 0, 1) == "-")
                {
@@ -1833,10 +1939,11 @@ float matchacl(string acl, string str)
                }
                else if(substring(t, 0, 1) == "+")
                        t = substring(t, 1, strlen(t) - 1);
+
                if(substring(t, -1, 1) == "*")
                {
                        t = substring(t, 0, strlen(t) - 1);
-                       s = substring(s, 0, strlen(t));
+                       s = substring(str, 0, strlen(t));
                }
                else
                        s = str;
@@ -2257,3 +2364,55 @@ void queue_to_execute_next_frame(string s)
        }
        to_execute_next_frame = strzone(s);
 }
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+       return
+               (((     startspeedfactor + endspeedfactor - 2
+               ) * x - 2 * startspeedfactor - endspeedfactor + 3
+               ) * x + startspeedfactor
+               ) * x;
+}
+
+float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+       if(startspeedfactor < 0 || endspeedfactor < 0)
+               return FALSE;
+
+       /*
+       // if this is the case, the possible zeros of the first derivative are outside
+       // 0..1
+       We can calculate this condition as condition 
+       if(se <= 3)
+               return TRUE;
+       */
+
+       // better, see below:
+       if(startspeedfactor <= 3 && endspeedfactor <= 3)
+               return TRUE;
+
+       // if this is the case, the first derivative has no zeros at all
+       float se = startspeedfactor + endspeedfactor;
+       float s_e = startspeedfactor - endspeedfactor;
+       if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+               return TRUE;
+
+       // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+       // we also get s_e <= 6 - se
+       // 3 * (se - 4)^2 + (6 - se)^2
+       // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+       // Therefore, above "better" check works!
+
+       return FALSE;
+
+       // known good cases:
+       // (0, [0..3])
+       // (0.5, [0..3.8])
+       // (1, [0..4])
+       // (1.5, [0..3.9])
+       // (2, [0..3.7])
+       // (2.5, [0..3.4])
+       // (3, [0..3])
+       // (3.5, [0.2..2.3])
+       // (4, 1)
+}
index 64830ca1d73330931919e01e2b5d537f8c5141ab..3ce173bf638e95d705a70042fc6bfae62f4838aa 100644 (file)
@@ -168,6 +168,9 @@ vector solve_quadratic(float a, float b, float c);
 // z = 1 if a real solution exists, 0 if not
 // if no real solution exists, x contains the real part and y the imaginary part of the complex solutions x+iy and x-iy
 
+vector solve_shotdirection(vector myorg, vector myvel, vector eorg, vector evel, float spd, float newton_style);
+vector get_shotvelocity(vector myvel, vector mydir, float spd, float newton_style, float mi, float ma);
+
 void check_unacceptable_compiler_bugs();
 
 float compressShotOrigin(vector v);
@@ -314,3 +317,20 @@ float ReadApproxPastTime();
 // execute-stuff-next-frame subsystem
 void execute_next_frame();
 void queue_to_execute_next_frame(string s);
+
+// for marking written-to values as unused where it's a good idea to do this
+noref float unused_float;
+
+
+
+// a function f with:
+// f(0) = 0
+// f(1) = 1
+// f'(0) = startspeedfactor
+// f'(1) = endspeedfactor
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x);
+
+// checks whether f'(x) = 0 anywhere from 0 to 1
+// because if this is the case, the function is not usable for platforms
+// as it may exceed 0..1 bounds, or go in reverse
+float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor);
index bf6eefa6971b0b0c3f9687c61e60608e9e13ff3d..e6e4cfe43a091e3f2fd1a5efa615a8e2d6132e66 100644 (file)
@@ -29,6 +29,10 @@ float CSQCModel_Send(entity to, float sf)
        float islocalplayer = (self == to);
        float isnolocalplayer = (isplayer && (self != to));
 
+       unused_float = isplayer;
+       unused_float = islocalplayer;
+       unused_float = isnolocalplayer;
+
        WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
        WriteShort(MSG_ENTITY, sf);
 
@@ -59,6 +63,10 @@ void CSQCModel_CheckUpdate()
        float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
        float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
 
+       unused_float = isplayer;
+       unused_float = islocalplayer;
+       unused_float = isnolocalplayer;
+
 #ifdef CSQCPLAYER_FORCE_UPDATES
        if(isplayer && time > self.csqcmodel_nextforcedupdate)
        {
index 0acf262b113f212500a08f2e511bb1b81510e569..0a5504392736ebd13e4ee1456a5bb39e80a71950 100644 (file)
@@ -593,9 +593,11 @@ float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(
 // string autocvar__cl_name;
 //NOTE: copying a string-typed autocvar to another variable/field, and then
 //changing the cvar or returning from progs is UNDEFINED. Writing to autocvar
-//globals is UNDEFINED.  Accessing autocvar globals after cvar_set()ing that
-//cvar in the same frame is IMPLEMENTATION DEFINED (an implementation may
-//either yield the previous, or the current, value). Whether autocvar globals,
+//globals is UNDEFINED. Accessing autocvar globals after changing that cvar in
+//the same frame by any means other than cvar_set() from the same QC VM is
+//IMPLEMENTATION DEFINED (an implementation may either yield the previous, or
+//the current, value). Changing them via cvar_set() in the same QC VM
+//immediately must reflect on the autocvar globals. Whether autocvar globals,
 //after restoring a savegame, have the cvar's current value, or the original
 //value at time of saving, is UNDEFINED. Restoring a savegame however must not
 //restore the cvar values themselves.
@@ -2485,6 +2487,28 @@ void(float bufhandle, float string_index) bufstr_free = #469;
 //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;
 
+//DP_QC_STRINGBUFFERS_EXT_WIP
+//idea: VorteX
+//darkplaces implementation: VorteX
+//constant definitions:
+const float MATCH_AUTO = 0;
+const float MATCH_WHOLE = 1;
+const float MATCH_LEFT = 2;
+const float MATCH_RIGHT = 3;
+const float MATCH_MIDDLE = 4;
+const float MATCH_PATTERN = 5;
+//builtin definitions:
+float(string filename, float bufhandle) buf_loadfile = #535; // append each line of file as new buffer string, return 1 if succesful
+float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile = #536; // writes buffer strings as lines, returns 1 if succesful
+float(float bufhandle, string match, float matchrule, float startpos, float step) bufstr_find = #537; // returns string index
+float(string s, string pattern, float matchrule) matchpattern = #538; // returns 0/1
+float(string s, string pattern, float matchrule, float pos) matchpatternofs = #538;
+//description:
+//provides a set of functions to manipulate with string buffers
+//pattern wildcards: * - any character (or no characters), ? - any 1 character
+//Warning: This extension is work-in-progress, it may be changed/revamped/removed at any time, dont use it if you dont want any trouble
+//wip note: UTF8 is not supported yet
+
 //DP_QC_STRREPLACE
 //idea: Sajt
 //darkplaces implementation: Sajt
diff --git a/qcsrc/fteqcc-bugs.qc b/qcsrc/fteqcc-bugs.qc
new file mode 100644 (file)
index 0000000..dd4fd45
--- /dev/null
@@ -0,0 +1,30 @@
+void error(...) = #1;
+float id(float x) { return x; }
+
+void Oassignments(float foo) // pass 1
+{
+       float bar;
+       bar = 2;
+       bar = (foo ? 0 : (foo & 1));
+       if(bar == 2)
+               error("FTEQCC SUCKS");
+}
+
+void Oreturn_only(float foo) // pass 0
+{
+       if(foo)
+       {
+               return;
+       }
+}
+
+void Oreturn_only_trap(void)
+{
+       error("FTEQCC SUCKS");
+}
+
+.float fld;
+void Ono_assignments(entity e, float wep) // pass an e with e.fld == 1, and wep == 3. e.fld will be 2 instead of 3. Observe the INDIRECT and the SUB use the same field for storage, wreaking havoc.
+{
+               ((e).fld |= id(wep - 1));
+}
index 48a45bda8465795e8883373ab088918783c4c0d3..ae84e0957da7be5efaff03271861b81b5810d6c4 100644 (file)
@@ -29,8 +29,7 @@ void AnimHost_addAnim(entity me, entity other)
 
        other.parent = me;
 
-       entity f, l;
-       f = me.firstChild;
+       entity l;
        l = me.lastChild;
 
        if(l)
@@ -50,9 +49,7 @@ void AnimHost_removeAnim(entity me, entity other)
 
        other.parent = NULL;
 
-       entity n, p, f, l;
-       f = me.firstChild;
-       l = me.lastChild;
+       entity n, p;
        n = other.nextSibling;
        p = other.prevSibling;
 
index de5d54ae1002ad79486867e1a8f4d83da5a152f0..3bcda94e692939b733c668cf09e46b27e59364c6 100644 (file)
@@ -75,8 +75,7 @@ void Keyframe_addAnim(entity me, entity other)
 
        other.parent = me;
 
-       entity f, l;
-       f = me.firstChild;
+       entity l;
        l = me.lastChild;
 
        if(l)
index 1f223f281affc2bc9ba5a42e90c1b3b3160f8981..9c0d032432f384a60299fddc697c5b2df918ee06 100644 (file)
@@ -16,11 +16,21 @@ void draw_drawMousePointer(vector where)
 
 void draw_reset(float cw, float ch, float ox, float oy)
 {
-       drawfont = FONT_USER+0;
        draw_shift = '1 0 0' * ox + '0 1 0' * oy;
        draw_scale = '1 0 0' * cw + '0 1 0' * ch;
        draw_alpha = 1;
        draw_fontscale = '1 1 0';
+       draw_endBoldFont();
+}
+
+void draw_beginBoldFont()
+{
+       drawfont = FONT_USER+3;
+}
+
+void draw_endBoldFont()
+{
+       drawfont = FONT_USER+0;
 }
 
 vector globalToBox(vector v, vector theOrigin, vector theScale)
index 301a5f440f80fbf768c77182b3f24e2207c64f5a..7178628d8b2f6e093ecc1116e976e6343244266f 100644 (file)
@@ -11,6 +11,8 @@ float draw_alpha;
 vector draw_fontscale;
 
 void draw_reset(float cw, float ch, float ox, float oy);
+void draw_beginBoldFont();
+void draw_endBoldFont();
 void draw_setMousePointer(string pic, vector theSize, vector theOffset);
 void draw_drawMousePointer(vector where);
 
index 1032e805a5017cabe92eba152d8a8f40ac4661fb..3a345a43dfa1b6f4849cc017d26469f5b0aa5d03 100644 (file)
@@ -3,6 +3,7 @@ CLASS(BorderImage) EXTENDS(Label)
        METHOD(BorderImage, configureBorderImage, void(entity, string, float, vector, string, float))
        METHOD(BorderImage, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(BorderImage, recalcPositionWithText, void(entity, string))
+       ATTRIB(BorderImage, isBold, float, 1)
        METHOD(BorderImage, draw, void(entity))
        ATTRIB(BorderImage, src, string, string_null)
        ATTRIB(BorderImage, borderHeight, float, 0)
@@ -71,15 +72,16 @@ void BorderImage_draw(entity me)
 {
        if(me.src)
                draw_BorderPicture('0 0 0', me.src, '1 1 0', me.color, 1, me.borderVec);
+
        if(me.fontSize > 0)
        {
-               vector ro, rf, df;
-
                if(me.recalcPos)
                        me.recalcPositionWithText(me, me.text);
 
                if(me.isNexposeeTitleBar)
                {
+                       vector ro, rf, df;
+
                        // me.parent.Nexposee_animationFactor 0 (small) or 1 (full)
                        // default values are for 1
                        ro = me.realOrigin;
@@ -88,18 +90,17 @@ void BorderImage_draw(entity me)
                        me.realOrigin = ro * me.parent.Nexposee_animationFactor + me.realOrigin_Nexposeed * (1 - me.parent.Nexposee_animationFactor);
                        me.realFontSize = rf * me.parent.Nexposee_animationFactor + me.realFontSize_Nexposeed * (1 - me.parent.Nexposee_animationFactor);
                        draw_fontscale = globalToBoxSize(boxToGlobalSize(df, me.realFontSize), rf);
-               }
 
-               SUPER(BorderImage).draw(me);
+                       SUPER(BorderImage).draw(me);
 
-               if(me.isNexposeeTitleBar)
-               {
                        // me.Nexposee_animationState 0 (small) or 1 (full)
                        // default values are for 1
                        me.realOrigin = ro;
                        me.realFontSize = rf;
                        draw_fontscale = df;
                }
+               else
+                       SUPER(BorderImage).draw(me);
        }
        else
        {
index 0e8fa9ea0a6d1d627e780759e33edb3dac1fa557..6241cee03968c077249d62bfbdcb8b81a91ec3a9 100644 (file)
@@ -304,8 +304,7 @@ void Container_addItem(entity me, entity other, vector theOrigin, vector theSize
        other.Container_size = theSize;
        me.setAlphaOf(me, other, theAlpha);
 
-       entity f, l;
-       f = me.firstChild;
+       entity l;
        l = me.lastChild;
 
        if(l)
@@ -330,9 +329,7 @@ void Container_removeItem(entity me, entity other)
 
        other.parent = NULL;
 
-       entity n, p, f, l;
-       f = me.firstChild;
-       l = me.lastChild;
+       entity n, p;
        n = other.nextSibling;
        p = other.prevSibling;
 
@@ -371,13 +368,11 @@ void Container_setFocus(entity me, entity other)
 void Container_moveItemAfter(entity me, entity other, entity dest)
 {
        // first: remove other from the chain
-       entity n, p, f, l;
+       entity n, p;
 
        if(other.parent != me)
                error("Can't move in wrong container!");
 
-       f = me.firstChild;
-       l = me.lastChild;
        n = other.nextSibling;
        p = other.prevSibling;
 
index da6a4013cecd772051b12c76aac0f0a74a681a1c..ed73be09501a6a81db14751e73d824b5cd1a618e 100644 (file)
@@ -124,7 +124,6 @@ void Dialog_TDempty(entity me, float colspan)
 
 void Dialog_configureDialog(entity me)
 {
-       entity closebutton;
        float absWidth, absHeight;
 
        me.frame = spawnBorderImage();
@@ -154,14 +153,13 @@ void Dialog_configureDialog(entity me)
 
        if(me.closable && me.borderLines > 0)
        {
-               closebutton = me.closeButton = spawnButton();
+               entity closebutton;
+               closebutton = me.closeButton = me.frame.closeButton = spawnButton();
                closebutton.configureButton(closebutton, "", 0, me.closeButtonImage);
                closebutton.onClick = Dialog_Close; closebutton.onClickEntity = me;
                closebutton.srcMulti = 0;
                me.addItem(me, closebutton, '0 0 0', '1 1 0', 1); // put it as LAST
        }
-
-       me.frame.closeButton = closebutton;
 }
 
 void Dialog_close(entity me)
index af6587b5a67ebca90ecdb614524bd94923b5fdd0..572d3a0710dd866bef056667cb2862165d80cf0b 100644 (file)
@@ -226,7 +226,6 @@ void InputBox_draw(entity me)
                                else if(ch2 == "x") // ^x found
                                {
                                        theColor = '1 1 1';
-                                       theTempColor = '0 0 0';
                                        
                                        component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1));
                                        if (component >= 0) // ^xr found
index e1b14d3b1602d468d08ccdf6b26ef0aaf48b43df..65129b294dd6c0229436da186734c244d30b6b6f 100644 (file)
@@ -153,8 +153,7 @@ float InputContainer_mousePress(entity me, vector pos)
 }
 float InputContainer_mouseRelease(entity me, vector pos)
 {
-       float r;
-       r = SUPER(InputContainer).mouseRelease(me, pos);
+       SUPER(InputContainer).mouseRelease(me, pos); // return value?
        if(me.focused) // am I still eligible for this? (UGLY HACK, but a mouse event could have changed focus away)
                if(me._changeFocusXY(me, pos))
                        return 1;
index e1543ce2756f60579cf1eeb1b5c79be924bc5a7b..378e74adbcb1268ddaa34d7c33af0bb9031bce2e 100644 (file)
@@ -6,6 +6,7 @@ CLASS(Label) EXTENDS(Item)
        METHOD(Label, setText, void(entity, string))
        METHOD(Label, toString, string(entity))
        METHOD(Label, recalcPositionWithText, void(entity, string))
+       ATTRIB(Label, isBold, float, 0)
        ATTRIB(Label, text, string, string_null)
        ATTRIB(Label, fontSize, float, 8)
        ATTRIB(Label, align, float, 0.5)
@@ -45,6 +46,9 @@ void Label_recalcPositionWithText(entity me, string t)
        float spaceAvail;
        spaceAvail = 1 - me.keepspaceLeft - me.keepspaceRight;
 
+       if(me.isBold)
+               draw_beginBoldFont();
+
        float spaceUsed;
        spaceUsed = draw_TextWidth(t, me.allowColors, me.realFontSize);
 
@@ -107,6 +111,9 @@ void Label_recalcPositionWithText(entity me, string t)
                me.realOrigin_y = 0.5 * (1 - lines * me.realFontSize_y);
        }
 
+       if(me.isBold)
+               draw_endBoldFont();
+
        me.recalcPos = 0;
 }
 void Label_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
@@ -153,6 +160,9 @@ void Label_draw(entity me)
                        vector dfs;
                        vector fs;
 
+                       if(me.isBold)
+                               draw_beginBoldFont();
+
                        // set up variables to draw in condensed size, but use hinting for original size
                        fs = me.realFontSize;
                        fs_x *= me.condenseFactor;
@@ -180,6 +190,9 @@ void Label_draw(entity me)
                                draw_Text(me.realOrigin, t, fs, me.colorL, me.alpha, me.allowColors);
 
                        draw_fontscale = dfs;
+
+                       if(me.isBold)
+                               draw_endBoldFont();
                }
 
        SUPER(Label).draw(me);
index 4f8dca622c239e0294ba023b68f8101f737c6f15..60da88a09ca957307f3616e57526f2e3b19a0e19 100644 (file)
@@ -167,7 +167,6 @@ float ListBox_mousePress(entity me, vector pos)
 }
 float ListBox_mouseRelease(entity me, vector pos)
 {
-       vector absSize;
        if(me.pressed == 1)
        {
                // slider dragging mode
@@ -182,7 +181,6 @@ float ListBox_mouseRelease(entity me, vector pos)
                // and give it a nice click event
                if(me.nItems > 0)
                {
-                       absSize = boxToGlobalSize(me.size, eX * (1 - me.controlWidth) + eY * me.itemHeight);
                        me.clickListBoxItem(me, me.selectedItem, globalToBox(pos, eY * (me.selectedItem * me.itemHeight - me.scrollPos), eX * (1 - me.controlWidth) + eY * me.itemHeight));
                }
        }
index 4f1ff4e9edd2cb580dff3f8f304dc39748aa1b6b..5a5541dc7b0da4706800380998b531d67e5de329 100644 (file)
@@ -144,6 +144,7 @@ void ModalController_draw(entity me)
        vector fs;
        animating = 0;
 
+       front = world;
        for(e = me.firstChild; e; e = e.nextSibling)
                if(e.ModalController_state)
                {
index 02f12242525835f1735029b0eda0365f03907faf..8f8f45119f8744bd74d900776d4b97015bc25406 100644 (file)
@@ -305,6 +305,7 @@ float Nexposee_keyDown(entity me, float scan, float ascii, float shift)
        }
        switch(me.animationState)
        {
+               default:
                case 0:
                case 3:
                        nexposeeKey = ((scan == K_SPACE) || (scan == K_ENTER) || (scan == K_KP_ENTER));
@@ -318,6 +319,7 @@ float Nexposee_keyDown(entity me, float scan, float ascii, float shift)
        {
                switch(me.animationState)
                {
+                       default:
                        case 0:
                        case 3:
                                me.animationState = 1;
index b541a7f0639f973e1063ba0c90f3af994973c21d..b4c7ce746a8cd749a1eeed4cfd8d2d9b08b23da3 100644 (file)
@@ -344,6 +344,7 @@ void drawBackground(string img, float a, string algn, float force1)
 
        scalemode = SCALEMODE_CROP;
 
+       l = 0;
        for(i = 0; i < strlen(algn); ++i)
        {
                c = substring(algn, i, 1);
index 4e81a4acc24d2aa7d5ecce525e54d15090e307ce..e0f4c5b2e4c616e02ea7eca35595969d5953618a 100644 (file)
@@ -70,6 +70,9 @@ void XonoticColorButton_loadCvars(entity me)
        if not(me.cvarName)
                return;
 
+       if(cvar_string(me.cvarName) == cvar_defstring(me.cvarName))
+               cvar_set(me.cvarName, ftos(16 * floor(random() * 15) + floor(random() * 15)));
+
        if(me.cvarPart == 1)
                me.checked = (cvar(me.cvarName) & 240) == me.cvarValueFloat * 16;
        else
index 226f346b643ae55e715a7b5e5cf87eea887412cf..3fcabaaab6f8aa2e25030b7e420c45b52f308baf 100644 (file)
@@ -25,36 +25,36 @@ void XonoticAdvancedDialog_fill(entity me)
                me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Game settings:")));
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "sv_spectate", _("Allow spectating")));
+               me.TD(me, 1, 2.8, makeXonoticCheckBox(0, "sv_spectate", _("Allow spectating")));
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Spawn shield:")));
-               me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime"));
+               me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Spawn shield:")));
+               me.TD(me, 1, 1.6, makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime"));
        me.TR(me);
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Game speed:")));
-               me.TD(me, 1, 1.6, e = makeXonoticSlider(0.5, 2.0, 0.1, "slowmo"));
+               me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Game speed:")));
+               me.TD(me, 1, 1.6, makeXonoticSlider(0.5, 2.0, 0.1, "slowmo"));
        me.TR(me);
        me.TR(me);
                me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Teamplay settings:")));
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Friendly fire scale:")));
-               me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire"));
+               me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Friendly fire scale:")));
+               me.TD(me, 1, 1.6, makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire"));
        me.TR(me);
                me.TDempty(me, 0.4);
-               me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "g_friendlyfire_virtual", _("Virtual friendly fire (effect only)")));
+               me.TD(me, 1, 2.6, makeXonoticCheckBox(0, "g_friendlyfire_virtual", _("Virtual friendly fire (effect only)")));
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Friendly fire penalty:")));
-               me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage"));
+               me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Friendly fire penalty:")));
+               me.TD(me, 1, 1.6, makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage"));
        me.TR(me);
                me.TDempty(me, 0.4);
-               me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "g_mirrordamage_virtual", _("Virtual penalty (effect only)")));
+               me.TD(me, 1, 2.6, makeXonoticCheckBox(0, "g_mirrordamage_virtual", _("Virtual penalty (effect only)")));
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Teams:")));
+               me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Teams:")));
                me.TD(me, 1, 1.6, e = makeXonoticTextSlider("g_tdm_teams_override g_domination_teams_override g_keyhunt_teams_override"));
                        e.addValue(e, "Default", "0");
                        e.addValue(e, "2 teams", "2");
@@ -63,7 +63,7 @@ void XonoticAdvancedDialog_fill(entity me)
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
        me.TR(me);
-               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Map voting:")));
+               me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Map voting:")));
                me.TD(me, 1, 2, e = makeXonoticTextSlider("g_maplist_votable"));
                        e.addValue(e, _("No voting"), "0");
                        e.addValue(e, _("2 choices"), "2");
@@ -76,7 +76,7 @@ void XonoticAdvancedDialog_fill(entity me)
                        e.addValue(e, _("9 choices"), "9");
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", _("Simple majority wins vcall")));
+               me.TD(me, 1, 3, makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", _("Simple majority wins vcall")));
 
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
index d33a1eab12d5439e5435280fd40cd3439f3503f9..ef930b4e1490fe879c28ca7a83a191f191610777 100644 (file)
@@ -31,7 +31,7 @@ void XonoticPlayerSettingsTab_draw(entity me)
 void XonoticPlayerSettingsTab_fill(entity me)
 {
        entity e, pms, label, box;
-       float i, r, m, n;
+       float i;
 
        me.TR(me);
                me.TD(me, 1, 0.5, me.playerNameLabel = makeXonoticTextLabel(0, _("Name:")));
@@ -54,34 +54,38 @@ void XonoticPlayerSettingsTab_fill(entity me)
        me.TR(me);
        me.TR(me);
        me.TR(me);
+
+       me.TR(me);
+               me.TDempty(me, 1);
+               me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Model:")));
        me.TR(me);
-       me.gotoRC(me, 8, 0.0);
+               me.TDempty(me, 1);
                pms = makeXonoticPlayerModelSelector();
-               me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, _("Model:")));
                me.TD(me, 1, 0.3, e = makeXonoticButton("<<", '0 0 0'));
                        e.onClick = PlayerModelSelector_Prev_Click;
                        e.onClickEntity = pms;
-               me.TD(me, me.rows - (me.currentRow + 2), 1.8, pms);
+               me.TD(me, me.rows - (me.currentRow + 2), 1.4, pms);
                me.TD(me, 1, 0.3, e = makeXonoticButton(">>", '0 0 0'));
                        e.onClick = PlayerModelSelector_Next_Click;
                        e.onClickEntity = pms;
        me.TR(me);
-               r = me.currentRow;
-               m = me.rows - (r + 3);
-               n = 16 - !cvar("developer");
-               m = m / (n - 1);
-               for(i = 0; i < n; ++i)
+               me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Glowing color:")));
+               for(i = 0; i < 15; ++i)
                {
-                       me.gotoRC(me, r + i * m, 0.1);
-                       me.TDNoMargin(me, m, 0.2, e = makeXonoticColorButton(1, 0, i), '0 1 0');
+                       if(mod(i, 5) == 0)
+                               me.TR(me);
+                       me.TDNoMargin(me, 1, 0.2, e = makeXonoticColorButton(1, 0, i), '0 1 0');
                }
-               for(i = 0; i < n; ++i)
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Detail color:")));
+               for(i = 0; i < 15; ++i)
                {
-                       me.gotoRC(me, r + i * m, 0.4);
-                       me.TDNoMargin(me, m, 0.2, e = makeXonoticColorButton(2, 1, i), '0 1 0');
+                       if(mod(i, 5) == 0)
+                               me.TR(me);
+                       me.TDNoMargin(me, 1, 0.2, e = makeXonoticColorButton(2, 1, i), '0 1 0');
                }
 
-
        // crosshair_enabled: 0 = no crosshair options, 1 = no crosshair selection, but everything else enabled, 2 = all crosshair options enabled
        // FIXME: In the future, perhaps make one global crosshair_type cvar which has 0 for disabled, 1 for custom, 2 for per weapon, etc?
        me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
index 1f1ee385b219b762945dee382ff2916e355a4286..174873fe7fc79f211a41d0321a1bae083b977e65 100644 (file)
@@ -114,12 +114,12 @@ void XonoticAudioSettingsTab_fill(entity me)
                setDependentStringNotEqual(s, "mastervolume", "0");
        me.TR(me);
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation")));
+               me.TD(me, 1, 3, makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation")));
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "snd_mutewhenidle", _("Mute sounds when not active")));
+               me.TD(me, 1, 3, makeXonoticCheckBox(0, "snd_mutewhenidle", _("Mute sounds when not active")));
        
        me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
-               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Frequency:")));
+               me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Frequency:")));
                me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_speed"));
                        e.addValue(e, _("8 kHz"), "8000");
                        e.addValue(e, _("11.025 kHz"), "11025");
@@ -131,7 +131,7 @@ void XonoticAudioSettingsTab_fill(entity me)
                        e.addValue(e, _("48 kHz"), "48000");
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
-               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Channels:")));
+               me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Channels:")));
                me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_channels"));
                        e.addValue(e, _("Mono"), "1");
                        e.addValue(e, _("Stereo"), "2");
@@ -148,33 +148,15 @@ void XonoticAudioSettingsTab_fill(entity me)
                me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "snd_spatialization_control", _("Headphone friendly mode")));
                setDependent(e, "snd_channels", 1.5, 0.5);
        me.TR(me);
-       /*me.TR(me); // Samual: I REALLY don't think these are relevant to anyone, and just clutter up the menu pointlessly. The defaults are fine.
-               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Spatial voices:")));
-               me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "0", ZCTX(_("VOCS^None"))));
-               me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "2", ZCTX(_("VOCS^Taunts"))));
-               me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "1", ZCTX(_("VOCS^All"))));
        me.TR(me);
-               me.TDempty(me, 0.2);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Taunt range:")));
-               setDependent(e, "cl_voice_directional", 0.5, -0.5);
-               me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_voice_directional_taunt_attenuation"));
-                       e.addValue(e, ZCTX(_("RNG^Very short")), "3");
-                       e.addValue(e, ZCTX(_("RNG^Short")), "2");
-                       e.addValue(e, ZCTX(_("RNG^Normal")), "0.5");
-                       e.addValue(e, ZCTX(_("RNG^Long")), "0.25");
-                       e.addValue(e, ZCTX(_("RNG^Full")), "0.015625");
-                       e.configureXonoticTextSliderValues(e);
-               setDependent(e, "cl_voice_directional", 0.5, -0.5);
-       me.TR(me);*/
+               me.TD(me, 1, 3, makeXonoticCheckBox(0, "cl_hitsound", _("Hit indication sound")));
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_hitsound", _("Hit indication sound")));
+               me.TD(me, 1, 3, makeXonoticCheckBox(0, "con_chatsound", _("Chat message sound")));
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_chatsound", _("Chat message sound")));
+               me.TD(me, 1, 3, makeXonoticCheckBoxEx(2, 0, "menu_sounds", _("Menu sounds")));
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "menu_sounds", _("Menu sounds")));
        me.TR(me);
-       me.TR(me);
-               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Time announcer:")));
+               me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Time announcer:")));
                me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_announcer_maptime"));
                        e.addValue(e, ZCTX(_("WRN^Disabled")), "0");
                        e.addValue(e, _("1 minute"), "1");
@@ -191,13 +173,12 @@ void XonoticAudioSettingsTab_fill(entity me)
                        e.savedValue = 0.65; // default
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Frequency:")));
+               me.TD(me, 1, 0.8, makeXonoticTextLabel(0, _("Frequency:")));
                me.TD(me, 1, 2, sl);
        me.TR(me);
        me.TR(me);
                if(cvar("developer"))
-                       me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showsound", _("Debug info about sounds")));
-       
+                       me.TD(me, 1, 3, makeXonoticCheckBox(0, "showsound", _("Debug info about sounds")));
 
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; snd_attenuation_method_$menu_snd_attenuation_method; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY));
index 5f6226f493fbee1ec5c5d1214cdf6aae16f62b1e..5be639a07559ec27058539e8c838b3526f8e8d43 100644 (file)
@@ -153,6 +153,7 @@ void XonoticLanguageList_getLanguages(entity me)
        buf = buf_create();
 
        fh = fopen("languages.txt", FILE_READ);
+       i = 0;
        while((s = fgets(fh)))
        {
                n = tokenize_console(s);
index 61eb4a681651f6cd0d82ec7cac6274c26df3e499..f37aaeb0750d8568dea1d8cf79b9a6f738bb71ff 100644 (file)
@@ -180,8 +180,13 @@ void XonoticPlayerModelSelector_draw(entity me)
 
        SUPER(XonoticPlayerModelSelector).draw(me);
        // draw text on the image, handle \n in the description
+
+       draw_beginBoldFont();
+
        draw_CenterText('0.5 0 0', me.currentModelTitle, me.realFontSize * (me.titleFontSize / me.fontSize), SKINCOLOR_MODELTITLE, SKINALPHA_MODELTITLE, FALSE);
 
+       draw_endBoldFont();
+
        o = '0.5 1 0' - eY * me.realFontSize_y * ((n = tokenizebyseparator(me.currentModelDescription, "\n")) + 0.5);
        for(i = 0; i < n; ++i)
        {
index f1d45ab5b08f88c0b0a23c5fd7fb52407ce8ac9a..44ca1b227943cf7da354dbe5219f72b387f3fa48 100644 (file)
@@ -608,6 +608,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
 
        s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
        m = tokenizebyseparator(s, ":");
+       typestr = "";
        if(m >= 2)
        {
                typestr = argv(0);
@@ -616,6 +617,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        freeslots = -1;
        sflags = -1;
        modname = "";
+       pure = 0;
        for(j = 2; j < m; ++j)
        {
                if(argv(j) == "")
index 78ac9de46c1bc96aeda3db938b27d8bc29b49cfd..4c03eaa5f9caa9edb5255ee3f4a217a904799463 100644 (file)
@@ -622,6 +622,8 @@ float GameType_GetID(float cnt)
        #define GAMETYPE(id) if(i++ == cnt) return id;
        GAMETYPES
        #undef GAMETYPE
+
+       unused_float = i;
        
        return 0;
 }
index 68ec68324d78f785ff84fde5167d7a44a0b1493a..73025f1f61004ed50996fc1dfa692aafac943895 100644 (file)
@@ -15,6 +15,9 @@ void antilag_dummy()
 
 void antilag_record(entity e, float t)
 {
+    if (e.vehicle && e.vehicle.vehicle_flags == VHF_PLAYERSLOT)
+        return;
+        
     if(e.vehicle)
         antilag_record(e.vehicle, t);
 
@@ -92,6 +95,10 @@ vector antilag_takebackavgvelocity(entity e, float t0, float t1)
 
 void antilag_takeback(entity e, float t)
 {
+
+    if (e.vehicle && e.vehicle.vehicle_flags == VHF_PLAYERSLOT)
+        return;
+
        if(e.vehicle)
                antilag_takeback(e.vehicle, t);
 
@@ -104,6 +111,9 @@ void antilag_takeback(entity e, float t)
 
 void antilag_restore(entity e)
 {
+    if (e.vehicle && e.vehicle.vehicle_flags == VHF_PLAYERSLOT)
+        return;
+
        if(e.vehicle)
                antilag_restore(e.vehicle);
 
@@ -122,7 +132,7 @@ void antilag_clear(entity e)
        for(i = 0; i < ANTILAG_MAX_ORIGINS; ++i)
        {
                e.(antilag_times[i]) = -2342;
-               e.(antilag_origins[i]) = self.origin;
+               e.(antilag_origins[i]) = e.origin;
        }
        e.antilag_index = ANTILAG_MAX_ORIGINS - 1; // next one is 0
 }
index 5e1c65f796e159525962b01e0cd69074475710f8..12a343eb726b6fac85a0ff52693bc9bec340b8d2 100644 (file)
@@ -686,8 +686,8 @@ float autocvar_g_balance_shotgun_secondary_refire;
 float autocvar_g_balance_shotgun_reload_ammo;
 float autocvar_g_balance_shotgun_reload_time;
 float autocvar_g_balance_teams;
-float autocvar_g_balance_teams_force;
 float autocvar_g_balance_teams_prevent_imbalance;
+float autocvar_g_balance_teams_scorefactor;
 float autocvar_g_balance_tuba_animtime;
 float autocvar_g_balance_tuba_attenuation;
 float autocvar_g_balance_tuba_damage;
@@ -809,7 +809,6 @@ float autocvar_g_freezetag_warmup;
 float autocvar_g_full_getstatus_responses;
 float autocvar_g_fullbrightitems;
 float autocvar_g_fullbrightplayers;
-string autocvar_g_ghost_items_color;
 #define autocvar_g_grappling_hook cvar("g_grappling_hook")
 float autocvar_g_grappling_hook_tarzan;
 float autocvar_g_hitplots;
@@ -928,6 +927,7 @@ float autocvar_g_playerclip_collisions;
 string autocvar_g_playerstats_uri;
 float autocvar_g_powerups;
 float autocvar_g_projectiles_damage;
+float autocvar_g_projectiles_keep_owner;
 float autocvar_g_projectiles_newton_style;
 float autocvar_g_projectiles_newton_style_2_maxfactor;
 float autocvar_g_projectiles_newton_style_2_minfactor;
index 039e21daed025bf588322272997456ed3f2fb240..b06d578d1813b096ea7a49e2475e3ce59dfea55c 100644 (file)
@@ -128,7 +128,10 @@ void bot_setnameandstuff()
        file = fopen(autocvar_bot_config_file, FILE_READ);
 
        if(file < 0)
+       {
                print(strcat("Error: Can not open the bot configuration file '",autocvar_bot_config_file,"'\n"));
+               readfile = "";
+       }
        else
        {
                RandomSelection_Init();
index 18e4341718e67e698e12c76045a8d035418e8af8..e03cbac66a5937baa08cea8a4cd3575a6675c057 100644 (file)
@@ -493,8 +493,8 @@ void havocbot_movetogoal()
                {
                        if(fabs(self.velocity_z)<50)
                        {
-                               entity head, newgoal;
-                               float distance, bestdistance;
+                               entity head, newgoal = world;
+                               float distance, bestdistance = 0;
 
                                for (head = findchain(classname, "waypoint"); head; head = head.chain)
                                {
@@ -908,7 +908,7 @@ void havocbot_chooseenemy()
 
        self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
 
-       for(;;)
+       for(i = 0; ; ++i)
        {
                while (head)
                {
@@ -939,7 +939,6 @@ void havocbot_chooseenemy()
                self.dphitcontentsmask |= DPCONTENTS_OPAQUE;
 
                head = head2;
-               ++i;
        }
 
        // Restore hit flags
@@ -960,7 +959,7 @@ float havocbot_chooseweapon_checkreload(float new_weapon)
        // if this weapon is scheduled for reloading, don't switch to it during combat
        if (self.weapon_load[new_weapon] < 0)
        {
-               float i, other_weapon_available;
+               float i, other_weapon_available = FALSE;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
                        // if we are out of ammo for all other weapons, it's an emergency to switch to anything else
index 74c611ea18ddf6bdfe8f54dc94c3de1c29c59c57..178ee0da6e8cfe236be697a433ba96a6c4a4cb55 100644 (file)
@@ -60,7 +60,7 @@ float havocbot_ctf_teamcount(entity bot, vector org, float radius)
        if not(teamplay)
                return 0;
 
-       float c;
+       float c = 0;
        entity head;
 
        FOR_EACH_PLAYER(head)
@@ -562,9 +562,8 @@ void havocbot_role_ctf_defense()
                navigation_goalrating_start();
 
                // if enemies are closer to our base, go there
-               entity head, closestplayer;
-               float distance, bestdistance;
-               distance = 10000;
+               entity head, closestplayer = world;
+               float distance, bestdistance = 10000;
                FOR_EACH_PLAYER(head)
                {
                        if(head.deadflag!=DEAD_NO)
@@ -596,20 +595,21 @@ void havocbot_role_ctf_defense()
 void havocbot_calculate_middlepoint()
 {
        entity f;
-       vector p1, p2;
+       vector s = '0 0 0';
+       vector fo = '0 0 0';
+       float n = 0;
 
        f = ctf_worldflaglist;
        while (f)
        {
-               if(p1)
-                       p2 = f.origin;
-               else
-                       p1 = f.origin;
-
+               fo = f.origin;
+               s = s + fo;
                f = f.ctf_worldflagnext;
        }
-       havocbot_ctf_middlepoint = p1 + ((p2-p1) * 0.5);
-       havocbot_ctf_middlepoint_radius  = vlen(p2-p1) * 0.5;
+       if(!n)
+               return;
+       havocbot_ctf_middlepoint = s * (1.0 / n);
+       havocbot_ctf_middlepoint_radius  = vlen(fo - havocbot_ctf_middlepoint);
 }
 
 void havocbot_ctf_reset_role(entity bot)
index 90150e2ab3c4d027b6219c905497ea821563c858..b17697d2f8524d6ae21bc3c9dee8205161a07cf3 100644 (file)
@@ -28,13 +28,14 @@ void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplay
 void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
 {
        entity head;
-       float t, i, c, needarmor, needweapons;
+       float t, i, c, needarmor = FALSE, needweapons = FALSE;
 
        // Needs armor/health?
        if(self.health<100)
                needarmor = TRUE;
 
        // Needs weapons?
+       c = 0;
        for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
        {
                // Find weapon
@@ -98,7 +99,7 @@ void havocbot_role_ons_setrole(entity bot, float role)
 
 float havocbot_ons_teamcount(entity bot, float role)
 {
-       float c;
+       float c = 0;
        entity head;
 
        FOR_EACH_PLAYER(head)
@@ -152,6 +153,7 @@ void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
 
        // We'll consider only the best case
        bestvalue = 99999999999;
+       cp = world;
        for (; cp1; cp1 = cp1.chain)
        {
                if not(cp1.wpconsidered)
index bf963bc7cd703be9d53cacf49c422d0f84c726bd..a5c60e3935bca171b1e16e30971d2b34997141cd 100644 (file)
@@ -27,6 +27,7 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float
        dir = normalize(move);
        stepdist = 32;
        ignorehazards = FALSE;
+       swimming = FALSE;
 
        // Analyze starting point
        traceline(start, start, MOVE_NORMAL, e);
@@ -1218,6 +1219,7 @@ void debuggoalstack()
        else if(self.goalcounter==29)goal=self.goalstack29;
        else if(self.goalcounter==30)goal=self.goalstack30;
        else if(self.goalcounter==31)goal=self.goalstack31;
+       else goal=world;
 
        if(goal==world)
        {
index 63a6cb336d4054c90d3aa0283be057005139bed0..5752e2f499c506e42686b8770e22a925dfe18473 100644 (file)
@@ -38,9 +38,9 @@ void bot_queuecommand(entity bot, string cmdstring)
                {
                        parm = substring(cmdstr, sp + 1, -1);
                        cmdstr = substring(cmdstr, 0, sp);
+                       if(cmdstr == "sound")
+                               precache_sound(cmdstr);
                }
-               if(cmdstr == "sound")
-                       precache_sound(cmdstr);
        }
 
        bot.bot_cmdqueuebuf_end += 1;
@@ -292,7 +292,7 @@ entity find_bot_by_name(string name)
 entity find_bot_by_number(float number)
 {
        entity bot;
-       float c;
+       float c = 0;
 
        if(!number)
                return world;
index 7c2509d21a514c550e2d453e106573cc49ae3333..b69e0fbe097479687200957a1f8bef54fda96c89 100644 (file)
@@ -183,7 +183,7 @@ void CampaignPreIntermission()
        float lost;
        string savevar;
 
-       won = 0;
+       won = lost = 0;
 
        head = findchain(classname, "player");
        while(head)
index 19ee93868a59f04b69c5dd061a80a79e7e668ca9..2f6a660cb203f4debee868d307f05fd4c018e4d4 100644 (file)
@@ -749,6 +749,7 @@ float CheatFrame()
 
                                float drag;
                                crosshair_trace_plusvisibletriggers(self);
+                               drag = FALSE;
                                if(vlen(self.origin - trace_ent.origin) <= autocvar_g_grab_range)
                                {
                                        switch(trace_ent.grab)
index b68bce6949eb272048cd6594a6e9a7b81b9d2d18..7c3308041e670a8270eca36b9a660a640746a6e0 100644 (file)
@@ -415,7 +415,7 @@ void PutObserverInServer (void)
        }
 
        if(self.vehicle)
-           vehicles_exit(VHEF_RELESE);
+               vehicles_exit(VHEF_RELESE);         
 
        if(self.flagcarried)
                DropFlag(self.flagcarried, world, world);
@@ -472,6 +472,7 @@ void PutObserverInServer (void)
        self.invincible_finished = 0;
        self.superweapons_finished = 0;
        self.pushltime = 0;
+       self.istypefrag = 0;
        self.think = SUB_Null;
        self.nextthink = 0;
        self.hook_time = 0;
@@ -547,11 +548,11 @@ void FixPlayermodel()
        vector m1, m2;
 
        defaultmodel = "";
+       defaultskin = 0;
+       chmdl = FALSE;
 
        if(autocvar_sv_defaultcharacter == 1)
        {
-               defaultskin = 0;
-
                if(teamplay)
                {
                        string s;
@@ -1069,8 +1070,7 @@ void ClientKill_Now_TeamChange()
 {
        if(self.killindicator_teamchange == -1)
        {
-               self.team = -1;
-               JoinBestTeam( self, FALSE, FALSE );
+               JoinBestTeam( self, FALSE, TRUE );
        }
        else if(self.killindicator_teamchange == -2)
        {
@@ -1118,7 +1118,7 @@ void KillIndicator_Think()
                return;
        }
 
-       if (self.owner.alpha < 0)
+       if (self.owner.alpha < 0 && !self.owner.vehicle)
        {
                self.owner.killindicator = world;
                remove(self);
@@ -1439,7 +1439,7 @@ void ClientConnect (void)
        } else {
                if(teamplay)
                {
-                       if(autocvar_g_balance_teams || autocvar_g_balance_teams_force)
+                       if(autocvar_g_balance_teams)
                        {
                                self.classname = "player";
                                campaign_bots_may_start = 1;
@@ -1564,7 +1564,6 @@ void ClientConnect (void)
                        rr = CTS_RECORD;
                else
                        rr = RACE_RECORD;
-               t = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
 
                msg_entity = self;
                race_send_recordtime(MSG_ONE);
@@ -2123,6 +2122,15 @@ void GetPressedKeys(void) {
                self.pressedkeys |= KEY_CROUCH;
        else
                self.pressedkeys &~= KEY_CROUCH;
+
+       if (self.BUTTON_ATCK)
+               self.pressedkeys |= KEY_ATCK;
+       else
+               self.pressedkeys &~= KEY_ATCK;
+       if (self.BUTTON_ATCK2)
+               self.pressedkeys |= KEY_ATCK2;
+       else
+               self.pressedkeys &~= KEY_ATCK2;
 }
 
 /*
@@ -2163,29 +2171,24 @@ void SpectateCopy(entity spectatee) {
        self.minelayer_mines = spectatee.minelayer_mines;
        self.punchangle = spectatee.punchangle;
        self.view_ofs = spectatee.view_ofs;
-       self.v_angle = spectatee.v_angle;
        self.velocity = spectatee.velocity;
        self.dmg_take = spectatee.dmg_take;
        self.dmg_save = spectatee.dmg_save;
        self.dmg_inflictor = spectatee.dmg_inflictor;
+       self.v_angle = spectatee.v_angle;
        self.angles = spectatee.v_angle;
        if(!self.BUTTON_USE)
                self.fixangle = TRUE;
        setorigin(self, spectatee.origin);
        setsize(self, spectatee.mins, spectatee.maxs);
        SetZoomState(spectatee.zoomstate);
-
-       anticheat_spectatecopy(spectatee);
-
-       //self.vehicle = spectatee.vehicle;
-
+    
+    anticheat_spectatecopy(spectatee);
        self.hud = spectatee.hud;
        if(spectatee.vehicle)
     {
-        setorigin(self, spectatee.origin);
-        self.velocity = spectatee.vehicle.velocity;
-        self.v_angle += spectatee.vehicle.angles;
-        //self.v_angle_x *= -1;
+        self.fixangle = FALSE;
+        //self.velocity = spectatee.vehicle.velocity;
         self.vehicle_health = spectatee.vehicle_health;
         self.vehicle_shield = spectatee.vehicle_shield;
         self.vehicle_energy = spectatee.vehicle_energy;
@@ -2193,11 +2196,18 @@ void SpectateCopy(entity spectatee) {
         self.vehicle_ammo2 = spectatee.vehicle_ammo2;
         self.vehicle_reload1 = spectatee.vehicle_reload1;
         self.vehicle_reload2 = spectatee.vehicle_reload2;
-        
+
         msg_entity = self;
-        WriteByte (MSG_ONE, SVC_SETVIEWPORT);
-        WriteEntity(MSG_ONE, spectatee);
-        //self.tur_head = spectatee.vehicle.vehicle_viewport;
+        
+        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+            WriteAngle(MSG_ONE,  spectatee.v_angle_x);
+            WriteAngle(MSG_ONE,  spectatee.v_angle_y);
+            WriteAngle(MSG_ONE,  spectatee.v_angle_z);
+
+        //WriteByte (MSG_ONE, SVC_SETVIEW);
+        //    WriteEntity(MSG_ONE, self);            
+        //makevectors(spectatee.v_angle);
+        //setorigin(self, spectatee.origin - v_forward * 400 + v_up * 300);*/    
     }
 }
 
@@ -2240,8 +2250,13 @@ entity CA_SpectateNext(entity start) {
        return other;
 }
 
-float SpectateNext() {
-       other = find(self.enemy, classname, "player");
+float SpectateNext(entity _prefer) {
+       
+       if(_prefer)
+               other = _prefer;        
+       else
+               other = find(self.enemy, classname, "player");
+       
        if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer) {
                // CA and ca players when spectating enemies is forbidden
                other = CA_SpectateNext(other);
@@ -2255,17 +2270,19 @@ float SpectateNext() {
                self.enemy = other;
 
        if(self.enemy.classname == "player") {
-           if(self.enemy.vehicle)
+           /*if(self.enemy.vehicle)
            {      
+            
             msg_entity = self;
-            WriteByte(MSG_ONE, SVC_SETVIEWPORT);
+            WriteByte(MSG_ONE, SVC_SETVIEW);
             WriteEntity(MSG_ONE, self.enemy);
             //stuffcmd(self, "set viewsize $tmpviewsize \n");
+            
             self.movetype = MOVETYPE_NONE;
             accuracy_resend(self);
            }
            else 
-           {           
+           {*/         
             msg_entity = self;
             WriteByte(MSG_ONE, SVC_SETVIEW);
             WriteEntity(MSG_ONE, self.enemy);
@@ -2275,7 +2292,7 @@ float SpectateNext() {
 
             if(!SpectateUpdate())
                 PutObserverInServer();
-        }
+        //}
         return 1;
        } else {
                return 0;
@@ -2315,7 +2332,7 @@ void LeaveSpectatorMode()
                if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) {
                        self.classname = "player";
 
-                       if(autocvar_g_campaign || autocvar_g_balance_teams || autocvar_g_balance_teams_force)
+                       if(autocvar_g_campaign || autocvar_g_balance_teams)
                                JoinBestTeam(self, FALSE, TRUE);
 
                        if(autocvar_g_campaign)
@@ -2377,7 +2394,7 @@ float nJoinAllowed(entity ignore) {
 
        // TODO simplify this
        entity e;
-       float totalClients;
+       float totalClients = 0;
        FOR_EACH_CLIENT(e)
                if(e != ignore)
                        totalClients += 1;
@@ -2385,7 +2402,7 @@ float nJoinAllowed(entity ignore) {
        if (!autocvar_g_maxplayers)
                return maxclients - totalClients;
 
-       float currentlyPlaying;
+       float currentlyPlaying = 0;
        FOR_EACH_REALPLAYER(e)
                currentlyPlaying += 1;
 
@@ -2453,7 +2470,7 @@ void ObserverThink()
                        self.flags |= FL_SPAWNING;
                } else if(self.BUTTON_ATCK && !self.version_mismatch) {
                        self.flags &~= FL_JUMPRELEASED;
-                       if(SpectateNext() == 1) {
+                       if(SpectateNext(world) == 1) {
                                self.classname = "spectator";
                        }
                } else {
@@ -2484,7 +2501,7 @@ void SpectatorThink()
                        self.flags |= FL_SPAWNING;
                } else if(self.BUTTON_ATCK) {
                        self.flags &~= FL_JUMPRELEASED;
-                       if(SpectateNext() == 1) {
+                       if(SpectateNext(world) == 1) {
                                self.classname = "spectator";
                        } else {
                                self.classname = "observer";
@@ -2782,6 +2799,7 @@ void PlayerPreThink (void)
 
                self.prevorigin = self.origin;
 
+               if (!self.vehicle)
                if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x) // prevent crouching if using melee attack
                {
                        if (!self.crouch)
index 524e796af2e32859054ee3a82522eae1ddb85147..987e07c46f228b892e9741c3c4b75e00a5571968 100644 (file)
@@ -48,7 +48,13 @@ void ImpulseCommands (void)
 
        if (timeout_status == TIMEOUT_ACTIVE) //don't allow any impulses while the game is paused
                return;
-
+    
+    if(self.vehicle)
+        if(self.vehicle.deadflag == DEAD_NO)
+            if(self.vehicle.vehicles_impusle)
+                if(self.vehicle.vehicles_impusle(imp))
+                    return;
+    
        if(CheatImpulse(imp))
        {
        }
index db2707fb9e828ae10ce2d437c6dc07fe92f8feea..b57c18a17872ccb4552e73398b03b1c00b2aadc1 100644 (file)
@@ -123,6 +123,7 @@ void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot)
 
 .entity pusher;
 .float pushltime;
+.float istypefrag;
 
 .float CopyBody_nextthink;
 .void(void) CopyBody_think;
@@ -580,11 +581,13 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                // don't reset pushltime for self damage as it may be an attempt to
                // escape a lava pit or similar
                //self.pushltime = 0;
+               self.istypefrag = 0;
        }
        else if(attacker.classname == "player")
        {
                self.pusher = attacker;
                self.pushltime = time + autocvar_g_maxpushtime;
+               self.istypefrag = self.BUTTON_CHAT;
        }
        else if(time < self.pushltime)
        {
@@ -592,13 +595,18 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                self.pushltime = max(self.pushltime, time + 0.6);
        }
        else
+       {
                self.pushltime = 0;
+               self.istypefrag = 0;
+       }
 
        float abot, vbot, awep;
        abot = (clienttype(attacker) == CLIENTTYPE_BOT);
        vbot = (clienttype(self) == CLIENTTYPE_BOT);
 
        valid_damage_for_weaponstats = 0;
+       awep = 0;
+
        if(vbot || clienttype(self) == CLIENTTYPE_REAL)
        if(abot || clienttype(attacker) == CLIENTTYPE_REAL)
        if(attacker && self != attacker)
@@ -805,11 +813,12 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
 //   0 = reject
 //  -1 = fake accept
 {
-       string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, privatemsgprefix;
-       float flood, privatemsgprefixlen;
+       string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr;
+       float flood;
        var .float flood_field;
        entity head;
        float ret;
+       string privatemsgprefix = string_null; float privatemsgprefixlen = 0;
 
        if(!teamsay && !privatesay)
                if(substring(msgin, 0, 1) == " ")
@@ -822,7 +831,10 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
        else if(teamplay)
                colorstr = Team_ColorCode(source.team);
        else
+       {
+               colorstr = "";
                teamsay = FALSE;
+       }
 
        if(intermission_running)
                teamsay = FALSE;
@@ -881,6 +893,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
 
        // FLOOD CONTROL
        flood = 0;
+       flood_field = floodcontrol_chat;
        if(floodcontrol)
        {
                float flood_spl;
index 59efb74d5458508fab560ddb0f5338fa12013372..236c0923fdc330834469234bc9eb2285a1f6bb26 100644 (file)
@@ -318,7 +318,9 @@ float W_IsWeaponThrowable(float w)
                return 0;
        if (g_nexball && w == WEP_GRENADE_LAUNCHER)
                return 0;
-
+    if(w == 0)
+        return 0;
+       
        wa = W_AmmoItemCode(w);
        if(WEPSET_CONTAINS_AW(start_weapons, w))
        {
index d2c2546d2f3e091660282b3626e6b5521996011c..402b692af1230fba959a89c1fce3aef5a999ab13 100644 (file)
@@ -69,6 +69,7 @@ vector W_HitPlotNormalizedUntransform(vector org, entity targ, vector screenforw
 
        // x = 0..1 relative to hitbox; y = 0..1 relative to hitbox; z = distance
 
+       mi = ma = targ.origin + 0.5 * (targ.mins + targ.maxs);
        for(i = 0; i < 2; ++i) for(j = 0; j < 2; ++j) for(k = 0; k < 2; ++k)
        {
                thisv = targ.origin;
@@ -557,7 +558,6 @@ void CL_Weaponentity_Think()
 
        self.angles = '0 0 0';
        float f;
-       f = 0;
        if (self.state == WS_RAISE && !intermission_running)
        {
                f = (self.owner.weapon_nextthink - time) * g_weaponratefactor / autocvar_g_balance_weaponswitchdelay;
@@ -1077,8 +1077,6 @@ vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float f
 {
        vector mdirection;
        float mspeed;
-       float outspeed;
-       float nstyle;
        vector outvelocity;
 
        mvelocity = mvelocity * g_weaponspeedfactor;
@@ -1086,61 +1084,7 @@ vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float f
        mdirection = normalize(mvelocity);
        mspeed = vlen(mvelocity);
 
-       nstyle = autocvar_g_projectiles_newton_style;
-       if(nstyle == 0 || forceAbsolute)
-       {
-               // absolute velocity
-               outvelocity = mvelocity;
-       }
-       else if(nstyle == 1)
-       {
-               // true Newtonian projectiles
-               outvelocity = pvelocity + mvelocity;
-       }
-       else if(nstyle == 2)
-       {
-               // true Newtonian projectiles with automatic aim adjustment
-               //
-               // solve: |outspeed * mdirection - pvelocity| = mspeed
-               // outspeed^2 - 2 * outspeed * (mdirection * pvelocity) + pvelocity^2 - mspeed^2 = 0
-               // outspeed = (mdirection * pvelocity) +- sqrt((mdirection * pvelocity)^2 - pvelocity^2 + mspeed^2)
-               // PLUS SIGN!
-               // not defined?
-               // then...
-               // pvelocity^2 - (mdirection * pvelocity)^2 > mspeed^2
-               // velocity without mdirection component > mspeed
-               // fire at smallest possible mspeed that works?
-               // |(mdirection * pvelocity) * pvelocity - pvelocity| = mspeed
-
-               vector solution;
-               solution = solve_quadratic(1, -2 * (mdirection * pvelocity), pvelocity * pvelocity - mspeed * mspeed);
-               if(solution_z)
-                       outspeed = solution_y; // the larger one
-               else
-               {
-                       //outspeed = 0; // slowest possible shot
-                       outspeed = solution_x; // the real part (that is, the average!)
-                       //dprint("impossible shot, adjusting\n");
-               }
-
-               outspeed = bound(mspeed * autocvar_g_projectiles_newton_style_2_minfactor, outspeed, mspeed * autocvar_g_projectiles_newton_style_2_maxfactor);
-               outvelocity = mdirection * outspeed;
-       }
-       else if(nstyle == 3)
-       {
-               // pseudo-Newtonian:
-               outspeed = mspeed + mdirection * pvelocity;
-               outspeed = bound(mspeed * 0.7, outspeed, mspeed * 5.0);
-               outvelocity = mdirection * outspeed;
-       }
-       else if(nstyle == 4)
-       {
-               // tZorkian:
-               outspeed = mspeed + vlen(pvelocity);
-               outvelocity = mdirection * outspeed;
-       }
-       else
-               error("g_projectiles_newton_style must be 0 (absolute), 1 (Newtonian), 2 (Newtonian + aimfix), 3 (pseudo Newtonian) or 4 (tZorkian)!");
+       outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor);
 
        return outvelocity;
 }
index 7a6138283f5c8ed466dfd91b238078b4b68779cb..8e3ecb7ba0369ab674ac56ccc2198c9bf01c11a6 100644 (file)
@@ -3,7 +3,7 @@
 //  Last updated: December 29th, 2011
 // =====================================
 
-#define GET_BAN_ARG(v,d) if((argc > reason_arg) && ((v = stof(argv(reason_arg))) != 0)) ++reason_arg; else v = d
+#define GET_BAN_ARG(v,d) if(argc > reason_arg) { if((v = stof(argv(reason_arg))) != 0) ++reason_arg; else v = d; } else v = d
 #define GET_BAN_REASON(v,d) if(argc > reason_arg) v = substring(command, argv_start_index(reason_arg), strlen(command) - argv_start_index(reason_arg)); else v = d
 
 void Ban_KickBanClient(entity client, float bantime, float masksize, string reason);
@@ -12,4 +12,4 @@ float Ban_Insert(string ip, float bantime, string reason, float dosync);
 float Ban_Delete(float i);
 
 // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
-void BanCommand_macro_write_aliases(float fh)
\ No newline at end of file
+void BanCommand_macro_write_aliases(float fh)
index 32bd688d3bdbd26c2460157eca266974873ae203..530646afd2ec8fbb105dc8a080b41dadaaa25d0f 100644 (file)
@@ -90,7 +90,7 @@ void ClientCommand_clientversion(float request, float argc) // internal command,
                                                self.version_mismatch = 1;
                                                ClientKill_TeamChange(-2); // observe
                                        } 
-                                       else if(autocvar_g_campaign || autocvar_g_balance_teams || autocvar_g_balance_teams_force
+                                       else if(autocvar_g_campaign || autocvar_g_balance_teams) 
                                        {
                                                //JoinBestTeam(self, FALSE, TRUE);
                                        } 
@@ -226,40 +226,6 @@ void ClientCommand_ready(float request) // todo: anti-spam for toggling readynes
        }
 }
 
-void ClientCommand_reportcvar(float request, float argc, string command)
-{      
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       if(argv(1) != "")
-                       {
-                               float tokens;
-                               string s;
-                               
-                               if(substring(argv(2), 0, 1) == "$") // undefined cvar: use the default value on the server then
-                               {
-                                       s = strcat(substring(command, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\"");
-                                       tokens = tokenize_console(s);
-                               }
-                               
-                               GetCvars(1);
-                               
-                               return;
-                       }
-               }
-                       
-               default:
-                       sprint(self, "Incorrect parameters for ^2reportcvar^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       sprint(self, "\nUsage:^3 cmd reportcvar <cvar>\n");
-                       sprint(self, "  Where 'cvar' is the cvar plus arguments to send to the server.\n");
-                       return;
-               }
-       }
-}
-
 void ClientCommand_say(float request, float argc, string command)
 {
        switch(request)
@@ -324,7 +290,7 @@ void ClientCommand_selectteam(float request, float argc)
                                                                        case "pink": selection = COLOR_TEAM4; break;
                                                                        case "auto": selection = (-1); break;
                                                                        
-                                                                       default: break;
+                                                                       default: selection = 0; break;
                                                                }
                                                                
                                                                if(selection)
@@ -392,13 +358,13 @@ void ClientCommand_sentcvar(float request, float argc, string command)
                {
                        if(argv(1) != "")
                        {
-                               float tokens;
+                               //float tokens;
                                string s;
                                
                                if(argc == 2) // undefined cvar: use the default value on the server then
                                {
                                        s = strcat(substring(command, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\"");
-                                       tokens = tokenize_console(s);
+                                       tokenize_console(s);
                                }
                                
                                GetCvars(1);
@@ -595,7 +561,6 @@ void ClientCommand_(float request)
        CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("join", ClientCommand_join(request), "Become a player in the game") \
        CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
-       CLIENT_COMMAND("reportcvar", ClientCommand_reportcvar(request, arguments, command), "Old system for sending a client cvar to the server") \
        CLIENT_COMMAND("say", ClientCommand_say(request, arguments, command), "Print a message to chat to all players") \
        CLIENT_COMMAND("say_team", ClientCommand_say_team(request, arguments, command), "Print a message to chat to all team mates") \
        CLIENT_COMMAND("selectteam", ClientCommand_selectteam(request, arguments), "Attempt to choose a team to join into") \
@@ -683,7 +648,6 @@ void SV_ParseClientCommand(string command)
                case "mv_getpicture": break; // handled by server in this file
                case "pause": break; // handled by engine in host_cmd.c
                case "prespawn": break; // handled by engine in host_cmd.c
-               case "reportcvar": break; // handled by server in this file
                case "sentcvar": break; // handled by server in this file
                case "spawn": break; // handled by engine in host_cmd.c
                
index 99313b38bf4f9e3b2331fcc5a6d75fb09622b6b4..13e667ad87123b72c7a282f3633d6940ec1abbd1 100644 (file)
@@ -63,6 +63,7 @@ entity GetIndexedEntity(float argc, float start_index)
        
        next_token = -1;
        index = start_index;
+       selection = world;
        
        if(argc > start_index)
        {
@@ -80,6 +81,8 @@ entity GetIndexedEntity(float argc, float start_index)
                                tmp_number = stof(argv(index));
                                ++index;
                        }
+                       else
+                               tmp_number = 0;
                }
                else // maybe it's ONLY a number?
                {
@@ -123,6 +126,7 @@ entity GetFilteredEntity(string input)
        }
        else
        {
+               selection = world;
                FOR_EACH_CLIENT(tmp_player)
                        if (strdecolorize(tmp_player.netname) == strdecolorize(input))
                                selection = tmp_player;
@@ -137,7 +141,7 @@ float GetFilteredNumber(string input)
        entity selection = GetFilteredEntity(input);
        float output;
        
-       if(selection) { output = num_for_edict(selection); }
+       output = num_for_edict(selection);
 
        return output;
 }
@@ -614,6 +618,7 @@ void CommonCommand_who(float request, entity caller, float argc)
                        print_to(caller, sprintf(strreplace(" ", separator, " %-4s %-20s %-5s %-3s %-9s %-16s %s "), 
                                "ent", "nickname", "ping", "pl", "time", "ip", "crypto_id"));
                        
+                       total_listed_players = 0;
                        FOR_EACH_CLIENT(tmp_player)
                        {
                                is_bot = (clienttype(tmp_player) == CLIENTTYPE_BOT);
@@ -759,4 +764,4 @@ void CommonCommand_macro_write_aliases(float fh)
        #undef COMMON_COMMAND
        
        return;
-}
\ No newline at end of file
+}
index be4928e8a76296568f1aa21ab2d7270f9ec42d0b..0bedd6d5e21f3ce44f0b2d479eed092a59029b65 100644 (file)
@@ -14,6 +14,8 @@ string getrecords(float page) // 50 records per page
 {      
        float rec = 0, r, i;
        string h, s;
+       
+       s = "";
 
        if (g_ctf)
        {
@@ -85,6 +87,7 @@ string getrankings()
 
        map = GetMapname();
 
+       s = "";
        for (i = 1; i <= RANKINGS_CNT; ++i)
        {
                t = race_readTime(map, i);
@@ -107,7 +110,7 @@ string getrankings()
 
 string getladder()
 {
-       float i, j, k, uidcnt, thiscnt;
+       float i, j, k, uidcnt = 0, thiscnt;
        string s, temp_s, rr, myuid, thisuid;
        
        if(g_cts)
@@ -281,4 +284,4 @@ string getladder()
                return "No ladder on this server!\n";
        else
                return strcat("Top ", ftos(LADDER_SIZE), " ladder rankings:\n", s);
-}
\ No newline at end of file
+}
index 16f3212eda0cc1852569ac0de61a11d67b1ff470..d8651762965d9d6859dbc05ed205b5ee0407d8dc 100644 (file)
@@ -28,7 +28,7 @@ float FullTraceFraction(vector a, vector mi, vector ma, vector b)
                        c = trace_endpos;
                }
 
-               n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world);
+               n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world, FALSE);
 
                white += vlen(trace_endpos - c);
                c = trace_endpos;
@@ -424,4 +424,4 @@ float RadarMap_Make(float argc)
        }
        
        return FALSE;
-}
\ No newline at end of file
+}
index e70ce44ddbd06b3a7059d6fcc750d51ba0365895..4699049d2deece5103cd4fd67b94be28d1085083 100644 (file)
@@ -81,6 +81,7 @@ void GameCommand_adminmsg(float request, float argc)
                        float infobartime = stof(argv(3));
                        
                        string successful, t;
+                       successful = string_null;
                        
                        if((targets) && (admin_message))
                        {
@@ -166,7 +167,7 @@ void GameCommand_allspec(float request, float argc)
                {
                        entity client;
                        string reason = argv(1);
-                       float i;
+                       float i = 0;
                        
                        FOR_EACH_REALPLAYER(client)
                        {
@@ -528,7 +529,7 @@ void GameCommand_defer_clear_all(float request)
                case CMD_REQUEST_COMMAND:
                {
                        entity client;
-                       float i;
+                       float i = 0;
                        float argc;
                        
                        FOR_EACH_CLIENT(client)
@@ -904,6 +905,7 @@ void GameCommand_moveplayer(float request, float argc)
                        string notify = argv(3);
                        
                        string successful, t;
+                       successful = string_null;
                        
                        // lets see if the target(s) even actually exist.
                        if((targets) && (destination))
@@ -1242,6 +1244,8 @@ void GameCommand_shuffleteams(float request)
                                float i, x, z, t_teams, t_players, team_color;
 
                                // count the total amount of players and total amount of teams
+                               t_players = 0;
+                               t_teams = 0;
                                FOR_EACH_PLAYER(tmp_player)
                                {
                                        CheckAllowedTeams(tmp_player);
@@ -1347,7 +1351,7 @@ void GameCommand_stuffto(float request, float argc)
                {
                        if(argv(2))
                        {
-                               entity client = GetIndexedEntity(argc, 1));
+                               entity client = GetIndexedEntity(argc, 1);
                                float accepted = VerifyClientEntity(client, TRUE, FALSE);
                                
                                if(accepted > 0)
@@ -1421,7 +1425,6 @@ void GameCommand_trace(float request, float argc)
                                                        {
                                                                rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid
                                                                tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world);
-                                                               tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world);
 
                                                                if(trace_startsolid)
                                                                {
@@ -1803,4 +1806,4 @@ void GameCommand(string command)
        print(((command != "") ? strcat("Unknown server command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try sv_cmd help.\n");
        
        return;
-}
\ No newline at end of file
+}
index 1e43564001d58957a7fafb6c278a8672e7af067d..e4564753008b889303ab4992bb4afbfd2f71edbd 100644 (file)
@@ -194,9 +194,9 @@ void VoteCount(float first_count)
                                || ((autocvar_sv_vote_nospectators == 1) && (inWarmupStage || gameover))
                                || (autocvar_sv_vote_nospectators == 0));
                                
-       float vote_player_count, is_player, notvoters;
-       float vote_real_player_count, vote_real_accept_count;
-       float vote_real_reject_count, vote_real_abstain_count;
+       float vote_player_count = 0, is_player, notvoters = 0;
+       float vote_real_player_count = 0, vote_real_accept_count = 0;
+       float vote_real_reject_count = 0, vote_real_abstain_count = 0;
        float vote_needed_of_voted, final_needed_votes;
        float vote_factor_overall, vote_factor_of_voted;
        
@@ -404,7 +404,7 @@ void ReadyCount()
 {
        entity tmp_player;
        float ready_needed_factor, ready_needed_count;
-       float t_ready, t_players;
+       float t_ready = 0, t_players = 0;
 
        FOR_EACH_REALPLAYER(tmp_player)
        {
@@ -476,15 +476,6 @@ float VoteCommand_checkinlist(string vote_command, string list)
        if(strstrofs(l, strcat(" ", vote_command, " "), 0) >= 0)
                return TRUE;
        
-       // if gotomap is allowed, chmap is too, and vice versa
-       if(vote_command == "gotomap")
-               if(strstrofs(l, " chmap ", 0) >= 0)
-                       return TRUE;
-                       
-       if(vote_command == "chmap")
-               if(strstrofs(l, " gotomap ", 0) >= 0)
-                       return TRUE;
-       
        return FALSE;
 }
 
@@ -516,30 +507,92 @@ string ValidateMap(string validated_map, entity caller)
        return validated_map;
 }
 
-float VoteCommand_parse(entity caller, string vote_command, string vote_list, float startpos, float argc)
+float VoteCommand_checkargs(float startpos, float argc)
 {
-       string first_command;
-       
-       first_command = argv(startpos);
+       float p, q, check, minargs;
+       string cvarname = strcat("sv_vote_command_restriction_", argv(startpos));
+       string cmdrestriction = cvar_string(cvarname); // note: this warns on undefined cvar. We want that.
+       string charlist, arg;
+       float checkmate;
 
-       if not(VoteCommand_checkinlist(first_command, vote_list))
+       if(cmdrestriction == "")
+               return TRUE;
+
+       ++startpos; // skip command name
+
+       // check minimum arg count
+
+       // 0 args: argc == startpos
+       // 1 args: argc == startpos + 1
+       // ...
+
+       minargs = stof(cmdrestriction);
+       if(argc - startpos < minargs)
                return FALSE;
 
-       if(argc < startpos) // These commands won't work without arguments
+       p = strstrofs(cmdrestriction, ";", 0); // find first semicolon
+
+       for(;;)
        {
-               switch(first_command)
+               // we know that at any time, startpos <= argc - minargs
+               // so this means: argc-minargs >= startpos >= argc, thus
+               // argc-minargs >= argc, thus minargs <= 0, thus all minargs
+               // have been seen already
+
+               if(startpos >= argc) // all args checked? GOOD
+                       break;
+
+               if(p < 0) // no more args? FAIL
                {
-                       case "map":
-                       case "chmap":
-                       case "gotomap":
-                       case "kick":
-                       case "kickban":
-                               return FALSE;
-                               
-                       default: { break; }
+                       // exception: exactly minargs left, this one included
+                       if(argc - startpos == minargs)
+                               break;
+
+                       // otherwise fail
+                       return FALSE;
+               }
+
+               // cut to next semicolon
+               q = strstrofs(cmdrestriction, ";", p+1); // find next semicolon
+               if(q < 0)
+                       charlist = substring(cmdrestriction, p+1, -1);
+               else
+                       charlist = substring(cmdrestriction, p+1, q - (p+1));
+
+               // in case we ever want to allow semicolons in VoteCommand_checknasty
+               // charlist = strreplace("^^", ";", charlist);
+
+               if(charlist != "")
+               {
+                       // verify the arg only contains allowed chars
+                       arg = argv(startpos);
+                       checkmate = strlen(arg);
+                       for(check = 0; check < checkmate; ++check)
+                               if(strstrofs(charlist, substring(arg, check, 1), 0) < 0)
+                                       return FALSE; // not allowed character
+                       // all characters are allowed. FINE.
                }
+
+               ++startpos;
+               --minargs;
+               p = q;
        }
+
+       return TRUE;
+}
+
+float VoteCommand_parse(entity caller, string vote_command, string vote_list, float startpos, float argc)
+{
+       string first_command;
        
+       first_command = argv(startpos);
+
+       if not(VoteCommand_checkinlist(first_command, vote_list))
+               return FALSE;
+
+       if not(VoteCommand_checkargs(startpos, argc))
+               return FALSE;
+
        switch(first_command) // now go through and parse the proper commands to adjust as needed.
        {
                case "kick":
@@ -635,7 +688,7 @@ void VoteCommand_call(float request, entity caller, float argc, string vote_comm
                                || ((autocvar_sv_vote_nospectators == 1) && inWarmupStage) 
                                || (autocvar_sv_vote_nospectators == 0));
                                
-                       float tmp_playercount;
+                       float tmp_playercount = 0;
                        entity tmp_player;
                        
                        vote_command = VoteCommand_extractcommand(vote_command, 2, argc);
index d5b6697f25932c34ca6936951f6283fd235f9acd..3554f1ff67235142f837507183b772c41c841c09 100644 (file)
@@ -13,6 +13,7 @@ float CSQCProjectile_SendEntity(entity to, float sf)
        if(self.flags & FL_ONGROUND)
                sf |= 0x40;
 
+       ft = fr = 0;
        if(self.fade_time != 0 || self.fade_rate != 0)
        {
                ft = (self.fade_time - time) / sys_frametime;
@@ -79,9 +80,9 @@ void CSQCProjectile(entity e, float clientanimate, float type, float docull)
        else
                e.gravity = 0;
 
-       e.csqcprojectile_type = type;
        if(!sound_allowed(MSG_BROADCAST, e))
                type |= 0x80;
+       e.csqcprojectile_type = type;
 }
 
 void UpdateCSQCProjectile(entity e)
index 47a72d904a48145139648a28de27725a77038d02..8564e04e9d3c7cb7624287acb8343486a46e989c 100644 (file)
@@ -100,6 +100,7 @@ float maxclients;
 .float         t_length, t_width;
 
 .vector destvec;               // for rain
+.vector destvec2;              // for train
 .float cnt;            // for rain
 .float count;
 //.float cnt2;
@@ -276,6 +277,7 @@ float blockSpectators; //if set, new or existing spectators or observers will be
 .float spectatortime; //point in time since the client is spectating or observing
 void checkSpectatorBlock();
 
+float game_completion_ratio; // 0 at start, 1 near end
 .float winning;
 .float jointime; // time of joining
 .float alivetime; // time of being alive
@@ -656,3 +658,20 @@ typedef vector(entity player, entity spot, vector current) spawn_evalfunc_t;
 .entity conveyor;
 
 string modname;
+
+.float missile_flags;
+#define MIF_SPLASH 2
+#define MIF_ARC 4
+#define MIF_PROXY 8
+#define MIF_GUIDED_MANUAL 16
+#define MIF_GUIDED_HEAT 32
+#define MIF_GUIDED_LASER 64
+#define MIF_GUIDED_AI 128
+#define MIF_GUIDED_TAG 128
+#define MIF_GUIDED_ALL (MIF_GUIDED_MANUAL | MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG)
+#define MIF_GUIDED_TRACKING (MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG)
+#define MIF_GUIDED_CONFUSABLE (MIF_GUIDED_HEAT | MIF_GUIDED_AI)
+
+#define MISSILE_IS_CONFUSABLE(m) ((m.missile_flags & MIF_GUIDED_CONFUSABLE) ? TRUE : FALSE)
+#define MISSILE_IS_GUIDED(m) ((m.missile_flags & MIF_GUIDED_ALL) ? TRUE : FALSE)
+#define MISSILE_IS_TRACKING(m) ((m.missile_flags & MIF_GUIDED_TRACKING) ? TRUE : FALSE)
index 9e56023cb500ebb5425d08321fbff54d55d4a7e8..0a2fe02b66fcf13c88c02240c0fb5b653f31ed88 100644 (file)
@@ -395,196 +395,6 @@ void dom_controlpoint_setup()
 
 
 
-// player has joined game, get him on a team
-// depreciated
-/*void dom_player_join_team(entity pl)
-{
-       entity head;
-       float c1, c2, c3, c4, totalteams, smallestteam, smallestteam_count, selectedteam;
-       float balance_teams, force_balance, balance_type;
-
-       balance_teams = autocvar_g_balance_teams;
-       balance_teams = autocvar_g_balance_teams_force;
-
-       c1 = c2 = c3 = c4 = -1;
-       totalteams = 0;
-
-       // first find out what teams are allowed
-       head = find(world, classname, "dom_team");
-       while(head)
-       {
-               if(head.netname != "")
-               {
-                       //if(head.team == pl.team)
-                       //      selected = head;
-                       if(head.team == COLOR_TEAM1)
-                       {
-                                       c1 = 0;
-                       }
-                       if(head.team == COLOR_TEAM2)
-                       {
-                                       c2 = 0;
-                       }
-                       if(head.team == COLOR_TEAM3)
-                       {
-                                       c3 = 0;
-                       }
-                       if(head.team == COLOR_TEAM4)
-                       {
-                                       c4 = 0;
-                       }
-               }
-               head = find(head, classname, "dom_team");
-       }
-
-       // make sure there are at least 2 teams to join
-       if(c1 >= 0)
-               totalteams = totalteams + 1;
-       if(c2 >= 0)
-               totalteams = totalteams + 1;
-       if(c3 >= 0)
-               totalteams = totalteams + 1;
-       if(c4 >= 0)
-               totalteams = totalteams + 1;
-
-       if(totalteams <= 1)
-               error("dom_player_join_team: Too few teams available for domination\n");
-
-       // whichever teams that are available are set to 0 instead of -1
-
-       // if we don't care what team he ends up on, put him on whatever team he entered as.
-       // if he's not on a valid team, then put him on the smallest team
-       if(!balance_teams && !force_balance)
-       {
-               if(     c1 >= 0 && pl.team == COLOR_TEAM1)
-                       selectedteam = pl.team;
-               else if(c2 >= 0 && pl.team == COLOR_TEAM2)
-                       selectedteam = pl.team;
-               else if(c3 >= 0 && pl.team == COLOR_TEAM3)
-                       selectedteam = pl.team;
-               else if(c4 >= 0 && pl.team == COLOR_TEAM4)
-                       selectedteam = pl.team;
-               else
-                       selectedteam = -1;
-               if(selectedteam > 0)
-               {
-                       SetPlayerColors(pl, selectedteam - 1);
-                       return;
-               }
-               // otherwise end up on the smallest team (handled below)
-       }
-
-       // now count how many players are on each team already
-
-       head = find(world, classname, "player");
-       while(head)
-       {
-               //if(head.netname != "")
-               {
-                       if(head.team == COLOR_TEAM1)
-                       {
-                               if(c1 >= 0)
-                                       c1 = c1 + 1;
-                       }
-                       if(head.team == COLOR_TEAM2)
-                       {
-                               if(c2 >= 0)
-                                       c2 = c2 + 1;
-                       }
-                       if(head.team == COLOR_TEAM3)
-                       {
-                               if(c3 >= 0)
-                                       c3 = c3 + 1;
-                       }
-                       if(head.team == COLOR_TEAM4)
-                       {
-                               if(c4 >= 0)
-                                       c4 = c4 + 1;
-                       }
-               }
-               head = find(head, classname, "player");
-       }
-
-       // c1...c4 now have counts of each team
-       // figure out which is smallest, giving priority to the team the player is already on as a tie-breaker
-
-       smallestteam = 0;
-       smallestteam_count = 999;
-
-       // 2 gives priority to what team you're already on, 1 goes in order
-       balance_type = 1;
-
-       if(balance_type == 1)
-       {
-               if(c1 >= 0 && c1 < smallestteam_count)
-               {
-                       smallestteam = 1;
-                       smallestteam_count = c1;
-               }
-               if(c2 >= 0 && c2 < smallestteam_count)
-               {
-                       smallestteam = 2;
-                       smallestteam_count = c2;
-               }
-               if(c3 >= 0 && c3 < smallestteam_count)
-               {
-                       smallestteam = 3;
-                       smallestteam_count = c3;
-               }
-               if(c4 >= 0 && c4 < smallestteam_count)
-               {
-                       smallestteam = 4;
-                       smallestteam_count = c4;
-               }
-       }
-       else
-       {
-               if(c1 >= 0 && (c1 < smallestteam_count ||
-                                       (c1 == smallestteam_count && self.team == COLOR_TEAM1) ) )
-               {
-                       smallestteam = 1;
-                       smallestteam_count = c1;
-               }
-               if(c2 >= 0 && c2 < (c2 < smallestteam_count ||
-                                       (c2 == smallestteam_count && self.team == COLOR_TEAM2) ) )
-               {
-                       smallestteam = 2;
-                       smallestteam_count = c2;
-               }
-               if(c3 >= 0 && c3 < (c3 < smallestteam_count ||
-                                       (c3 == smallestteam_count && self.team == COLOR_TEAM3) ) )
-               {
-                       smallestteam = 3;
-                       smallestteam_count = c3;
-               }
-               if(c4 >= 0 && c4 < (c4 < smallestteam_count ||
-                                       (c4 == smallestteam_count && self.team == COLOR_TEAM4) ) )
-               {
-                       smallestteam = 4;
-                       smallestteam_count = c4;
-               }
-       }
-
-       if(smallestteam == 1)
-       {
-               selectedteam = COLOR_TEAM1 - 1;
-       }
-       if(smallestteam == 2)
-       {
-               selectedteam = COLOR_TEAM2 - 1;
-       }
-       if(smallestteam == 3)
-       {
-               selectedteam = COLOR_TEAM3 - 1;
-       }
-       if(smallestteam == 4)
-       {
-               selectedteam = COLOR_TEAM4 - 1;
-       }
-
-       SetPlayerColors(pl, selectedteam);
-}
-*/
 /*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
 Control point for Domination gameplay.
 */
index b037e08a2d6821efd5cf6a6b033612a4f688765d..7b02f4e5ecdc9a2fe0446c49782089aa4b89dd43 100644 (file)
@@ -55,6 +55,7 @@ float damage_headshotbonus; // bonus multiplier for head shots, set to 0 after u
 .float teamkill_soundtime;
 .entity teamkill_soundsource;
 .entity pusher;
+.float istypefrag;
 .float taunt_soundtime;
 
 
@@ -140,7 +141,9 @@ void GiveFrags (entity attacker, entity targ, float f, float deathtype)
                // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
                float culprit;
                culprit = DEATH_WEAPONOF(deathtype);
-               if(!culprit || !WEPSET_CONTAINS_EW(attacker, culprit))
+               if(!culprit)
+                       culprit = attacker.weapon;
+               else if(!WEPSET_CONTAINS_EW(attacker, culprit))
                        culprit = attacker.weapon;
 
                if(g_weaponarena_random_with_laser && culprit == WEP_LASER)
@@ -231,10 +234,10 @@ void GiveFrags (entity attacker, entity targ, float f, float deathtype)
 
 string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
 {
-       string health_output;
-       string ping_output;
-       string handicap_output;
-       string output;
+       string health_output = string_null;
+       string ping_output = string_null;
+       string handicap_output = string_null;
+       string output = string_null;
 
        if(autocvar_sv_fraginfo && ((autocvar_sv_fraginfo == 2) || inWarmupStage))
        {
@@ -352,6 +355,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                {
                        if (deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
                                msg = ColoredTeamName(targ.team); // TODO: check if needed?
+                       else
+                               msg = "";
             if(!g_cts) // no "killed your own dumb self" message in CTS
                 Send_CSQC_KillCenterprint(targ, msg, "", deathtype, MSG_SUICIDE);
 
@@ -363,6 +368,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
 
                        if (targ.killcount > 2)
                                msg = ftos(targ.killcount);
+                       else
+                               msg = "";
                        if(teamplay && deathtype == DEATH_MIRRORDAMAGE)
                        {
                                if(attacker.team == COLOR_TEAM1)
@@ -386,9 +393,10 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
 
                                Send_CSQC_KillCenterprint(attacker, s, "", type, MSG_KILL);
 
-                               if (targ.killcount > 2) {
+                               if (targ.killcount > 2)
                                        msg = ftos(targ.killcount);
-                               }
+                               else
+                                       msg = "";
 
                                if (attacker.killcount > 2) {
                                        msg = ftos(attacker.killcount);
@@ -413,7 +421,7 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                                        PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
                                }
 
-                               if(targ.BUTTON_CHAT) {
+                               if(targ.istypefrag) {
                                        Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL);
                                        Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL);
                                } else {
@@ -423,11 +431,12 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
 
                                attacker.taunt_soundtime = time + 1;
 
-                               // TODO: fix this?
-                               if (deathtype == DEATH_CUSTOM)
+                               if (deathtype == DEATH_HURTTRIGGER && inflictor.message2 != "")
+                                       msg = inflictor.message2;
+                               else if (deathtype == DEATH_CUSTOM)
                                        msg = deathmessage;
                                else
-                                       msg = inflictor.message2;
+                                       msg = "";
 
                                if(strstrofs(msg, "%", 0) < 0)
                                        msg = strcat("%s ", msg, " by %s");
@@ -504,6 +513,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                                msg = inflictor.message;
                        else if (deathtype == DEATH_CUSTOM)
                                msg = deathmessage;
+                       else
+                               msg = "";
                        if(strstrofs(msg, "%", 0) < 0)
                                msg = strcat("%s ", msg);
 
@@ -637,9 +648,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
 
                                                        if(autocvar_g_mirrordamage_virtual)
                                                        {
-                                                               vector v;
-                                                               v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
-                                                               v_z = 0; // fteqcc sucks
+                                                               vector v  = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
                                                                attacker.dmg_take += v_x;
                                                                attacker.dmg_save += v_y;
                                                                attacker.dmg_inflictor = inflictor;
@@ -649,9 +658,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
 
                                                        if(autocvar_g_friendlyfire_virtual)
                                                        {
-                                                               vector v;
-                                                               v = healtharmor_applydamage(targ.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
-                                                               v_z = 0; // fteqcc sucks
+                                                               vector v = healtharmor_applydamage(targ.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
                                                                targ.dmg_take += v_x;
                                                                targ.dmg_save += v_y;
                                                                targ.dmg_inflictor = inflictor;
@@ -1263,43 +1270,59 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
 
                if(maxtime > mintime || maxdps > mindps)
                {
+                       // Constraints:
+                       
+                       // damage we have right now
                        mindamage = mindps * mintime;
-                       maxdamage = mindamage + d;
-
-                       // interval [mintime, maxtime] * [mindps, maxdps]
-                       // intersected with
-                       // [mindamage, maxdamage]
-                       // maximum of this!
 
-                       if(maxdamage >= maxtime * maxdps)
-                       {
-                               totaltime = maxtime;
-                               totaldamage = maxtime * maxdps;
-
-                               // this branch increases totaldamage if either t > mintime, or dps > mindps
-                       }
-                       else
-                       {
-                               // maxdamage is inside the interval!
-                               // first, try to use mindps; only if this fails, increase dps as needed
-                               totaltime = min(maxdamage / mindps, maxtime); // maxdamage / mindps >= mindamage / mindps = mintime
-                               totaldamage = maxdamage;
-                               // can totaldamage / totaltime be >= maxdps?
-                               // max(mindps, maxdamage / maxtime) >= maxdps?
-                               // we know maxdamage < maxtime * maxdps
-                               // so it cannot be
-
-                               // this branch ALWAYS increases totaldamage, but requires maxdamage < maxtime * maxdps
-                       }
+                       // damage we want to get
+                       maxdamage = mindamage + d;
 
-                       // total conditions for increasing:
-                       //     maxtime > mintime OR maxdps > mindps OR maxtime * maxdps > maxdamage
-                       // however:
-                       //     if maxtime = mintime, maxdps = mindps
-                       // then:
-                       //     maxdamage = mindamage + d
-                       //     mindamage = mindps * mintime = maxdps * maxtime < maxdamage!
-                       // so the last condition is not needed
+                       // but we can't exceed maxtime * maxdps!
+                       totaldamage = min(maxdamage, maxtime * maxdps);
+
+                       // LEMMA:
+                       // Look at:
+                       // totaldamage = min(mindamage + d, maxtime * maxdps)
+                       // We see:
+                       // totaldamage <= maxtime * maxdps
+                       // ==> totaldamage / maxdps <= maxtime.
+                       // We also see:
+                       // totaldamage / mindps = min(mindamage / mindps + d, maxtime * maxdps / mindps)
+                       //                     >= min(mintime, maxtime)
+                       // ==> totaldamage / maxdps >= mintime.
+
+                       /*
+                       // how long do we damage then?
+                       // at least as long as before
+                       // but, never exceed maxdps
+                       totaltime = max(mintime, totaldamage / maxdps); // always <= maxtime due to lemma
+                       */
+
+                       // alternate:
+                       // at most as long as maximum allowed
+                       // but, never below mindps
+                       totaltime = min(maxtime, totaldamage / mindps); // always >= mintime due to lemma
+
+                       // assuming t > mintime, dps > mindps:
+                       // we get d = t * dps = maxtime * maxdps
+                       // totaldamage = min(maxdamage, maxtime * maxdps) = min(... + d, maxtime * maxdps) = maxtime * maxdps
+                       // totaldamage / maxdps = maxtime
+                       // totaldamage / mindps > totaldamage / maxdps = maxtime
+                       // FROM THIS:
+                       // a) totaltime = max(mintime, maxtime) = maxtime
+                       // b) totaltime = min(maxtime, totaldamage / maxdps) = maxtime
+
+                       // assuming t <= mintime:
+                       // we get maxtime = mintime
+                       // a) totaltime = max(mintime, ...) >= mintime, also totaltime <= maxtime by the lemma, therefore totaltime = mintime = maxtime
+                       // b) totaltime = min(maxtime, ...) <= maxtime, also totaltime >= mintime by the lemma, therefore totaltime = mintime = maxtime
+
+                       // assuming dps <= mindps:
+                       // we get mindps = maxdps.
+                       // With this, the lemma says that mintime <= totaldamage / mindps = totaldamage / maxdps <= maxtime.
+                       // a) totaltime = max(mintime, totaldamage / maxdps) = totaldamage / maxdps
+                       // b) totaltime = min(maxtime, totaldamage / mindps) = totaldamage / maxdps
 
                        e.fire_damagepersec = totaldamage / totaltime;
                        e.fire_endtime = time + totaltime;
index 370f2fb9878041cea1bac0cd540d82d2c450a231..8867d0725b0f7c3a6cea40d022c5e133a01291dc 100644 (file)
@@ -213,6 +213,7 @@ void GrapplingHookThink()
                                                self.aiment.flags &~= FL_ONGROUND;
                                                self.aiment.pusher = self.realowner;
                                                self.aiment.pushltime = time + autocvar_g_maxpushtime;
+                                               self.aiment.istypefrag = self.aiment.BUTTON_CHAT;
                                        }
                                }
 
@@ -285,6 +286,7 @@ void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, floa
                {
                        self.realowner.pusher = attacker;
                        self.realowner.pushltime = time + autocvar_g_maxpushtime;
+                       self.realowner.istypefrag = self.realowner.BUTTON_CHAT;
                }
                RemoveGrapplingHook(self.realowner);
        }
index e119e5aba40040a359eca73d26d6a909f6f5d128..df63a70bb85d4f01578823b1b4ea3ceaba48f8ce 100644 (file)
@@ -178,24 +178,29 @@ void SUB_CalcMove_controller_think (void)
        float phasepos;
        float nexttick;
        vector delta;
+       vector delta2;
        vector veloc;
        vector nextpos;
+       delta = self.destvec;
+       delta2 = self.destvec2;
        if(time < self.animstate_endtime) {
-               delta = self.destvec;
                nexttick = time + sys_frametime;
 
-               if(nexttick < self.animstate_endtime) {
-                       traveltime = self.animstate_endtime - self.animstate_starttime;
-                       phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
+               traveltime = self.animstate_endtime - self.animstate_starttime;
+               phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
+               if(self.platmovetype != 1)
+               {
                        phasepos = 3.14159265 + (phasepos * 3.14159265); // range: [pi, 2pi]
                        phasepos = cos(phasepos); // cos [pi, 2pi] is in [-1, 1]
                        phasepos = phasepos + 1; // correct range to [0, 2]
                        phasepos = phasepos / 2; // correct range to [0, 1]
-                       nextpos = self.origin + (delta * phasepos);
+               }
+               nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
+               // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
 
+               if(nexttick < self.animstate_endtime) {
                        veloc = nextpos - self.owner.origin;
                        veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
-
                } else {
                        veloc = self.finaldest - self.owner.origin;
                        veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
@@ -203,6 +208,7 @@ void SUB_CalcMove_controller_think (void)
                self.owner.velocity = veloc;
                self.nextthink = nexttick;
        } else {
+               // derivative: delta + 2 * delta2 (e.g. for angle positioning)
                oldself = self;
                self.owner.think = self.think1;
                self = self.owner;
@@ -211,9 +217,35 @@ void SUB_CalcMove_controller_think (void)
        }
 }
 
-void SUB_CalcMove (vector tdest, float tspeed, void() func)
+void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector control, vector dest)
+{
+       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
+       // 2 * control * t - 2 * control * t * t + dest * t * t
+       // 2 * control * t + (dest - 2 * control) * t * t
+
+       controller.origin = org; // starting point
+       control -= org;
+       dest -= org;
+
+       controller.destvec = 2 * control; // control point
+       controller.destvec2 = dest - 2 * control; // quadratic part required to reach end point
+}
+
+void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector dest)
+{
+       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
+       // 2 * control * t - 2 * control * t * t + dest * t * t
+       // 2 * control * t + (dest - 2 * control) * t * t
+
+       controller.origin = org; // starting point
+       dest -= org;
+
+       controller.destvec = dest; // end point
+       controller.destvec2 = '0 0 0';
+}
+
+void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() func)
 {
-       vector  delta;
        float   traveltime;
        entity controller;
 
@@ -224,40 +256,24 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func)
        self.finaldest = tdest;
        self.think = SUB_CalcMoveDone;
 
-       if (tdest == self.origin)
-       {
-               self.velocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
+       if(tspeed > 0) // positive: start speed
+               traveltime = 2 * vlen(tcontrol - self.origin) /  tspeed;
+       else // negative: end speed
+               traveltime = 2 * vlen(tcontrol - tdest)       / -tspeed;
 
-       delta = tdest - self.origin;
-       traveltime = vlen (delta) / tspeed;
-
-       if (traveltime < 0.1)
+       if (traveltime < 0.1) // useless anim
        {
                self.velocity = '0 0 0';
                self.nextthink = self.ltime + 0.1;
                return;
        }
 
-       // Very short animations don't really show off the effect
-       // of controlled animation, so let's just use linear movement.
-       // Alternatively entities can choose to specify non-controlled movement.
-        // The only currently implemented alternative movement is linear (value 1)
-       if (traveltime < 0.15 || self.platmovetype == 1)
-       {
-               self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
-               self.nextthink = self.ltime + traveltime;
-               return;
-       }
-
        controller = spawn();
        controller.classname = "SUB_CalcMove_controller";
        controller.owner = self;
-       controller.origin = self.origin; // starting point
+       controller.platmovetype = self.platmovetype;
+       SUB_CalcMove_controller_setbezier(controller, self.origin, tcontrol, tdest);
        controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit.
-       controller.destvec = delta;
        controller.animstate_starttime = time;
        controller.animstate_endtime = time + traveltime;
        controller.think = SUB_CalcMove_controller_think;
@@ -273,6 +289,43 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func)
        self = self.owner;
 }
 
+void SUB_CalcMove (vector tdest, float tspeed, void() func)
+{
+       vector  delta;
+       float   traveltime;
+
+       if (!tspeed)
+               objerror ("No speed is defined!");
+
+       self.think1 = func;
+       self.finaldest = tdest;
+       self.think = SUB_CalcMoveDone;
+
+       if (tdest == self.origin)
+       {
+               self.velocity = '0 0 0';
+               self.nextthink = self.ltime + 0.1;
+               return;
+       }
+
+       delta = tdest - self.origin;
+       traveltime = vlen (delta) / tspeed;
+
+       // Very short animations don't really show off the effect
+       // of controlled animation, so let's just use linear movement.
+       // Alternatively entities can choose to specify non-controlled movement.
+        // The only currently implemented alternative movement is linear (value 1)
+       if (traveltime < 0.15 || self.platmovetype == 1)
+       {
+               self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
+               self.nextthink = self.ltime + traveltime;
+               return;
+       }
+
+       // now just run like a bezier curve...
+       SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeed, func);
+}
+
 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
 {
        entity  oldself;
@@ -382,11 +435,9 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma,
                lag = 0; // only antilag for clients
 
        // change shooter to SOLID_BBOX so the shot can hit corpses
+       oldsolid = source.dphitcontentsmask;
        if(source)
-       {
-               oldsolid = source.dphitcontentsmask;
                source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-       }
 
        if (lag)
        {
@@ -447,10 +498,11 @@ void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma,
        tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, TRUE);
 }
 
-float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent) // returns the number of traces done, for benchmarking
+float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float stopatentity) // returns the number of traces done, for benchmarking
 {
        vector pos, dir, t;
        float nudge;
+       entity stopentity;
 
        //nudge = 2 * cvar("collision_impactnudge"); // why not?
        nudge = 0.5;
@@ -483,6 +535,8 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
                        dprint("  trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
                }
 
+               stopentity = trace_ent;
+
                if(trace_startsolid)
                {
                        // we started inside solid.
@@ -495,6 +549,15 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
                                // t is still inside solid? bad
                                // force advance, then, and retry
                                pos = t + dir * nudge;
+
+                               // but if we hit an entity, stop RIGHT before it
+                               if(stopatentity && stopentity)
+                               {
+                                       trace_ent = stopentity;
+                                       trace_endpos = t;
+                                       trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
+                                       return c;
+                               }
                        }
                        else
                        {
@@ -513,59 +576,9 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
        }
 }
 
-void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent)
+void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity)
 {
-#if 0
-       vector pos, dir, t;
-       float nudge;
-
-       //nudge = 2 * cvar("collision_impactnudge"); // why not?
-       nudge = 0.5;
-
-       dir = normalize(v2 - v1);
-
-       pos = v1 + dir * nudge;
-
-       for(;;)
-       {
-               if((pos - v1) * dir >= (v2 - v1) * dir)
-               {
-                       // went too far
-                       trace_fraction = 1;
-                       return;
-               }
-
-               traceline(pos, v2, nomonsters, forent);
-
-               if(trace_startsolid)
-               {
-                       // we started inside solid.
-                       // then trace from endpos to pos
-                       t = trace_endpos;
-                       traceline(t, pos, nomonsters, forent);
-                       if(trace_startsolid)
-                       {
-                               // t is inside solid? bad
-                               // force advance, then
-                               pos = pos + dir * nudge;
-                       }
-                       else
-                       {
-                               // we actually LEFT solid!
-                               trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
-                               return;
-                       }
-               }
-               else
-               {
-                       // pos is outside solid?!? but why?!? never mind, just return it.
-                       trace_endpos = pos;
-                       trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
-                       return;
-               }
-       }
-#else
-       tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent);
+       tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity);
 }
 
 /*
index 4e97136ce8b45354b0a1f695ff36ba9f06fad634..6115b4218a8f45834d4477f3684a0168e5c17f6f 100644 (file)
@@ -545,6 +545,7 @@ void trigger_heal_touch()
        if (other.iscreature)
        {
                if (other.takedamage)
+               if (!other.deadflag)
                if (other.triggerhealtime < time)
                {
                        EXACTTRIGGER_TOUCH;
@@ -1390,6 +1391,8 @@ void trigger_impulse_touch1()
         return;
     }
 
+    str = min(self.radius, vlen(self.origin - other.origin));
+
     if(self.falloff == 1)
         str = (str / self.radius) * self.strength;
     else if(self.falloff == 2)
index c2f895c48243707e166dc4fa8b823f81499bff1a..4b5bc74add74a5e7b6f454dd26842d9c302da55b 100644 (file)
@@ -348,7 +348,8 @@ void cvar_changes_init()
                BADCVAR("gametype");
                BADCVAR("g_antilag");
                BADCVAR("g_balance_teams");
-               BADCVAR("g_balance_teams_force");
+               BADCVAR("g_balance_teams_prevent_imbalance");
+               BADCVAR("g_balance_teams_scorefactor");
                BADCVAR("g_ban_sync_trusted_servers");
                BADCVAR("g_ban_sync_uri");
                BADCVAR("g_ctf_ignore_frags");
@@ -1441,6 +1442,8 @@ void DumpStats(float final)
                print(s, "\n");
        if(to_eventlog)
                GameLogEcho(s);
+
+       file = -1;
        if(to_file)
        {
                file = fopen(autocvar_sv_logscores_filename, FILE_APPEND);
@@ -1977,6 +1980,9 @@ float WinningCondition_Scores(float limit, float leadlimit)
                        limitreached = (limitreached || leadlimitreached);
        }
 
+       if(limit)
+               game_completion_ratio = max(game_completion_ratio, bound(0, WinningConditionHelper_topscore / limit, 1));
+
        return GetWinningCode(
                WinningConditionHelper_topscore && limitreached,
                WinningConditionHelper_equality
@@ -2072,10 +2078,14 @@ float WinningCondition_RanOutOfSpawns()
        else if(team1_score + team2_score + team3_score + team4_score == 1)
        {
                float t, i;
-               if(team1_score) t = COLOR_TEAM1;
-               if(team2_score) t = COLOR_TEAM2;
-               if(team3_score) t = COLOR_TEAM3;
-               if(team4_score) t = COLOR_TEAM4;
+               if(team1_score)
+                       t = COLOR_TEAM1;
+               else if(team2_score)
+                       t = COLOR_TEAM2;
+               else if(team3_score)
+                       t = COLOR_TEAM3;
+               else // if(team4_score)
+                       t = COLOR_TEAM4;
                CheckAllowedTeams(world);
                for(i = 0; i < MAX_TEAMSCORE; ++i)
                {
@@ -2161,6 +2171,11 @@ void CheckRules_World()
        float wantovertime;
        wantovertime = 0;
 
+       if(timelimit > game_starttime)
+               game_completion_ratio = (time - game_starttime) / (timelimit - game_starttime);
+       else
+               game_completion_ratio = 0;
+
        if(checkrules_suddendeathend)
        {
                if(!checkrules_suddendeathwarning)
@@ -2363,6 +2378,7 @@ void MapVote_AddVotable(string nextMap, float isSuggestion)
        mapvote_maps[mapvote_count] = strzone(nextMap);
        mapvote_maps_suggested[mapvote_count] = isSuggestion;
 
+       pakfile = string_null;
        for(i = 0; i < mapvote_screenshot_dirs_count; ++i)
        {
                mapfile = strcat(mapvote_screenshot_dirs[i], "/", mapvote_maps[i]);
index 91416b8352f9ae450e5688e12532f9ea474272f9..38a1e249d7847a954e20a9df455dd2dfa8289b67 100644 (file)
@@ -324,6 +324,7 @@ void Ban_View()
        
        print("^2Listing all existing active bans:\n");
        
+       n = 0;
        for(i = 0; i < ban_count; ++i)
        {
                if(time > ban_expire[i])
index e39f2813450abfad76fd6a9750cee7bee470770f..7b386ec97514ef571a9aa7ab5186e50c1773ee0a 100644 (file)
@@ -36,6 +36,8 @@ string item_keys_keylist(float keylist) {
        if ((keylist & (keylist-1)) != 0)
                return strcat("the ", item_keys_names[lowestbit(keylist)]);
        
+       n = "";
+       base = 0;
        while (keylist) {
                l = lowestbit(keylist);
                if (n)
@@ -181,12 +183,13 @@ void spawnfunc_item_key() {
                break;
        
        default:
+               _netname = "FLUFFY PINK keycard";
+               _colormod = '1 1 1';
+
                if (!self.netname) {
                        objerror("item_key doesn't have a default name for this key and a custom one was not specified!");
                        remove(self);
                        return;
-               } else if (!self.colormod) {
-                       _colormod = '1 1 1';
                }
                break;
                
index 3686568d83b123b0a036d578bc7b92ba66db9853..1e8cb45aa8b56df58ba1f15717a950c3d42e9f15 100644 (file)
@@ -67,6 +67,16 @@ float DistributeEvenly_Get(float weight)
     DistributeEvenly_amount -= f;
     return f;
 }
+float DistributeEvenly_GetRandomized(float weight)
+{
+    float f;
+    if (weight <= 0)
+        return 0;
+    f = floor(random() + DistributeEvenly_amount * weight / DistributeEvenly_totalweight);
+    DistributeEvenly_totalweight -= weight;
+    DistributeEvenly_amount -= f;
+    return f;
+}
 
 #define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
 
@@ -526,7 +536,7 @@ string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
 }
 void GetCvars(float f)
 {
-       string s;
+       string s = string_null;
 
        if (f > 0)
                s = strcat1(argv(f));
@@ -772,7 +782,6 @@ float warmup_start_ammo_fuel;
 float warmup_start_health;
 float warmup_start_armorvalue;
 float g_weapon_stay;
-float g_ghost_items;
 
 entity get_weaponinfo(float w);
 
@@ -860,8 +869,11 @@ void readplayerstartcvars()
                g_weaponarena = 1;
                g_weaponarena_list = "All Weapons";
                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+               {
+                       e = get_weaponinfo(j);
                        if not(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
                                WEPSET_OR_AW(g_weaponarena_weapons, j);
+               }
        }
        else if (s == "most")
        {
@@ -1018,6 +1030,8 @@ void readplayerstartcvars()
                        warmup_start_health = cvar("g_warmup_start_health");
                        warmup_start_armorvalue = cvar("g_warmup_start_armor");
                        WEPSET_CLEAR_A(warmup_start_weapons);
+                       WEPSET_CLEAR_A(warmup_start_weapons_default);
+                       WEPSET_CLEAR_A(warmup_start_weapons_defaultmask);
                        for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
                                e = get_weaponinfo(i);
@@ -1115,7 +1129,9 @@ void readlevelcvars(void)
                if(cvar("g_rocket_flying"))
                        MUTATOR_ADD(mutator_rocketflying);
                if(cvar("g_vampire"))
-                       MUTATOR_ADD(mutator_vampire);
+                       MUTATOR_ADD(mutator_vampire);           
+               if(cvar("g_superspectate"))
+                       MUTATOR_ADD(mutator_superspec);
        }
 
        // is this a mutator? is this a mode?
@@ -1244,11 +1260,6 @@ void readlevelcvars(void)
     if(!g_weapon_stay)
         g_weapon_stay = cvar("g_weapon_stay");
 
-       g_ghost_items = cvar("g_ghost_items");
-
-       if(g_ghost_items >= 1)
-               g_ghost_items = 0.25; // default alpha value
-
        if not(inWarmupStage && !g_ca)
                game_starttime = cvar("g_start_delay");
 
@@ -1694,7 +1705,7 @@ void make_safe_for_remove(entity e)
 {
     if (e.initialize_entity)
     {
-        entity ent, prev;
+        entity ent, prev = world;
         for (ent = initialize_entity_first; ent; )
         {
             if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
@@ -1766,6 +1777,7 @@ void InitializeEntity(entity e, void(void) func, float order)
     e.initialize_entity_order = order;
 
     cur = initialize_entity_first;
+    prev = world;
     for (;;)
     {
         if (!cur || cur.initialize_entity_order > order)
@@ -2116,7 +2128,7 @@ void race_writeTime(string map, float t, string myuid)
        float newpos;
        newpos = race_readPos(map, t);
 
-       float i, prevpos;
+       float i, prevpos = 0;
        for(i = 1; i <= RANKINGS_CNT; ++i)
        {
                if(race_readUID(map, i) == myuid)
@@ -2178,6 +2190,8 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f
     org = world.mins;
     delta = world.maxs - world.mins;
 
+    start = end = org;
+
     for (i = 0; i < attempts; ++i)
     {
         start_x = org_x + random() * delta_x;
@@ -2434,12 +2448,8 @@ vector shotorg_adjust(vector vecs, float y_is_right, float visual)
 void attach_sameorigin(entity e, entity to, string tag)
 {
     vector org, t_forward, t_left, t_up, e_forward, e_up;
-    vector org0, ang0;
     float tagscale;
 
-    ang0 = e.angles;
-    org0 = e.origin;
-
     org = e.origin - gettaginfo(to, gettagindex(to, tag));
     tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
     t_forward = v_forward * tagscale;
diff --git a/qcsrc/server/mode_onslaught.qc b/qcsrc/server/mode_onslaught.qc
deleted file mode 100644 (file)
index 2e0443c..0000000
+++ /dev/null
@@ -1,1430 +0,0 @@
-void onslaught_generator_updatesprite(entity e);
-void onslaught_controlpoint_updatesprite(entity e);
-void onslaught_link_checkupdate();
-
-.entity sprite;
-.string target2;
-.float iscaptured;
-.float islinked;
-.float isgenneighbor_red;
-.float isgenneighbor_blue;
-.float iscpneighbor_red;
-.float iscpneighbor_blue;
-.float isshielded;
-.float lasthealth;
-.float lastteam;
-.float lastshielded;
-.float lastcaptured;
-
-.string model1, model2, model3;
-
-void ons_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-{
-       self.velocity = self.velocity + vforce;
-}
-
-.float giblifetime;
-void ons_throwgib_think()
-{
-       float d;
-
-       self.nextthink = time + 0.05;
-
-       d = self.giblifetime - time;
-
-       if(d<0)
-       {
-               self.think = SUB_Remove;
-               return;
-       }
-       if(d<1)
-               self.alpha = d;
-
-       if(d>2)
-       if(random()<0.6)
-               pointparticles(particleeffectnum("onslaught_generator_gib_flame"), self.origin, '0 0 0', 1);
-}
-
-void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn)
-{
-       entity gib;
-
-       gib = spawn();
-
-       setmodel(gib, smodel);
-       setorigin(gib, v_from);
-       gib.solid = SOLID_BBOX;
-       gib.movetype = MOVETYPE_BOUNCE;
-       gib.takedamage = DAMAGE_YES;
-       gib.event_damage = ons_gib_damage;
-       gib.health = -1;
-       gib.effects = EF_LOWPRECISION;
-       gib.flags = FL_NOTARGET;
-       gib.velocity = v_to;
-       gib.giblifetime = time + f_lifetime;
-
-       if (b_burn)
-       {
-               gib.think = ons_throwgib_think;
-               gib.nextthink = time + 0.05;
-       }
-       else
-               SUB_SetFade(gib, gib.giblifetime, 2);
-}
-
-void onslaught_updatelinks()
-{
-       entity l, links;
-       float stop, t1, t2, t3, t4;
-       // first check if the game has ended
-       dprint("--- updatelinks ---\n");
-       links = findchain(classname, "onslaught_link");
-       // mark generators as being shielded and networked
-       l = findchain(classname, "onslaught_generator");
-       while (l)
-       {
-               if (l.iscaptured)
-                       dprint(etos(l), " (generator) belongs to team ", ftos(l.team), "\n");
-               else
-                       dprint(etos(l), " (generator) is destroyed\n");
-               l.islinked = l.iscaptured;
-               l.isshielded = l.iscaptured;
-               l = l.chain;
-       }
-       // mark points as shielded and not networked
-       l = findchain(classname, "onslaught_controlpoint");
-       while (l)
-       {
-               l.islinked = FALSE;
-               l.isshielded = TRUE;
-               l.isgenneighbor_red = FALSE;
-               l.isgenneighbor_blue = FALSE;
-               l.iscpneighbor_red = FALSE;
-               l.iscpneighbor_blue = FALSE;
-               dprint(etos(l), " (point) belongs to team ", ftos(l.team), "\n");
-               l = l.chain;
-       }
-       // flow power outward from the generators through the network
-       l = links;
-       while (l)
-       {
-               dprint(etos(l), " (link) connects ", etos(l.goalentity), " with ", etos(l.enemy), "\n");
-               l = l.chain;
-       }
-       stop = FALSE;
-       while (!stop)
-       {
-               stop = TRUE;
-               l = links;
-               while (l)
-               {
-                       // if both points are captured by the same team, and only one of
-                       // them is powered, mark the other one as powered as well
-                       if (l.enemy.iscaptured && l.goalentity.iscaptured)
-                               if (l.enemy.islinked != l.goalentity.islinked)
-                                       if (l.enemy.team == l.goalentity.team)
-                                       {
-                                               if (!l.goalentity.islinked)
-                                               {
-                                                       stop = FALSE;
-                                                       l.goalentity.islinked = TRUE;
-                                                       dprint(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n");
-                                               }
-                                               else if (!l.enemy.islinked)
-                                               {
-                                                       stop = FALSE;
-                                                       l.enemy.islinked = TRUE;
-                                                       dprint(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n");
-                                               }
-                                       }
-                       l = l.chain;
-               }
-       }
-       // now that we know which points are powered we can mark their neighbors
-       // as unshielded if team differs
-       l = links;
-       while (l)
-       {
-               if (l.goalentity.islinked)
-               {
-                       if (l.goalentity.team != l.enemy.team)
-                       {
-                               dprint(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n");
-                               l.enemy.isshielded = FALSE;
-                       }
-                       if(l.goalentity.classname == "onslaught_generator")
-                       {
-                               if(l.goalentity.team == COLOR_TEAM1)
-                                       l.enemy.isgenneighbor_red = TRUE;
-                               else if(l.goalentity.team == COLOR_TEAM2)
-                                       l.enemy.isgenneighbor_blue = TRUE;
-                       }
-                       else
-                       {
-                               if(l.goalentity.team == COLOR_TEAM1)
-                                       l.enemy.iscpneighbor_red = TRUE;
-                               else if(l.goalentity.team == COLOR_TEAM2)
-                                       l.enemy.iscpneighbor_blue = TRUE;
-                       }
-               }
-               if (l.enemy.islinked)
-               {
-                       if (l.goalentity.team != l.enemy.team)
-                       {
-                               dprint(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n");
-                               l.goalentity.isshielded = FALSE;
-                       }
-                       if(l.enemy.classname == "onslaught_generator")
-                       {
-                               if(l.enemy.team == COLOR_TEAM1)
-                                       l.goalentity.isgenneighbor_red = TRUE;
-                               else if(l.enemy.team == COLOR_TEAM2)
-                                       l.goalentity.isgenneighbor_blue = TRUE;
-                       }
-                       else
-                       {
-                               if(l.enemy.team == COLOR_TEAM1)
-                                       l.goalentity.iscpneighbor_red = TRUE;
-                               else if(l.enemy.team == COLOR_TEAM2)
-                                       l.goalentity.iscpneighbor_blue = TRUE;
-                       }
-               }
-               l = l.chain;
-       }
-       // now update the takedamage and alpha variables on generator shields
-       l = findchain(classname, "onslaught_generator");
-       while (l)
-       {
-               if (l.isshielded)
-               {
-                       dprint(etos(l), " (generator) is shielded\n");
-                       l.enemy.alpha = 1;
-                       l.takedamage = DAMAGE_NO;
-                       l.bot_attack = FALSE;
-               }
-               else
-               {
-                       dprint(etos(l), " (generator) is not shielded\n");
-                       l.enemy.alpha = -1;
-                       l.takedamage = DAMAGE_AIM;
-                       l.bot_attack = TRUE;
-               }
-               l = l.chain;
-       }
-       // now update the takedamage and alpha variables on control point icons
-       l = findchain(classname, "onslaught_controlpoint");
-       while (l)
-       {
-               if (l.isshielded)
-               {
-                       dprint(etos(l), " (point) is shielded\n");
-                       l.enemy.alpha = 1;
-                       if (l.goalentity)
-                       {
-                               l.goalentity.takedamage = DAMAGE_NO;
-                               l.goalentity.bot_attack = FALSE;
-                       }
-               }
-               else
-               {
-                       dprint(etos(l), " (point) is not shielded\n");
-                       l.enemy.alpha = -1;
-                       if (l.goalentity)
-                       {
-                               l.goalentity.takedamage = DAMAGE_AIM;
-                               l.goalentity.bot_attack = TRUE;
-                       }
-               }
-               onslaught_controlpoint_updatesprite(l);
-               l = l.chain;
-       }
-       // count generators owned by each team
-       t1 = t2 = t3 = t4 = 0;
-       l = findchain(classname, "onslaught_generator");
-       while (l)
-       {
-               if (l.iscaptured)
-               {
-                       if (l.team == COLOR_TEAM1) t1 = 1;
-                       if (l.team == COLOR_TEAM2) t2 = 1;
-                       if (l.team == COLOR_TEAM3) t3 = 1;
-                       if (l.team == COLOR_TEAM4) t4 = 1;
-               }
-               onslaught_generator_updatesprite(l);
-               l = l.chain;
-       }
-       // see if multiple teams remain (if not, it's game over)
-       if (t1 + t2 + t3 + t4 < 2)
-               dprint("--- game over ---\n");
-       else
-               dprint("--- done updating links ---\n");
-}
-
-float onslaught_controlpoint_can_be_linked(entity cp, float t)
-{
-       if(t == COLOR_TEAM1)
-       {
-               if(cp.isgenneighbor_red)
-                       return 2;
-               if(cp.iscpneighbor_red)
-                       return 1;
-       }
-       else if(t == COLOR_TEAM2)
-       {
-               if(cp.isgenneighbor_blue)
-                       return 2;
-               if(cp.iscpneighbor_blue)
-                       return 1;
-       }
-       return 0;
-       /*
-          entity e;
-       // check to see if this player has a legitimate claim to capture this
-       // control point - more specifically that there is a captured path of
-       // points leading back to the team generator
-       e = findchain(classname, "onslaught_link");
-       while (e)
-       {
-       if (e.goalentity == cp)
-       {
-       dprint(etos(e), " (link) connects to ", etos(e.enemy), " (point)");
-       if (e.enemy.islinked)
-       {
-       dprint(" which is linked");
-       if (e.enemy.team == t)
-       {
-       dprint(" and has the correct team!\n");
-       return 1;
-       }
-       else
-       dprint(" but has the wrong team\n");
-       }
-       else
-       dprint("\n");
-       }
-       else if (e.enemy == cp)
-       {
-       dprint(etos(e), " (link) connects to ", etos(e.goalentity), " (point)");
-       if (e.goalentity.islinked)
-       {
-       dprint(" which is linked");
-       if (e.goalentity.team == t)
-       {
-       dprint(" and has a team!\n");
-       return 1;
-       }
-       else
-       dprint(" but has the wrong team\n");
-       }
-       else
-       dprint("\n");
-       }
-       e = e.chain;
-       }
-       return 0;
-        */
-}
-
-float onslaught_controlpoint_attackable(entity cp, float t)
-       // -2: SAME TEAM, attackable by enemy!
-       // -1: SAME TEAM!
-       // 0: off limits
-       // 1: attack it
-       // 2: touch it
-       // 3: attack it (HIGH PRIO)
-       // 4: touch it (HIGH PRIO)
-{
-       float a;
-
-       if(cp.isshielded)
-       {
-               return 0;
-       }
-       else if(cp.goalentity)
-       {
-               // if there's already an icon built, nothing happens
-               if(cp.team == t)
-               {
-                       a = onslaught_controlpoint_can_be_linked(cp, COLOR_TEAM1 + COLOR_TEAM2 - t);
-                       if(a) // attackable by enemy?
-                               return -2; // EMERGENCY!
-                       return -1;
-               }
-               // we know it can be linked, so no need to check
-               // but...
-               a = onslaught_controlpoint_can_be_linked(cp, t);
-               if(a == 2) // near our generator?
-                       return 3; // EMERGENCY!
-               return 1;
-       }
-       else
-       {
-               // free point
-               if(onslaught_controlpoint_can_be_linked(cp, t))
-               {
-                       a = onslaught_controlpoint_can_be_linked(cp, COLOR_TEAM1 + COLOR_TEAM2 - t);
-                       if(a == 2)
-                               return 4; // GET THIS ONE NOW!
-                       else
-                               return 2; // TOUCH ME
-               }
-       }
-       return 0;
-}
-
-float overtime_msg_time;
-void onslaught_generator_think()
-{
-       float d;
-       entity e;
-       self.nextthink = ceil(time + 1);
-       if (!gameover)
-       {
-               if (autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60)
-               {
-                       if (!overtime_msg_time)
-                       {
-                               FOR_EACH_PLAYER(e)
-                                       centerprint(e, "^3Now playing ^1OVERTIME^3!\n^3Generators start now to self-damaging.\n^3The more control points your team holds,\n^3the more damage the enemy generator gets.");
-                               overtime_msg_time = time;
-                       }
-                       // self.max_health / 300 gives 5 minutes of overtime.
-                       // control points reduce the overtime duration.
-                       sound(self, CH_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTN_NORM);
-                       d = 1;
-                       e = findchain(classname, "onslaught_controlpoint");
-                       while (e)
-                       {
-                               if (e.team != self.team)
-                                       if (e.islinked)
-                                               d = d + 1;
-                               e = e.chain;
-                       }
-                       if(autocvar_g_campaign && autocvar__campaign_testrun)
-                               d = d * self.max_health;
-                       else
-                               d = d * self.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
-                       Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0');
-               }
-               else if (overtime_msg_time)
-                       overtime_msg_time = 0;
-       }
-}
-
-void onslaught_generator_ring_spawn(vector org)
-{
-       modeleffect_spawn("models/onslaught/shockwavetransring.md3", 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, -16, 0.1, 1.25, 0.25);
-}
-
-void onslaught_generator_ray_think()
-{
-       self.nextthink = time + 0.05;
-       if(self.count > 10)
-       {
-               self.think = SUB_Remove;
-               return;
-       }
-
-       if(self.count > 5)
-               self.alpha -= 0.1;
-       else
-               self.alpha += 0.1;
-
-       self.scale += 0.2;
-       self.count +=1;
-}
-
-void onslaught_generator_ray_spawn(vector org)
-{
-       entity e;
-       e = spawn();
-       setmodel(e, "models/onslaught/ons_ray.md3");
-       setorigin(e, org);
-       e.angles = randomvec() * 360;
-       e.alpha = 0;
-       e.scale = random() * 5 + 8;
-       e.think = onslaught_generator_ray_think;
-       e.nextthink = time + 0.05;
-}
-
-void onslaught_generator_shockwave_spawn(vector org)
-{
-       shockwave_spawn("models/onslaught/shockwave.md3", org, -64, 0.75, 0.5);
-}
-
-void onslaught_generator_damage_think()
-{
-       if(self.owner.health < 0)
-       {
-               self.think = SUB_Remove;
-               return;
-       }
-       self.nextthink = time+0.1;
-
-       // damaged fx (less probable the more damaged is the generator)
-       if(random() < 0.9 - self.owner.health / self.owner.max_health)
-               if(random() < 0.01)
-               {
-                       pointparticles(particleeffectnum("electro_ballexplode"), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
-                       sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTN_NORM);
-               }
-               else
-                       pointparticles(particleeffectnum("torch_small"), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
-}
-
-void onslaught_generator_damage_spawn(entity gd_owner)
-{
-       entity e;
-       e = spawn();
-       e.owner = gd_owner;
-       e.health = self.owner.health;
-       setorigin(e, gd_owner.origin);
-       e.think = onslaught_generator_damage_think;
-       e.nextthink = time+1;
-}
-
-void onslaught_generator_deaththink()
-{
-       vector org;
-       float i;
-
-       if not (self.count)
-               self.count = 40;
-
-       // White shockwave
-       if(self.count==40||self.count==20)
-       {
-               onslaught_generator_ring_spawn(self.origin);
-               sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTN_NORM);
-       }
-
-       // Throw some gibs
-       if(random() < 0.3)
-       {
-               i = random();
-               if(i < 0.3)
-                       ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 11 + '0 0 20', "models/onslaught/gen_gib1.md3", 6, TRUE);
-               else if(i > 0.7)
-                       ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 12 + '0 0 20', "models/onslaught/gen_gib2.md3", 6, TRUE);
-               else
-                       ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 13 + '0 0 20', "models/onslaught/gen_gib3.md3", 6, TRUE);
-       }
-
-       // Spawn fire balls
-       for(i=0;i < 10;++i)
-       {
-               org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
-               pointparticles(particleeffectnum("onslaught_generator_gib_explode"), org, '0 0 0', 1);
-       }
-
-       // Short explosion sound + small explosion
-       if(random() < 0.25)
-       {
-               te_explosion(self.origin);
-               sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
-       }
-
-       // Particles
-       org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
-       pointparticles(particleeffectnum("onslaught_generator_smallexplosion"), org, '0 0 0', 1);
-
-       // rays
-       if(random() > 0.25 )
-       {
-               onslaught_generator_ray_spawn(self.origin);
-       }
-
-       // Final explosion
-       if(self.count==1)
-       {
-               org = self.origin;
-               te_explosion(org);
-               onslaught_generator_shockwave_spawn(org);
-               pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1);
-               sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
-       }
-       else
-               self.nextthink = time + 0.05;
-
-       self.count = self.count - 1;
-}
-
-void onslaught_generator_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-       float i;
-       if (damage <= 0)
-               return;
-       if(inWarmupStage)
-               return;
-       if (attacker != self)
-       {
-               if (self.isshielded)
-               {
-                       // this is protected by a shield, so ignore the damage
-                       if (time > self.pain_finished)
-                               if (attacker.classname == "player")
-                               {
-                                       play2(attacker, "onslaught/damageblockedbyshield.wav");
-                                       self.pain_finished = time + 1;
-                               }
-                       return;
-               }
-               if (time > self.pain_finished)
-               {
-                       self.pain_finished = time + 10;
-                       bprint(ColoredTeamName(self.team), " generator under attack!\n");
-                       play2team(self.team, "onslaught/generator_underattack.wav");
-               }
-       }
-       self.health = self.health - damage;
-       WaypointSprite_UpdateHealth(self.sprite, self.health);
-       // choose an animation frame based on health
-       self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
-       // see if the generator is still functional, or dying
-       if (self.health > 0)
-       {
-#ifdef ONSLAUGHT_SPAM
-               float h, lh;
-               lh = ceil(self.lasthealth / 100) * 100;
-               h = ceil(self.health / 100) * 100;
-               if(lh != h)
-                       bprint(ColoredTeamName(self.team), " generator has less than ", ftos(h), " health remaining\n");
-#endif
-               self.lasthealth = self.health;
-       }
-       else if not(inWarmupStage)
-       {
-               if (attacker == self)
-                       bprint(ColoredTeamName(self.team), " generator spontaneously exploded due to overtime!\n");
-               else
-               {
-                       string t;
-                       t = ColoredTeamName(attacker.team);
-                       bprint(ColoredTeamName(self.team), " generator destroyed by ", t, "!\n");
-               }
-               self.iscaptured = FALSE;
-               self.islinked = FALSE;
-               self.isshielded = FALSE;
-               self.takedamage = DAMAGE_NO; // can't be hurt anymore
-               self.event_damage = SUB_Null; // won't do anything if hurt
-               self.count = 0; // reset counter
-               self.think = onslaught_generator_deaththink; // explosion sequence
-               self.nextthink = time; // start exploding immediately
-               self.think(); // do the first explosion now
-
-               WaypointSprite_UpdateMaxHealth(self.sprite, 0);
-
-               onslaught_updatelinks();
-       }
-
-       if(self.health <= 0)
-               setmodel(self, "models/onslaught/generator_dead.md3");
-       else if(self.health < self.max_health * 0.10)
-               setmodel(self, "models/onslaught/generator_dmg9.md3");
-       else if(self.health < self.max_health * 0.20)
-               setmodel(self, "models/onslaught/generator_dmg8.md3");
-       else if(self.health < self.max_health * 0.30)
-               setmodel(self, "models/onslaught/generator_dmg7.md3");
-       else if(self.health < self.max_health * 0.40)
-               setmodel(self, "models/onslaught/generator_dmg6.md3");
-       else if(self.health < self.max_health * 0.50)
-               setmodel(self, "models/onslaught/generator_dmg5.md3");
-       else if(self.health < self.max_health * 0.60)
-               setmodel(self, "models/onslaught/generator_dmg4.md3");
-       else if(self.health < self.max_health * 0.70)
-               setmodel(self, "models/onslaught/generator_dmg3.md3");
-       else if(self.health < self.max_health * 0.80)
-               setmodel(self, "models/onslaught/generator_dmg2.md3");
-       else if(self.health < self.max_health * 0.90)
-               setmodel(self, "models/onslaught/generator_dmg1.md3");
-       setsize(self, '-52 -52 -14', '52 52 75');
-
-       // Throw some flaming gibs on damage, more damage = more chance for gib
-       if(random() < damage/220)
-       {
-               sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
-               i = random();
-               if(i < 0.3)
-                       ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib1.md3", 5, TRUE);
-               else if(i > 0.7)
-                       ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib2.md3", 5, TRUE);
-               else
-                       ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib3.md3", 5, TRUE);
-       }
-       else
-       {
-               // particles on every hit
-               pointparticles(particleeffectnum("sparks"), hitloc, force * -1, 1);
-
-               //sound on every hit
-               if (random() < 0.5)
-                       sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTN_NORM);
-               else
-                       sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM);
-       }
-
-       //throw some gibs on damage
-       if(random() < damage/200+0.2)
-               if(random() < 0.5)
-                       ons_throwgib(hitloc + '0 0 20', randomvec()*360, "models/onslaught/gen_gib1.md3", 5, FALSE);
-}
-
-// update links after a delay
-void onslaught_generator_delayed()
-{
-       onslaught_updatelinks();
-       // now begin normal thinking
-       self.think = onslaught_generator_think;
-       self.nextthink = time;
-}
-
-string onslaught_generator_waypointsprite_for_team(entity e, float t)
-{
-       if(t == e.team)
-       {
-               if(e.team == COLOR_TEAM1)
-                       return "ons-gen-red";
-               else if(e.team == COLOR_TEAM2)
-                       return "ons-gen-blue";
-       }
-       if(e.isshielded)
-               return "ons-gen-shielded";
-       if(e.team == COLOR_TEAM1)
-               return "ons-gen-red";
-       else if(e.team == COLOR_TEAM2)
-               return "ons-gen-blue";
-       return "";
-}
-
-void onslaught_generator_updatesprite(entity e)
-{
-       string s1, s2, s3;
-       s1 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM1);
-       s2 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM2);
-       s3 = onslaught_generator_waypointsprite_for_team(e, -1);
-       WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
-
-       if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
-       {
-               e.lastteam = e.team + 2;
-               e.lastshielded = e.isshielded;
-               if(e.lastshielded)
-               {
-                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
-                       else
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
-               }
-               else
-               {
-                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, FALSE));
-                       else
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
-               }
-               WaypointSprite_Ping(e.sprite);
-       }
-}
-
-string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
-{
-       float a;
-       if(t != -1)
-       {
-               a = onslaught_controlpoint_attackable(e, t);
-               if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
-               {
-                       if(e.team == COLOR_TEAM1)
-                               return "ons-cp-atck-red";
-                       else if(e.team == COLOR_TEAM2)
-                               return "ons-cp-atck-blue";
-                       else
-                               return "ons-cp-atck-neut";
-               }
-               else if(a == -2) // DEFEND THIS ONE NOW
-               {
-                       if(e.team == COLOR_TEAM1)
-                               return "ons-cp-dfnd-red";
-                       else if(e.team == COLOR_TEAM2)
-                               return "ons-cp-dfnd-blue";
-               }
-               else if(e.team == t || a == -1 || a == 1) // own point, or fire at it
-               {
-                       if(e.team == COLOR_TEAM1)
-                               return "ons-cp-red";
-                       else if(e.team == COLOR_TEAM2)
-                               return "ons-cp-blue";
-               }
-               else if(a == 2) // touch it
-                       return "ons-cp-neut";
-       }
-       else
-       {
-               if(e.team == COLOR_TEAM1)
-                       return "ons-cp-red";
-               else if(e.team == COLOR_TEAM2)
-                       return "ons-cp-blue";
-               else
-                       return "ons-cp-neut";
-       }
-       return "";
-}
-
-void onslaught_controlpoint_updatesprite(entity e)
-{
-       string s1, s2, s3;
-       s1 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM1);
-       s2 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM2);
-       s3 = onslaught_controlpoint_waypointsprite_for_team(e, -1);
-       WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
-
-       float sh;
-       sh = !(onslaught_controlpoint_can_be_linked(e, COLOR_TEAM1) || onslaught_controlpoint_can_be_linked(e, COLOR_TEAM2));
-
-       if(e.lastteam != e.team + 2 || e.lastshielded != sh || e.iscaptured != e.lastcaptured)
-       {
-               if(e.iscaptured) // don't mess up build bars!
-               {
-                       if(sh)
-                       {
-                               WaypointSprite_UpdateMaxHealth(e.sprite, 0);
-                       }
-                       else
-                       {
-                               WaypointSprite_UpdateMaxHealth(e.sprite, e.goalentity.max_health);
-                               WaypointSprite_UpdateHealth(e.sprite, e.goalentity.health);
-                       }
-               }
-               if(e.lastshielded)
-               {
-                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
-                       else
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0.5 0.5');
-               }
-               else
-               {
-                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, colormapPaletteColor(e.team - 1, FALSE));
-                       else
-                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
-               }
-               WaypointSprite_Ping(e.sprite);
-
-               e.lastteam = e.team + 2;
-               e.lastshielded = sh;
-               e.lastcaptured = e.iscaptured;
-       }
-}
-
-void onslaught_generator_reset()
-{
-       self.team = self.team_saved;
-       self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
-       self.takedamage = DAMAGE_AIM;
-       self.bot_attack = TRUE;
-       self.iscaptured = TRUE;
-       self.islinked = TRUE;
-       self.isshielded = TRUE;
-       self.enemy.solid = SOLID_NOT;
-       self.think = onslaught_generator_delayed;
-       self.nextthink = time + 0.2;
-       setmodel(self, "models/onslaught/generator.md3");
-       setsize(self, '-52 -52 -14', '52 52 75');
-
-       WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
-       WaypointSprite_UpdateHealth(self.sprite, self.health);
-}
-
-/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
-  Base generator.
-
-  spawnfunc_onslaught_link entities can target this.
-
-keys:
-"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
-"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
- */
-void spawnfunc_onslaught_generator()
-{
-       if (!g_onslaught)
-       {
-               remove(self);
-               return;
-       }
-
-       entity e;
-       precache_model("models/onslaught/generator.md3");
-       precache_model("models/onslaught/generator_shield.md3");
-       precache_model("models/onslaught/generator_dmg1.md3");
-       precache_model("models/onslaught/generator_dmg2.md3");
-       precache_model("models/onslaught/generator_dmg3.md3");
-       precache_model("models/onslaught/generator_dmg4.md3");
-       precache_model("models/onslaught/generator_dmg5.md3");
-       precache_model("models/onslaught/generator_dmg6.md3");
-       precache_model("models/onslaught/generator_dmg7.md3");
-       precache_model("models/onslaught/generator_dmg8.md3");
-       precache_model("models/onslaught/generator_dmg9.md3");
-       precache_model("models/onslaught/generator_dead.md3");
-       precache_model("models/onslaught/shockwave.md3");
-       precache_model("models/onslaught/shockwavetransring.md3");
-       precache_model("models/onslaught/gen_gib1.md3");
-       precache_model("models/onslaught/gen_gib2.md3");
-       precache_model("models/onslaught/gen_gib3.md3");
-       precache_model("models/onslaught/ons_ray.md3");
-       precache_sound("onslaught/generator_decay.wav");
-       precache_sound("weapons/grenade_impact.wav");
-       precache_sound("weapons/rocket_impact.wav");
-       precache_sound("onslaught/generator_underattack.wav");
-       precache_sound("onslaught/shockwave.wav");
-       precache_sound("onslaught/ons_hit1.wav");
-       precache_sound("onslaught/ons_hit2.wav");
-       precache_sound("onslaught/electricity_explode.wav");
-       if (!self.team)
-               objerror("team must be set");
-       self.team_saved = self.team;
-       self.colormap = 1024 + (self.team - 1) * 17;
-       self.solid = SOLID_BBOX;
-       self.movetype = MOVETYPE_NONE;
-       self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
-       setmodel(self, "models/onslaught/generator.md3");
-       setsize(self, '-52 -52 -14', '52 52 75');
-       setorigin(self, self.origin);
-       self.takedamage = DAMAGE_AIM;
-       self.bot_attack = TRUE;
-       self.event_damage = onslaught_generator_damage;
-       self.iscaptured = TRUE;
-       self.islinked = TRUE;
-       self.isshielded = TRUE;
-       // helper entity that create fx when generator is damaged
-       onslaught_generator_damage_spawn(self);
-       // spawn shield model which indicates whether this can be damaged
-       self.enemy = e = spawn();
-       e.classname = "onslaught_generator_shield";
-       e.solid = SOLID_NOT;
-       e.movetype = MOVETYPE_NONE;
-       e.effects = EF_ADDITIVE;
-       setmodel(e, "models/onslaught/generator_shield.md3");
-       setorigin(e, self.origin);
-       e.colormap = self.colormap;
-       e.team = self.team;
-       self.think = onslaught_generator_delayed;
-       self.nextthink = time + 0.2;
-       InitializeEntity(self, onslaught_generator_delayed, INITPRIO_LAST);
-
-       WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite, RADARICON_NONE, '0 0 0');
-       WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
-       WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
-       WaypointSprite_UpdateHealth(self.sprite, self.health);
-
-       waypoint_spawnforitem(self);
-
-       onslaught_updatelinks();
-
-       self.reset = onslaught_generator_reset;
-}
-
-.float waslinked;
-.float cp_bob_spd;
-.vector cp_origin, cp_bob_origin, cp_bob_dmg;
-
-float ons_notification_time_team1;
-float ons_notification_time_team2;
-
-void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-       entity oself;
-       float nag;
-
-       if (damage <= 0)
-               return;
-       if (self.owner.isshielded)
-       {
-               // this is protected by a shield, so ignore the damage
-               if (time > self.pain_finished)
-                       if (attacker.classname == "player")
-                       {
-                               play2(attacker, "onslaught/damageblockedbyshield.wav");
-                               self.pain_finished = time + 1;
-                       }
-               return;
-       }
-
-       if (attacker.classname == "player")
-       {
-               if(self.team == COLOR_TEAM1)
-               {
-                       if(time - ons_notification_time_team1 > 10)
-                       {
-                               nag = TRUE;
-                               ons_notification_time_team1 = time;
-                       }
-               }
-               else if(self.team == COLOR_TEAM2)
-               {
-                       if(time - ons_notification_time_team2 > 10)
-                       {
-                               nag = TRUE;
-                               ons_notification_time_team2 = time;
-                       }
-               }
-               else
-                       nag = TRUE;
-
-               if(nag)
-                       play2team(self.team, "onslaught/controlpoint_underattack.wav");
-       }
-
-       self.health = self.health - damage;
-       if(self.owner.iscaptured)
-               WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
-       else
-               WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / sys_frametime));
-       self.pain_finished = time + 1;
-       self.punchangle = (2 * randomvec() - '1 1 1') * 45;
-       self.cp_bob_dmg_z = (2 * random() - 1) * 15;
-       // colormod flash when shot
-       self.colormod = '2 2 2';
-       // particles on every hit
-       pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
-       //sound on every hit
-       if (random() < 0.5)
-               sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTN_NORM);
-       else
-               sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTN_NORM);
-
-       if (self.health < 0)
-       {
-               sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
-               pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
-               {
-                       string t;
-                       t = ColoredTeamName(attacker.team);
-                       bprint(ColoredTeamName(self.team), " ", self.message, " control point destroyed by ", t, "\n");
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 25, "models/onslaught/controlpoint_icon_gib1.md3", 3, FALSE);
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, FALSE);
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, FALSE);
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
-                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
-               }
-               self.owner.goalentity = world;
-               self.owner.islinked = FALSE;
-               self.owner.iscaptured = FALSE;
-               self.owner.team = 0;
-               self.owner.colormap = 1024;
-
-               WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
-
-               onslaught_updatelinks();
-
-               // Use targets now (somebody make sure this is in the right place..)
-               oself = self;
-               self = self.owner;
-               activator = self;
-               SUB_UseTargets ();
-               self = oself;
-
-
-               self.owner.waslinked = self.owner.islinked;
-               if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
-                       setmodel(self.owner, "models/onslaught/controlpoint_pad.md3");
-               //setsize(self, '-32 -32 0', '32 32 8');
-
-               remove(self);
-       }
-}
-
-void onslaught_controlpoint_icon_think()
-{
-       entity oself;
-       self.nextthink = time + sys_frametime;
-       if (time > self.pain_finished + 5)
-       {
-               if(self.health < self.max_health)
-               {
-                       self.health = self.health + self.count;
-                       if (self.health >= self.max_health)
-                               self.health = self.max_health;
-                       WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
-               }
-       }
-       if (self.health < self.max_health * 0.25)
-               setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
-       else if (self.health < self.max_health * 0.50)
-               setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
-       else if (self.health < self.max_health * 0.75)
-               setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
-       else if (self.health < self.max_health * 0.90)
-               setmodel(self, "models/onslaught/controlpoint_icon.md3");
-       // colormod flash when shot
-       self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
-
-       if(self.owner.islinked != self.owner.waslinked)
-       {
-               // unteam the spawnpoint if needed
-               float t;
-               t = self.owner.team;
-               if(!self.owner.islinked)
-                       self.owner.team = 0;
-
-               oself = self;
-               self = self.owner;
-               activator = self;
-               SUB_UseTargets ();
-               self = oself;
-
-               self.owner.team = t;
-
-               self.owner.waslinked = self.owner.islinked;
-       }
-
-       if (self.punchangle_x > 0)
-       {
-               self.punchangle_x = self.punchangle_x - 60 * sys_frametime;
-               if (self.punchangle_x < 0)
-                       self.punchangle_x = 0;
-       }
-       else if (self.punchangle_x < 0)
-       {
-               self.punchangle_x = self.punchangle_x + 60 * sys_frametime;
-               if (self.punchangle_x > 0)
-                       self.punchangle_x = 0;
-       }
-
-       if (self.punchangle_y > 0)
-       {
-               self.punchangle_y = self.punchangle_y - 60 * sys_frametime;
-               if (self.punchangle_y < 0)
-                       self.punchangle_y = 0;
-       }
-       else if (self.punchangle_y < 0)
-       {
-               self.punchangle_y = self.punchangle_y + 60 * sys_frametime;
-               if (self.punchangle_y > 0)
-                       self.punchangle_y = 0;
-       }
-
-       if (self.punchangle_z > 0)
-       {
-               self.punchangle_z = self.punchangle_z - 60 * sys_frametime;
-               if (self.punchangle_z < 0)
-                       self.punchangle_z = 0;
-       }
-       else if (self.punchangle_z < 0)
-       {
-               self.punchangle_z = self.punchangle_z + 60 * sys_frametime;
-               if (self.punchangle_z > 0)
-                       self.punchangle_z = 0;
-       }
-
-       self.angles_x = self.punchangle_x;
-       self.angles_y = self.punchangle_y + self.mangle_y;
-       self.angles_z = self.punchangle_z;
-       self.mangle_y = self.mangle_y + 45 * sys_frametime;
-
-       self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
-       self.cp_bob_spd = self.cp_bob_spd + 1.875 * sys_frametime;
-       if(self.cp_bob_dmg_z > 0)
-               self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * sys_frametime;
-       else
-               self.cp_bob_dmg_z = 0;
-       setorigin(self,self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
-
-       // damaged fx
-       if(random() < 0.6 - self.health / self.max_health)
-       {
-               pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
-
-               if(random() > 0.8)
-                       sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTN_NORM);
-               else if (random() > 0.5)
-                       sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTN_NORM);
-       }
-}
-
-void onslaught_controlpoint_icon_buildthink()
-{
-       entity oself;
-       float a;
-
-       self.nextthink = time + sys_frametime;
-
-       // only do this if there is power
-       a = onslaught_controlpoint_can_be_linked(self.owner, self.owner.team);
-       if(!a)
-               return;
-
-       self.health = self.health + self.count;
-
-       if (self.health >= self.max_health)
-       {
-               self.health = self.max_health;
-               self.count = autocvar_g_onslaught_cp_regen * sys_frametime; // slow repair rate from now on
-               self.think = onslaught_controlpoint_icon_think;
-               sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTN_NORM);
-               bprint(ColoredTeamName(self.team), " captured ", self.owner.message, " control point\n");
-               self.owner.iscaptured = TRUE;
-
-               WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
-               WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
-
-               onslaught_updatelinks();
-
-               // Use targets now (somebody make sure this is in the right place..)
-               oself = self;
-               self = self.owner;
-               activator = self;
-               SUB_UseTargets ();
-               self = oself;
-               self.cp_origin = self.origin;
-               self.cp_bob_origin = '0 0 0.1';
-               self.cp_bob_spd = 0;
-       }
-       self.alpha = self.health / self.max_health;
-       // colormod flash when shot
-       self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
-       if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
-               setmodel(self.owner, "models/onslaught/controlpoint_pad2.md3");
-       //setsize(self, '-32 -32 0', '32 32 8');
-
-       if(random() < 0.9 - self.health / self.max_health)
-               pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
-}
-
-
-
-
-void onslaught_controlpoint_touch()
-{
-       entity e;
-       float a;
-       if (other.classname != "player")
-               return;
-       a = onslaught_controlpoint_attackable(self, other.team);
-       if(a != 2 && a != 4)
-               return;
-       // we've verified that this player has a legitimate claim to this point,
-       // so start building the captured point icon (which only captures this
-       // point if it successfully builds without being destroyed first)
-       self.goalentity = e = spawn();
-       e.classname = "onslaught_controlpoint_icon";
-       e.owner = self;
-       e.max_health = autocvar_g_onslaught_cp_health;
-       e.health = autocvar_g_onslaught_cp_buildhealth;
-       e.solid = SOLID_BBOX;
-       e.movetype = MOVETYPE_NONE;
-       setmodel(e, "models/onslaught/controlpoint_icon.md3");
-       setsize(e, '-32 -32 -32', '32 32 32');
-       setorigin(e, self.origin + '0 0 96');
-       e.takedamage = DAMAGE_AIM;
-       e.bot_attack = TRUE;
-       e.event_damage = onslaught_controlpoint_icon_damage;
-       e.team = other.team;
-       e.colormap = 1024 + (e.team - 1) * 17;
-       e.think = onslaught_controlpoint_icon_buildthink;
-       e.nextthink = time + sys_frametime;
-       e.count = (e.max_health - e.health) * sys_frametime / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
-       sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTN_NORM);
-       self.team = e.team;
-       self.colormap = e.colormap;
-       WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime));
-       onslaught_updatelinks();
-}
-
-void onslaught_controlpoint_reset()
-{
-       if(self.goalentity && self.goalentity != world)
-               remove(self.goalentity);
-       self.goalentity = world;
-       self.team = 0;
-       self.colormap = 1024;
-       self.iscaptured = FALSE;
-       self.islinked = FALSE;
-       self.isshielded = TRUE;
-       self.enemy.solid = SOLID_NOT;
-       self.enemy.colormap = self.colormap;
-       self.think = self.enemy.think = SUB_Null;
-       self.nextthink = 0; // don't like SUB_Null :P
-       setmodel(self, "models/onslaught/controlpoint_pad.md3");
-       //setsize(self, '-32 -32 0', '32 32 8');
-
-       WaypointSprite_UpdateMaxHealth(self.sprite, 0);
-
-       onslaught_updatelinks();
-
-       activator = self;
-       SUB_UseTargets(); // to reset the structures, playerspawns etc.
-}
-
-/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
-  Control point. Be sure to give this enough clearance so that the shootable part has room to exist
-
-  This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
-
-keys:
-"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
-"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
-"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
- */
-void spawnfunc_onslaught_controlpoint()
-{
-       entity e;
-       if (!g_onslaught)
-       {
-               remove(self);
-               return;
-       }
-       precache_model("models/onslaught/controlpoint_pad.md3");
-       precache_model("models/onslaught/controlpoint_pad2.md3");
-       precache_model("models/onslaught/controlpoint_shield.md3");
-       precache_model("models/onslaught/controlpoint_icon.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
-       precache_model("models/onslaught/controlpoint_icon_gib1.md3");
-       precache_model("models/onslaught/controlpoint_icon_gib2.md3");
-       precache_model("models/onslaught/controlpoint_icon_gib4.md3");
-       precache_sound("onslaught/controlpoint_build.wav");
-       precache_sound("onslaught/controlpoint_built.wav");
-       precache_sound("weapons/grenade_impact.wav");
-       precache_sound("onslaught/damageblockedbyshield.wav");
-       precache_sound("onslaught/controlpoint_underattack.wav");
-       precache_sound("onslaught/ons_spark1.wav");
-       precache_sound("onslaught/ons_spark2.wav");
-       self.solid = SOLID_BBOX;
-       self.movetype = MOVETYPE_NONE;
-       setmodel(self, "models/onslaught/controlpoint_pad.md3");
-       //setsize(self, '-32 -32 0', '32 32 8');
-       setorigin(self, self.origin);
-       self.touch = onslaught_controlpoint_touch;
-       self.team = 0;
-       self.colormap = 1024;
-       self.iscaptured = FALSE;
-       self.islinked = FALSE;
-       self.isshielded = TRUE;
-       // spawn shield model which indicates whether this can be damaged
-       self.enemy = e = spawn();
-       e.classname = "onslaught_controlpoint_shield";
-       e.solid = SOLID_NOT;
-       e.movetype = MOVETYPE_NONE;
-       e.effects = EF_ADDITIVE;
-       setmodel(e, "models/onslaught/controlpoint_shield.md3");
-       //setsize(e, '-32 -32 0', '32 32 128');
-       setorigin(e, self.origin);
-       e.colormap = self.colormap;
-
-       waypoint_spawnforitem(self);
-
-       WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite, RADARICON_NONE, '0 0 0');
-       WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
-
-       onslaught_updatelinks();
-
-       self.reset = onslaught_controlpoint_reset;
-}
-
-float onslaught_link_send(entity to, float sendflags)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
-       WriteByte(MSG_ENTITY, sendflags);
-       if(sendflags & 1)
-       {
-               WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
-               WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
-               WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
-       }
-       if(sendflags & 2)
-       {
-               WriteCoord(MSG_ENTITY, self.enemy.origin_x);
-               WriteCoord(MSG_ENTITY, self.enemy.origin_y);
-               WriteCoord(MSG_ENTITY, self.enemy.origin_z);
-       }
-       if(sendflags & 4)
-       {
-               WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
-       }
-       return TRUE;
-}
-
-void onslaught_link_checkupdate()
-{
-       // TODO check if the two sides have moved (currently they won't move anyway)
-       float redpower, bluepower;
-
-       redpower = bluepower = 0;
-       if(self.goalentity.islinked)
-       {
-               if(self.goalentity.team == COLOR_TEAM1)
-                       redpower = 1;
-               else if(self.goalentity.team == COLOR_TEAM2)
-                       bluepower = 1;
-       }
-       if(self.enemy.islinked)
-       {
-               if(self.enemy.team == COLOR_TEAM1)
-                       redpower = 2;
-               else if(self.enemy.team == COLOR_TEAM2)
-                       bluepower = 2;
-       }
-
-       float cc;
-       if(redpower == 1 && bluepower == 2)
-               cc = (COLOR_TEAM1 - 1) * 0x01 + (COLOR_TEAM2 - 1) * 0x10;
-       else if(redpower == 2 && bluepower == 1)
-               cc = (COLOR_TEAM1 - 1) * 0x10 + (COLOR_TEAM2 - 1) * 0x01;
-       else if(redpower)
-               cc = (COLOR_TEAM1 - 1) * 0x11;
-       else if(bluepower)
-               cc = (COLOR_TEAM2 - 1) * 0x11;
-       else
-               cc = 0;
-
-       //print(etos(self), " rp=", ftos(redpower), " bp=", ftos(bluepower), " ");
-       //print("cc=", ftos(cc), "\n");
-
-       if(cc != self.clientcolors)
-       {
-               self.clientcolors = cc;
-               self.SendFlags |= 4;
-       }
-
-       self.nextthink = time;
-}
-
-void onslaught_link_delayed()
-{
-       self.goalentity = find(world, targetname, self.target);
-       self.enemy = find(world, targetname, self.target2);
-       if (!self.goalentity)
-               objerror("can not find target\n");
-       if (!self.enemy)
-               objerror("can not find target2\n");
-       dprint(etos(self.goalentity), " linked with ", etos(self.enemy), "\n");
-       self.SendFlags |= 3;
-       self.think = onslaught_link_checkupdate;
-       self.nextthink = time;
-}
-
-/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
-  Link between control points.
-
-  This entity targets two different spawnfunc_onslaught_controlpoint or spawnfunc_onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
-
-keys:
-"target" - first control point.
-"target2" - second control point.
- */
-void spawnfunc_onslaught_link()
-{
-       if (!g_onslaught)
-       {
-               remove(self);
-               return;
-       }
-       if (self.target == "" || self.target2 == "")
-               objerror("target and target2 must be set\n");
-       InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET);
-       Net_LinkEntity(self, FALSE, 0, onslaught_link_send);
-}
index 8a6235127cbcd5d721a9020d3609219b62979974..9b9f7fde01abe5dc22dcd51310665c265aa15e6d 100644 (file)
@@ -190,7 +190,7 @@ Yed need to set v_up and v_forward (generally by calling makevectors) before cal
 **/
 #endif
 
-void movelib_groundalign4point(float spring_length, float spring_up, float blendrate)
+void movelib_groundalign4point(float spring_length, float spring_up, float blendrate, float _max)
 {
     vector a, b, c, d, e, r, push_angle, ahead, side;
 
@@ -227,11 +227,11 @@ void movelib_groundalign4point(float spring_length, float spring_up, float blend
     r = self.origin;
     r_z = r_z;
 
-    push_angle_x = (a_z - c_z) * 45;
-    push_angle_x += (b_z - d_z) * 45;
+    push_angle_x = (a_z - c_z) * _max;
+    push_angle_x += (b_z - d_z) * _max;
 
-    push_angle_z = (b_z - a_z) * 45;
-    push_angle_z += (d_z - c_z) * 45;
+    push_angle_z = (b_z - a_z) * _max;
+    push_angle_z += (d_z - c_z) * _max;
 
     //self.angles_x += push_angle_x * 0.95;
     //self.angles_z += push_angle_z * 0.95;
index fdf24edb75a399a526e085a7f28c11b6791c349c..9be5745cb5e4ec24afbde80bee85c4e58bf94097 100644 (file)
@@ -59,6 +59,7 @@ float CallbackChain_Remove(entity cb, float() func)
        entity e;
        float n;
        n = 0;
+       order = 0;
        for(e = cb; e.cbc_next; e = e.cbc_next)
        {
                while(e.cbc_next.cbc_func == func)
index fa5a365ba48316b07c96ed3cdfc6b53619b3a2bb..2a2ae9ee2900fea47c6d90233a5fbae180281d96 100644 (file)
@@ -351,13 +351,11 @@ MUTATOR_DEFINITION(gamemode_freezetag)
        {
                if(time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
-               g_freezetag = 1;
                freezetag_Initialize();
        }
 
        MUTATOR_ONREMOVE
        {
-               g_freezetag = 0;
                error("This is a game type and it cannot be removed at runtime.");
        }
 
index 9134353e015574860dc4478938633ba80e3a56ec..1f6a82b84b7c9475a29f5d1fdfcd21aa5d624720 100644 (file)
@@ -329,13 +329,11 @@ MUTATOR_DEFINITION(gamemode_keepaway)
        {
                if(time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
-               g_keepaway = 1;
                ka_Initialize();
        }
 
        MUTATOR_ONREMOVE
        {
-               g_keepaway = 0;
                error("This is a game type and it cannot be removed at runtime.");
        }
 
index bc8e85f35da34fcec837b503c38df659ac5eacea..58d732d7f70b926c6cb13c6f93aa0f9a5807f48e 100644 (file)
@@ -32,11 +32,11 @@ float kh_no_radar_circles;
 .float siren_time;  //  time delay the siren
 //.float stuff_time;  //  time delay to stuffcmd a cvar
 
-float test[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-//test[0] = status of dropped keys, test[1 - 16] = player #
+float kh_keystatus[17];
+//kh_keystatus[0] = status of dropped keys, kh_keystatus[1 - 16] = player #
 //replace 17 with cvar("maxplayers") or similar !!!!!!!!!
 //for(i = 0; i < maxplayers; ++i)
-//     test[i] = "0";
+//     kh_keystatus[i] = "0";
 
 float kh_Team_ByID(float t)
 {
@@ -342,7 +342,7 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        key.kh_next.kh_prev = key;
 
                float i;
-               i = test[key.owner.playerid];
+               i = kh_keystatus[key.owner.playerid];
                        if(key.netname == "^1red key")
                                i += 1;
                        if(key.netname == "^4blue key")
@@ -351,7 +351,7 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                                i += 4;
                        if(key.netname == "^6pink key")
                                i += 8;
-               test[key.owner.playerid] = i;
+               kh_keystatus[key.owner.playerid] = i;
 
                kh_Key_Attach(key);
 
@@ -545,6 +545,8 @@ void kh_WinnerTeam(float teem)  // runs when a team wins
 
        first = TRUE;
        midpoint = '0 0 0';
+       firstorigin = '0 0 0';
+       lastorigin = '0 0 0';
        FOR_EACH_KH_KEY(key)
        {
                vector thisorigin;
@@ -935,7 +937,7 @@ void kh_StartRound()  // runs at the start of each round
        {
                teem = kh_Team_ByID(i);
                players = 0;
-               entity my_player;
+               entity my_player = world;
                FOR_EACH_PLAYER(player)
                        if(player.deadflag == DEAD_NO)
                                if(!player.BUTTON_CHAT)
@@ -1106,13 +1108,11 @@ MUTATOR_DEFINITION(gamemode_keyhunt)
        {
                if(time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
-               g_keyhunt = 1;
                kh_Initialize();
        }
 
        MUTATOR_ONREMOVE
        {
-               g_keyhunt = 0;
                error("This is a game type and it cannot be removed at runtime.");
        }
 
index 85d0efefbc400ddfefdc580e1304332af5a52c96..ec8de781e257fa754167f2c028c3e6c5dc5ea3cc 100644 (file)
@@ -323,6 +323,8 @@ void GoalTouch(void)
 
        if(nb_teams == 2)
                otherteam = OtherTeam(ball.team);
+       else
+               otherteam = 0;
 
        if((isclient = ball.pusher.flags & FL_CLIENT))
                pname = ball.pusher.netname;
@@ -416,7 +418,7 @@ void nb_spawnteam(string teamname, float teamcolor)
 
 void nb_spawnteams(void)
 {
-       float t_r, t_b, t_y, t_p;
+       float t_r = 0, t_b = 0, t_y = 0, t_p = 0;
        entity e;
        for(e = world; (e = find(e, classname, "nexball_goal"));)
        {
@@ -960,7 +962,6 @@ MUTATOR_DEFINITION(gamemode_nexball)
 
        MUTATOR_ONADD
        {
-           g_nexball = 1;
                g_nexball_meter_period = autocvar_g_nexball_meter_period;
                if(g_nexball_meter_period <= 0)
                        g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
diff --git a/qcsrc/server/mutators/gamemode_onslaught.qc b/qcsrc/server/mutators/gamemode_onslaught.qc
new file mode 100644 (file)
index 0000000..060447c
--- /dev/null
@@ -0,0 +1,1703 @@
+float autocvar_g_onslaught_spawn_at_controlpoints;
+float autocvar_g_onslaught_spawn_at_generator;
+float autocvar_g_onslaught_controlpoints_proxycap;
+float autocvar_g_onslaught_controlpoints_proxycap_distance = 512;
+float autocvar_g_onslaught_controlpoints_proxycap_dps = 100;
+
+void onslaught_generator_updatesprite(entity e);
+void onslaught_controlpoint_updatesprite(entity e);
+void onslaught_link_checkupdate();
+
+.entity sprite;
+.string target2;
+.float iscaptured;
+.float islinked;
+.float isgenneighbor_red;
+.float isgenneighbor_blue;
+.float iscpneighbor_red;
+.float iscpneighbor_blue;
+.float isshielded;
+.float lasthealth;
+.float lastteam;
+.float lastshielded;
+.float lastcaptured;
+
+.string model1, model2, model3;
+
+entity ons_red_generator;
+entity ons_blue_generator;
+
+void ons_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{
+       self.velocity = self.velocity + vforce;
+}
+
+.float giblifetime;
+void ons_throwgib_think()
+{
+       float d;
+
+       self.nextthink = time + 0.05;
+
+       d = self.giblifetime - time;
+
+       if(d<0)
+       {
+               self.think = SUB_Remove;
+               return;
+       }
+       if(d<1)
+               self.alpha = d;
+
+       if(d>2)
+       if(random()<0.6)
+               pointparticles(particleeffectnum("onslaught_generator_gib_flame"), self.origin, '0 0 0', 1);
+}
+
+void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn)
+{
+       entity gib;
+
+       gib = spawn();
+
+       setmodel(gib, smodel);
+       setorigin(gib, v_from);
+       gib.solid = SOLID_BBOX;
+       gib.movetype = MOVETYPE_BOUNCE;
+       gib.takedamage = DAMAGE_YES;
+       gib.event_damage = ons_gib_damage;
+       gib.health = -1;
+       gib.effects = EF_LOWPRECISION;
+       gib.flags = FL_NOTARGET;
+       gib.velocity = v_to;
+       gib.giblifetime = time + f_lifetime;
+
+       if (b_burn)
+       {
+               gib.think = ons_throwgib_think;
+               gib.nextthink = time + 0.05;
+       }
+       else
+               SUB_SetFade(gib, gib.giblifetime, 2);
+}
+
+void onslaught_updatelinks()
+{
+       entity l, links;
+       float stop, t1, t2, t3, t4;
+       // first check if the game has ended
+       dprint("--- updatelinks ---\n");
+       links = findchain(classname, "onslaught_link");
+       // mark generators as being shielded and networked
+       l = findchain(classname, "onslaught_generator");
+       while (l)
+       {
+               if (l.iscaptured)
+                       dprint(etos(l), " (generator) belongs to team ", ftos(l.team), "\n");
+               else
+                       dprint(etos(l), " (generator) is destroyed\n");
+               l.islinked = l.iscaptured;
+               l.isshielded = l.iscaptured;
+               l = l.chain;
+       }
+       // mark points as shielded and not networked
+       l = findchain(classname, "onslaught_controlpoint");
+       while (l)
+       {
+               l.islinked = FALSE;
+               l.isshielded = TRUE;
+               l.isgenneighbor_red = FALSE;
+               l.isgenneighbor_blue = FALSE;
+               l.iscpneighbor_red = FALSE;
+               l.iscpneighbor_blue = FALSE;
+               dprint(etos(l), " (point) belongs to team ", ftos(l.team), "\n");
+               l = l.chain;
+       }
+       // flow power outward from the generators through the network
+       l = links;
+       while (l)
+       {
+               dprint(etos(l), " (link) connects ", etos(l.goalentity), " with ", etos(l.enemy), "\n");
+               l = l.chain;
+       }
+       stop = FALSE;
+       while (!stop)
+       {
+               stop = TRUE;
+               l = links;
+               while (l)
+               {
+                       // if both points are captured by the same team, and only one of
+                       // them is powered, mark the other one as powered as well
+                       if (l.enemy.iscaptured && l.goalentity.iscaptured)
+                               if (l.enemy.islinked != l.goalentity.islinked)
+                                       if (l.enemy.team == l.goalentity.team)
+                                       {
+                                               if (!l.goalentity.islinked)
+                                               {
+                                                       stop = FALSE;
+                                                       l.goalentity.islinked = TRUE;
+                                                       dprint(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n");
+                                               }
+                                               else if (!l.enemy.islinked)
+                                               {
+                                                       stop = FALSE;
+                                                       l.enemy.islinked = TRUE;
+                                                       dprint(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n");
+                                               }
+                                       }
+                       l = l.chain;
+               }
+       }
+       // now that we know which points are powered we can mark their neighbors
+       // as unshielded if team differs
+       l = links;
+       while (l)
+       {
+               if (l.goalentity.islinked)
+               {
+                       if (l.goalentity.team != l.enemy.team)
+                       {
+                               dprint(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n");
+                               l.enemy.isshielded = FALSE;
+                       }
+                       if(l.goalentity.classname == "onslaught_generator")
+                       {
+                               if(l.goalentity.team == COLOR_TEAM1)
+                                       l.enemy.isgenneighbor_red = TRUE;
+                               else if(l.goalentity.team == COLOR_TEAM2)
+                                       l.enemy.isgenneighbor_blue = TRUE;
+                       }
+                       else
+                       {
+                               if(l.goalentity.team == COLOR_TEAM1)
+                                       l.enemy.iscpneighbor_red = TRUE;
+                               else if(l.goalentity.team == COLOR_TEAM2)
+                                       l.enemy.iscpneighbor_blue = TRUE;
+                       }
+               }
+               if (l.enemy.islinked)
+               {
+                       if (l.goalentity.team != l.enemy.team)
+                       {
+                               dprint(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n");
+                               l.goalentity.isshielded = FALSE;
+                       }
+                       if(l.enemy.classname == "onslaught_generator")
+                       {
+                               if(l.enemy.team == COLOR_TEAM1)
+                                       l.goalentity.isgenneighbor_red = TRUE;
+                               else if(l.enemy.team == COLOR_TEAM2)
+                                       l.goalentity.isgenneighbor_blue = TRUE;
+                       }
+                       else
+                       {
+                               if(l.enemy.team == COLOR_TEAM1)
+                                       l.goalentity.iscpneighbor_red = TRUE;
+                               else if(l.enemy.team == COLOR_TEAM2)
+                                       l.goalentity.iscpneighbor_blue = TRUE;
+                       }
+               }
+               l = l.chain;
+       }
+       // now update the takedamage and alpha variables on generator shields
+       l = findchain(classname, "onslaught_generator");
+       while (l)
+       {
+               if (l.isshielded)
+               {
+                       dprint(etos(l), " (generator) is shielded\n");
+                       l.enemy.alpha = 1;
+                       l.takedamage = DAMAGE_NO;
+                       l.bot_attack = FALSE;
+               }
+               else
+               {
+                       dprint(etos(l), " (generator) is not shielded\n");
+                       l.enemy.alpha = -1;
+                       l.takedamage = DAMAGE_AIM;
+                       l.bot_attack = TRUE;
+               }
+               l = l.chain;
+       }
+       // now update the takedamage and alpha variables on control point icons
+       l = findchain(classname, "onslaught_controlpoint");
+       while (l)
+       {
+               if (l.isshielded)
+               {
+                       dprint(etos(l), " (point) is shielded\n");
+                       l.enemy.alpha = 1;
+                       if (l.goalentity)
+                       {
+                               l.goalentity.takedamage = DAMAGE_NO;
+                               l.goalentity.bot_attack = FALSE;
+                       }
+               }
+               else
+               {
+                       dprint(etos(l), " (point) is not shielded\n");
+                       l.enemy.alpha = -1;
+                       if (l.goalentity)
+                       {
+                               l.goalentity.takedamage = DAMAGE_AIM;
+                               l.goalentity.bot_attack = TRUE;
+                       }
+               }
+               onslaught_controlpoint_updatesprite(l);
+               l = l.chain;
+       }
+       // count generators owned by each team
+       t1 = t2 = t3 = t4 = 0;
+       l = findchain(classname, "onslaught_generator");
+       while (l)
+       {
+               if (l.iscaptured)
+               {
+                       if (l.team == COLOR_TEAM1) t1 = 1;
+                       if (l.team == COLOR_TEAM2) t2 = 1;
+                       if (l.team == COLOR_TEAM3) t3 = 1;
+                       if (l.team == COLOR_TEAM4) t4 = 1;
+               }
+               onslaught_generator_updatesprite(l);
+               l = l.chain;
+       }
+       // see if multiple teams remain (if not, it's game over)
+       if (t1 + t2 + t3 + t4 < 2)
+               dprint("--- game over ---\n");
+       else
+               dprint("--- done updating links ---\n");
+}
+
+float onslaught_controlpoint_can_be_linked(entity cp, float t)
+{
+       if(t == COLOR_TEAM1)
+       {
+               if(cp.isgenneighbor_red)
+                       return 2;
+               if(cp.iscpneighbor_red)
+                       return 1;
+       }
+       else if(t == COLOR_TEAM2)
+       {
+               if(cp.isgenneighbor_blue)
+                       return 2;
+               if(cp.iscpneighbor_blue)
+                       return 1;
+       }
+       return 0;
+       /*
+          entity e;
+       // check to see if this player has a legitimate claim to capture this
+       // control point - more specifically that there is a captured path of
+       // points leading back to the team generator
+       e = findchain(classname, "onslaught_link");
+       while (e)
+       {
+       if (e.goalentity == cp)
+       {
+       dprint(etos(e), " (link) connects to ", etos(e.enemy), " (point)");
+       if (e.enemy.islinked)
+       {
+       dprint(" which is linked");
+       if (e.enemy.team == t)
+       {
+       dprint(" and has the correct team!\n");
+       return 1;
+       }
+       else
+       dprint(" but has the wrong team\n");
+       }
+       else
+       dprint("\n");
+       }
+       else if (e.enemy == cp)
+       {
+       dprint(etos(e), " (link) connects to ", etos(e.goalentity), " (point)");
+       if (e.goalentity.islinked)
+       {
+       dprint(" which is linked");
+       if (e.goalentity.team == t)
+       {
+       dprint(" and has a team!\n");
+       return 1;
+       }
+       else
+       dprint(" but has the wrong team\n");
+       }
+       else
+       dprint("\n");
+       }
+       e = e.chain;
+       }
+       return 0;
+        */
+}
+
+float onslaught_controlpoint_attackable(entity cp, float t)
+       // -2: SAME TEAM, attackable by enemy!
+       // -1: SAME TEAM!
+       // 0: off limits
+       // 1: attack it
+       // 2: touch it
+       // 3: attack it (HIGH PRIO)
+       // 4: touch it (HIGH PRIO)
+{
+       float a;
+
+       if(cp.isshielded)
+       {
+               return 0;
+       }
+       else if(cp.goalentity)
+       {
+               // if there's already an icon built, nothing happens
+               if(cp.team == t)
+               {
+                       a = onslaught_controlpoint_can_be_linked(cp, COLOR_TEAM1 + COLOR_TEAM2 - t);
+                       if(a) // attackable by enemy?
+                               return -2; // EMERGENCY!
+                       return -1;
+               }
+               // we know it can be linked, so no need to check
+               // but...
+               a = onslaught_controlpoint_can_be_linked(cp, t);
+               if(a == 2) // near our generator?
+                       return 3; // EMERGENCY!
+               return 1;
+       }
+       else
+       {
+               // free point
+               if(onslaught_controlpoint_can_be_linked(cp, t))
+               {
+                       a = onslaught_controlpoint_can_be_linked(cp, COLOR_TEAM1 + COLOR_TEAM2 - t);
+                       if(a == 2)
+                               return 4; // GET THIS ONE NOW!
+                       else
+                               return 2; // TOUCH ME
+               }
+       }
+       return 0;
+}
+
+float overtime_msg_time;
+void onslaught_generator_think()
+{
+       float d;
+       entity e;
+       self.nextthink = ceil(time + 1);
+       if (!gameover)
+       {
+               if (autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60)
+               {
+                       if (!overtime_msg_time)
+                       {
+                               FOR_EACH_PLAYER(e)
+                                       centerprint(e, "^3Now playing ^1OVERTIME^3!\n^3Generators start now to decay.\n^3The more control points your team holds,\n^3the faster the enemy generator decays.");
+                               overtime_msg_time = time;
+                       }
+                       // self.max_health / 300 gives 5 minutes of overtime.
+                       // control points reduce the overtime duration.
+                       sound(self, CH_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTN_NORM);
+                       d = 1;
+                       e = findchain(classname, "onslaught_controlpoint");
+                       while (e)
+                       {
+                               if (e.team != self.team)
+                                       if (e.islinked)
+                                               d = d + 1;
+                               e = e.chain;
+                       }
+                       
+                       if(autocvar_g_campaign && autocvar__campaign_testrun)
+                               d = d * self.max_health;
+                       else
+                               d = d * self.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
+                       
+                       Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0');
+               }
+               else if (overtime_msg_time)
+                       overtime_msg_time = 0;
+        
+        if(!self.isshielded && self.wait < time)
+        {
+            self.wait = time + 5;
+            FOR_EACH_PLAYER(e)
+            {
+                if(e.team == self.team)
+                {
+                    centerprint(e, "^1Your generator is NOT shielded!\n^7Re-capture controlpoints to shield it!");
+                    soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTN_NONE);    // FIXME: Uniqe sound?
+                }                                  
+            }                                              
+        }    
+       }
+}
+
+void onslaught_generator_ring_spawn(vector org)
+{
+       modeleffect_spawn("models/onslaught/shockwavetransring.md3", 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, -16, 0.1, 1.25, 0.25);
+}
+
+void onslaught_generator_ray_think()
+{
+       self.nextthink = time + 0.05;
+       if(self.count > 10)
+       {
+               self.think = SUB_Remove;
+               return;
+       }
+
+       if(self.count > 5)
+               self.alpha -= 0.1;
+       else
+               self.alpha += 0.1;
+
+       self.scale += 0.2;
+       self.count +=1;
+}
+
+void onslaught_generator_ray_spawn(vector org)
+{
+       entity e;
+       e = spawn();
+       setmodel(e, "models/onslaught/ons_ray.md3");
+       setorigin(e, org);
+       e.angles = randomvec() * 360;
+       e.alpha = 0;
+       e.scale = random() * 5 + 8;
+       e.think = onslaught_generator_ray_think;
+       e.nextthink = time + 0.05;
+}
+
+void onslaught_generator_shockwave_spawn(vector org)
+{
+       shockwave_spawn("models/onslaught/shockwave.md3", org, -64, 0.75, 0.5);
+}
+
+void onslaught_generator_damage_think()
+{
+       if(self.owner.health < 0)
+       {
+               self.think = SUB_Remove;
+               return;
+       }
+       self.nextthink = time+0.1;
+
+       // damaged fx (less probable the more damaged is the generator)
+       if(random() < 0.9 - self.owner.health / self.owner.max_health)
+               if(random() < 0.01)
+               {
+                       pointparticles(particleeffectnum("electro_ballexplode"), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
+                       sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTN_NORM);
+               }
+               else
+                       pointparticles(particleeffectnum("torch_small"), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
+}
+
+void onslaught_generator_damage_spawn(entity gd_owner)
+{
+       entity e;
+       e = spawn();
+       e.owner = gd_owner;
+       e.health = self.owner.health;
+       setorigin(e, gd_owner.origin);
+       e.think = onslaught_generator_damage_think;
+       e.nextthink = time+1;
+}
+
+void onslaught_generator_deaththink()
+{
+       vector org;
+       float i;
+
+       if not (self.count)
+               self.count = 40;
+
+       // White shockwave
+       if(self.count==40||self.count==20)
+       {
+               onslaught_generator_ring_spawn(self.origin);
+               sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTN_NORM);
+       }
+
+       // Throw some gibs
+       if(random() < 0.3)
+       {
+               i = random();
+               if(i < 0.3)
+                       ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 11 + '0 0 20', "models/onslaught/gen_gib1.md3", 6, TRUE);
+               else if(i > 0.7)
+                       ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 12 + '0 0 20', "models/onslaught/gen_gib2.md3", 6, TRUE);
+               else
+                       ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 13 + '0 0 20', "models/onslaught/gen_gib3.md3", 6, TRUE);
+       }
+
+       // Spawn fire balls
+       for(i=0;i < 10;++i)
+       {
+               org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
+               pointparticles(particleeffectnum("onslaught_generator_gib_explode"), org, '0 0 0', 1);
+       }
+
+       // Short explosion sound + small explosion
+       if(random() < 0.25)
+       {
+               te_explosion(self.origin);
+               sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
+       }
+
+       // Particles
+       org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
+       pointparticles(particleeffectnum("onslaught_generator_smallexplosion"), org, '0 0 0', 1);
+
+       // rays
+       if(random() > 0.25 )
+       {
+               onslaught_generator_ray_spawn(self.origin);
+       }
+
+       // Final explosion
+       if(self.count==1)
+       {
+               org = self.origin;
+               te_explosion(org);
+               onslaught_generator_shockwave_spawn(org);
+               pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1);
+               sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+       }
+       else
+               self.nextthink = time + 0.05;
+
+       self.count = self.count - 1;
+}
+
+void onslaught_generator_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+       float i;
+       if (damage <= 0)
+               return;
+       if(inWarmupStage)
+               return;
+       if (attacker != self)
+       {
+               if (self.isshielded)
+               {
+                       // this is protected by a shield, so ignore the damage
+                       if (time > self.pain_finished)
+                               if (attacker.classname == "player")
+                               {
+                                       play2(attacker, "onslaught/damageblockedbyshield.wav");
+                                       self.pain_finished = time + 1;
+                               }
+                       return;
+               }
+               if (time > self.pain_finished)
+               {
+                       self.pain_finished = time + 10;
+                       bprint(ColoredTeamName(self.team), " generator under attack!\n");
+                       play2team(self.team, "onslaught/generator_underattack.wav");
+               }
+       }
+       self.health = self.health - damage;
+       WaypointSprite_UpdateHealth(self.sprite, self.health);
+       // choose an animation frame based on health
+       self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
+       // see if the generator is still functional, or dying
+       if (self.health > 0)
+       {
+#ifdef ONSLAUGHT_SPAM
+               float h, lh;
+               lh = ceil(self.lasthealth / 100) * 100;
+               h = ceil(self.health / 100) * 100;
+               if(lh != h)
+                       bprint(ColoredTeamName(self.team), " generator has less than ", ftos(h), " health remaining\n");
+#endif
+               self.lasthealth = self.health;
+       }
+       else if not(inWarmupStage)
+       {
+               if (attacker == self)
+                       bprint(ColoredTeamName(self.team), " generator spontaneously exploded due to overtime!\n");
+               else
+               {
+                       string t;
+                       t = ColoredTeamName(attacker.team);
+                       bprint(ColoredTeamName(self.team), " generator destroyed by ", t, "!\n");
+               }
+               self.iscaptured = FALSE;
+               self.islinked = FALSE;
+               self.isshielded = FALSE;
+               self.takedamage = DAMAGE_NO; // can't be hurt anymore
+               self.event_damage = SUB_Null; // won't do anything if hurt
+               self.count = 0; // reset counter
+               self.think = onslaught_generator_deaththink; // explosion sequence
+               self.nextthink = time; // start exploding immediately
+               self.think(); // do the first explosion now
+
+               WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+
+               onslaught_updatelinks();
+       }
+
+       if(self.health <= 0)
+               setmodel(self, "models/onslaught/generator_dead.md3");
+       else if(self.health < self.max_health * 0.10)
+               setmodel(self, "models/onslaught/generator_dmg9.md3");
+       else if(self.health < self.max_health * 0.20)
+               setmodel(self, "models/onslaught/generator_dmg8.md3");
+       else if(self.health < self.max_health * 0.30)
+               setmodel(self, "models/onslaught/generator_dmg7.md3");
+       else if(self.health < self.max_health * 0.40)
+               setmodel(self, "models/onslaught/generator_dmg6.md3");
+       else if(self.health < self.max_health * 0.50)
+               setmodel(self, "models/onslaught/generator_dmg5.md3");
+       else if(self.health < self.max_health * 0.60)
+               setmodel(self, "models/onslaught/generator_dmg4.md3");
+       else if(self.health < self.max_health * 0.70)
+               setmodel(self, "models/onslaught/generator_dmg3.md3");
+       else if(self.health < self.max_health * 0.80)
+               setmodel(self, "models/onslaught/generator_dmg2.md3");
+       else if(self.health < self.max_health * 0.90)
+               setmodel(self, "models/onslaught/generator_dmg1.md3");
+       setsize(self, '-52 -52 -14', '52 52 75');
+
+       // Throw some flaming gibs on damage, more damage = more chance for gib
+       if(random() < damage/220)
+       {
+               sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+               i = random();
+               if(i < 0.3)
+                       ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib1.md3", 5, TRUE);
+               else if(i > 0.7)
+                       ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib2.md3", 5, TRUE);
+               else
+                       ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib3.md3", 5, TRUE);
+       }
+       else
+       {
+               // particles on every hit
+               pointparticles(particleeffectnum("sparks"), hitloc, force * -1, 1);
+
+               //sound on every hit
+               if (random() < 0.5)
+                       sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTN_NORM);
+               else
+                       sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM);
+       }
+
+       //throw some gibs on damage
+       if(random() < damage/200+0.2)
+               if(random() < 0.5)
+                       ons_throwgib(hitloc + '0 0 20', randomvec()*360, "models/onslaught/gen_gib1.md3", 5, FALSE);
+}
+
+// update links after a delay
+void onslaught_generator_delayed()
+{
+       onslaught_updatelinks();
+       // now begin normal thinking
+       self.think = onslaught_generator_think;
+       self.nextthink = time;
+}
+
+string onslaught_generator_waypointsprite_for_team(entity e, float t)
+{
+       if(t == e.team)
+       {
+               if(e.team == COLOR_TEAM1)
+                       return "ons-gen-red";
+               else if(e.team == COLOR_TEAM2)
+                       return "ons-gen-blue";
+       }
+       if(e.isshielded)
+               return "ons-gen-shielded";
+       if(e.team == COLOR_TEAM1)
+               return "ons-gen-red";
+       else if(e.team == COLOR_TEAM2)
+               return "ons-gen-blue";
+       return "";
+}
+
+void onslaught_generator_updatesprite(entity e)
+{
+       string s1, s2, s3;
+       s1 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM1);
+       s2 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM2);
+       s3 = onslaught_generator_waypointsprite_for_team(e, -1);
+       WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+
+       if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
+       {
+               e.lastteam = e.team + 2;
+               e.lastshielded = e.isshielded;
+               if(e.lastshielded)
+               {
+                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
+                       else
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
+               }
+               else
+               {
+                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, FALSE));
+                       else
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
+               }
+               WaypointSprite_Ping(e.sprite);
+       }
+}
+
+string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
+{
+       float a;
+       if(t != -1)
+       {
+               a = onslaught_controlpoint_attackable(e, t);
+               if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
+               {
+                       if(e.team == COLOR_TEAM1)
+                               return "ons-cp-atck-red";
+                       else if(e.team == COLOR_TEAM2)
+                               return "ons-cp-atck-blue";
+                       else
+                               return "ons-cp-atck-neut";
+               }
+               else if(a == -2) // DEFEND THIS ONE NOW
+               {
+                       if(e.team == COLOR_TEAM1)
+                               return "ons-cp-dfnd-red";
+                       else if(e.team == COLOR_TEAM2)
+                               return "ons-cp-dfnd-blue";
+               }
+               else if(e.team == t || a == -1 || a == 1) // own point, or fire at it
+               {
+                       if(e.team == COLOR_TEAM1)
+                               return "ons-cp-red";
+                       else if(e.team == COLOR_TEAM2)
+                               return "ons-cp-blue";
+               }
+               else if(a == 2) // touch it
+                       return "ons-cp-neut";
+       }
+       else
+       {
+               if(e.team == COLOR_TEAM1)
+                       return "ons-cp-red";
+               else if(e.team == COLOR_TEAM2)
+                       return "ons-cp-blue";
+               else
+                       return "ons-cp-neut";
+       }
+       return "";
+}
+
+void onslaught_controlpoint_updatesprite(entity e)
+{
+       string s1, s2, s3;
+       s1 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM1);
+       s2 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM2);
+       s3 = onslaught_controlpoint_waypointsprite_for_team(e, -1);
+       WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+
+       float sh;
+       sh = !(onslaught_controlpoint_can_be_linked(e, COLOR_TEAM1) || onslaught_controlpoint_can_be_linked(e, COLOR_TEAM2));
+
+       if(e.lastteam != e.team + 2 || e.lastshielded != sh || e.iscaptured != e.lastcaptured)
+       {
+               if(e.iscaptured) // don't mess up build bars!
+               {
+                       if(sh)
+                       {
+                               WaypointSprite_UpdateMaxHealth(e.sprite, 0);
+                       }
+                       else
+                       {
+                               WaypointSprite_UpdateMaxHealth(e.sprite, e.goalentity.max_health);
+                               WaypointSprite_UpdateHealth(e.sprite, e.goalentity.health);
+                       }
+               }
+               if(e.lastshielded)
+               {
+                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
+                       else
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0.5 0.5');
+               }
+               else
+               {
+                       if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, colormapPaletteColor(e.team - 1, FALSE));
+                       else
+                               WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
+               }
+               WaypointSprite_Ping(e.sprite);
+
+               e.lastteam = e.team + 2;
+               e.lastshielded = sh;
+               e.lastcaptured = e.iscaptured;
+       }
+}
+
+void onslaught_generator_reset()
+{
+       self.team = self.team_saved;
+       self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
+       self.takedamage = DAMAGE_AIM;
+       self.bot_attack = TRUE;
+       self.iscaptured = TRUE;
+       self.islinked = TRUE;
+       self.isshielded = TRUE;
+       self.enemy.solid = SOLID_NOT;
+       self.think = onslaught_generator_delayed;
+       self.nextthink = time + 0.2;
+       setmodel(self, "models/onslaught/generator.md3");
+       setsize(self, '-52 -52 -14', '52 52 75');
+
+       if (!self.noalign)
+        droptofloor();
+
+       WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+       WaypointSprite_UpdateHealth(self.sprite, self.health);
+}
+
+/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
+  Base generator.
+
+  spawnfunc_onslaught_link entities can target this.
+
+keys:
+"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
+"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
+ */
+void spawnfunc_onslaught_generator()
+{
+       if (!g_onslaught)
+       {
+               remove(self);
+               return;
+       }
+
+       //entity e;
+       precache_model("models/onslaught/generator.md3");
+       precache_model("models/onslaught/generator_shield.md3");
+       precache_model("models/onslaught/generator_dmg1.md3");
+       precache_model("models/onslaught/generator_dmg2.md3");
+       precache_model("models/onslaught/generator_dmg3.md3");
+       precache_model("models/onslaught/generator_dmg4.md3");
+       precache_model("models/onslaught/generator_dmg5.md3");
+       precache_model("models/onslaught/generator_dmg6.md3");
+       precache_model("models/onslaught/generator_dmg7.md3");
+       precache_model("models/onslaught/generator_dmg8.md3");
+       precache_model("models/onslaught/generator_dmg9.md3");
+       precache_model("models/onslaught/generator_dead.md3");
+       precache_model("models/onslaught/shockwave.md3");
+       precache_model("models/onslaught/shockwavetransring.md3");
+       precache_model("models/onslaught/gen_gib1.md3");
+       precache_model("models/onslaught/gen_gib2.md3");
+       precache_model("models/onslaught/gen_gib3.md3");
+       precache_model("models/onslaught/ons_ray.md3");
+       precache_sound("onslaught/generator_decay.wav");
+       precache_sound("weapons/grenade_impact.wav");
+       precache_sound("weapons/rocket_impact.wav");
+       precache_sound("onslaught/generator_underattack.wav");
+       precache_sound("onslaught/shockwave.wav");
+       precache_sound("onslaught/ons_hit1.wav");
+       precache_sound("onslaught/ons_hit2.wav");
+       precache_sound("onslaught/electricity_explode.wav");
+       if (!self.team)
+               objerror("team must be set");
+       
+       if(self.team == COLOR_TEAM1)
+        ons_red_generator = self;
+
+       if(self.team == COLOR_TEAM2)
+        ons_blue_generator = self;
+        
+       self.team_saved = self.team;
+       self.colormap = 1024 + (self.team - 1) * 17;
+       self.solid = SOLID_BBOX;
+       self.movetype = MOVETYPE_NONE;
+       self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
+       setmodel(self, "models/onslaught/generator.md3");
+       setsize(self, '-52 -52 -14', '52 52 75');
+       setorigin(self, self.origin);
+       self.takedamage = DAMAGE_AIM;
+       self.bot_attack = TRUE;
+       self.event_damage = onslaught_generator_damage;
+       self.iscaptured = TRUE;
+       self.islinked = TRUE;
+       self.isshielded = TRUE;
+       // helper entity that create fx when generator is damaged
+       onslaught_generator_damage_spawn(self);
+       // spawn shield model which indicates whether this can be damaged
+       self.enemy = spawn();
+       setattachment(self.enemy , self, "");
+       self.enemy.classname = "onslaught_generator_shield";
+       self.enemy.solid = SOLID_NOT;
+       self.enemy.movetype = MOVETYPE_NONE;
+       self.enemy.effects = EF_ADDITIVE;
+       setmodel(self.enemy, "models/onslaught/generator_shield.md3");
+       //setorigin(e, self.origin);
+       self.enemy.colormap = self.colormap;
+       self.enemy.team = self.team;
+       //self.think = onslaught_generator_delayed;
+       //self.nextthink = time + 0.2;
+       InitializeEntity(self, onslaught_generator_delayed, INITPRIO_LAST);
+
+       WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
+       WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
+       WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+       WaypointSprite_UpdateHealth(self.sprite, self.health);
+
+       waypoint_spawnforitem(self);
+
+       onslaught_updatelinks();
+       
+       self.reset = onslaught_generator_reset;
+}
+
+.float waslinked;
+.float cp_bob_spd;
+.vector cp_origin, cp_bob_origin, cp_bob_dmg;
+
+float ons_notification_time_team1;
+float ons_notification_time_team2;
+
+void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+       entity oself;
+       float nag;
+
+       if (damage <= 0)
+               return;
+       if (self.owner.isshielded)
+       {
+               // this is protected by a shield, so ignore the damage
+               if (time > self.pain_finished)
+                       if (attacker.classname == "player")
+                       {
+                               play2(attacker, "onslaught/damageblockedbyshield.wav");
+                               self.pain_finished = time + 1;
+                       }
+               return;
+       }
+
+       if (attacker.classname == "player")
+       {
+               nag = FALSE;
+               if(self.team == COLOR_TEAM1)
+               {
+                       if(time - ons_notification_time_team1 > 10)
+                       {
+                               nag = TRUE;
+                               ons_notification_time_team1 = time;
+                       }
+               }
+               else if(self.team == COLOR_TEAM2)
+               {
+                       if(time - ons_notification_time_team2 > 10)
+                       {
+                               nag = TRUE;
+                               ons_notification_time_team2 = time;
+                       }
+               }
+               else
+                       nag = TRUE;
+
+               if(nag)
+                       play2team(self.team, "onslaught/controlpoint_underattack.wav");
+       }
+
+       self.health = self.health - damage;
+       if(self.owner.iscaptured)
+               WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+       else
+               WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / sys_frametime));
+       self.pain_finished = time + 1;
+       self.punchangle = (2 * randomvec() - '1 1 1') * 45;
+       self.cp_bob_dmg_z = (2 * random() - 1) * 15;
+       // colormod flash when shot
+       self.colormod = '2 2 2';
+       // particles on every hit
+       pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
+       //sound on every hit
+       if (random() < 0.5)
+               sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTN_NORM);
+       else
+               sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTN_NORM);
+
+       if (self.health < 0)
+       {
+               sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
+               pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+               {
+                       string t;
+                       t = ColoredTeamName(attacker.team);
+                       bprint(ColoredTeamName(self.team), " ", self.message, " control point destroyed by ", t, "\n");
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 25, "models/onslaught/controlpoint_icon_gib1.md3", 3, FALSE);
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, FALSE);
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, FALSE);
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
+                       ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
+               }
+               self.owner.goalentity = world;
+               self.owner.islinked = FALSE;
+               self.owner.iscaptured = FALSE;
+               self.owner.team = 0;
+               self.owner.colormap = 1024;
+
+               WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
+
+               onslaught_updatelinks();
+
+               // Use targets now (somebody make sure this is in the right place..)
+               oself = self;
+               self = self.owner;
+               activator = self;
+               SUB_UseTargets ();
+               self = oself;
+
+
+               self.owner.waslinked = self.owner.islinked;
+               if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
+                       setmodel(self.owner, "models/onslaught/controlpoint_pad.md3");
+               //setsize(self, '-32 -32 0', '32 32 8');
+
+               remove(self);
+       }
+}
+
+void onslaught_controlpoint_icon_think()
+{
+       entity oself;
+       self.nextthink = time + sys_frametime;
+       
+       if(autocvar_g_onslaught_controlpoints_proxycap)
+       {        
+        float _enemy_count;
+        float _friendly_count;
+        float _dist;
+        entity _player;
+        
+        FOR_EACH_PLAYER(_player)
+        {
+            if(!_player.deadflag)
+            {
+                _dist = vlen(_player.origin - self.origin);
+                if(_dist < autocvar_g_onslaught_controlpoints_proxycap_distance)
+                {
+                    if(_player.team == self.team)
+                        ++_friendly_count;
+                    else
+                        ++_enemy_count;
+                }
+            }
+        }
+
+        _friendly_count = _friendly_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
+        _enemy_count = _enemy_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
+        
+        self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
+        if(self.health <= 0)
+        {
+            onslaught_controlpoint_icon_damage(self, self, 1, 0, self.origin, '0 0 0');
+            return;
+        }
+    }
+    
+       if (time > self.pain_finished + 5)
+       {
+               if(self.health < self.max_health)
+               {
+                       self.health = self.health + self.count;
+                       if (self.health >= self.max_health)
+                               self.health = self.max_health;
+                       WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+               }
+       }
+       if (self.health < self.max_health * 0.25)
+               setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
+       else if (self.health < self.max_health * 0.50)
+               setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
+       else if (self.health < self.max_health * 0.75)
+               setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
+       else if (self.health < self.max_health * 0.90)
+               setmodel(self, "models/onslaught/controlpoint_icon.md3");
+       // colormod flash when shot
+       self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+
+       if(self.owner.islinked != self.owner.waslinked)
+       {
+               // unteam the spawnpoint if needed
+               float t;
+               t = self.owner.team;
+               if(!self.owner.islinked)
+                       self.owner.team = 0;
+
+               oself = self;
+               self = self.owner;
+               activator = self;
+               SUB_UseTargets ();
+               self = oself;
+
+               self.owner.team = t;
+
+               self.owner.waslinked = self.owner.islinked;
+       }
+
+       if (self.punchangle_x > 0)
+       {
+               self.punchangle_x = self.punchangle_x - 60 * sys_frametime;
+               if (self.punchangle_x < 0)
+                       self.punchangle_x = 0;
+       }
+       else if (self.punchangle_x < 0)
+       {
+               self.punchangle_x = self.punchangle_x + 60 * sys_frametime;
+               if (self.punchangle_x > 0)
+                       self.punchangle_x = 0;
+       }
+
+       if (self.punchangle_y > 0)
+       {
+               self.punchangle_y = self.punchangle_y - 60 * sys_frametime;
+               if (self.punchangle_y < 0)
+                       self.punchangle_y = 0;
+       }
+       else if (self.punchangle_y < 0)
+       {
+               self.punchangle_y = self.punchangle_y + 60 * sys_frametime;
+               if (self.punchangle_y > 0)
+                       self.punchangle_y = 0;
+       }
+
+       if (self.punchangle_z > 0)
+       {
+               self.punchangle_z = self.punchangle_z - 60 * sys_frametime;
+               if (self.punchangle_z < 0)
+                       self.punchangle_z = 0;
+       }
+       else if (self.punchangle_z < 0)
+       {
+               self.punchangle_z = self.punchangle_z + 60 * sys_frametime;
+               if (self.punchangle_z > 0)
+                       self.punchangle_z = 0;
+       }
+
+       self.angles_x = self.punchangle_x;
+       self.angles_y = self.punchangle_y + self.mangle_y;
+       self.angles_z = self.punchangle_z;
+       self.mangle_y = self.mangle_y + 45 * sys_frametime;
+
+       self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
+       self.cp_bob_spd = self.cp_bob_spd + 1.875 * sys_frametime;
+       if(self.cp_bob_dmg_z > 0)
+               self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * sys_frametime;
+       else
+               self.cp_bob_dmg_z = 0;
+       setorigin(self,self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
+
+       // damaged fx
+       if(random() < 0.6 - self.health / self.max_health)
+       {
+               pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
+
+               if(random() > 0.8)
+                       sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTN_NORM);
+               else if (random() > 0.5)
+                       sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTN_NORM);
+       }
+}
+
+void onslaught_controlpoint_icon_buildthink()
+{
+       entity oself;
+       float a;
+
+       self.nextthink = time + sys_frametime;
+
+       // only do this if there is power
+       a = onslaught_controlpoint_can_be_linked(self.owner, self.owner.team);
+       if(!a)
+               return;
+    
+       self.health = self.health + self.count;
+
+       if (self.health >= self.max_health)
+       {
+               self.health = self.max_health;
+               self.count = autocvar_g_onslaught_cp_regen * sys_frametime; // slow repair rate from now on
+               self.think = onslaught_controlpoint_icon_think;
+               sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTN_NORM);
+               bprint(ColoredTeamName(self.team), " captured ", self.owner.message, " control point\n");
+               self.owner.iscaptured = TRUE;
+
+               WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
+               WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+
+               onslaught_updatelinks();
+
+               // Use targets now (somebody make sure this is in the right place..)
+               oself = self;
+               self = self.owner;
+               activator = self;
+               SUB_UseTargets ();
+               self = oself;
+               self.cp_origin = self.origin;
+               self.cp_bob_origin = '0 0 0.1';
+               self.cp_bob_spd = 0;
+       }
+       self.alpha = self.health / self.max_health;
+       // colormod flash when shot
+       self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+       if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
+               setmodel(self.owner, "models/onslaught/controlpoint_pad2.md3");
+       //setsize(self, '-32 -32 0', '32 32 8');
+
+       if(random() < 0.9 - self.health / self.max_health)
+               pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
+}
+
+
+
+
+void onslaught_controlpoint_touch()
+{
+       entity e;
+       float a;
+       if (other.classname != "player")
+               return;
+       a = onslaught_controlpoint_attackable(self, other.team);
+       if(a != 2 && a != 4)
+               return;
+       // we've verified that this player has a legitimate claim to this point,
+       // so start building the captured point icon (which only captures this
+       // point if it successfully builds without being destroyed first)
+       self.goalentity = e = spawn();
+       e.classname = "onslaught_controlpoint_icon";
+       e.owner = self;
+       e.max_health = autocvar_g_onslaught_cp_health;
+       e.health = autocvar_g_onslaught_cp_buildhealth;
+       e.solid = SOLID_BBOX;
+       e.movetype = MOVETYPE_NONE;
+       setmodel(e, "models/onslaught/controlpoint_icon.md3");
+       setsize(e, '-32 -32 -32', '32 32 32');
+       setorigin(e, self.origin + '0 0 96');
+       e.takedamage = DAMAGE_AIM;
+       e.bot_attack = TRUE;
+       e.event_damage = onslaught_controlpoint_icon_damage;
+       e.team = other.team;
+       e.colormap = 1024 + (e.team - 1) * 17;
+       e.think = onslaught_controlpoint_icon_buildthink;
+       e.nextthink = time + sys_frametime;
+       e.count = (e.max_health - e.health) * sys_frametime / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
+       sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTN_NORM);
+       self.team = e.team;
+       self.colormap = e.colormap;
+       WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime));
+       onslaught_updatelinks();
+}
+
+void onslaught_controlpoint_reset()
+{
+       if(self.goalentity && self.goalentity != world)
+               remove(self.goalentity);
+       self.goalentity = world;
+       self.team = 0;
+       self.colormap = 1024;
+       self.iscaptured = FALSE;
+       self.islinked = FALSE;
+       self.isshielded = TRUE;
+       self.enemy.solid = SOLID_NOT;
+       self.enemy.colormap = self.colormap;
+       self.think = self.enemy.think = SUB_Null;
+       self.nextthink = 0; // don't like SUB_Null :P
+       setmodel(self, "models/onslaught/controlpoint_pad.md3");
+       //setsize(self, '-32 -32 0', '32 32 8');
+
+       WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+
+       onslaught_updatelinks();
+
+       activator = self;
+       SUB_UseTargets(); // to reset the structures, playerspawns etc.
+}
+
+/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
+  Control point. Be sure to give this enough clearance so that the shootable part has room to exist
+
+  This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
+
+keys:
+"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
+"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
+"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
+ */
+ /*
+void onslaught_controlpoint_think()
+{
+    self.nextthink = time;
+       //if(autocvar_g_onslaught_controlpoints_proxycap)
+                   
+    float _enemy_count;
+    float _friendly_count;
+    float _dist;
+    entity _player;
+    
+    FOR_EACH_PLAYER(_player)
+    {
+        if(!_player.deadflag)
+        {
+            _dist = vlen(_player.origin - self.origin);
+            if(_dist < autocvar_g_onslaught_controlpoints_proxycap_distance)
+            {
+                if(_player.team == self.team)
+                    ++_friendly_count;
+                else
+                    ++_enemy_count;
+            }
+        }
+    }
+
+    _friendly_count = _friendly_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
+    _enemy_count = _enemy_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
+    
+    self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
+    if(self.health <= 0)
+    {
+        onslaught_controlpoint_icon_damage(self, self, 1, 0, self.origin, '0 0 0');
+        return;
+    }
+    
+    if(self.health == max_health)
+       {
+           
+       }
+}
+*/
+
+void spawnfunc_onslaught_controlpoint()
+{
+       //entity e;
+       if (!g_onslaught)
+       {
+               remove(self);
+               return;
+       }
+       precache_model("models/onslaught/controlpoint_pad.md3");
+       precache_model("models/onslaught/controlpoint_pad2.md3");
+       precache_model("models/onslaught/controlpoint_shield.md3");
+       precache_model("models/onslaught/controlpoint_icon.md3");
+       precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
+       precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
+       precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
+       precache_model("models/onslaught/controlpoint_icon_gib1.md3");
+       precache_model("models/onslaught/controlpoint_icon_gib2.md3");
+       precache_model("models/onslaught/controlpoint_icon_gib4.md3");
+       precache_sound("onslaught/controlpoint_build.wav");
+       precache_sound("onslaught/controlpoint_built.wav");
+       precache_sound("weapons/grenade_impact.wav");
+       precache_sound("onslaught/damageblockedbyshield.wav");
+       precache_sound("onslaught/controlpoint_underattack.wav");
+       precache_sound("onslaught/ons_spark1.wav");
+       precache_sound("onslaught/ons_spark2.wav");
+       self.solid = SOLID_BBOX;
+       self.movetype = MOVETYPE_NONE;
+       setmodel(self, "models/onslaught/controlpoint_pad.md3");
+       //setsize(self, '-32 -32 0', '32 32 8');
+       if (!self.noalign)
+        droptofloor();
+       
+       setorigin(self, self.origin);
+       self.touch = onslaught_controlpoint_touch;
+       self.team = 0;
+       self.colormap = 1024;
+       self.iscaptured = FALSE;
+       self.islinked = FALSE;
+       self.isshielded = TRUE;
+       // spawn shield model which indicates whether this can be damaged
+       self.enemy = spawn();
+       self.enemy.classname = "onslaught_controlpoint_shield";
+       self.enemy.solid = SOLID_NOT;
+       self.enemy.movetype = MOVETYPE_NONE;
+       self.enemy.effects = EF_ADDITIVE;
+       setmodel(self.enemy , "models/onslaught/controlpoint_shield.md3");
+       
+       setattachment(self.enemy , self, "");
+       //setsize(e, '-32 -32 0', '32 32 128');
+
+       //setorigin(e, self.origin);
+       self.enemy.colormap = self.colormap;
+
+       waypoint_spawnforitem(self);
+
+       WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
+       WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
+
+       onslaught_updatelinks();
+       
+       self.reset = onslaught_controlpoint_reset;
+}
+
+float onslaught_link_send(entity to, float sendflags)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
+       WriteByte(MSG_ENTITY, sendflags);
+       if(sendflags & 1)
+       {
+               WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
+               WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
+               WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
+       }
+       if(sendflags & 2)
+       {
+               WriteCoord(MSG_ENTITY, self.enemy.origin_x);
+               WriteCoord(MSG_ENTITY, self.enemy.origin_y);
+               WriteCoord(MSG_ENTITY, self.enemy.origin_z);
+       }
+       if(sendflags & 4)
+       {
+               WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
+       }
+       return TRUE;
+}
+
+void onslaught_link_checkupdate()
+{
+       // TODO check if the two sides have moved (currently they won't move anyway)
+       float redpower, bluepower;
+
+       redpower = bluepower = 0;
+       if(self.goalentity.islinked)
+       {
+               if(self.goalentity.team == COLOR_TEAM1)
+                       redpower = 1;
+               else if(self.goalentity.team == COLOR_TEAM2)
+                       bluepower = 1;
+       }
+       if(self.enemy.islinked)
+       {
+               if(self.enemy.team == COLOR_TEAM1)
+                       redpower = 2;
+               else if(self.enemy.team == COLOR_TEAM2)
+                       bluepower = 2;
+       }
+
+       float cc;
+       if(redpower == 1 && bluepower == 2)
+               cc = (COLOR_TEAM1 - 1) * 0x01 + (COLOR_TEAM2 - 1) * 0x10;
+       else if(redpower == 2 && bluepower == 1)
+               cc = (COLOR_TEAM1 - 1) * 0x10 + (COLOR_TEAM2 - 1) * 0x01;
+       else if(redpower)
+               cc = (COLOR_TEAM1 - 1) * 0x11;
+       else if(bluepower)
+               cc = (COLOR_TEAM2 - 1) * 0x11;
+       else
+               cc = 0;
+
+       //print(etos(self), " rp=", ftos(redpower), " bp=", ftos(bluepower), " ");
+       //print("cc=", ftos(cc), "\n");
+
+       if(cc != self.clientcolors)
+       {
+               self.clientcolors = cc;
+               self.SendFlags |= 4;
+       }
+
+       self.nextthink = time;
+}
+
+void onslaught_link_delayed()
+{
+       self.goalentity = find(world, targetname, self.target);
+       self.enemy = find(world, targetname, self.target2);
+       if (!self.goalentity)
+               objerror("can not find target\n");
+       if (!self.enemy)
+               objerror("can not find target2\n");
+       dprint(etos(self.goalentity), " linked with ", etos(self.enemy), "\n");
+       self.SendFlags |= 3;
+       self.think = onslaught_link_checkupdate;
+       self.nextthink = time;
+}
+
+/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
+  Link between control points.
+
+  This entity targets two different spawnfunc_onslaught_controlpoint or spawnfunc_onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
+
+keys:
+"target" - first control point.
+"target2" - second control point.
+ */
+void spawnfunc_onslaught_link()
+{
+       if (!g_onslaught)
+       {
+               remove(self);
+               return;
+       }
+       if (self.target == "" || self.target2 == "")
+               objerror("target and target2 must be set\n");
+       InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET);
+       Net_LinkEntity(self, FALSE, 0, onslaught_link_send);
+}
+
+MUTATOR_HOOKFUNCTION(ons_BuildMutatorsString)
+{
+       ret_string = strcat(ret_string, ":ONS");
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(ons_BuildMutatorsPrettyString)
+{
+       ret_string = strcat(ret_string, ", Onslught");
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(ons_Spawn_Score)
+{
+    
+    /*
+    float _neer_home = (random() > 0.5 ? TRUE : FALSE);
+    
+       RandomSelection_Init();
+       
+       if(self.team == COLOR_TEAM1)
+        RandomSelection_Add(ons_red_generator, 0, string_null, 1, 1);
+       
+       if(self.team == COLOR_TEAM2)
+        RandomSelection_Add(ons_blue_generator, 0, string_null, 1, 1);
+       
+       entity _cp = findchain(classname, "onslaught_controlpoint"):
+       while _cp;
+       {
+           if(_cp.team == self.team)            
+            RandomSelection_Add(_cp, 0, string_null, 1, 1);
+               
+               _cp = _cp.chain;
+       }
+
+       if(RandomSelection_chosen_ent)
+       {
+               self.tur_head = RandomSelection_chosen_ent;
+               spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND;
+       }
+       else if(self.team == spawn_spot.team)
+               spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate
+    
+    */
+    
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
+{
+    if(!autocvar_g_onslaught_spawn_at_controlpoints)
+        return 0;
+        
+    if(random() < 0.5)  // 50/50 chane to use default spawnsystem.
+        return 0;
+    
+    float _close_to_home = ((random() > 0.5) ? TRUE : FALSE);
+    entity _best, _trg_gen;
+    float _score, _best_score = MAX_SHOT_DISTANCE;
+    
+       RandomSelection_Init();
+    
+       if(self.team == COLOR_TEAM1)
+       {
+           if(!_close_to_home)
+            _trg_gen = ons_blue_generator;
+        else    
+            _trg_gen  = ons_red_generator;        
+       }
+       
+       if(self.team == COLOR_TEAM2)
+       {
+           if(_close_to_home)
+            _trg_gen = ons_blue_generator;
+        else    
+            _trg_gen  = ons_red_generator;        
+       }
+       
+       entity _cp = findchain(classname, "onslaught_controlpoint");
+       while(_cp)
+       {
+           if(_cp.team == self.team)            
+        {            
+            _score = vlen(_trg_gen.origin - _cp.origin);
+            if(_score < _best_score)
+            {
+                _best = _cp;
+                _best_score = _score;            
+            }
+        }              
+               _cp = _cp.chain;
+       }
+       
+    vector _loc;        
+    float i;    
+    if(_best)
+    {
+        for(i = 0; i < 10; ++i)
+        {
+            _loc = _best.origin + '0 0 96';
+            _loc += ('0 1 0' * random()) * 128; 
+            tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
+            if(trace_fraction == 1.0 && !trace_startsolid)
+            {
+                setorigin(self, _loc);
+                self.angles = normalize(_loc - _best.origin) * RAD2DEG;
+                return 0;
+            }
+        }
+    }
+    else
+    {
+        if(!autocvar_g_onslaught_spawn_at_generator)
+            return 0;
+        
+        _trg_gen = ((self.team == COLOR_TEAM1) ? ons_red_generator : ons_blue_generator);
+        
+        for(i = 0; i < 10; ++i)
+        {
+            _loc = _trg_gen.origin + '0 0 96';
+            _loc += ('0 1 0' * random()) * 128; 
+            tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
+            if(trace_fraction == 1.0 && !trace_startsolid)
+            {
+                setorigin(self, _loc);
+                self.angles = normalize(_loc - _trg_gen.origin) * RAD2DEG;
+                return 0;
+            }
+        }
+    }
+    
+    return 0;
+}
+
+MUTATOR_DEFINITION(gamemode_onslaught)
+{
+       //MUTATOR_HOOK(PlayerDies, nexball_BallDrop, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(MakePlayerObserver, nexball_BallDrop, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(ClientDisconnect, nexball_BallDrop, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
+       MUTATOR_HOOK(BuildMutatorsPrettyString, ons_BuildMutatorsPrettyString, CBC_ORDER_ANY);
+       MUTATOR_HOOK(BuildMutatorsString, ons_BuildMutatorsString, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerSpawn, ons_PlayerSpawn, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(Spawn_Score, ons_Spawn_Score, CBC_ORDER_ANY);
+       
+       MUTATOR_ONADD
+       {
+               //InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
+       }
+
+       return 0;
+}
index 3b193c163c9d61ea0cce471f7df999bdd0139323..bdd39b1283f487fe0e74ab42135b6d66f4b180c7 100644 (file)
@@ -55,6 +55,9 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
        float velocity_difference;
        float clean_up_and_do_nothing;
 
+    if (self.deadflag != DEAD_NO)
+        return 0;
+
        new_velocity_gain = 0;
        clean_up_and_do_nothing = 0;
 
@@ -241,8 +244,6 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
                }
        }
 
-
-
        if (dodge_detected == 1) {
                self.last_dodging_time = time;
 
@@ -255,7 +256,7 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
                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 =          self.dodging_direction_x * self.dodging_direction_x;
                length = length + self.dodging_direction_y * self.dodging_direction_y;
                length = sqrt(length);
 
diff --git a/qcsrc/server/mutators/mutator_superspec.qc b/qcsrc/server/mutators/mutator_superspec.qc
new file mode 100644 (file)
index 0000000..2adef63
--- /dev/null
@@ -0,0 +1,137 @@
+float _spectate(entity _player)
+{
+       if(SpectateNext(_player) == 1)
+       {
+               PutObserverInServer();
+               self.classname = "spectator";
+       }       
+       return TRUE;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
+{
+       if(MUTATOR_RETURNVALUE) // command was already handled?
+               return FALSE;
+
+       if(self.classname == "player")
+               return FALSE;
+
+       if(cmd_name == "followpowerup")
+       {
+               entity _player;
+               FOR_EACH_PLAYER(_player)
+               {
+                       if(_player.strength_finished > time || _player.invincible_finished > time)
+                               return _spectate(_player);
+               }
+               
+               centerprint(self, "No active powerups\n");
+               return TRUE;
+       }
+
+       if(cmd_name == "followstrength")
+       {
+               entity _player;
+               FOR_EACH_PLAYER(_player)
+               {
+                       if(_player.strength_finished > time)
+                               return _spectate(_player);
+               }
+               
+               centerprint(self, "No active Strength\n");
+               return TRUE;
+       }
+
+       if(cmd_name == "followstshield")
+       {
+               entity _player;
+               FOR_EACH_PLAYER(_player)
+               {
+                       if(_player.invincible_finished > time)
+                               return _spectate(_player);
+               }
+               
+               centerprint(self, "No active Shield\n");
+               return TRUE;
+       }
+
+       if(cmd_name == "followfc")
+       {
+               if(!g_ctf)
+                       return TRUE;
+               
+               entity _player;         
+               float _team;
+               
+               if(cmd_argc == 2)
+               {                       
+                       if(argv(1) == "red")
+                               _team = COLOR_TEAM1;
+                       else
+                               _team = COLOR_TEAM2;
+               }
+               
+               FOR_EACH_PLAYER(_player)
+               {
+                       if(_player.flagcarried && (_player.team == _team || _team == 0))
+                               return _spectate(_player);
+               }
+               
+               centerprint(self, "No active flag carrier\n");
+               return TRUE;
+       }       
+
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_BuildMutatorsString)
+{
+       ret_string = strcat(ret_string, ":SS");
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_BuildMutatorsPrettyString)
+{
+       ret_string = strcat(ret_string, ", Super Spectators");
+       return 0;
+}
+
+/*
+MUTATOR_HOOKFUNCTION(superspec_PlayerSpawn)
+{
+
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_ClientDisconnect)
+{
+
+       return FALSE;
+}
+MUTATOR_HOOKFUNCTION(superspec_PlayerPreThink)
+{
+       return FALSE;
+}
+*/
+
+MUTATOR_DEFINITION(mutator_superspec)
+{
+
+       MUTATOR_HOOK(BuildMutatorsString, superspec_BuildMutatorsString, CBC_ORDER_ANY);
+       MUTATOR_HOOK(BuildMutatorsPrettyString, superspec_BuildMutatorsPrettyString, CBC_ORDER_ANY);
+       MUTATOR_HOOK(SV_ParseClientCommand, superspec_SV_ParseClientCommand, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(ClientConnect, superspec_ClientConnect, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(PlayerSpawn, superspec_PlayerSpawn, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(PlayerPreThink, superspec_PlayerPreThink, CBC_ORDER_ANY);
+       //MUTATOR_HOOK(ClientDisconnect, superspec_ClientDisconnect, CBC_ORDER_ANY);
+
+       MUTATOR_ONADD
+       {
+       }
+
+       MUTATOR_ONREMOVE
+       {
+       }
+
+       return 0;
+}
index 4e7d9a6512bd47b8806d2f791fa5fc04cd9ab035..61c2b896ae50d1d036ebe71ba942d99dd9afd276 100644 (file)
@@ -2,6 +2,7 @@ MUTATOR_DECLARATION(gamemode_keyhunt);
 MUTATOR_DECLARATION(gamemode_freezetag);
 MUTATOR_DECLARATION(gamemode_keepaway);
 MUTATOR_DECLARATION(gamemode_nexball);
+MUTATOR_DECLARATION(gamemode_onslaught);
 
 MUTATOR_DECLARATION(mutator_dodging);
 MUTATOR_DECLARATION(mutator_invincibleprojectiles);
@@ -10,5 +11,6 @@ MUTATOR_DECLARATION(mutator_nix);
 MUTATOR_DECLARATION(mutator_rocketflying);
 MUTATOR_DECLARATION(mutator_spawn_near_teammate);
 MUTATOR_DECLARATION(mutator_vampire);
+MUTATOR_DECLARATION(mutator_superspec);
 
 MUTATOR_DECLARATION(sandbox);
index 31a1a4e8546d7256018798902e5da0d174bbdec8..d7fec13264e5cc70bdfa10e02a21570d0b1d7c50 100644 (file)
@@ -205,7 +205,7 @@ string port_string[MAX_STORAGE_ATTACHMENTS]; // fteqcc crashes if this isn't def
 string sandbox_ObjectPort_Save(entity e, float database)
 {
        // save object properties, and return them as a string
-       float i;
+       float i = 0;
        string s;
        entity head;
 
@@ -268,6 +268,7 @@ string sandbox_ObjectPort_Save(entity e, float database)
        }
 
        // now apply the array to a simple string, with the ; symbol separating objects
+       s = "";
        for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i)
        {
                if(port_string[i])
@@ -744,13 +745,16 @@ MUTATOR_HOOKFUNCTION(sandbox_PlayerCommand)
                                                        print_to(self, strcat("^2SANDBOX - INFO: ^7Object is owned by \"^7", e.netname, "^7\", created \"^3", e.message, "^7\", last edited \"^3", e.message2, "^7\""));
                                                        return TRUE;
                                                case "mesh":
+                                                       s = "";
                                                        FOR_EACH_TAG(e)
                                                                s = strcat(s, "^7\"^5", gettaginfo_name, "^7\", ");
                                                        print_to(self, strcat("^2SANDBOX - INFO: ^7Object mesh is \"^3", e.model, "^7\" at animation frame ^3", ftos(e.frame), " ^7containing the following tags: ", s));
                                                        return TRUE;
                                                case "attachments":
                                                        // this should show the same info as 'mesh' but for attachments
+                                                       s = "";
                                                        entity head;
+                                                       i = 0;
                                                        for(head = world; (head = find(head, classname, "object")); )
                                                        {
                                                                if(head.owner == e)
index 95aa2f9658909983c085061cd5079d5d030af413..ce4c2b4b8d74a40c13455b05d9020f05473e7cfc 100644 (file)
@@ -598,6 +598,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     {
         pathlib_expandnode = pathlib_expandnode_box;
         pathlib_movenode   = pathlib_swimnode;
+       doedge = 0;
     }
     else
     {
@@ -605,6 +606,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
         {
             pathlib_expandnode = pathlib_expandnode_box;
             pathlib_movenode   = pathlib_swimnode;
+           doedge = 0;
         }
         else
         {
index 4647fea1392abdba4013b61f2b2c6c99fdde31bb..a08c66b3ae5f48fd657adf5ee61ac53282177c92 100644 (file)
@@ -49,6 +49,7 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
     plib_points2[0] = plib_points[0];
     vector bp;
     bp = plib_points[0];
+    fc2 = 0;
     for(i = 0; i < 8; ++i)
     {
         c = 0;
index 5d9fc3d9788c38aab12173b5c7054e3b45e7d2b2..0a5ea42b1c22e7e996665ee98238dd55a6eb3307 100644 (file)
@@ -156,7 +156,7 @@ float tile_check_plus(vector where)
 float tile_check_plus2(vector where)
 {
     vector p,f,r;
-    float i,e;
+    float i = 0, e = 0;
 
     f = PLIB_FORWARD * pathlib_gridsize;
     r = PLIB_RIGHT   * pathlib_gridsize;
index 3533b4882e4b94264cb3dcf4a4c6b3fa1337f9e8..87220328fb8a58ba5aa435bbc274cdb6d62002aa 100644 (file)
@@ -189,6 +189,7 @@ void PlayerStats_TeamScore(float t, string event_id, float value) // TODO: doesn
        P: player ID of an existing player; this also sets the owner for all following "n", "e" and "t" lines (lower case!)
        n: nickname of the player (optional)
        t: team ID
+       i: player index
        e: followed by an event name, a space, and the event count/score
                event names can be:
                        alivetime: total playing time of the player
@@ -198,13 +199,31 @@ void PlayerStats_TeamScore(float t, string event_id, float value) // TODO: doesn
                        scoreboardvalid: set to 1 if the player was there at the end of the match
                        total-<scoreboardname>: total score of that scoreboard item
                        scoreboard-<scoreboardname>: end-of-game score of that scoreboard item (can differ in non-team games)
-                       achievement-<achievementname>: achievement counters
+                       achievement-<achievementname>: achievement counters (their "count" is usually 1 if nonzero at all)
+                       kills-<index>: number of kills against the indexed player
                        rank <number>: rank of player
                        acc-<weapon netname>-hit: total damage dealt
                        acc-<weapon netname>-fired: total damage that all fired projectiles *could* have dealt
                        acc-<weapon netname>-cnt-hit: amount of shots that actually hit
                        acc-<weapon netname>-cnt-fired: amount of fired shots
                        acc-<weapon netname>-frags: amount of frags dealt by weapon
+
+       Response format (not used yet):
+
+       V: format version (always 1) - this MUST be the first line!
+       #: comment (MUST be ignored by any parser)
+       R: release information on the XonStat server
+       T: current time
+       S: in case of a stats submit request, the human readable xonstat URL for the submitted match
+       P: player ID of an existing player; this also sets the owner for all following "n", "e" and "t" lines (lower case!)
+       e: followed by an event name, a space, and the event count/score, and - if this is a reply to a stats submit request - a space, and the delta of the event count/score caused by this match
+               event names can be the same as above (they then are either sums, or minimum/maximum values, depending on context), as well as:
+                       elo: current Elo calculated by the stats server
+                       rank <number>: global rank of player for this game type (for stats submit requests)
+                       rank-<gametype> <number>: global rank of player for any game type (for non stats submit requests)
+               not all events need to be included, of course
+               if an event is counted additively from unprocessed submitted data, it should not be sent as part of stats submit response
+               achievement-<achievementname> events may be generated by the xonstat server and reported as part of stats submit responses!
 */
 
 void PlayerStats_ready(entity fh, entity pass, float status)
index 1890eddd97a679ae3f279e258dcfe0eb55c6c9f4..b58f5d53216631dc990389cb1fd54558146b0335 100644 (file)
@@ -140,7 +140,7 @@ antilag.qc
 
 ctf.qc
 domination.qc
-mode_onslaught.qc
+//mode_onslaught.qc
 //nexball.qc
 g_hook.qc
 
@@ -209,6 +209,7 @@ mutators/gamemode_nexball.qc
 mutators/gamemode_keyhunt.qc
 mutators/gamemode_freezetag.qc
 mutators/gamemode_keepaway.qc
+mutators/gamemode_onslaught.qc
 mutators/mutator_invincibleproj.qc
 mutators/mutator_new_toys.qc
 mutators/mutator_nix.qc
@@ -217,6 +218,7 @@ mutators/mutator_rocketflying.qc
 mutators/mutator_vampire.qc
 mutators/mutator_spawn_near_teammate.qc
 mutators/sandbox.qc
+mutators/mutator_superspec.qc
 
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/mathlib.qc
index 911106a30560358e6ae03054ab21526dc0e6ad8a..c7c38165dd9845225420660ddede82ae65de8dd5 100644 (file)
@@ -141,6 +141,7 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e)
        newpos = race_readPos(map, t);
 
        float i;
+       player_prevpos = 0;
        for(i = 1; i <= RANKINGS_CNT; ++i)
        {
                if(race_readUID(map, i) == myuid)
@@ -490,8 +491,8 @@ void checkpoint_passed()
                        self.race_checkpoint = other.race_checkpoint;
                }
 
-               float largest_cp_id;
-               float cp_amount;
+               float largest_cp_id = 0;
+               float cp_amount = 0;
                for(cp = world; (cp = find(cp, classname, "target_checkpoint"));) {
                        cp_amount += 1;
                        if(cp.race_checkpoint > largest_cp_id) // update the finish id if someone hit a new checkpoint
@@ -664,7 +665,7 @@ void trigger_race_checkpoint_verify()
                g_race_qualifying = 1;
                self.race_place = race_lowest_place_spawn;
                if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE))
-                       error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out"));
+                       error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out"));
        }
        else
        {
@@ -710,7 +711,7 @@ void trigger_race_checkpoint_verify()
                        }
 
                        if(defragcpexists != -1){
-                               float largest_cp_id;
+                               float largest_cp_id = 0;
                                for(cp = world; (cp = find(cp, classname, "target_checkpoint"));)
                                        if(cp.race_checkpoint > largest_cp_id)
                                                largest_cp_id = cp.race_checkpoint;
index 8f5e005a425811016052ba7b63882c9cab3f83bb..239afb04a81c4d72702fa840078e50dc1928c29f 100644 (file)
@@ -133,7 +133,8 @@ string RuneName(float r)
 
 vector RuneColormod(float r)
 {
-       vector _color;
+       vector _color = '255 0 255';
+
        if(r == RUNE_STRENGTH)
                _color = '255 0 0';
        if(r == RUNE_DEFENSE)
@@ -178,6 +179,7 @@ void RuneCarriedThink()
        // count runes my owner holds
        rcount = 0;
        rune = find(world, classname, "rune");
+       rnum = -1;
        while(rune)
        {
                if(rune.owner == self.owner)
@@ -341,7 +343,6 @@ void DropAllRunes(entity pl)
 
        entity curse1, rune1, curse2, rune2;
 
-       rune = curse = world;
        rcount = ccount = r = c = 0;
        rune = find(rune, classname, "rune");
        while(rune)
@@ -361,7 +362,6 @@ void DropAllRunes(entity pl)
        numtodrop = autocvar_g_runematch_drop_runes_max;
        prevent_same = !autocvar_g_runematch_allow_same;
 
-       rune = curse = world;
        do
        {
                rune = find(rune, classname, "rune");
@@ -588,6 +588,7 @@ float RunematchHandleFrags(entity attacker, entity targ, float f)
        if(!arunes && !trunes)
                return f - 1 + autocvar_g_runematch_frags_norune; // don't give points to players when no runes are involved.
 
+       newfrags = 0;
        if(arunes)
        {       // got a kill while holding runes
                newfrags = newfrags + autocvar_g_runematch_frags_killedby_runeholder;//5;
index 10f5d12fcdd76b47fb0efeb139f42ff7baf60875..102dd6a33ef326af860bdd8d66c0ba537f5f8a89 100644 (file)
@@ -127,7 +127,7 @@ float TeamScore_Compare(entity t1, entity t2)
 {
        if(!t1 || !t2) return (!t2) - !t1;
 
-       vector result;
+       vector result = '0 0 0';
        float i;
        for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
@@ -356,7 +356,7 @@ float PlayerScore_Compare(entity t1, entity t2)
 {
        if(!t1 || !t2) return (!t2) - !t1;
 
-       vector result;
+       vector result = '0 0 0';
        float i;
        for(i = 0; i < MAX_SCORE; ++i)
        {
index a586252555dcf58beaa904975135ba0e5e71e4c3..2f59924df6e894c9a4d96a8281fb671bec802abb 100644 (file)
@@ -172,8 +172,8 @@ vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
 vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
 {
     entity flock_member;
-    vector push,pull;
-    float ccount;
+    vector push = '0 0 0', pull = '0 0 0';
+    float ccount = 0;
 
     flock_member = findradius(self.origin,radius);
     while(flock_member)
@@ -198,8 +198,8 @@ vector steerlib_flock(float radius, float standoff,float separation_force,float
 vector steerlib_flock2d(float radius, float standoff,float separation_force,float flock_force)
 {
     entity flock_member;
-    vector push,pull;
-    float ccount;
+    vector push = '0 0 0', pull = '0 0 0';
+    float ccount = 0;
 
     flock_member = findradius(self.origin,radius);
     while(flock_member)
@@ -229,8 +229,8 @@ vector steerlib_flock2d(float radius, float standoff,float separation_force,floa
 vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
 {
     entity swarm_member;
-    vector force,center;
-    float ccount;
+    vector force = '0 0 0', center = '0 0 0';
+    float ccount = 0;
 
     swarm_member = findradius(self.origin,radius);
 
index 007c6369ede68e3e5239d1b774076b1cf65e3840..63d91f6070ca3ecee2ecb56527f7a0c6710c9a98 100644 (file)
@@ -231,8 +231,6 @@ void StartFrame (void)
        CreatureFrame ();
        CheckRules_World ();
 
-       AuditTeams();
-
        RuneMatchGivePoints();
        bot_serverframe();
 
index 76a7838f2f20f09066194f07dece515c1ea06275..0abef68d2a54f2e2a771af76d20d02391310433a 100644 (file)
@@ -1,3 +1,288 @@
+#define ISF_LOCATION 2
+#define ISF_MODEL    4
+#define ISF_STATUS   8
+    #define ITS_STAYWEP   1
+    #define ITS_ANIMATE1  2
+    #define ITS_ANIMATE2  4
+    #define ITS_AVAILABLE 8
+    #define ITS_ALLOWFB   16
+    #define ITS_ALLOWSI   32
+    #define ITS_POWERUP   64
+#define ISF_COLORMAP 16
+#define ISF_DROP 32
+#define ISF_ANGLES 64
+
+.float ItemStatus;
+
+#ifdef CSQC
+
+var float  autocvar_cl_animate_items = 1;
+var float  autocvar_cl_ghost_items = 0.45;
+var vector autocvar_cl_ghost_items_color = '-1 -1 -1';
+float  autocvar_cl_fullbright_items;
+vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
+float  autocvar_cl_weapon_stay_alpha = 0.75;
+float  autocvar_cl_simple_items;
+float  cl_simple_items;
+float  cl_ghost_items_alpha;
+
+.float  spawntime;
+.float  gravity;
+.vector colormod;
+void ItemDraw()
+{    
+    if(self.gravity)
+    {        
+        Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+        if(self.move_flags & FL_ONGROUND) 
+        { // For some reason move_avelocity gets set to '0 0 0' here ...
+            self.oldorigin = self.origin;
+            self.gravity = 0;
+
+            if(autocvar_cl_animate_items)   
+            { // ... so reset it if animations are requested. 
+                if(self.ItemStatus & ITS_ANIMATE1)
+                    self.move_avelocity = '0 180 0';
+                
+                if(self.ItemStatus & ITS_ANIMATE2)
+                    self.move_avelocity = '0 -90 0';
+            }
+        }
+    }
+    else if (autocvar_cl_animate_items)
+    {        
+        if(self.ItemStatus & ITS_ANIMATE1)
+        {
+            self.angles += self.move_avelocity * frametime;
+            setorigin(self, '0 0 10' + self.oldorigin + '0 0 8' * sin(time * 2));        
+        }    
+        
+        if(self.ItemStatus & ITS_ANIMATE2)
+        {
+            self.angles += self.move_avelocity * frametime;
+            setorigin(self, '0 0 8' + self.oldorigin + '0 0 4' * sin(time * 3));        
+        }
+    }
+}
+
+void ItemDrawSimple()
+{
+    if(self.gravity)
+    {        
+        Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);    
+        
+        if(self.move_flags & FL_ONGROUND)
+            self.gravity = 0;
+    }
+}
+
+float csqcitems_started; // remove this after a release or two
+void csqcitems_start()
+{
+    if(autocvar_cl_ghost_items == 1)
+        cl_ghost_items_alpha = 0.55;
+    else
+        cl_ghost_items_alpha = bound(0, autocvar_cl_ghost_items, 1);
+    
+    csqcitems_started = TRUE;
+}
+
+void ItemRead(float _IsNew)
+{
+    if(!csqcitems_started)
+        csqcitems_start();
+    
+    float sf = ReadByte();
+
+    if(sf & ISF_LOCATION)
+    {
+        self.origin_x = ReadCoord();
+        self.origin_y = ReadCoord();
+        self.origin_z = ReadCoord();
+        setorigin(self, self.origin);
+        self.oldorigin = self.origin;
+    }
+    
+    if(sf & ISF_ANGLES) 
+    {
+        self.angles_x = ReadCoord();
+        self.angles_y = ReadCoord();
+        self.angles_z = ReadCoord();        
+        self.move_angles = self.angles;
+    }
+    
+    if(sf & ISF_STATUS) // need to read/write status frist so model can handle simple, fb etc.
+    {
+        self.ItemStatus = ReadByte();    
+        
+        if(self.ItemStatus & ITS_AVAILABLE)
+        {
+            self.alpha = 1;
+            self.colormod = self.glowmod = '1 1 1';
+        }
+        else
+        {
+            if (cl_ghost_items_alpha)
+            {
+                self.alpha = autocvar_cl_ghost_items;
+                self.colormod = self.glowmod = autocvar_cl_ghost_items_color;
+            }
+            else
+                self.alpha = -1;
+        }    
+        
+        if(autocvar_cl_fullbright_items)
+            if(self.ItemStatus & ITS_ALLOWFB)
+                self.effects |= EF_FULLBRIGHT;
+            
+        if(self.ItemStatus & ITS_STAYWEP)
+        {
+            self.colormod = self.glowmod = autocvar_cl_weapon_stay_color;
+            self.alpha = autocvar_cl_weapon_stay_alpha;
+            
+        }
+        
+        if(self.ItemStatus & ITS_POWERUP)
+        {
+            if(self.ItemStatus & ITS_AVAILABLE)
+                self.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
+            else
+                 self.effects &~= (EF_ADDITIVE | EF_FULLBRIGHT);
+        }
+    }
+    
+    if(sf & ISF_MODEL)
+    {
+        self.drawmask  = MASK_NORMAL;
+        self.movetype  = MOVETYPE_NOCLIP;
+        self.draw       = ItemDraw;
+        
+        if(self.mdl)
+            strunzone(self.mdl);
+        
+        self.mdl = "";
+        string _fn = ReadString();
+        
+        if(cl_simple_items && (self.ItemStatus & ITS_ALLOWSI))
+        {
+            string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
+            self.draw = ItemDrawSimple;
+                    
+            if(fexists(strcat(_fn2, "_simple.md3")))
+                self.mdl = strzone(strcat(_fn2, "_simple.md3"));
+            else if(fexists(strcat(_fn2, "_simple.dpm")))
+                self.mdl = strzone(strcat(_fn2, "_simple.dpm"));
+            else if(fexists(strcat(_fn2, "_simple.iqm")))
+                self.mdl = strzone(strcat(_fn2, "_simple.iqm"));
+            else if(fexists(strcat(_fn2, "_simple.obj")))
+                self.mdl = strzone(strcat(_fn2, "_simple.obj"));
+            else
+            {
+                self.draw = ItemDraw;
+                dprint("Simple item requested for ", _fn, " but no model exsist for it\n");
+            }
+        }
+        
+        if(self.draw != ItemDrawSimple)        
+            self.mdl = strzone(_fn);                
+        
+        
+        if(self.mdl == "")
+            dprint("^1WARNING!^7 self.mdl is unset for item ", self.classname, " tell tZork aboute this!\n");
+        
+        precache_model(self.mdl);
+        setmodel(self, self.mdl);
+    }
+    
+    if(sf & ISF_COLORMAP)
+        self.colormap = ReadShort();
+    
+    if(sf & ISF_DROP)
+    {
+        self.gravity = 1;
+        self.move_angles = '0 0 0';
+        self.move_movetype = MOVETYPE_TOSS;
+        self.move_velocity_x = ReadCoord();
+        self.move_velocity_y = ReadCoord();
+        self.move_velocity_z = ReadCoord();
+        self.velocity = self.move_velocity;
+        self.move_origin = self.oldorigin;
+        
+        if(!self.move_time)
+        {
+            self.move_time = time;
+            self.spawntime = time;
+        }
+        else
+            self.move_time = max(self.move_time, time);
+    }
+        
+    if(autocvar_cl_animate_items)
+    {        
+        if(self.ItemStatus & ITS_ANIMATE1)
+            self.move_avelocity = '0 180 0';
+                
+        if(self.ItemStatus & ITS_ANIMATE2)
+            self.move_avelocity = '0 -90 0';
+    }
+}
+
+#endif
+
+#ifdef SVQC
+float autocvar_sv_simple_items;
+float ItemSend(entity to, float sf)
+{
+    if(self.gravity)
+        sf |= ISF_DROP;
+    else
+        sf &~= ISF_DROP;
+       
+       WriteByte(MSG_ENTITY, ENT_CLIENT_ITEM); 
+       WriteByte(MSG_ENTITY, sf);
+
+       //WriteByte(MSG_ENTITY, self.cnt);
+    if(sf & ISF_LOCATION)
+    {
+        WriteCoord(MSG_ENTITY, self.origin_x);
+        WriteCoord(MSG_ENTITY, self.origin_y);
+        WriteCoord(MSG_ENTITY, self.origin_z);
+    }
+    
+    if(sf & ISF_ANGLES)
+    {
+        WriteCoord(MSG_ENTITY, self.angles_x);
+        WriteCoord(MSG_ENTITY, self.angles_y);
+        WriteCoord(MSG_ENTITY, self.angles_z);
+    }
+
+    if(sf & ISF_STATUS)
+        WriteByte(MSG_ENTITY, self.ItemStatus);
+
+    if(sf & ISF_MODEL)
+    {
+        
+        if(self.mdl == "")
+            dprint("^1WARNING!^7 self.mdl is unset for item ", self.classname, "exspect a crash just aboute now\n");
+        
+        WriteString(MSG_ENTITY, self.mdl);
+    }
+        
+        
+    if(sf & ISF_COLORMAP)
+        WriteShort(MSG_ENTITY, self.colormap);
+
+    if(sf & ISF_DROP)
+    {
+        WriteCoord(MSG_ENTITY, self.velocity_x);
+        WriteCoord(MSG_ENTITY, self.velocity_y);
+        WriteCoord(MSG_ENTITY, self.velocity_z);
+    }
+        
+    return TRUE;
+}
+
+
 float have_pickup_item(void)
 {
        // minstagib: only allow filtered items
@@ -78,7 +363,7 @@ string Item_CounterFieldName(float it)
 
 .float max_armorvalue;
 .float pickup_anyway;
-
+/*
 float Item_Customize()
 {
        if(self.spawnshieldtime)
@@ -103,80 +388,63 @@ float Item_Customize()
                        return FALSE;
        }
 }
+*/
 
 void Item_Show (entity e, float mode)
-{
+{    
        e.effects &~= EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST;
+       e.ItemStatus &~= ITS_STAYWEP;
        if (mode > 0)
        {
                // make the item look normal, and be touchable
                e.model = e.mdl;
                e.solid = SOLID_TRIGGER;
-               e.colormod = '0 0 0';
-               self.glowmod = self.colormod;
-               e.alpha = 0;
-               e.customizeentityforclient = func_null;
-
                e.spawnshieldtime = 1;
+               e.ItemStatus |= ITS_AVAILABLE;
        }
        else if (mode < 0)
        {
                // hide the item completely
                e.model = string_null;
                e.solid = SOLID_NOT;
-               e.colormod = '0 0 0';
-               self.glowmod = self.colormod;
-               e.alpha = 0;
-               e.customizeentityforclient = func_null;
-
                e.spawnshieldtime = 1;
+               e.ItemStatus &~= ITS_AVAILABLE;
        }
        else if((e.flags & FL_WEAPON) && !(e.flags & FL_NO_WEAPON_STAY) && g_weapon_stay)
        {
                // make the item translucent and not touchable
                e.model = e.mdl;
                e.solid = SOLID_TRIGGER; // can STILL be picked up!
-               e.colormod = '0 0 0';
-               self.glowmod = self.colormod;
                e.effects |= EF_STARDUST;
-               e.customizeentityforclient = Item_Customize;
-
                e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon
-       }
-       else if(g_ghost_items)
-       {
-               // make the item translucent and not touchable
-               e.model = e.mdl;
-               e.solid = SOLID_NOT;
-               e.colormod = stov(autocvar_g_ghost_items_color);
-               e.glowmod = e.colormod;
-               e.alpha = g_ghost_items;
-               e.customizeentityforclient = func_null;
-
-               e.spawnshieldtime = 1;
+               e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP);
        }
        else
        {
-               // hide the item completely
-               e.model = string_null;
+               //setmodel(e, "null");
                e.solid = SOLID_NOT;
                e.colormod = '0 0 0';
                e.glowmod = e.colormod;
-               e.alpha = 0;
-               e.customizeentityforclient = func_null;
-
                e.spawnshieldtime = 1;
+               e.ItemStatus &~= ITS_AVAILABLE;
        }
-
-       if (e.items & (IT_STRENGTH | IT_INVINCIBLE))
-               e.effects |= EF_ADDITIVE | EF_FULLBRIGHT;
+       
+       if (e.items & IT_STRENGTH || e.items & IT_INVINCIBLE)
+           e.ItemStatus |= ITS_POWERUP;                
+       
        if (autocvar_g_nodepthtestitems)
                e.effects |= EF_NODEPTHTEST;
-       if (autocvar_g_fullbrightitems)
-               e.effects |= EF_FULLBRIGHT;
+               
+    
+    if (autocvar_g_fullbrightitems)
+               e.ItemStatus |= ITS_ALLOWFB;
+       
+       if (autocvar_sv_simple_items)
+        e.ItemStatus |= ITS_ALLOWSI;
 
        // relink entity (because solid may have changed)
        setorigin(e, e.origin);
+    e.SendFlags |= ISF_STATUS;
 }
 
 void Item_Respawn (void)
@@ -209,7 +477,7 @@ void Item_RespawnCountdown (void)
                if(self.count == 1)
                {
                        string name;
-                       vector rgb;
+                       vector rgb = '1 0 1';
                        name = string_null;
                        if(g_minstagib)
                        {
@@ -555,6 +823,7 @@ void Item_Touch (void)
                                }
                        }
                        e = RandomSelection_chosen_ent;
+
                }
                else
                        e = self;
@@ -674,7 +943,8 @@ float weapon_pickupevalfunc(entity player, entity item)
 
 float commodity_pickupevalfunc(entity player, entity item)
 {
-       float c, i, need_shells, need_nails, need_rockets, need_cells, need_fuel;
+       float c, i;
+       float need_shells = FALSE, need_nails = FALSE, need_rockets = FALSE, need_cells = FALSE, need_fuel = FALSE;
        entity wi;
        c = 0;
 
@@ -744,8 +1014,16 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 
        if(self.model == "")
                self.model = itemmodel;
+       
+       if(self.model == "")
+    {
+        error(strcat("^1Tried to spawn ", itemname, " with no model!\n"));
+        return;
+    }
+        
        if(self.item_pickupsound == "")
                self.item_pickupsound = pickupsound;
+       
        if(!self.respawntime) // both need to be set
        {
                self.respawntime = defaultrespawntime;
@@ -757,6 +1035,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 
        if(weaponid)
                WEPSET_COPY_EW(self, weaponid);
+       
        self.flags = FL_ITEM | itemflags;
 
        if(MUTATOR_CALLHOOK(FilterItem)) // error means we do not want the item
@@ -814,6 +1093,9 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                        remove (self);
                        return;
                }
+               
+               if(self.angles != '0 0 0')
+            self.SendFlags |= ISF_ANGLES;
 
                self.reset = Item_Reset;
                // it's a level item
@@ -857,6 +1139,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                        entity otheritem;
                        for(otheritem = findradius(self.origin, 3); otheritem; otheritem = otheritem.chain)
                        {
+                           // why not flags & fl_item?
                                if(otheritem.is_item)
                                {
                                        dprint("XXX Found duplicated item: ", itemname, vtos(self.origin));
@@ -890,32 +1173,51 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        self.mdl = self.model;
        self.netname = itemname;
        self.touch = Item_Touch;
-       setmodel (self, self.mdl); // precision set below
-       self.effects |= EF_LOWPRECISION;
+       setmodel(self, "null"); // precision set below
+       //self.effects |= EF_LOWPRECISION; 
+       
        if((itemflags & FL_POWERUP) || self.health || self.armorvalue)
-               setsize (self, '-16 -16 0', '16 16 48');
+    {
+        self.pos1 = '-16 -16 0';
+        self.pos2 = '16 16 48';
+    }
        else
-               setsize (self, '-16 -16 0', '16 16 32');
+    {
+        self.pos1 = '-16 -16 0';
+        self.pos2 = '16 16 32';
+    }
+    setsize (self, self.pos1, self.pos2);
+    
+    if(itemflags & FL_POWERUP) 
+        self.ItemStatus |= ITS_ANIMATE1;
+       
+       if(self.armorvalue || self.health)
+        self.ItemStatus |= ITS_ANIMATE2;
+       
        if(itemflags & FL_WEAPON)
-               self.modelflags |= MF_ROTATE;
-
-       if (self.classname != "droppedweapon") // if dropped, colormap is already set up nicely
-       if (itemflags & FL_WEAPON)
        {
-               // neutral team color for pickup weapons
-               self.colormap = 1024; // color shirt=0 pants=0 grey
+               if (self.classname != "droppedweapon") // if dropped, colormap is already set up nicely
+            self.colormap = 1024; // color shirt=0 pants=0 grey
+        else
+            self.gravity = 1;
+            
+               self.ItemStatus |= ITS_ANIMATE1;
+               self.ItemStatus |= ISF_COLORMAP;
        }
 
        self.state = 0;
-       if(self.team)
+       if(self.team) // broken, no idea why.
        {
                if(!self.cnt)
                        self.cnt = 1; // item probability weight
-               self.effects = self.effects | EF_NODRAW; // marker for item team search
+                       
+               self.effects |= EF_NODRAW; // marker for item team search
                InitializeEntity(self, Item_FindTeam, INITPRIO_FINDTARGET);
        }
        else
                Item_Reset();
+        
+    Net_LinkEntity(self, FALSE, 0, ItemSend);
 }
 
 /* replace items in minstagib
@@ -923,10 +1225,10 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
  * IT_NAILS     = extra lives
  * IT_INVINCIBLE = speed
  */
-void minstagib_items (float itemid)
+void minstagib_items (float itemid) // will be deleted soon.
 {
        float rnd;
-       self.classname = "minstagib";
+       self.classname = "minstagib"; // ...?
 
        // replace rocket launchers and nex guns with ammo cells
        if (itemid == IT_CELLS)
@@ -1354,7 +1656,7 @@ void spawnfunc_item_invincible (void) {
 void spawnfunc_item_minst_cells (void) {
        if (g_minstagib)
        {
-               minst_no_auto_cells = 1;
+               minst_no_auto_cells = TRUE;
                minstagib_items(IT_CELLS);
        }
        else
@@ -1427,19 +1729,21 @@ void spawnfunc_target_items (void)
                        else if(argv(i) == "jetpack")                self.items |= IT_JETPACK;
                        else if(argv(i) == "fuel_regen")             self.items |= IT_FUEL_REGEN;
                        else
-                       for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                        {
-                               e = get_weaponinfo(j);
-                               if(argv(i) == e.netname)
+                               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                                {
-                                       WEPSET_OR_EW(self, j);
-                                       if(self.spawnflags == 0 || self.spawnflags == 2)
-                                               weapon_action(e.weapon, WR_PRECACHE);
-                                       break;
+                                       e = get_weaponinfo(j);
+                                       if(argv(i) == e.netname)
+                                       {
+                                               WEPSET_OR_EW(self, j);
+                                               if(self.spawnflags == 0 || self.spawnflags == 2)
+                                                       weapon_action(e.weapon, WR_PRECACHE);
+                                               break;
+                                       }
                                }
+                               if(j > WEP_LAST)
+                                       print("target_items: invalid item ", argv(i), "\n");
                        }
-                       if(j > WEP_LAST)
-                               print("target_items: invalid item ", argv(i), "\n");
                }
 
                string itemprefix, valueprefix;
@@ -1868,3 +2172,4 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        return got;
 }
+#endif
index cce0aab32bb5f062ca66a853f2a7996dfafef5c4..8923c19f18300e1f742acd0586e61539744c3c15 100644 (file)
@@ -2,6 +2,7 @@ float PUSH_ONCE                 = 1;
 float PUSH_SILENT              = 2;
 
 .float pushltime;
+.float istypefrag;
 .float height;
 
 void() SUB_UseTargets;
@@ -213,6 +214,7 @@ void trigger_push_touch()
 
                // reset tracking of who pushed you into a hazard (for kill credit)
                other.pushltime = 0;
+               other.istypefrag = 0;
        }
 
        if(self.enemy.target)
@@ -286,7 +288,7 @@ void trigger_push_findtarget()
                else if(n == 1)
                {
                        // exactly one dest - bots love that
-                       self.enemy = find(e, targetname, self.target);
+                       self.enemy = find(world, targetname, self.target);
                }
                else
                {
index 1705d8f8ea705edc6f71d4c5490bb32cd5d40c76..25dc837f953a514ce0ad9918b02d6d0bec92adc2 100644 (file)
@@ -131,10 +131,12 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
                {
                        player.pusher = teleporter.owner;
                        player.pushltime = time + autocvar_g_maxpushtime;
+                       player.istypefrag = player.BUTTON_CHAT;
                }
                else
                {
                        player.pushltime = 0;
+                       player.istypefrag = 0;
                }
 
                player.lastteleporttime = time;
index 960e59d67492f8ddf5ad3959515d303932c9f043..c245a30a32995bc8f2a7560ebbc1a77ee504061a 100644 (file)
@@ -8,21 +8,6 @@ float cb1, cb2, cb3, cb4;
 
 float audit_teams_time;
 
-float IsTeamBalanceForced()
-{
-       if(intermission_running)
-               return 0; // no rebalancing whatsoever please
-       if(!teamplay)
-               return 0;
-       if(autocvar_g_campaign)
-               return 0;
-       if(autocvar_bot_vs_human && (c3==-1 && c4==-1))
-               return 0;
-       if(!autocvar_g_balance_teams_force)
-               return -1;
-       return 1;
-}
-
 void TeamchangeFrags(entity e)
 {
        PlayerScore_Clear(e);
@@ -228,6 +213,7 @@ void InitGameplayMode()
        {
                ActivateTeamplay();
                have_team_spawns = -1; // request team spawns
+               MUTATOR_ADD(gamemode_onslaught);
        }
 
        if(g_race)
@@ -462,6 +448,7 @@ void CheckAllowedTeams (entity for_whom)
        c1 = c2 = c3 = c4 = -1;
        cb1 = cb2 = cb3 = cb4 = 0;
 
+       teament_name = string_null;
        if(g_onslaught)
        {
                // onslaught is special
@@ -561,8 +548,6 @@ void CheckAllowedTeams (entity for_whom)
 
 float PlayerValue(entity p)
 {
-       if(IsTeamBalanceForced() == 1)
-               return 1;
        return 1;
        // FIXME: it always returns 1...
 }
@@ -642,11 +627,73 @@ void GetTeamCounts(entity ignore)
        }
 }
 
+float TeamSmallerEqThanTeam(float ta, float tb, entity e)
+{
+       // we assume that CheckAllowedTeams and GetTeamCounts have already been called
+       float f;
+       float ca = -1, cb = -1, cba = 0, cbb = 0, sa = 0, sb = 0;
+
+       switch(ta)
+       {
+               case 1: ca = c1; cba = cb1; sa = team1_score; break;
+               case 2: ca = c2; cba = cb2; sa = team2_score; break;
+               case 3: ca = c3; cba = cb3; sa = team3_score; break;
+               case 4: ca = c4; cba = cb4; sa = team4_score; break;
+       }
+       switch(tb)
+       {
+               case 1: cb = c1; cbb = cb1; sb = team1_score; break;
+               case 2: cb = c2; cbb = cb2; sb = team2_score; break;
+               case 3: cb = c3; cbb = cb3; sb = team3_score; break;
+               case 4: cb = c4; cbb = cb4; sb = team4_score; break;
+       }
+
+       // invalid
+       if(ca < 0 || cb < 0)
+               return FALSE;
+
+       // equal
+       if(ta == tb)
+               return TRUE;
+
+       if(clienttype(e) == CLIENTTYPE_REAL)
+       {
+               if(bots_would_leave)
+               {
+                       ca -= cba * 0.999;
+                       cb -= cbb * 0.999;
+               }
+       }
+       
+       // keep teams alive (teams of size 0 always count as smaller, ignoring score)
+       if(ca < 1)
+               if(cb >= 1)
+                       return TRUE;
+       if(ca >= 1)
+               if(cb < 1)
+                       return FALSE;
+
+       // first, normalize
+       f = max(ca, cb, 1);
+       ca /= f;
+       cb /= f;
+       f = max(sa, sb, 1);
+       sa /= f;
+       sb /= f;
+
+       // the more we're at the end of the match, the more take scores into account
+       f = bound(0, game_completion_ratio * autocvar_g_balance_teams_scorefactor, 1);
+       ca += (sa - ca) * f;
+       cb += (sb - cb) * f;
+
+       return ca <= cb;
+}
+
 // returns # of smallest team (1, 2, 3, 4)
 // NOTE: Assumes CheckAllowedTeams has already been called!
 float FindSmallestTeam(entity pl, float ignore_pl)
 {
-       float totalteams, balance_type, maxc;
+       float totalteams, t;
        totalteams = 0;
 
        // find out what teams are available
@@ -687,49 +734,26 @@ float FindSmallestTeam(entity pl, float ignore_pl)
        else
                GetTeamCounts(world);
 
-       // c1...c4 now have counts of each team
-       // figure out which is smallest, giving priority to the team the player is already on as a tie-breaker
-
-       // 2 gives priority to what team you're already on, 1 goes in order
-       // 2 doesn't seem to work though...
-       balance_type = 1;
-
-       if(bots_would_leave)
-       //if(pl.classname != "player")
-       if(clienttype(pl) != CLIENTTYPE_BOT)
-       {
-               c1 -= cb1 * 255.0/256.0;
-               c2 -= cb2 * 255.0/256.0;
-               c3 -= cb3 * 255.0/256.0;
-               c4 -= cb4 * 255.0/256.0;
-       }
-       maxc = max4(c1, c2, c3, c4);
-
        RandomSelection_Init();
-       if(balance_type == 1)
-       {
-               // 1: use team count, then score (note: can only use 8 significant bits of score)
-               if(c1 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + float2range01(-team1_score) / 256.0);
-               if(c2 >= 0) RandomSelection_Add(world, 2, string_null, 1, (maxc - c2) + float2range01(-team2_score) / 256.0);
-               if(c3 >= 0) RandomSelection_Add(world, 3, string_null, 1, (maxc - c3) + float2range01(-team3_score) / 256.0);
-               if(c4 >= 0) RandomSelection_Add(world, 4, string_null, 1, (maxc - c4) + float2range01(-team4_score) / 256.0);
-       }
-       else if(balance_type == 2)
-       {
-               // 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, 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)
-       {
-               // 1: use team count, then score, if equal prefer own team (probably fails due to float accuracy problems)
-               if(c1 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + float2range01(-team1_score + 0.5 * (self.team == COLOR_TEAM1)) / 256.0);
-               if(c2 >= 0) RandomSelection_Add(world, 2, string_null, 1, (maxc - c2) + float2range01(-team2_score + 0.5 * (self.team == COLOR_TEAM2)) / 256.0);
-               if(c3 >= 0) RandomSelection_Add(world, 3, string_null, 1, (maxc - c3) + float2range01(-team3_score + 0.5 * (self.team == COLOR_TEAM3)) / 256.0);
-               if(c4 >= 0) RandomSelection_Add(world, 4, string_null, 1, (maxc - c4) + float2range01(-team4_score + 0.5 * (self.team == COLOR_TEAM4)) / 256.0);
-       }
+       
+       t = 1;
+       if(TeamSmallerEqThanTeam(2, t, pl))
+               t = 2;
+       if(TeamSmallerEqThanTeam(3, t, pl))
+               t = 3;
+       if(TeamSmallerEqThanTeam(4, t, pl))
+               t = 4;
+
+       // now t is the minimum, or A minimum!
+       if(t == 1 || TeamSmallerEqThanTeam(1, t, pl))
+               RandomSelection_Add(world, 1, string_null, 1, 1);
+       if(t == 2 || TeamSmallerEqThanTeam(2, t, pl))
+               RandomSelection_Add(world, 2, string_null, 1, 1);
+       if(t == 3 || TeamSmallerEqThanTeam(3, t, pl))
+               RandomSelection_Add(world, 3, string_null, 1, 1);
+       if(t == 4 || TeamSmallerEqThanTeam(4, t, pl))
+               RandomSelection_Add(world, 4, string_null, 1, 1);
+
        return RandomSelection_chosen_float;
 }
 
@@ -860,62 +884,15 @@ void SV_ChangeTeam(float _color)
                return; // changing teams is not allowed
        }
 
-       if(autocvar_g_balance_teams_prevent_imbalance)
+       // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
+       if(autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance)
        {
-               // only allow changing to a smaller or equal size team
-
-               // find out what teams are available
-               //CheckAllowedTeams();
-               // count how many players on each team
-               GetTeamCounts(world);
-
-               // get desired team
-               if(dteam == 1 && c1 >= 0)//dcolor == COLOR_TEAM1 - 1)
+               GetTeamCounts(self);
+               if(!TeamSmallerEqThanTeam(dteam, steam, self))
                {
-                       dcount = c1;
-                       dbotcount = cb1;
-               }
-               else if(dteam == 2 && c2 >= 0)//dcolor == COLOR_TEAM2 - 1)
-               {
-                       dcount = c2;
-                       dbotcount = cb2;
-               }
-               else if(dteam == 3 && c3 >= 0)//dcolor == COLOR_TEAM3 - 1)
-               {
-                       dcount = c3;
-                       dbotcount = cb3;
-               }
-               else if(dteam == 4 && c4 >= 0)//dcolor == COLOR_TEAM4 - 1)
-               {
-                       dcount = c4;
-                       dbotcount = cb4;
-               }
-               else
-               {
-                       sprint(self, "Cannot change to an invalid team\n");
-
+                       sprint(self, "Cannot change to a larger/better/shinier team\n");
                        return;
                }
-
-               // get starting team
-               if(steam == 1)//scolor == COLOR_TEAM1 - 1)
-                       scount = c1;
-               else if(steam == 2)//scolor == COLOR_TEAM2 - 1)
-                       scount = c2;
-               else if(steam == 3)//scolor == COLOR_TEAM3 - 1)
-                       scount = c3;
-               else if(steam == 4)//scolor == COLOR_TEAM4 - 1)
-                       scount = c4;
-
-               if(scount) // started at a valid, nonempty team
-               {
-                       // check if we're trying to change to a larger team that doens't have bots to swap with
-                       if(dcount >= scount && dbotcount <= 0)
-                       {
-                               sprint(self, "Cannot change to a larger team\n");
-                               return; // can't change to a larger team
-                       }
-               }
        }
 
 //     bprint("allow change teams from ", ftos(steam), " to ", ftos(dteam), "\n");
@@ -979,7 +956,7 @@ void ShufflePlayerOutOfTeam (float source_team)
                steam = COLOR_TEAM2;
        else if(source_team == 3)
                steam = COLOR_TEAM3;
-       else if(source_team == 4)
+       else // if(source_team == 4)
                steam = COLOR_TEAM4;
 
        lowest_bot = world;
@@ -1078,87 +1055,6 @@ void ShufflePlayerOutOfTeam (float source_team)
        centerprint(selected, strcat("You have been moved into a different team to improve team balance\nYou are now on: ", ColoredTeamName(selected.team)));
 }
 
-void CauseRebalance(float source_team, float howmany_toomany)
-{
-       if(IsTeamBalanceForced() == 1)
-       {
-               bprint("Rebalancing Teams\n");
-               ShufflePlayerOutOfTeam(source_team);
-       }
-}
-
-// part of g_balance_teams_force
-// occasionally perform an audit of the teams to make
-// sure they're more or less balanced in player count.
-void AuditTeams()
-{
-       float numplayers, numteams, smallest, toomany;
-       float balance;
-       balance = IsTeamBalanceForced();
-       if(balance == 0)
-               return;
-
-       if(audit_teams_time > time)
-               return;
-
-       audit_teams_time = time + 4 + random();
-
-//     bprint("Auditing teams\n");
-
-       CheckAllowedTeams(world);
-       GetTeamCounts(world);
-
-
-       numteams = numplayers = smallest = 0;
-       if(c1 >= 0)
-       {
-               numteams = numteams + 1;
-               numplayers = numplayers + c1;
-               smallest = c1;
-       }
-       if(c2 >= 0)
-       {
-               numteams = numteams + 1;
-               numplayers = numplayers + c2;
-               if(c2 < smallest)
-                       smallest = c2;
-       }
-       if(c3 >= 0)
-       {
-               numteams = numteams + 1;
-               numplayers = numplayers + c3;
-               if(c3 < smallest)
-                       smallest = c3;
-       }
-       if(c4 >= 0)
-       {
-               numteams = numteams + 1;
-               numplayers = numplayers + c4;
-               if(c4 < smallest)
-                       smallest = c4;
-       }
-
-       if(numplayers <= 0)
-               return; // no players to move around
-       if(numteams < 2)
-               return; // don't bother shuffling if for some reason there aren't any teams
-
-       toomany = smallest + 1;
-
-       if(c1 && c1 > toomany)
-               CauseRebalance(1, c1 - toomany);
-       if(c2 && c2 > toomany)
-               CauseRebalance(2, c2 - toomany);
-       if(c3 && c3 > toomany)
-               CauseRebalance(3, c3 - toomany);
-       if(c4 && c4 > toomany)
-               CauseRebalance(4, c4 - toomany);
-
-       // if teams are still unbalanced, balance them further in the next audit,
-       // which will happen sooner (keep doing rapid audits until things are in order)
-       audit_teams_time = time + 0.7 + random()*0.3;
-}
-
 // code from here on is just to support maps that don't have team entities
 void tdm_spawnteam (string teamname, float teamcolor)
 {
index 7247a3a3476816e6c116019903975c4e48365661..c8bbf537c336ba548310dc896b9680ac41e21f20 100644 (file)
@@ -726,7 +726,7 @@ entity turret_select_target()
         m_score = self.turret_score_target(self,e_enemy) * self.target_select_samebias;
     }
     else
-        self.enemy = world;
+        e_enemy = self.enemy = world;
 
     e = findradius(self.origin, self.target_range);
 
index 1c0a3bad5269ef4552a0b71686b6a8c0d44c6599..5a94b442343832f8ebceef28639d72cd9e277ae0 100644 (file)
@@ -60,7 +60,7 @@ vector shortangle_vxy(vector ang1, vector ang2)
 vector real_origin(entity ent)
 {
     entity e;
-    vector v;
+    vector v = ((ent.absmin + ent.absmax) * 0.5);
 
     e = ent.tag_entity;
     while(e)
@@ -68,7 +68,7 @@ vector real_origin(entity ent)
         v = v + ((e.absmin + e.absmax) * 0.5);
         e = e.tag_entity;
     }
-    v = v + ((ent.absmin + ent.absmax) * 0.5);
+
     return v;
 }
 
index 6b8f8e7d4cbadaa337953dee17dc4f5cacaa7349..767c346620547b0dd565f58f093f46b675b1f8f8 100644 (file)
@@ -7,12 +7,15 @@
 void ewheel_attack()
 {
     float i;
-
+    entity _mis;
+    
     for (i = 0; i < 1; ++i)
     {
         turret_do_updates(self);
 
-        turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE);    
+        _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE); 
+        _mis.missile_flags = MIF_SPLASH;
+
         pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
 
         self.tur_head.frame += 2;
index 975abbd4c928254ec566a3d8858df8ad67b3f28a..7c21ba7abef9e0bdea8535d6b805167fc3f50953 100644 (file)
@@ -29,7 +29,8 @@ void turret_flac_attack()
     pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
     proj.think      = turret_flac_projectile_think_explode;
     proj.nextthink  = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
-
+    proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+    
     self.tur_head.frame = self.tur_head.frame + 1;
     if (self.tur_head.frame >= 4) 
         self.tur_head.frame = 0;
index 08bfad2a611e71546139ce17ff9beee69f02b62d..75360bcd7142bf7af73518c7226f42ba217bb375 100644 (file)
@@ -79,6 +79,7 @@ void turret_hellion_attack()
     missile.flags        = FL_PROJECTILE;
     missile.tur_health   = time + 9;
     missile.tur_aimpos   = randomvec() * 128;
+    missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
        self.tur_head.frame += 1;
 }
 
index d61289dcbe62e50a458c92f482c30cd5ba0ec0de..8676091f583aaaebf708b814ec7b415f7a9e8b17 100644 (file)
@@ -108,6 +108,8 @@ void turret_hk_missile_think()
     }
     else
     {
+       edist = 0;
+       ve = '0 0 0';
         fe = 0;
     }
 
@@ -255,7 +257,8 @@ void turret_hk_attack()
     missile.angles           = vectoangles(missile.velocity);
     missile.cnt              = time + 30;
     missile.ticrate          = max(autocvar_sys_ticrate, 0.05);
-
+    missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
+    
     if (self.tur_head.frame == 0)
         self.tur_head.frame = self.tur_head.frame + 1;
 
index 65c0ed058500873456c5b7b4c443b062b85e295b..a12d9d7259f6b8c1cc5a3aa610768d4d7b499173 100644 (file)
@@ -20,6 +20,7 @@ void turret_mlrs_attack()
     turret_tag_fire_update();    
     missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
     missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
+    missile.missile_flags = MIF_SPLASH;
     te_explosion (missile.origin);    
 }
 
index d5abf654be6a8c0f9c9d453d5cb44ea005f3108c..aacca522ec9a1d63c05ac5a042da69ab7e2614fc 100644 (file)
@@ -27,7 +27,9 @@ void turret_plasma_dual_postthink()
 
 void turret_plasma_attack()
 { 
-    turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);    
+    entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);    
+    missile.missile_flags = MIF_SPLASH;
+    
     pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
     if (self.tur_head.frame == 0)
         self.tur_head.frame = 1;
@@ -35,7 +37,8 @@ void turret_plasma_attack()
 
 void turret_plasma_dual_attack()
 {
-    turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);    
+    entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE); 
+    missile.missile_flags = MIF_SPLASH;   
     pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
     self.tur_head.frame += 1;
 }
index 6c2cce6a73341ad4d3b80fcd25a19233b269b688..85fb8bb18205bb367dd194b7e800ea9499d1c554 100644 (file)
@@ -5,7 +5,7 @@ void turret_tesla_fire();
 entity toast(entity from, float range, float damage)
 {
     entity e;
-    entity etarget;
+    entity etarget = world;
     float d,dd;
     float r;
 
index 646fccccb2b8ab7e57751e40e6f26c76e9fdcbc8..f47003f4bb19d0d581ed529e8d4c71246dba2a28 100644 (file)
@@ -199,7 +199,7 @@ void walker_fire_rocket(vector org)
     rocket.tur_shotorg        = randomvec() * 512;
     rocket.cnt                = time + 1;
     rocket.enemy              = self.enemy;
-
+    
     if (random() < 0.01)
         rocket.think          = walker_rocket_loop;
     else
@@ -215,7 +215,8 @@ void walker_fire_rocket(vector org)
     rocket.flags              = FL_PROJECTILE;
     rocket.solid              = SOLID_BBOX;
     rocket.tur_health         = time + 9;
-
+    rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+    
     CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
 }
 
diff --git a/qcsrc/server/vehicles/bumblebee.qc b/qcsrc/server/vehicles/bumblebee.qc
new file mode 100644 (file)
index 0000000..0f98412
--- /dev/null
@@ -0,0 +1,1099 @@
+#define BRG_SETUP 2
+#define BRG_START 4
+#define BRG_END 8
+
+#ifdef SVQC
+// Auto cvars
+float autocvar_g_vehicle_bumblebee_speed_forward;
+float autocvar_g_vehicle_bumblebee_speed_strafe;
+float autocvar_g_vehicle_bumblebee_speed_up;
+float autocvar_g_vehicle_bumblebee_speed_down;
+float autocvar_g_vehicle_bumblebee_turnspeed;
+float autocvar_g_vehicle_bumblebee_pitchspeed;
+float autocvar_g_vehicle_bumblebee_pitchlimit;
+float autocvar_g_vehicle_bumblebee_friction;
+
+float autocvar_g_vehicle_bumblebee_energy;
+float autocvar_g_vehicle_bumblebee_energy_regen;
+float autocvar_g_vehicle_bumblebee_energy_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_health;
+float autocvar_g_vehicle_bumblebee_health_regen;
+float autocvar_g_vehicle_bumblebee_health_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_shield;
+float autocvar_g_vehicle_bumblebee_shield_regen;
+float autocvar_g_vehicle_bumblebee_shield_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_cannon_cost;
+float autocvar_g_vehicle_bumblebee_cannon_damage;
+float autocvar_g_vehicle_bumblebee_cannon_radius;
+float autocvar_g_vehicle_bumblebee_cannon_refire;
+float autocvar_g_vehicle_bumblebee_cannon_speed;
+float autocvar_g_vehicle_bumblebee_cannon_spread;
+float autocvar_g_vehicle_bumblebee_cannon_force;
+
+float autocvar_g_vehicle_bumblebee_cannon_ammo;
+float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
+float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
+
+var float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
+
+float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+
+
+float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
+float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
+
+float autocvar_g_vehicle_bumblebee_raygun_range;
+float autocvar_g_vehicle_bumblebee_raygun_dps;
+float autocvar_g_vehicle_bumblebee_raygun_aps;
+float autocvar_g_vehicle_bumblebee_raygun_fps;
+
+float autocvar_g_vehicle_bumblebee_raygun;
+float autocvar_g_vehicle_bumblebee_healgun_hps;
+float autocvar_g_vehicle_bumblebee_healgun_hmax;
+float autocvar_g_vehicle_bumblebee_healgun_aps;
+float autocvar_g_vehicle_bumblebee_healgun_amax;
+float autocvar_g_vehicle_bumblebee_healgun_sps;
+float autocvar_g_vehicle_bumblebee_healgun_locktime;
+
+float autocvar_g_vehicle_bumblebee_respawntime;
+
+float autocvar_g_vehicle_bumblebee_blowup_radius;
+float autocvar_g_vehicle_bumblebee_blowup_coredamage;
+float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
+float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
+var vector autocvar_g_vehicle_bumblebee_bouncepain;
+
+var float autocvar_g_vehicle_bumblebee = 0;
+
+
+float bumble_raygun_send(entity to, float sf);
+
+#define BUMB_MIN '-130 -130 -130'
+#define BUMB_MAX '130 130 130'
+
+void bumb_fire_cannon(entity _gun, string _tagname, entity _owner)
+{
+       vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
+       vehicles_projectile("bigplasma_muzzleflash", "weapons/flacexp3.wav",
+                                               v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
+                                               autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force,  0,
+                                               DEATH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, TRUE, TRUE, _owner);
+}
+
+float bumb_gunner_frame()
+{
+       entity vehic    = self.vehicle.owner;
+       entity gun      = self.vehicle;
+       entity gunner   = self;
+       self = vehic;
+
+
+       
+       
+       vehic.solid = SOLID_NOT;
+       //setorigin(gunner, vehic.origin);
+       gunner.velocity = vehic.velocity;
+       
+       float _in, _out;
+       vehic.angles_x *= -1;
+       makevectors(vehic.angles);
+       vehic.angles_x *= -1;
+       if((gun == vehic.gun1))
+       {
+               _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+               _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+               setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
+       }
+       else
+       {
+               _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+               _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+               setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);                
+       }
+       
+       crosshair_trace(gunner);
+       vector _ct = trace_endpos;
+       vector ad;
+
+       if(autocvar_g_vehicle_bumblebee_cannon_lock)
+       {
+               if(gun.lock_time < time)
+                       gun.enemy = world;
+
+               if(trace_ent)
+                       if(trace_ent.movetype)
+                               if(trace_ent.takedamage)
+                                       if(!trace_ent.deadflag)
+                                       {
+                                               if(teamplay)
+                                               {
+                                                       if(trace_ent.team != gunner.team)
+                                                       {
+                                                               gun.enemy = trace_ent;
+                                                               gun.lock_time = time + 5;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       gun.enemy = trace_ent;
+                                                       gun.lock_time = time + 5;
+                                               }
+                                       }
+       }
+
+       if(gun.enemy)
+       {
+               float i, distance, impact_time;
+
+               vector vf = real_origin(gun.enemy);
+               vector _vel = gun.enemy.velocity;
+               if(gun.enemy.movetype == MOVETYPE_WALK)
+                       _vel_z *= 0.1;
+
+
+               ad = vf;
+               for(i = 0; i < 4; ++i)
+               {
+                       distance = vlen(ad - gunner.origin);
+                       impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
+                       ad = vf + _vel * impact_time;
+               }
+               trace_endpos = ad;
+
+
+               UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
+               vehicle_aimturret(vehic, trace_endpos, gun, "fire",
+                                                 autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
+                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+
+       }
+       else
+               vehicle_aimturret(vehic, _ct, gun, "fire",
+                                                 autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
+                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+
+       if(gunner.BUTTON_ATCK)
+               if(time > gun.attack_finished_single)
+                       if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
+                       {
+                               gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
+                               bumb_fire_cannon(gun, "fire", gunner);
+                               gun.delay = time;
+                               gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
+                       }
+
+       VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
+
+       if(vehic.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
+
+       ad = gettaginfo(gun, gettagindex(gun, "fire"));
+       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
+
+       UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
+
+       if(vehic.owner)
+               UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
+
+       vehic.solid = SOLID_BBOX;
+       gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
+       gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+
+       self = gunner;
+       return 1;
+}
+
+void bumb_gunner_exit(float _exitflag)
+{
+
+
+       if(clienttype(self) == CLIENTTYPE_REAL)
+       {
+               msg_entity = self;
+               WriteByte(MSG_ONE, SVC_SETVIEWPORT);
+               WriteEntity(MSG_ONE, self);
+
+               WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
+               WriteAngle(MSG_ONE, 0);
+               WriteAngle(MSG_ONE, self.vehicle.angles_y);
+               WriteAngle(MSG_ONE, 0);
+       }
+       
+       CSQCVehicleSetup(self, HUD_NORMAL);
+       setsize(self, PL_MIN, PL_MAX);
+
+       self.takedamage     = DAMAGE_AIM;
+       self.solid          = SOLID_SLIDEBOX;
+       self.movetype       = MOVETYPE_WALK;
+       self.effects        &~= EF_NODRAW;
+       self.alpha          = 1;
+       self.PlayerPhysplug = SUB_Null;
+       self.view_ofs       = PL_VIEW_OFS;
+       self.event_damage   = PlayerDamage;
+       self.hud            = HUD_NORMAL;
+       self.switchweapon   = self.vehicle.switchweapon;
+
+       if(self.flagcarried)
+       {
+               self.flagcarried.scale = 0.6;
+               setattachment(self.flagcarried, self, "");
+               setorigin(self.flagcarried, FLAG_CARRY_POS);
+       }
+
+       self.vehicle.vehicle_hudmodel.viewmodelforclient = self.vehicle;
+
+       fixedmakevectors(self.vehicle.owner.angles);
+
+       if(self == self.vehicle.owner.gunner1)
+       {
+               self.vehicle.owner.gunner1 = world;             
+       }
+       else if(self == self.vehicle.owner.gunner2)
+       {
+               self.vehicle.owner.gunner2 = world;     
+               v_right *= -1;
+       }       
+       else
+               dprint("^1self != gunner1 or gunner2, this is a BIG PROBLEM, tell tZork this happend.\n");
+               
+       vector spot = self.vehicle.owner.origin + + v_up * 128 + v_right * 300;
+       spot = vehicles_findgoodexit(spot);
+       //setorigin(self , spot);
+
+       self.velocity = 0.75 * self.vehicle.owner.velocity + normalize(spot - self.vehicle.owner.origin) * 200;
+       self.velocity_z += 10;
+
+       self.vehicle.phase = time + 5;
+       self.vehicle        = world;
+}
+
+float bumb_gunner_enter()
+{
+       RemoveGrapplingHook(other);
+       entity _gun, _gunner;
+       if(!self.gunner1)
+       {
+               _gun = self.gun1;
+               _gunner = self.gunner1;
+               self.gunner1 = other;
+       }
+       else if(!self.gunner2)
+       {
+               _gun = self.gun2;
+               _gunner = self.gunner2;
+               self.gunner2 = other;
+       }
+       else
+       {
+               dprint("^1ERROR:^7Tried to enter a fully occupied vehicle!\n");
+               return FALSE;
+       }
+
+       _gunner            = other;
+       _gunner.vehicle    = _gun;
+       _gun.switchweapon  = other.switchweapon;
+       _gun.vehicle_exit  = bumb_gunner_exit;
+
+       other.angles            = self.angles;
+       other.takedamage        = DAMAGE_NO;
+       other.solid             = SOLID_NOT;
+       other.movetype          = MOVETYPE_NOCLIP;
+       other.alpha             = -1;
+       other.event_damage      = SUB_Null;
+       other.view_ofs          = '0 0 0';
+       other.hud               = _gun.hud;
+       other.PlayerPhysplug    = _gun.PlayerPhysplug;
+       other.vehicle_ammo1     = self.vehicle_ammo1;
+       other.vehicle_ammo2     = self.vehicle_ammo2;
+       other.vehicle_reload1   = self.vehicle_reload1;
+       other.vehicle_reload2   = self.vehicle_reload2;
+       other.vehicle_energy    = self.vehicle_energy;
+       other.PlayerPhysplug    = bumb_gunner_frame;
+       other.flags             &~= FL_ONGROUND;
+
+       msg_entity = other;
+       WriteByte(MSG_ONE, SVC_SETVIEWPORT);
+       WriteEntity(MSG_ONE, _gun.vehicle_viewport);
+       WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
+       WriteAngle(MSG_ONE, _gun.angles_x + self.angles_x);    // tilt
+       WriteAngle(MSG_ONE, _gun.angles_y + self.angles_y);    // yaw
+       WriteAngle(MSG_ONE, 0);                             // roll
+       _gun.vehicle_hudmodel.viewmodelforclient = other;
+
+       CSQCVehicleSetup(other, other.hud);
+       
+    if(other.flagcarried)
+    {
+        if(!autocvar_g_vehicles_allow_flagcarry)
+            DropFlag(other.flagcarried, world, world);
+        else
+        {
+            other.flagcarried.scale = 1;
+            setattachment(other.flagcarried, self, "");
+            setorigin(other.flagcarried, '0 0 1' * self.maxs_z);
+        }
+    }
+
+       return TRUE;
+}
+
+float vehicles_valid_pilot()
+{
+       if(other.classname != "player")
+               return FALSE;
+
+       if(other.deadflag != DEAD_NO)
+               return FALSE;
+
+       if(other.vehicle != world)
+               return FALSE;
+
+       if(clienttype(other) != CLIENTTYPE_REAL)
+               if(!autocvar_g_vehicles_allow_bots)
+                       return FALSE;
+
+       if(teamplay && other.team != self.team)
+               return FALSE;
+
+       return TRUE;
+}
+
+void bumb_touch()
+{
+
+       if(self.gunner1 != world && self.gunner2 != world)
+       {
+               vehicles_touch();
+               return;
+       }
+
+       if(vehicles_valid_pilot())
+       {
+               if(self.gun1.phase <= time)
+                       if(bumb_gunner_enter())
+                               return;
+
+               if(self.gun2.phase <= time)
+                       if(bumb_gunner_enter())
+                               return;
+       }
+
+       vehicles_touch();
+}
+
+void bumb_regen()
+{
+       if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
+               self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
+                                                                          self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+
+       if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
+               self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
+                                                                          self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+
+       if(self.vehicle_flags  & VHF_SHIELDREGEN)
+               vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, TRUE);
+
+       if(self.vehicle_flags  & VHF_HEALTHREGEN)
+               vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, FALSE);
+
+       if(self.vehicle_flags  & VHF_ENERGYREGEN)
+               vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, FALSE);
+
+}
+
+float bumb_pilot_frame()
+{
+       entity pilot, vehic;
+       vector newvel;
+
+       pilot = self;
+       vehic = self.vehicle;
+       self   = vehic;
+
+
+       if(vehic.deadflag != DEAD_NO)
+       {
+               self = pilot;
+               pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
+               return 1;
+       }
+
+       bumb_regen();
+
+       crosshair_trace(pilot);
+
+       vector vang;
+       float ftmp;
+
+       vang = vehic.angles;
+       newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+       vang_x *= -1;
+       newvel_x *= -1;
+       if(newvel_x > 180)  newvel_x -= 360;
+       if(newvel_x < -180) newvel_x += 360;
+       if(newvel_y > 180)  newvel_y -= 360;
+       if(newvel_y < -180) newvel_y += 360;
+
+       ftmp = shortangle_f(pilot.v_angle_y - vang_y, vang_y);
+       if(ftmp > 180)  ftmp -= 360;
+       if(ftmp < -180) ftmp += 360;
+       vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity_y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
+
+       // Pitch
+       ftmp = 0;
+       if(pilot.movement_x > 0 && vang_x < autocvar_g_vehicle_bumblebee_pitchlimit) 
+               ftmp = 4;
+       else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit) 
+               ftmp = -8;
+
+       newvel_x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x , autocvar_g_vehicle_bumblebee_pitchlimit);
+       ftmp = vang_x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
+       vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity_x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
+
+       vehic.angles_x = anglemods(vehic.angles_x);
+       vehic.angles_y = anglemods(vehic.angles_y);
+       vehic.angles_z = anglemods(vehic.angles_z);
+
+       makevectors('0 1 0' * vehic.angles_y);
+       newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
+
+       if(pilot.movement_x != 0)
+       {
+               if(pilot.movement_x > 0)
+                       newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
+               else if(pilot.movement_x < 0)
+                       newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
+       }
+
+       if(pilot.movement_y != 0)
+       {
+               if(pilot.movement_y < 0)
+                       newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+               else if(pilot.movement_y > 0)
+                       newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+               ftmp = newvel * v_right;
+               ftmp *= frametime * 0.1;
+               vehic.angles_z = bound(-15, vehic.angles_z + ftmp, 15);
+       }
+       else
+       {
+               vehic.angles_z *= 0.95;
+               if(vehic.angles_z >= -1 && vehic.angles_z <= -1)
+                       vehic.angles_z = 0;
+       }
+
+       if(pilot.BUTTON_CROUCH)
+               newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
+       else if(pilot.BUTTON_JUMP)
+               newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
+
+       vehic.velocity  += newvel * frametime;
+       pilot.velocity = pilot.movement  = vehic.velocity;
+       
+
+       if(autocvar_g_vehicle_bumblebee_healgun_locktime)
+       {               
+               if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
+                       vehic.tur_head.enemy = world;
+
+               if(trace_ent)
+               if(trace_ent.movetype)
+               if(trace_ent.takedamage)
+               if(!trace_ent.deadflag)
+               {
+                       if(teamplay)
+                       {
+                               if(trace_ent.team == pilot.team)
+                               {
+                                       vehic.tur_head.enemy = trace_ent;
+                                       vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
+                               }
+                       }
+                       else
+                       {            
+                               vehic.tur_head.enemy = trace_ent;
+                               vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
+                       }
+               }
+                       
+               if(vehic.tur_head.enemy)
+               {
+                       trace_endpos = real_origin(vehic.tur_head.enemy);                       
+                       UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);               
+               }
+       }
+       
+       vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
+                                         autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1,  autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
+                                         autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
+
+       if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
+       {
+               vehic.gun3.enemy.realowner = pilot;
+               vehic.gun3.enemy.effects &~= EF_NODRAW;
+               
+               vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
+               vehic.gun3.enemy.SendFlags |= BRG_START;
+               
+               traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
+               
+               if(trace_ent)
+               {
+                       if(autocvar_g_vehicle_bumblebee_raygun)
+                       {
+                               Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
+                               vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
+                       }
+                       else
+                       {
+                               if(trace_ent.deadflag == DEAD_NO)
+                                       if((teamplay && trace_ent.team == pilot.team) || !teamplay)
+                                       {
+
+                                               if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
+                                               {
+                                                       if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.tur_health)
+                                                               trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.tur_health);
+
+                                                       if(autocvar_g_vehicle_bumblebee_healgun_hps)
+                                                               trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.tur_health);
+                                               }
+                                               else if(trace_ent.flags & FL_CLIENT)
+                                               {
+                                                       if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps)
+                                                               trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
+
+                                                       if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps)
+                                                               trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax);
+
+                                                       trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
+                                               }
+                                               else if(trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+                                               {
+                                                       if(trace_ent.health  <= trace_ent.tur_health && autocvar_g_vehicle_bumblebee_healgun_hps)
+                                                               trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.tur_health);
+                                                       //else ..hmmm what? ammo?
+
+                                                       trace_ent.SendFlags |= TNSF_STATUS;
+                                               }
+                                       }
+                       }
+               }
+               
+               vehic.gun3.enemy.hook_end = trace_endpos;
+               setorigin(vehic.gun3.enemy, trace_endpos);
+               vehic.gun3.enemy.SendFlags |= BRG_END;
+               
+               vehic.wait = time + 1;
+       }
+       else
+               vehic.gun3.enemy.effects |= EF_NODRAW;
+       /*{
+               if(vehic.gun3.enemy)
+                       remove(vehic.gun3.enemy);
+
+               vehic.gun3.enemy = world;
+       }
+       */
+       
+       VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
+       VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
+
+       pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+       pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+
+       if(vehic.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
+               
+       vehic.angles_x *= -1;
+       makevectors(vehic.angles);
+       vehic.angles_x *= -1;
+       setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
+
+       pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
+       self = pilot;
+
+       return 1;
+}
+
+void bumb_think()
+{
+       self.movetype = MOVETYPE_TOSS;
+               
+               //self.velocity = self.velocity * 0.5;
+       self.angles_z *= 0.8;
+       self.angles_x *= 0.8;
+       
+       self.nextthink = time + 0.05;
+       
+       if(!self.owner)
+       {
+               entity oldself = self;          
+               if(self.gunner1)
+               {
+                       self = self.gunner1;
+                       oldself.gun1.vehicle_exit(VHEF_EJECT);
+                       entity oldother = other;
+                       other = self;
+                       self = oldself;
+                       self.phase = 0;
+                       self.touch();
+                       other = oldother;
+                       return;
+               }
+               
+               if(self.gunner2)
+               {
+                       self = self.gunner2;
+                       oldself.gun2.vehicle_exit(VHEF_EJECT);
+                       entity oldother = other;
+                       other = self;
+                       self = oldself;
+                       self.phase = 0;
+                       self.touch();
+                       other = oldother;
+                       return;
+               }               
+       }
+       
+}
+
+void bumb_enter()
+{
+       self.touch = bumb_touch;
+       self.nextthink = 0;
+       self.movetype = MOVETYPE_BOUNCEMISSILE;
+       //setattachment(self.owner, self.vehicle_viewport, "");
+}
+
+void bumb_exit(float eject)
+{
+       self.touch = vehicles_touch;
+       self.think = bumb_think;
+       self.nextthink = time;
+       
+       if(!self.owner)
+               return;
+       
+       fixedmakevectors(self.angles);
+       vector spot;
+       if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)              
+               spot = self.origin + v_up * 128 + v_forward * 200;
+       else
+               spot = self.origin + v_up * 128 - v_forward * 200;
+       
+       spot = vehicles_findgoodexit(spot);
+       
+
+       self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
+       self.owner.velocity_z += 10;
+       setorigin(self.owner, spot);
+
+       /*if(eject)
+       {
+           spot = self.origin + v_forward * 100 + '0 0 64';
+           spot = vehicles_findgoodexit(spot);
+           //setorigin(self.owner , spot);
+           self.owner.velocity = (v_up + v_forward * 0.25) * 250;
+           self.owner.oldvelocity = self.owner.velocity;
+       }
+       else
+       {
+               if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)              
+               {
+                       if(vlen(self.velocity) > autocvar_sv_maxairspeed)
+                               self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed;
+                       else
+                               self.owner.velocity = self.velocity + v_forward * 100;
+                       
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 128 + '0 0 32';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin - v_forward * 300 + '0 0 32';
+                       spot = vehicles_findgoodexit(spot);
+               }
+           self.owner.oldvelocity = self.owner.velocity;
+           //setorigin(self.owner , spot);
+       }
+       */
+       
+       antilag_clear(self.owner);
+    self.owner = world;
+}
+
+void bumb_blowup()
+{
+       RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
+                                autocvar_g_vehicle_bumblebee_blowup_edgedamage,
+                                autocvar_g_vehicle_bumblebee_blowup_radius, self,
+                                autocvar_g_vehicle_bumblebee_blowup_forceintensity,
+                                DEATH_WAKIBLOWUP, world);
+
+       sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+       pointparticles(particleeffectnum("explosion_large"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+       
+       if(self.owner.deadflag == DEAD_DYING)
+               self.owner.deadflag = DEAD_DEAD;
+       
+       remove(self);
+}
+
+void bumb_diethink()
+{
+       if(time >= self.wait)
+               self.think = bumb_blowup;
+
+       if(random() < 0.1)
+       {
+               sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+               pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+       }
+
+       self.nextthink = time + 0.1;
+}
+
+void bumb_die()
+{
+       entity oldself = self;
+       
+       // Hide beam
+       if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
+               self.gun3.enemy.effects |= EF_NODRAW;
+       
+       if(self.gunner1)
+       {
+               self = self.gunner1;
+               oldself.gun1.vehicle_exit(VHEF_EJECT);
+               self = oldself;
+       }
+
+       if(self.gunner2)
+       {
+               self = self.gunner2;
+               oldself.gun2.vehicle_exit(VHEF_EJECT);
+               self = oldself;
+       }
+
+       self.vehicle_exit(VHEF_EJECT);
+
+       fixedmakevectors(self.angles);
+       vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
+       vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
+       vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
+
+       entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
+
+       if(random() > 0.5)
+               _body.touch = bumb_blowup;
+       else
+               _body.touch = SUB_Null;
+               
+       _body.think = bumb_diethink;
+       _body.nextthink = time;
+       _body.wait = time + 2 + (random() * 8);
+       _body.owner = self;
+       _body.enemy = self.enemy;
+       
+       pointparticles(particleeffectnum("explosion_medium"), findbetterlocation(self.origin, 16), '0 0 0', 1);
+       
+       self.health                     = 0;
+       self.event_damage       = SUB_Null;
+       self.solid                      = SOLID_CORPSE;
+       self.takedamage         = DAMAGE_NO;
+       self.deadflag           = DEAD_DYING;
+       self.movetype           = MOVETYPE_NONE;
+       self.effects            = EF_NODRAW;
+       self.colormod           = '0 0 0';
+       self.avelocity          = '0 0 0';
+       self.velocity           = '0 0 0';
+       self.touch                      = SUB_Null;
+       self.nextthink          = 0;
+
+       setorigin(self, self.pos1);
+
+}
+
+void bumb_impact()
+{
+    if(autocvar_g_vehicle_bumblebee_bouncepain_x)
+        vehilces_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, 
+                                               autocvar_g_vehicle_bumblebee_bouncepain_y, 
+                                               autocvar_g_vehicle_bumblebee_bouncepain_z);
+}
+
+void bumb_spawn(float _f)
+{
+       /*
+       float i;
+       for(i=1; gettaginfo(self.gun1, i), gettaginfo_name; ++i)
+       {
+
+           dprint(" ------- ^1gettaginfo_name^2(",ftos(i),") ^3=", gettaginfo_name, "\n");
+       }
+       */
+       if(!self.gun1)
+       {
+               // for some reason, autosizing of the shiled entity refuses to work for this one so set it up in advance.
+               self.vehicle_shieldent = spawn();
+               self.vehicle_shieldent.effects = EF_LOWPRECISION;
+               setmodel(self.vehicle_shieldent, "models/vhshield.md3");
+               setattachment(self.vehicle_shieldent, self, "");
+               setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
+               self.vehicle_shieldent.scale       = 512 / vlen(self.maxs - self.mins);
+               self.vehicle_shieldent.think       = shieldhit_think;
+               self.vehicle_shieldent.alpha = -1;
+               self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
+
+               self.gun1 = spawn();
+               self.gun2 = spawn();
+               self.gun3 = spawn();
+
+               self.vehicle_flags |= VHF_MULTISLOT;
+
+               self.gun1.owner = self;
+               self.gun2.owner = self;
+               self.gun3.owner = self;
+
+               setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
+               setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
+               setmodel(self.gun3, "models/vehicles/bumblebee_ray.dpm");
+
+               setattachment(self.gun1, self, "cannon_right");
+               setattachment(self.gun2, self, "cannon_left");
+
+               // Angled bones are no fun, messes up gun-aim; so work arround it.
+               self.gun3.pos1 = self.angles;
+               self.angles = '0 0 0';
+               vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
+               ofs -= self.origin;
+               setattachment(self.gun3, self, "");
+               setorigin(self.gun3, ofs);
+               self.angles = self.gun3.pos1;
+
+               vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumb_gunner_frame, bumb_gunner_exit);
+               vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumb_gunner_frame, bumb_gunner_exit);
+
+               setorigin(self.vehicle_hudmodel, '50 0 -5');    // Move cockpit forward - down.
+               setorigin(self.vehicle_viewport, '5 0 2');    // Move camera forward up
+
+               //fixme-model-bones
+               setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
+               setorigin(self.gun1.vehicle_viewport, '-85 0 50');
+               //fixme-model-bones
+               setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
+               setorigin(self.gun2.vehicle_viewport, '-85 0 50');
+
+               self.scale = 1.5;
+               
+               // Raygun beam
+               if(self.gun3.enemy == world)
+               {                       
+                       self.gun3.enemy = spawn();
+                       Net_LinkEntity(self.gun3.enemy, TRUE, 0, bumble_raygun_send);
+                       self.gun3.enemy.SendFlags = BRG_SETUP;                  
+                       self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;                      
+                       self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
+               }
+       }
+
+       self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+       self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+       self.solid          = SOLID_BBOX;
+       //self.movetype         = MOVETYPE_BOUNCEMISSILE;
+       self.movetype           = MOVETYPE_TOSS;
+       self.vehicle_impact = bumb_impact;
+       self.damageforcescale = 0.025;
+       
+       setorigin(self, self.origin + '0 0 25');
+}
+
+void spawnfunc_vehicle_bumblebee()
+{
+       if(!autocvar_g_vehicle_bumblebee)
+       {
+               remove(self);
+               return;
+       }
+
+       precache_model("models/vehicles/bumblebee_body.dpm");
+       precache_model("models/vehicles/bumblebee_plasma_left.dpm");
+       precache_model("models/vehicles/bumblebee_plasma_right.dpm");
+       precache_model("models/vehicles/bumblebee_ray.dpm");
+       precache_model("models/vehicles/wakizashi_cockpit.dpm");
+       precache_model("models/vehicles/spiderbot_cockpit.dpm");
+       precache_model("models/vehicles/raptor_cockpit.dpm");
+
+       if(autocvar_g_vehicle_bumblebee_energy)
+               if(autocvar_g_vehicle_bumblebee_energy_regen)
+                       self.vehicle_flags |= VHF_ENERGYREGEN;
+
+       if(autocvar_g_vehicle_bumblebee_shield)
+               self.vehicle_flags |= VHF_HASSHIELD;
+
+       if(autocvar_g_vehicle_bumblebee_shield_regen)
+               self.vehicle_flags |= VHF_SHIELDREGEN;
+
+       if(autocvar_g_vehicle_bumblebee_health_regen)
+               self.vehicle_flags |= VHF_HEALTHREGEN;
+
+       if not(vehicle_initialize(
+                          "Bumblebee", "models/vehicles/bumblebee_body.dpm",
+                          "", "models/vehicles/spiderbot_cockpit.dpm", "", "", "tag_viewport",
+                          HUD_BUMBLEBEE, BUMB_MIN, BUMB_MAX, FALSE,
+                          bumb_spawn, autocvar_g_vehicle_bumblebee_respawntime,
+                          bumb_pilot_frame, bumb_enter, bumb_exit,
+                          bumb_die, bumb_think, FALSE, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_shield))
+       {
+               remove(self);
+               return;
+       }
+}
+
+float bumble_raygun_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
+
+       WriteByte(MSG_ENTITY, sf);
+       if(sf & BRG_SETUP)
+       {
+               WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
+               WriteByte(MSG_ENTITY, self.realowner.team);
+               WriteByte(MSG_ENTITY, self.cnt);
+       }
+
+       if(sf & BRG_START)
+       {
+               WriteCoord(MSG_ENTITY, self.hook_start_x);
+               WriteCoord(MSG_ENTITY, self.hook_start_y);
+               WriteCoord(MSG_ENTITY, self.hook_start_z);
+       }
+
+       if(sf & BRG_END)
+       {
+               WriteCoord(MSG_ENTITY, self.hook_end_x);
+               WriteCoord(MSG_ENTITY, self.hook_end_y);
+               WriteCoord(MSG_ENTITY, self.hook_end_z);
+       }
+
+       return TRUE;
+}
+#endif // SVQC
+
+#ifdef CSQC
+/*
+.vector raygun_l1
+.vector raygun_l2;
+.vector raygun_l3;
+*/
+
+void bumble_raygun_draw()
+{
+       float _len;
+       vector _dir;
+       vector _vtmp1, _vtmp2;
+
+       _len = vlen(self.origin - self.move_origin);
+       _dir = normalize(self.move_origin - self.origin);
+       
+       if(self.total_damages < time)
+       {
+               boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
+               boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA);
+               self.total_damages = time + 0.1;
+       }
+
+       float i, df, sz, al;
+       for(i = -0.1; i < 0.2; i += 0.1)
+       {
+               df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN);
+               sz = 5 + random() * 5;
+               al = 0.25 + random() * 0.5;
+               _vtmp1 = self.origin + _dir * _len * (0.25 + i);
+               _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2));       //self.raygun_l1;
+               Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+               _vtmp2 = self.origin + _dir * _len * (0.5 + i);
+               _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5));       //self.raygun_l2;
+               Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+               _vtmp1 = self.origin + _dir * _len * (0.75 + i);
+               _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10);     //self.raygun_l3;
+               Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+               Draw_CylindricLine(_vtmp1, self.move_origin +  randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+       }
+}
+
+void bumble_raygun_read(float bIsNew)
+{
+       float sf = ReadByte();
+
+       if(sf & BRG_SETUP)
+       {
+               self.cnt  = ReadByte();
+               self.team = ReadByte();
+               self.cnt  = ReadByte();
+               
+               if(self.cnt)
+                       self.colormod = '1 0 0';
+               else
+                       self.colormod = '0 1 0';
+
+               self.traileffect = particleeffectnum("healray_muzzleflash");
+               self.lip = particleeffectnum("healray_impact");         
+
+               self.draw = bumble_raygun_draw;
+       }
+       
+       
+       if(sf & BRG_START)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
+       }
+
+       if(sf & BRG_END)
+       {
+               self.move_origin_x = ReadCoord();
+               self.move_origin_y = ReadCoord();
+               self.move_origin_z = ReadCoord();
+       }
+}
+
+void bumblebee_draw()
+{
+
+}
+
+void bumblebee_draw2d()
+{
+
+}
+
+void bumblebee_read_extra()
+{
+
+}
+
+void vehicle_bumblebee_assemble()
+{
+
+}
+#endif //CSQC
index 777820e48c261c26f18cc8c9b093b42abfa71a85..792be585023d064650cad8f9360b771d1d16a4f0 100644 (file)
@@ -6,6 +6,8 @@ void racer_exit(float eject);
 void racer_enter();
 
 // Auto cvars
+float autocvar_g_vehicle_racer;
+
 float autocvar_g_vehicle_racer_speed_afterburn;
 float autocvar_g_vehicle_racer_afterburn_cost;
 
@@ -58,6 +60,7 @@ float autocvar_g_vehicle_racer_rocket_locking_time;
 float autocvar_g_vehicle_racer_rocket_locking_releasetime;
 float autocvar_g_vehicle_racer_rocket_locked_time;
 float autocvar_g_vehicle_racer_rocket_locked_maxangle;
+float autocvar_g_vehicle_racer_rocket_climbspeed;
 
 float autocvar_g_vehicle_racer_respawntime;
 
@@ -71,37 +74,34 @@ float autocvar_g_vehicle_racer_bouncestop;
 vector autocvar_g_vehicle_racer_bouncepain;
 
 var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
+void racer_spawn(float _spawnflag);
 
-void racer_align4point()
+void racer_align4point(float _delta)
 {
-    vector push_vector, v_add;
+    vector push_vector;
     float fl_push, fr_push, bl_push, br_push;
 
-
     push_vector  = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
     fr_push      = force_fromtag_normpower;
-    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 
     push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
     fl_push      = force_fromtag_normpower;
-    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 
     push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
     br_push      = force_fromtag_normpower;
-    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 
     push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
     bl_push      = force_fromtag_normpower;
-    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+    //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 
-    self.velocity += (push_vector * frametime);
+   self.velocity += push_vector * _delta;
 
     // Anti ocilation
-    if(self.velocity_z  > 0)
-        self.velocity_z *= 1 - (autocvar_g_vehicle_racer_upforcedamper * frametime);
-
-    self.velocity   += v_add;
-    //self.velocity_z -= autocvar_sv_gravity * frametime;
+    if(self.velocity_z > 0)
+        self.velocity_z *= 1 - autocvar_g_vehicle_racer_upforcedamper * _delta;
 
     push_vector_x =  (fl_push - bl_push);
     push_vector_x += (fr_push - br_push);
@@ -112,12 +112,12 @@ void racer_align4point()
     push_vector_z *= 360;
 
     // Apply angle diffrance
-    self.angles_z += push_vector_z * frametime;
-    self.angles_x += push_vector_x * frametime;
+    self.angles_z += push_vector_z * _delta;
+    self.angles_x += push_vector_x * _delta;
 
     // Apply stabilizer
-    self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime);
-    self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime);
+    self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
+    self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
 }
 
 void racer_fire_cannon(string tagname)
@@ -129,7 +129,7 @@ void racer_fire_cannon(string tagname)
     bolt = vehicles_projectile("wakizashi_gun_muzzleflash", "weapons/lasergun_fire.wav",
                            v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
                            autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force,  0,
-                           DEATH_WAKIGUN, PROJECTILE_WAKICANNON, 0, TRUE, TRUE);
+                           DEATH_WAKIGUN, PROJECTILE_WAKICANNON, 0, TRUE, TRUE, self.owner);
 
        // Fix z-aim (for chase mode)
     v = normalize(trace_endpos - bolt.origin);
@@ -209,8 +209,14 @@ void racer_rocket_tracker()
     newvel = oldvel + self.lip;
     makevectors(vectoangles(olddir));
 
+       float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
+       vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
+
     traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
-    newdir = normalize(self.enemy.origin - self.origin);
+    newdir = normalize(predicted_origin - self.origin);
+
+    //vector
+       float height_diff = predicted_origin_z - self.origin_z;
 
     if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
     {
@@ -220,11 +226,12 @@ void racer_rocket_tracker()
         return;
     }
 
-    if(trace_fraction != 1.0)
+    if(trace_fraction != 1.0 && trace_ent != self.enemy)
         newdir_z += 16 * sys_frametime;
 
     self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
     self.velocity_z -= 800 * sys_frametime;
+    self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
 
     UpdateCSQCProjectile(self);
     return;
@@ -232,14 +239,11 @@ void racer_rocket_tracker()
 
 void racer_fire_rocket(string tagname, entity trg)
 {
-    vector v;
-    entity rocket;
-
-    v = gettaginfo(self, gettagindex(self, tagname));
-    rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
+    vector v = gettaginfo(self, gettagindex(self, tagname));
+    entity rocket = rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
                            v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
                            autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
-                           DEATH_WAKIROCKET, PROJECTILE_WAKIROCKET, 20, FALSE, FALSE);
+                           DEATH_WAKIROCKET, PROJECTILE_WAKIROCKET, 20, FALSE, FALSE, self.owner);
 
     rocket.lip              = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
     rocket.wait             = autocvar_g_vehicle_racer_rocket_turnrate;
@@ -265,11 +269,11 @@ float racer_frame()
     player  = self;
     racer   = self.vehicle;
     self    = racer;
-    
+
     player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
-    
+
     vehicles_painframe();
-    
+
     if(racer.deadflag != DEAD_NO)
     {
         self = player;
@@ -277,7 +281,7 @@ float racer_frame()
         return 1;
     }
 
-    racer_align4point();
+    racer_align4point(frametime);
 
     crosshair_trace(player);
 
@@ -299,84 +303,68 @@ float racer_frame()
     makevectors(racer.angles);
     racer.angles_x *= -1;
 
-
-    ftmp = racer.velocity_z;
+    //ftmp = racer.velocity_z;
     df = racer.velocity * -autocvar_g_vehicle_racer_friction;
-    racer.velocity_z = ftmp;
+    //racer.velocity_z = ftmp;
 
-    if(player.movement_x != 0)
-    {
-        if(player.movement_x > 0)
-            df += v_forward  * autocvar_g_vehicle_racer_speed_forward;
-        else if(player.movement_x < 0)
-            df -= v_forward  * autocvar_g_vehicle_racer_speed_forward;
-    }
-
-    if(player.movement_y != 0)
-    {
-        if(player.movement_y < 0)
-            df -= v_right * autocvar_g_vehicle_racer_speed_strafe;
-        else if(player.movement_y > 0)
-            df += v_right * autocvar_g_vehicle_racer_speed_strafe;
-    }
-    
     if(vlen(player.movement) != 0)
     {
+        if(player.movement_x)
+            df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward);
+
+        if(player.movement_y)
+            df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe);
+
         if(self.sound_nexttime < time || self.sounds != 1)
-        {        
+        {
             self.sounds = 1;
             self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
             sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_move.wav", VOL_VEHICLEENGINE, ATTN_NORM);
         }
     }
     else
-    {        
+    {
         if(self.sound_nexttime < time || self.sounds != 0)
-        {        
+        {
             self.sounds = 0;
             self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
             sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_idle.wav", VOL_VEHICLEENGINE, ATTN_NORM);
-        }        
+        }
     }
-    
+
     // Afterburn
     if (player.BUTTON_JUMP && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * frametime))
     {
         if(time - racer.wait > 0.2)
-            pointparticles(particleeffectnum("wakizashi_booster_smoke"), self.origin, '0 0 0', 1);            
-        
+            pointparticles(particleeffectnum("wakizashi_booster_smoke"), self.origin - v_forward * 32, v_forward  * vlen(self.velocity), 1);
+
         racer.wait = time;
         racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * frametime;
         df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
-        
-        if(self.invincible_finished < time)
-        {            
-            traceline(self.origin, self.origin - '0 0 256', MOVE_NORMAL, self);
+
+        if(racer.invincible_finished < time)
+        {
+            traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
             if(trace_fraction != 1.0)
                 pointparticles(particleeffectnum("smoke_small"), trace_endpos, '0 0 0', 1);
-            
-            self.invincible_finished = time + 0.1 + (random() * 0.1);
+
+            racer.invincible_finished = time + 0.1 + (random() * 0.1);
         }
 
-        if(self.strength_finished < time)
-        {        
-            //self.sounds = 2;
-            self.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
-            sound (self.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTN_NORM);            
-        }        
+        if(racer.strength_finished < time)
+        {
+            racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
+            sound (racer.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTN_NORM);
+        }
     }
     else
     {
-        self.strength_finished = 0;
-        sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM);
+        racer.strength_finished = 0;
+        sound (racer.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM);
     }
-        
 
-    racer.velocity  += df * frametime;
-
-    df = (vlen(racer.velocity) * autocvar_g_vehicle_racer_downforce * v_up) * frametime;
-    racer.velocity  = racer.velocity - df;
-    player.movement = racer.velocity;
+       df -= v_up * (vlen(racer.velocity) * autocvar_g_vehicle_racer_downforce);
+    player.movement = racer.velocity += df * frametime;
 
     if(player.BUTTON_ATCK)
     if(time > racer.attack_finished_single)
@@ -397,7 +385,6 @@ float racer_frame()
             racer.cnt = 1;
         }
         racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire;
-        //self.owner.vehicle_energy = racer.vehicle_energy / autocvar_g_vehicle_racer_energy;
     }
 
     if(autocvar_g_vehicle_racer_rocket_locktarget)
@@ -420,16 +407,17 @@ float racer_frame()
     if(time > racer.delay)
     if(player.BUTTON_ATCK2)
     {
-        self.misc_bulletcounter += 1;
+        racer.misc_bulletcounter += 1;
         racer.delay = time + 0.3;
-        if(self.misc_bulletcounter == 1)
-            racer_fire_rocket("tag_rocket_r", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world);
-        else if(self.misc_bulletcounter == 2)
+
+        if(racer.misc_bulletcounter == 1)
+            racer_fire_rocket("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+        else if(racer.misc_bulletcounter == 2)
         {
-            racer_fire_rocket("tag_rocket_l", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world);
-            self.lock_strength  = 0;
-            self.lock_target    = world;
-            self.misc_bulletcounter = 0;
+            racer_fire_rocket("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+            racer.lock_strength  = 0;
+            racer.lock_target    = world;
+            racer.misc_bulletcounter = 0;
 
             racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
             racer.lip = time;
@@ -437,22 +425,21 @@ float racer_frame()
     }
     player.vehicle_reload1 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
 
-    if(self.vehicle_flags  & VHF_SHIELDREGEN)
-        vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime);
+    if(racer.vehicle_flags  & VHF_SHIELDREGEN)
+        vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, TRUE);
 
-    if(self.vehicle_flags  & VHF_HEALTHREGEN)
-        vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime);
+    if(racer.vehicle_flags  & VHF_HEALTHREGEN)
+        vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, FALSE);
 
-    if(self.vehicle_flags  & VHF_ENERGYREGEN)
-        vehicles_regen(wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime);
+    if(racer.vehicle_flags  & VHF_ENERGYREGEN)
+        vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, FALSE);
 
 
-    VEHICLE_UPDATE_PLAYER(health, racer);
-    VEHICLE_UPDATE_PLAYER(energy, racer);
-
-    if(self.vehicle_flags & VHF_HASSHIELD)
-        VEHICLE_UPDATE_PLAYER(shield, racer);
+    VEHICLE_UPDATE_PLAYER(player, health, racer);
+    VEHICLE_UPDATE_PLAYER(player, energy, racer);
 
+    if(racer.vehicle_flags & VHF_HASSHIELD)
+        VEHICLE_UPDATE_PLAYER(player, shield, racer);
 
     player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
     setorigin(player,racer.origin + '0 0 32');
@@ -464,32 +451,24 @@ float racer_frame()
 
 void racer_think()
 {
-    /*
-    float a, b, c;a = autocvar_g_vehicle_racer_anglestabilizer;
-    b = autocvar_g_vehicle_racer_springlength;
-    c = autocvar_g_vehicle_racer_hoverpower;
-
-    autocvar_g_vehicle_racer_anglestabilizer = 36;
-    autocvar_g_vehicle_racer_springlength = 96;
-    autocvar_g_vehicle_racer_hoverpower = 300;
-    */
-
-    racer_align4point(); //time - self.nextthink);
-
-    /*
-    //if(self.velocity_z > 0)
-    //    self.velocity_z *= 0.95;
-
-    autocvar_g_vehicle_racer_anglestabilizer = a;
-    autocvar_g_vehicle_racer_springlength = b;
-    autocvar_g_vehicle_racer_hoverpower = c;
-    */
-
-    self.velocity_x *= 0.9;
-    self.velocity_y *= 0.9;
-    self.velocity_z *= 0.8;
-    self.velocity_z += sin(time * 2) * 16;
-    self.nextthink = time; // + 0.05;
+    self.nextthink = time;
+
+    float pushdeltatime = time - self.lastpushtime;
+    if (pushdeltatime > 0.15) pushdeltatime = 0;
+    self.lastpushtime = time;
+    if(!pushdeltatime) return;
+
+    tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NORMAL, self);
+
+    vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
+       df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
+
+       self.velocity += df * pushdeltatime;
+    if(self.velocity_z > 0)
+        self.velocity_z *= 1 - autocvar_g_vehicle_racer_upforcedamper * pushdeltatime;
+
+    self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+    self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
 }
 
 void racer_enter()
@@ -497,20 +476,22 @@ void racer_enter()
     self.movetype = MOVETYPE_BOUNCE;
     self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health)  * 100;
     self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield)  * 100;
-    
+
     if(self.owner.flagcarried)
        setorigin(self.owner.flagcarried, '-190 0 96');
+
+       //targetdrone_spawn(self.origin + '0 0 512' + randomvec() * 256, 1);
 }
 
 void racer_exit(float eject)
 {
     vector spot;
-    
+
     self.think      = racer_think;
     self.nextthink  = time;
-    self.movetype   = MOVETYPE_TOSS;
+    self.movetype   = MOVETYPE_BOUNCE;
     sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM);
-    
+
     if not (self.owner)
         return;
 
@@ -525,47 +506,39 @@ void racer_exit(float eject)
        }
        else
        {
-           self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed;
+               if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+               {
+                       self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 32 + '0 0 32';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin - v_forward * 200 + '0 0 32';
+                       spot = vehicles_findgoodexit(spot);
+               }
            self.owner.oldvelocity = self.owner.velocity;
-           spot = self.origin - v_forward * 200 + '0 0 64';
-           spot = vehicles_findgoodexit(spot);
            setorigin(self.owner , spot);
        }
        antilag_clear(self.owner);
     self.owner = world;
 }
+
 void racer_impact()
 {
     if(autocvar_g_vehicle_racer_bouncepain_x)
         vehilces_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
 }
 
-void racer_spawn()
-{
-    self.think          = racer_think;
-    self.nextthink      = time;
-    self.vehicle_health = autocvar_g_vehicle_racer_health;
-    self.vehicle_shield = autocvar_g_vehicle_racer_shield;
-
-    self.movetype       = MOVETYPE_TOSS;
-    self.solid          = SOLID_SLIDEBOX;
-    self.delay          = time;
-    self.scale          = 0.5;
-
-    setsize(self, RACER_MIN * 0.5, RACER_MAX * 0.5);
-    self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
-    self.bouncestop = autocvar_g_vehicle_racer_bouncestop;    
-    self.vehicle_impact = racer_impact;
-    //self.destvec = autocvar_g_vehicle_racer_bouncepain;
-}
-
-
 void racer_blowup()
 {
     self.deadflag    = DEAD_DEAD;
     self.vehicle_exit(VHEF_NORMAL);
 
-    RadiusDamage (self, self, autocvar_g_vehicle_racer_blowup_coredamage,
+    RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
                                        autocvar_g_vehicle_racer_blowup_edgedamage,
                                        autocvar_g_vehicle_racer_blowup_radius, world,
                                        autocvar_g_vehicle_racer_blowup_forceintensity,
@@ -604,8 +577,8 @@ void racer_die()
     self.wait         = time;
     self.cnt          = 1 + random() * 2;
     self.touch        = racer_deadtouch;
-    
-    pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);    
+
+    pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
 
     if(random() < 0.5)
         self.avelocity_z  = 32;
@@ -619,49 +592,57 @@ void racer_die()
        self.think     = racer_blowup;
        self.nextthink = 2 + time + random() * 3;
 }
-
-void racer_dinit()
+void racer_spawn(float _spawnflag)
 {
-    if not (vehicle_initialize(
-             "Wakizashi",
-             "models/vehicles/wakizashi.dpm",
-             "null", // we need this so tur_head is networked and usable for sounds
-             "models/vehicles/wakizashi_cockpit.dpm",
-             "", "", "tag_viewport",
-             HUD_WAKIZASHI,
-             0.5 * RACER_MIN, 0.5 * RACER_MAX,
-             FALSE,
-             racer_spawn, autocvar_g_vehicle_racer_respawntime,
-             racer_frame,
-             racer_enter, racer_exit,
-             racer_die,   racer_think,
-             TRUE))
+    if(self.scale != 0.5)
     {
-        remove(self);
-        return;
+        if(autocvar_g_vehicle_racer_hovertype != 0)
+            racer_force_from_tag = vehicles_force_fromtag_maglev;
+        else
+            racer_force_from_tag = vehicles_force_fromtag_hover;
+
+        // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
+        self.scale = 0.5;
+        setattachment(self.vehicle_hudmodel, self, "");
+        setattachment(self.vehicle_viewport, self, "tag_viewport");
+
+        self.mass               = 900;
     }
 
-    if(autocvar_g_vehicle_racer_hovertype != 0)
-        racer_force_from_tag = vehicles_force_fromtag_maglev;
-    else
-        racer_force_from_tag = vehicles_force_fromtag_hover;
+    self.think          = racer_think;
+    self.nextthink      = time;
+    self.vehicle_health = autocvar_g_vehicle_racer_health;
+    self.vehicle_shield = autocvar_g_vehicle_racer_shield;
 
-    // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
-    self.scale = 0.5;
-    setattachment(self.vehicle_hudmodel, self, "");
-    setattachment(self.vehicle_viewport, self, "tag_viewport");
+    self.movetype       = MOVETYPE_TOSS;
+    self.solid          = SOLID_SLIDEBOX;
+    self.delay          = time;
+    self.scale          = 0.5;
 
-    self.mass               = 900;
+    setsize(self, RACER_MIN * 0.5, RACER_MAX * 0.5);
+    self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
+    self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
+    self.vehicle_impact = racer_impact;
+    self.damageforcescale = 0.5;
+    //self.destvec = autocvar_g_vehicle_racer_bouncepain;
 }
 
+
+
 void spawnfunc_vehicle_racer()
 {
+    if(!autocvar_g_vehicle_racer)
+    {
+        remove(self);
+        return;
+    }        
+    
     self.vehicle_flags |= VHF_DMGSHAKE;
     self.vehicle_flags |= VHF_DMGROLL;
 
     precache_sound ("weapons/lasergun_fire.wav");
     precache_sound ("weapons/rocket_fire.wav");
-    
+
     precache_sound ("vehicles/racer_idle.wav");
     precache_sound ("vehicles/racer_move.wav");
     precache_sound ("vehicles/racer_boost.wav");
@@ -670,7 +651,6 @@ void spawnfunc_vehicle_racer()
     precache_model ("models/vehicles/wakizashi.dpm");
     precache_model ("models/vehicles/wakizashi_cockpit.dpm");
 
-    vehicles_configcheck("vehicle_racer.cfg", autocvar_g_vehicle_racer_health);
     if(autocvar_g_vehicle_racer_energy)
         if(autocvar_g_vehicle_racer_energy_regen)
             self.vehicle_flags |= VHF_ENERGYREGEN;
@@ -684,11 +664,25 @@ void spawnfunc_vehicle_racer()
     if(autocvar_g_vehicle_racer_health_regen)
         self.vehicle_flags |= VHF_HEALTHREGEN;
 
-    self.think = racer_dinit;
-    
-    if(g_assault)
-        self.nextthink = time + 0.5;
-    else
-        self.nextthink = time + (autocvar_g_vehicles_delayspawn ? autocvar_g_vehicle_racer_respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter) : 0.5);
+    if not (vehicle_initialize(
+             "Wakizashi",
+             "models/vehicles/wakizashi.dpm",
+             "null", // we need this so tur_head is networked and usable for sounds
+             "models/vehicles/wakizashi_cockpit.dpm",
+             "", "", "tag_viewport",
+             HUD_WAKIZASHI,
+             0.5 * RACER_MIN, 0.5 * RACER_MAX,
+             FALSE,
+             racer_spawn, autocvar_g_vehicle_racer_respawntime,
+             racer_frame,
+             racer_enter, racer_exit,
+             racer_die,   racer_think,
+             TRUE, 
+             autocvar_g_vehicle_racer_health,
+             autocvar_g_vehicle_racer_shield))
+    {
+        remove(self);
+        return;
+    }
 }
 #endif // SVQC
index ab0d388155bf7ca8d17c674d31507770656533e4..a623bd540727afbe8f054c6b7fb65ec277004e14 100644 (file)
@@ -1,8 +1,16 @@
-#ifdef SVQC
+#define RSM_FIRST 0
+#define RSM_BOMB 0
+#define RSM_FLARE 1
+#define RSM_LAST 1
+
 #define RAPTOR_MIN '-80 -80 0'
 #define RAPTOR_MAX '80 80 70'
 
+#ifdef SVQC
+float autocvar_g_vehicle_raptor;
+
 float autocvar_g_vehicle_raptor_respawntime;
+float autocvar_g_vehicle_raptor_takeofftime;
 
 float autocvar_g_vehicle_raptor_movestyle;
 float autocvar_g_vehicle_raptor_turnspeed;
@@ -26,6 +34,11 @@ float autocvar_g_vehicle_raptor_bomblet_force;
 float autocvar_g_vehicle_raptor_bomblet_explode_delay;
 float autocvar_g_vehicle_raptor_bombs_refire;
 
+float autocvar_g_vehicle_raptor_flare_refire;
+float autocvar_g_vehicle_raptor_flare_lifetime;
+float autocvar_g_vehicle_raptor_flare_chase;
+float autocvar_g_vehicle_raptor_flare_range;
+
 float autocvar_g_vehicle_raptor_cannon_turnspeed;
 float autocvar_g_vehicle_raptor_cannon_turnlimit;
 float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
@@ -61,7 +74,7 @@ float autocvar_g_vehicle_raptor_bouncefactor;
 float autocvar_g_vehicle_raptor_bouncestop;
 vector autocvar_g_vehicle_raptor_bouncepain;
 
-void raptor_spawn();
+void raptor_spawn(float);
 float raptor_frame();
 float raptor_takeoff();
 
@@ -172,7 +185,7 @@ void raptor_fire_cannon(entity gun, string tagname)
     vehicles_projectile("raptor_cannon_muzzleflash", "weapons/lasergun_fire.wav",
                            gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
                            autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
-                           DEATH_RAPTOR_CANNON, PROJECTILE_RAPTORCANNON, 0, TRUE, TRUE);
+                           DEATH_RAPTOR_CANNON, PROJECTILE_RAPTORCANNON, 0, TRUE, TRUE, self.owner);
 }
 
 void raptor_think()
@@ -181,6 +194,7 @@ void raptor_think()
 
 void raptor_enter()
 {
+    self.vehicle_weapon2mode = RSM_BOMB;
     self.owner.PlayerPhysplug = raptor_takeoff;
     self.movetype       = MOVETYPE_BOUNCEMISSILE;
     self.solid          = SOLID_SLIDEBOX;
@@ -194,7 +208,8 @@ void raptor_enter()
 
     if(self.owner.flagcarried)
        setorigin(self.owner.flagcarried, '-20 0 96');
-
+    
+    CSQCVehicleSetup(self.owner, 0);
 }
 
 void raptor_land()
@@ -236,7 +251,7 @@ void raptor_exit(float eject)
 
     if not (self.owner)
         return;
-
+       
        makevectors(self.angles);
        if(eject)
        {
@@ -248,12 +263,24 @@ void raptor_exit(float eject)
        }
        else
        {
-           self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed;
+               if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+               {
+                       self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 32 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin - v_forward * 200 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
            self.owner.oldvelocity = self.owner.velocity;
-           spot = self.origin - v_forward * 200 + '0 0 64';
-           spot = vehicles_findgoodexit(spot);
            setorigin(self.owner , spot);
        }
+       
        antilag_clear(self.owner);      
     self.owner = world;
 }
@@ -274,7 +301,7 @@ float raptor_takeoff()
     // Takeoff sequense
     if(raptor.frame < 25)
     {
-        raptor.frame += 0.25;
+        raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
         raptor.velocity_z = min(raptor.velocity_z * 1.5, 256);
         self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000);
         self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
@@ -286,32 +313,61 @@ float raptor_takeoff()
         player.PlayerPhysplug = raptor_frame;
 
     if(self.vehicle_flags  & VHF_SHIELDREGEN)
-        vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime);
+        vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, TRUE);
 
     if(self.vehicle_flags  & VHF_HEALTHREGEN)
-        vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime);
+        vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, FALSE);
 
     if(self.vehicle_flags  & VHF_ENERGYREGEN)
-        vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime);
+        vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, FALSE);
 
 
     raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
     player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
 
-    VEHICLE_UPDATE_PLAYER(health, raptor);
-    VEHICLE_UPDATE_PLAYER(energy, raptor);
+    VEHICLE_UPDATE_PLAYER(player, health, raptor);
+    VEHICLE_UPDATE_PLAYER(player, energy, raptor);
     if(self.vehicle_flags & VHF_HASSHIELD)
-        VEHICLE_UPDATE_PLAYER(shield, raptor);
+        VEHICLE_UPDATE_PLAYER(player, shield, raptor);
 
     player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
     self = player;
     return 1;
 }
 
+void raptor_flare_touch()
+{
+    remove(self);
+}
+
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+    self.health -= damage;
+    if(self.health <= 0)
+        remove(self);
+}
+
+void raptor_flare_think()
+{
+    self.nextthink = time + 0.1;
+    entity _missile = findchainentity(enemy, self.owner);
+    while(_missile)
+    {
+        if(_missile.flags & FL_PROJECTILE)
+        if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
+        if(random() > autocvar_g_vehicle_raptor_flare_chase)
+            _missile.enemy = self;
+        _missile = _missile.chain;
+    }
+    
+    if(self.tur_impacttime < time)
+        remove(self);
+}
+
 float raptor_frame()
 {
     entity player, raptor;
-    float ftmp, ftmp2;
+    float ftmp = 0;
     vector df;
     
        if(intermission_running)
@@ -422,7 +478,57 @@ float raptor_frame()
 
     vector vf, ad;
     // Target lock & predict
-    if(autocvar_g_vehicle_raptor_cannon_locktarget)
+    if(autocvar_g_vehicle_raptor_cannon_locktarget == 2)
+    {
+        if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag)
+            raptor.gun1.enemy = world;
+    
+        if(trace_ent)
+        if(trace_ent.movetype)
+        if(trace_ent.takedamage)
+        if(!trace_ent.deadflag)
+        {
+            if(teamplay)
+            {
+                if(trace_ent.team != player.team)
+                {
+                    raptor.gun1.enemy = trace_ent;
+                    raptor.gun1.lock_time = time + 5;
+                }
+            }
+            else
+            {            
+                raptor.gun1.enemy = trace_ent;
+                raptor.gun1.lock_time = time + 0.5;
+            }
+        }
+            
+        if(raptor.gun1.enemy)
+        {
+            float i, distance, impact_time;
+
+            vf = real_origin(raptor.gun1.enemy);
+            UpdateAuxiliaryXhair(player, vf, '1 0 0', 1);
+            vector _vel = raptor.gun1.enemy.velocity;
+            if(raptor.gun1.enemy.movetype == MOVETYPE_WALK)
+                _vel_z *= 0.1;
+            
+            if(autocvar_g_vehicle_raptor_cannon_predicttarget)
+            {
+                ad = vf;
+                for(i = 0; i < 4; ++i)
+                {
+                    distance = vlen(ad - player.origin);
+                    impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
+                    ad = vf + _vel * impact_time;
+                }
+                trace_endpos = ad;                        
+            }
+            else
+                trace_endpos = vf;                        
+        }
+    }
+    else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
     {
 
         vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
@@ -457,39 +563,14 @@ float raptor_frame()
         }
     }
 
-    // Aim the gunz
-    ftmp2 = autocvar_g_vehicle_raptor_cannon_turnspeed * frametime;
-    ftmp = -ftmp2;
-
-    // Gun1
-    df = gettaginfo(raptor.gun1, gettagindex(raptor.gun1, "fire1"));
-    //ad = df;
-    //vf = v_forward;
-    df = vectoangles(normalize(trace_endpos - df)); // Find the direction & angle    
-    df = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(raptor.angles), AnglesTransform_FromAngles(df))) - raptor.gun1.angles;
-    df = shortangle_vxy(df, raptor.gun1.angles);
-        
-    // Bind to aimspeed
-    df_x = bound(ftmp, df_x, ftmp2);
-    df_y = bound(ftmp, df_y, ftmp2);
-    // Bind to limts
-    raptor.gun1.angles_x = bound(-autocvar_g_vehicle_raptor_cannon_pitchlimit_down, df_x + raptor.gun1.angles_x, autocvar_g_vehicle_raptor_cannon_pitchlimit_up);
-    raptor.gun1.angles_y = bound(-autocvar_g_vehicle_raptor_cannon_turnlimit,  df_y + raptor.gun1.angles_y, autocvar_g_vehicle_raptor_cannon_turnlimit);
-
-    // Gun2
-    df = gettaginfo(raptor.gun2, gettagindex(raptor.gun2, "fire1"));
-    //ad += df;
-    //vf += v_forward;
-    df = vectoangles(normalize(trace_endpos - df)); // Find the direction & angle    
-    df = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(raptor.angles), AnglesTransform_FromAngles(df))) - raptor.gun2.angles;
-    df = shortangle_vxy(df, raptor.gun2.angles);
-    
-    // Bind to aimspeed
-    df_x = bound(ftmp, df_x, ftmp2);
-    df_y = bound(ftmp, df_y, ftmp2);
-    // Bind to limts
-    raptor.gun2.angles_x = bound(-autocvar_g_vehicle_raptor_cannon_pitchlimit_down, df_x + raptor.gun2.angles_x, autocvar_g_vehicle_raptor_cannon_pitchlimit_up);
-    raptor.gun2.angles_y = bound(-autocvar_g_vehicle_raptor_cannon_turnlimit,  df_y + raptor.gun2.angles_y, autocvar_g_vehicle_raptor_cannon_turnlimit);
+
+    vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1", 
+                          autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up, 
+                          autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
+
+    vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1", 
+                          autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up, 
+                          autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
 
     /*
     ad = ad * 0.5;
@@ -519,30 +600,85 @@ float raptor_frame()
     }
 
     if(self.vehicle_flags  & VHF_SHIELDREGEN)
-        vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime);
+        vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, TRUE);
 
     if(self.vehicle_flags  & VHF_HEALTHREGEN)
-        vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime);
+        vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, FALSE);
 
     if(self.vehicle_flags  & VHF_ENERGYREGEN)
-        vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime);
+        vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, FALSE);
 
-
-    if(time > raptor.delay)
-    if(player.BUTTON_ATCK2)
+    if(raptor.vehicle_weapon2mode == RSM_BOMB)
     {
-        raptor_bombdrop();
-        raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
-        raptor.lip   = time;
+        if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire)
+        if(player.BUTTON_ATCK2)
+        {
+            raptor_bombdrop();
+            raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
+            raptor.lip   = time;
+        }        
     }
-
+    else
+    {
+        if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire)
+        if(player.BUTTON_ATCK2)
+        {
+            float i;
+            entity _flare;
+            
+            for(i = 0; i < 3; ++i)
+            {
+            _flare = spawn();
+            setmodel(_flare, "models/runematch/rune.mdl"); 
+            _flare.effects = EF_LOWPRECISION | EF_FLAME;
+            _flare.scale = 0.5;
+            setorigin(_flare, self.origin - '0 0 16');
+            _flare.movetype = MOVETYPE_TOSS;
+            _flare.gravity = 0.15;
+            _flare.velocity = 0.25 * raptor.velocity + (v_forward + randomvec() * 0.25)* -500;
+            _flare.think = raptor_flare_think;
+            _flare.nextthink = time;
+            _flare.owner = raptor;
+            _flare.solid = SOLID_CORPSE;
+            _flare.takedamage = DAMAGE_YES;
+            _flare.event_damage = raptor_flare_damage;
+            _flare.health = 20;
+            _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
+            _flare.touch = raptor_flare_touch;
+            }
+            raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire;
+            raptor.lip   = time;
+        }
+    }
+    
     raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
     player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
 
-    VEHICLE_UPDATE_PLAYER(health, raptor);
-    VEHICLE_UPDATE_PLAYER(energy, raptor);
+    if(self.bomb1.cnt < time)
+    {
+        entity _missile = findchainentity(enemy, raptor);
+        float _incomming = 0;
+        while(_missile)
+        {
+            if(_missile.flags & FL_PROJECTILE)
+            if(MISSILE_IS_TRACKING(_missile))
+            if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range)
+                ++_incomming;
+
+            _missile = _missile.chain;
+        }
+        
+        if(_incomming)
+            sound(self, CH_PAIN_SINGLE, "vehicles/missile_alarm.wav", VOL_BASE, ATTN_NONE);
+        
+        self.bomb1.cnt = time + 1;
+    }
+    
+
+    VEHICLE_UPDATE_PLAYER(player, health, raptor);
+    VEHICLE_UPDATE_PLAYER(player, energy, raptor);
     if(self.vehicle_flags & VHF_HASSHIELD)
-        VEHICLE_UPDATE_PLAYER(shield, raptor);
+        VEHICLE_UPDATE_PLAYER(player, shield, raptor);
 
     player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
     
@@ -554,7 +690,7 @@ void raptor_blowup()
 {
     self.deadflag    = DEAD_DEAD;
     self.vehicle_exit(VHEF_NORMAL);
-    RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_WAKIBLOWUP, world);
+    RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_WAKIBLOWUP, world);
 
     self.alpha          = -1;
     self.movetype       = MOVETYPE_NONE;
@@ -570,6 +706,9 @@ void raptor_blowup()
 
 void raptor_diethink()
 {
+       if(time >= self.wait)
+               self.think = raptor_blowup;
+    
     if(random() < 0.1)
     {
         sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
@@ -588,6 +727,7 @@ void raptor_die()
     self.movetype     = MOVETYPE_BOUNCE;
     self.think        = raptor_diethink;
     self.nextthink    = time;
+    self.wait            = time + 5 + (random() * 5);
     
     pointparticles(particleeffectnum("explosion_medium"), findbetterlocation (self.origin, 16), '0 0 0', 1);
 
@@ -606,8 +746,120 @@ void raptor_impact()
         vehilces_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
 }
 
-void raptor_spawn()
+// If we dont do this ever now and then, the raptors rotors
+// stop working, presumably due to angle overflow. cute.
+void raptor_rotor_anglefix()
+{
+    self.gun1.angles_y = anglemods(self.gun1.angles_y);
+    self.gun2.angles_y = anglemods(self.gun2.angles_y);
+    self.nextthink = time + 15;
+}
+
+float raptor_impulse(float _imp)
+{
+    switch(_imp)
+    {
+        case 10:
+        case 15:        
+        case 18:
+            self.vehicle.vehicle_weapon2mode += 1;
+            if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
+                self.vehicle.vehicle_weapon2mode = RSM_FIRST;
+            
+            CSQCVehicleSetup(self, 0);
+            return TRUE;
+        case 12:
+        case 16:
+        case 19:
+            self.vehicle.vehicle_weapon2mode -= 1;
+            if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
+                self.vehicle.vehicle_weapon2mode = RSM_LAST;
+            
+            CSQCVehicleSetup(self, 0);
+            return TRUE;
+
+        /*                     
+        case 17: // toss gun, could be used to exit?
+            break;
+        case 20: // Manual minigun reload?
+            break;
+        */
+    }    
+    return FALSE;
+}
+
+void raptor_spawn(float _f)
 {
+    if(!self.gun1)
+    {
+        entity spinner;
+        vector ofs;
+
+        //FIXME: Camera is in a bad place in HUD model.
+        //setorigin(self.vehicle_viewport, '25 0 5');
+        
+        self.vehicles_impusle   = raptor_impulse;
+        
+        self.frame = 0;
+
+        self.bomb1 = spawn();
+        self.bomb2 = spawn();
+        self.gun1  = spawn();
+        self.gun2  = spawn();
+
+        setmodel(self.bomb1,"models/vehicles/clusterbomb_folded.md3");
+        setmodel(self.bomb2,"models/vehicles/clusterbomb_folded.md3");
+        setmodel(self.gun1, "models/vehicles/raptor_gun.dpm");
+        setmodel(self.gun2, "models/vehicles/raptor_gun.dpm");
+        setmodel(self.tur_head, "models/vehicles/raptor_body.dpm");
+
+        setattachment(self.bomb1, self, "bombmount_left");
+        setattachment(self.bomb2, self, "bombmount_right");
+        setattachment(self.tur_head, self,"root");
+
+        // FIXMODEL Guns mounts to angled bones
+        self.bomb1.angles = self.angles;
+        self.angles = '0 0 0';
+        // This messes up gun-aim, so work arround it.
+        //setattachment(self.gun1, self, "gunmount_left");
+        ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
+        ofs -= self.origin;
+        setattachment(self.gun1, self, "");
+        setorigin(self.gun1, ofs);
+
+        //setattachment(self.gun2, self, "gunmount_right");
+        ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
+        ofs -= self.origin;
+        setattachment(self.gun2, self, "");
+        setorigin(self.gun2, ofs);
+
+        self.angles = self.bomb1.angles;
+        self.bomb1.angles = '0 0 0';
+
+        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';
+        self.bomb1.gun1 = spinner;
+
+        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';
+        self.bomb1.gun2 = spinner;
+
+        // Sigh.
+        self.bomb1.think = raptor_rotor_anglefix;
+        self.bomb1.nextthink = time;
+
+        self.mass               = 1 ;
+    }
+
+
     self.frame          = 0;
     self.vehicle_health = autocvar_g_vehicle_raptor_health;
     self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
@@ -624,108 +876,17 @@ void raptor_spawn()
     self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
     self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;    
     self.vehicle_impact = raptor_impact;    
+    self.damageforcescale = 0.25;
 }
 
-// If we dont do this ever now and then, the raptors rotors
-// stop working, presumably due to angle overflow. cute.
-void raptor_rotor_anglefix()
-{
-    self.gun1.angles_y = anglemods(self.gun1.angles_y);
-    self.gun2.angles_y = anglemods(self.gun2.angles_y);
-    self.nextthink = time + 15;
-}
-
-void raptor_dinit()
+void spawnfunc_vehicle_raptor()
 {
-    entity spinner;
-    vector ofs;
-
-    if not (vehicle_initialize(
-             "Raptor",
-             "models/vehicles/raptor.dpm",
-             "",
-             "models/vehicles/raptor_cockpit.dpm",
-             "", "tag_hud", "tag_camera",
-             HUD_RAPTOR,
-             RAPTOR_MIN, RAPTOR_MAX,
-             FALSE,
-             raptor_spawn, autocvar_g_vehicle_raptor_respawntime,
-             raptor_frame,
-             raptor_enter, raptor_exit,
-             raptor_die,   raptor_think,
-             FALSE))
+    if(!autocvar_g_vehicle_raptor)
     {
         remove(self);
         return;
-    }
-
-    //FIXME: Camera is in a bad place in HUD model.
-    //setorigin(self.vehicle_viewport, '25 0 5');
-
-    self.frame = 0;
-
-    self.bomb1 = spawn();
-    self.bomb2 = spawn();
-    self.gun1  = spawn();
-    self.gun2  = spawn();
-
-    setmodel(self.bomb1,"models/vehicles/clusterbomb_folded.md3");
-    setmodel(self.bomb2,"models/vehicles/clusterbomb_folded.md3");
-    setmodel(self.gun1, "models/vehicles/raptor_gun.dpm");
-    setmodel(self.gun2, "models/vehicles/raptor_gun.dpm");
-    setmodel(self.tur_head, "models/vehicles/raptor_body.dpm");
-
-    setattachment(self.bomb1, self,"bombmount_left");
-    setattachment(self.bomb2, self,"bombmount_right");
-    setattachment(self.tur_head, self,"root");
-
-
-    // FIXME Guns mounts to angled bones
-    self.bomb1.angles = self.angles;
-    self.angles = '0 0 0';
-    // This messes up gun-aim, so work arround it.
-    //setattachment(self.gun1, self, "gunmount_left");
-    ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
-    ofs -= self.origin;
-    setattachment(self.gun1, self, "");
-    setorigin(self.gun1, ofs);
-
-    //setattachment(self.gun2, self, "gunmount_right");
-    ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
-    ofs -= self.origin;
-    setattachment(self.gun2, self, "");
-    setorigin(self.gun2, ofs);
-
-    self.angles = self.bomb1.angles;
-    self.bomb1.angles = '0 0 0';
-
-    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';
-    self.bomb1.gun1 = spinner;
-
-    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';
-    self.bomb1.gun2 = spinner;
-
-    // Sigh.
-    self.bomb1.think = raptor_rotor_anglefix;
-    self.bomb1.nextthink = time;
-
-    self.mass               = 1 ;
-}
-
-void spawnfunc_vehicle_raptor()
-{
-    vehicles_configcheck("vehicle_raptor.cfg", autocvar_g_vehicle_raptor_health);
-
+    }        
+    
     self.vehicle_flags |= VHF_DMGSHAKE;
     self.vehicle_flags |= VHF_DMGROLL;
    
@@ -751,12 +912,29 @@ void spawnfunc_vehicle_raptor()
     
     precache_sound ("vehicles/raptor_fly.wav");
     precache_sound ("vehicles/raptor_speed.wav");
+    precache_sound ("vehicles/missile_alarm.wav");
+    
+    if not (vehicle_initialize(
+             "Raptor",
+             "models/vehicles/raptor.dpm",
+             "",
+             "models/vehicles/raptor_cockpit.dpm",
+             "", "tag_hud", "tag_camera",
+             HUD_RAPTOR,
+             RAPTOR_MIN, RAPTOR_MAX,
+             FALSE,
+             raptor_spawn, autocvar_g_vehicle_raptor_respawntime,
+             raptor_frame,
+             raptor_enter, raptor_exit,
+             raptor_die,   raptor_think,
+             FALSE, 
+             autocvar_g_vehicle_raptor_health,
+             autocvar_g_vehicle_raptor_shield))
+    {
+        remove(self);
+        return;
+    }
     
-    self.think = raptor_dinit;
     
-    if(g_assault)
-        self.nextthink = time + 0.5;
-    else
-        self.nextthink = time + (autocvar_g_vehicles_delayspawn ? autocvar_g_vehicle_raptor_respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter) : 0.5);
 }
 #endif // SVQC
index 913e3316f012ecd2280611c1a2a05c6c6c4b0186..71e57a037f88213efee91d2f8a7091607c3abfe9 100644 (file)
@@ -2,21 +2,24 @@ const vector SPIDERBOT_MIN = '-75 -75 10';
 const vector SPIDERBOT_MAX  = '75 75 125';
 
 #ifdef SVQC
+float autocvar_g_vehicle_spiderbot;
+
 float autocvar_g_vehicle_spiderbot_respawntime;
 
 float autocvar_g_vehicle_spiderbot_speed_stop;
 float autocvar_g_vehicle_spiderbot_speed_strafe;
 float autocvar_g_vehicle_spiderbot_speed_walk;
 float autocvar_g_vehicle_spiderbot_turnspeed;
+float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
 float autocvar_g_vehicle_spiderbot_movement_inertia;
 
 float autocvar_g_vehicle_spiderbot_springlength;
 float autocvar_g_vehicle_spiderbot_springup;
 float autocvar_g_vehicle_spiderbot_springblend;
+float autocvar_g_vehicle_spiderbot_tiltlimit;
 
 float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
 float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
-float autocvar_g_vehicle_spiderbot_head_pitchspeed;
 float autocvar_g_vehicle_spiderbot_head_turnlimit;
 float autocvar_g_vehicle_spiderbot_head_turnspeed;
 
@@ -39,12 +42,17 @@ float autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
 float autocvar_g_vehicle_spiderbot_minigun_ammo_max;
 float autocvar_g_vehicle_spiderbot_minigun_ammo_regen;
 float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause;
+float autocvar_g_vehicle_spiderbot_minigun_force;
+float autocvar_g_vehicle_spiderbot_minigun_speed;
+float autocvar_g_vehicle_spiderbot_minigun_bulletconstant;
 
 float autocvar_g_vehicle_spiderbot_rocket_damage;
 float autocvar_g_vehicle_spiderbot_rocket_force;
 float autocvar_g_vehicle_spiderbot_rocket_radius;
 float autocvar_g_vehicle_spiderbot_rocket_speed;
+float autocvar_g_vehicle_spiderbot_rocket_spread;
 float autocvar_g_vehicle_spiderbot_rocket_refire;
+float autocvar_g_vehicle_spiderbot_rocket_refire2;
 float autocvar_g_vehicle_spiderbot_rocket_reload;
 float autocvar_g_vehicle_spiderbot_rocket_health;
 float autocvar_g_vehicle_spiderbot_rocket_noise;
@@ -56,7 +64,18 @@ vector autocvar_g_vehicle_spiderbot_bouncepain;
 
 void spiderbot_exit(float eject);
 void spiderbot_enter();
-void spiderbot_spawn();
+void spiderbot_spawn(float);
+#define SBRM_FIRST 0
+#define SBRM_VOLLY 0
+#define SBRM_GUIDE 1
+#define SBRM_ARTILLERY 2
+#define SBRM_LAST 2
+
+void spiderbot_rocket_artillery()
+{
+    self.nextthink  = time;
+    UpdateCSQCProjectile(self);
+}
 
 void spiderbot_rocket_unguided()
 {
@@ -113,65 +132,196 @@ void spiderbot_guide_release()
     }
 }
 
+float spiberbot_calcartillery_flighttime;  
+vector spiberbot_calcartillery(vector org, vector tgt, float ht)
+{
+       float grav, sdist, zdist, vs, vz, jumpheight;
+       vector sdir;
+       
+       grav  = autocvar_sv_gravity;
+       zdist = tgt_z - org_z;
+       sdist = vlen(tgt - org - zdist * '0 0 1');
+       sdir  = normalize(tgt - org - zdist * '0 0 1');
+
+       // how high do we need to go?
+       jumpheight = fabs(ht);
+       if(zdist > 0)
+               jumpheight = jumpheight + zdist;
+
+       // push so high...
+       vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
+
+       // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
+       if(ht < 0)
+               if(zdist < 0)
+                       vz = -vz;
+
+       vector solution;
+       solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
+       // ALWAYS solvable because jumpheight >= zdist
+       if(!solution_z)
+               solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
+       if(zdist == 0)
+               solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
+
+       if(zdist < 0)
+       {
+               // down-jump
+               if(ht < 0)
+               {
+                       // almost straight line type
+                       // jump apex is before the jump
+                       // we must take the larger one
+                       spiberbot_calcartillery_flighttime = solution_y;
+               }
+               else
+               {
+                       // regular jump
+                       // jump apex is during the jump
+                       // we must take the larger one too
+                       spiberbot_calcartillery_flighttime = solution_y;
+               }
+       }
+       else
+       {
+               // up-jump
+               if(ht < 0)
+               {
+                       // almost straight line type
+                       // jump apex is after the jump
+                       // we must take the smaller one
+                       spiberbot_calcartillery_flighttime = solution_x;
+               }
+               else
+               {
+                       // regular jump
+                       // jump apex is during the jump
+                       // we must take the larger one
+                       spiberbot_calcartillery_flighttime = solution_y;
+               }
+       }
+       vs = sdist / spiberbot_calcartillery_flighttime;
+
+       // finally calculate the velocity
+       return sdir * vs + '0 0 1' * vz;
+}
+
 void spiderbot_rocket_do()
 {
 
     vector v;
     entity rocket;
 
-    if (self.owner.BUTTON_ATCK2)
-    {
-        if (self.wait == 1)
-        if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
+    if (self.wait != -10)
+    {        
+        if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE)
         {
-            if(self.gun2.cnt < time && self.tur_head.frame == 9)
-                self.tur_head.frame = 1;
+            if (self.wait == 1)
+            if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
+            {
+                if(self.gun2.cnt < time && self.tur_head.frame == 9)
+                    self.tur_head.frame = 1;
 
-            return;
+                return;
+            }
+            self.wait = 1;
         }
-        self.wait = 1;
-    }
-    else
-    {
-        if(self.wait)
-            spiderbot_guide_release();
+        else
+        {
+            if(self.wait)
+                spiderbot_guide_release();
 
-        self.wait = 0;
+            self.wait = 0;
+        }
     }
-
+    
     if(self.gun2.cnt > time)
         return;
 
     if (self.tur_head.frame >= 9)
+    {
         self.tur_head.frame = 1;
+        self.wait = 0;
+    }
+        
+    if (self.wait != -10)
+        if not (self.owner.BUTTON_ATCK2)
+            return;
 
-    if not (self.owner.BUTTON_ATCK2)
-        return;
-
-    crosshair_trace(self.owner);
 
     v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
-    rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
-                           v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
-                           autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
-                           DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, FALSE);
-
-    rocket.cnt        = time + 15;
+    
+    switch(self.vehicle_weapon2mode)
+    {
+        case SBRM_VOLLY:
+            rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
+                                   v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+                                   autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+                                   DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, TRUE, self.owner);
+            crosshair_trace(self.owner);
+            float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
+            _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
+            rocket.nextthink  = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
+            rocket.think     = vehicles_projectile_explode;
+
+            if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1)
+                self.wait = -10;
+            break;
+        case SBRM_GUIDE:
+            rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
+                                   v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+                                   autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+                                   DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, FALSE, self.owner);
+            crosshair_trace(self.owner);
+            rocket.pos1       = trace_endpos;
+            rocket.nextthink  = time;
+            rocket.think      = spiderbot_rocket_guided;
+
+                
+        break;
+        case SBRM_ARTILLERY:
+            rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
+                                   v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+                                   autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+                                   DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, TRUE, self.owner);
+            
+            crosshair_trace(self.owner);
+            vector _ct_end = trace_endpos + trace_plane_normal;
+            
+            rocket.pos1       = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
+            rocket.pos1_z       = trace_endpos_z;
+            
+            traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);             
+            float h1 = 0.75 * vlen(v - trace_endpos);
+            
+            //v = trace_endpos;
+            traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self); 
+            float h2 = 0.75 * vlen(rocket.pos1 - v);
+            
+            rocket.velocity  = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
+            rocket.movetype  = MOVETYPE_TOSS;            
+            rocket.gravity   = 1;
+            //rocket.think     = spiderbot_rocket_artillery;   
+        break;
+    }
     rocket.classname  = "spiderbot_rocket";
-    rocket.pos1       = trace_endpos;
-    rocket.think      = spiderbot_rocket_guided;
-    rocket.nextthink  = time;
-    rocket.cnt        = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
-
+    
+    rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
+    
     self.tur_head.frame += 1;
     if (self.tur_head.frame == 9)
         self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload;
     else
-        self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_refire;
+        self.attack_finished_single = ((self.vehicle_weapon2mode ==  SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
 
     self.gun2.cnt = time + self.attack_finished_single;
 }
 
+float spiderbot_aiframe()
+{
+    return FALSE;
+}
+
 float spiderbot_frame()
 {
     vector ad, vf;
@@ -190,6 +340,7 @@ float spiderbot_frame()
     player.BUTTON_ZOOM      = 0;
     player.BUTTON_CROUCH    = 0;
     player.switchweapon     = 0;
+    
 
 #if 1 // 0 to enable per-gun impact aux crosshairs
     // Avarage gun impact point's -> aux cross
@@ -219,23 +370,19 @@ float spiderbot_frame()
     //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
     
     // Rotate head
-    ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
+    ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;    
     ad_y = bound(-ftmp, ad_y, ftmp);
     spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
 
     // Pitch head
-    ftmp = autocvar_g_vehicle_spiderbot_head_pitchspeed * sys_frametime;
     ad_x = bound(ftmp * -1, ad_x, ftmp);
     spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
 
-    // Turn Body
-    ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
-    ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
 
     //fixedmakevectors(spider.angles);
     makevectors(spider.angles + '-2 0 0' * spider.angles_x);
     
-    movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend);
+    movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
 
     if(spider.flags & FL_ONGROUND)
     {
@@ -272,6 +419,13 @@ float spiderbot_frame()
             }
             else
             {
+                // Turn Body
+                if(player.movement_x == 0 && player.movement_y != 0)
+                    ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
+                else
+                    ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
+                
+                ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);                
                 spider.angles_y = anglemods(spider.angles_y + ftmp);
                 spider.tur_head.angles_y -= ftmp;
 
@@ -323,8 +477,8 @@ float spiderbot_frame()
         }
     }
 
-    self.angles_x = bound(-45, self.angles_x, 45);
-    self.angles_z = bound(-45, self.angles_z, 45);
+    self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
+    self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
 
     if(player.BUTTON_ATCK)
     {
@@ -342,11 +496,17 @@ float spiderbot_frame()
             v_forward = normalize(v_forward);
             v += v_forward * 50;
 
-            fireBullet (v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
-                autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
+//void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant)
+
+            fireBallisticBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_speed,
+                                5, autocvar_g_vehicle_spiderbot_minigun_damage, 0, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_SBMINIGUN, 0, 1, autocvar_g_vehicle_spiderbot_minigun_bulletconstant);
+            endFireBallisticBullet();
+
+//            fireBullet (v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
+//                autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
 
             sound (gun, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
-            trailparticles(self, particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
+            //trailparticles(self, particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
             pointparticles(particleeffectnum("spiderbot_minigun_muzzleflash"), v, v_forward * 2500, 1);
 
             self = spider;
@@ -364,18 +524,18 @@ float spiderbot_frame()
         }
     }
     else
-        vehicles_regen(cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
+        vehicles_regen(spider.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
                                            autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause,
-                                           autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime);
+                                           autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, FALSE);
         
 
     spiderbot_rocket_do();
 
     if(self.vehicle_flags  & VHF_SHIELDREGEN)
-        vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime);
+        vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, TRUE);
 
     if(self.vehicle_flags  & VHF_HEALTHREGEN)
-        vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime);
+        vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, FALSE);
 
     player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
     player.vehicle_ammo2 = spider.tur_head.frame;
@@ -388,10 +548,10 @@ float spiderbot_frame()
     setorigin(player, spider.origin + '0 0 1' * SPIDERBOT_MAX_z);
     player.velocity = spider.velocity;
 
-    VEHICLE_UPDATE_PLAYER(health, spiderbot);
+    VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
 
     if(self.vehicle_flags & VHF_HASSHIELD)
-        VEHICLE_UPDATE_PLAYER(shield, spiderbot);
+        VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
 
     self = player;
     return 1;    
@@ -406,8 +566,9 @@ void spiderbot_think()
 
 void spiderbot_enter()
 {
+    self.vehicle_weapon2mode = SBRM_GUIDE;
     self.movetype   = MOVETYPE_WALK;
-
+    CSQCVehicleSetup(self.owner, 0);
     self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
     self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
 
@@ -434,7 +595,7 @@ void spiderbot_exit(float eject)
         e = e.chain;
     }
 
-    self.velocity   = '0 0 0';
+    //self.velocity   = '0 0 0';
     self.think      = spiderbot_think;
     self.nextthink  = time;
     self.frame      = 5;
@@ -454,37 +615,33 @@ void spiderbot_exit(float eject)
        }
        else
        {
-           self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed;
-           self.owner.oldvelocity = self.owner.velocity;           
-           spot = self.origin - v_forward * 200 + '0 0 64';
-           spot = vehicles_findgoodexit(spot);
+               if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe)
+               {
+                       self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 128 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin + v_forward * 256 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+           self.owner.oldvelocity = self.owner.velocity;
            setorigin(self.owner , spot);
        }
-    antilag_clear(self.owner);
+       
+       antilag_clear(self.owner);
     self.owner = world;
 }
+
 void spider_impact()
 {
     if(autocvar_g_vehicle_spiderbot_bouncepain_x)
         vehilces_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);    
 }
-void spiderbot_spawn()
-{
-    self.frame              = 5;
-    self.tur_head.frame     = 1;
-    self.think              = spiderbot_think;
-    self.nextthink          = time;
-    self.vehicle_health     = autocvar_g_vehicle_spiderbot_health;
-    self.vehicle_shield     = autocvar_g_vehicle_spiderbot_shield;
-    self.movetype           = MOVETYPE_WALK;
-    self.solid              = SOLID_SLIDEBOX;
-    self.alpha              = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
-    self.tur_head.angles    = '0 0 0';
-
-    setorigin(self, self.pos1 + '0 0 128');
-    self.angles = self.pos2;
-    self.vehicle_impact = spider_impact;
-}
 
 void spiderbot_headfade()
 {
@@ -566,7 +723,7 @@ void spiderbot_blowup()
     SUB_SetFade(g1, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10));
     SUB_SetFade(g2, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10));
 
-    RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_SBBLOWUP, world);
+    RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_SBBLOWUP, world);
 
     self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
     self.movetype   = MOVETYPE_NONE;
@@ -593,43 +750,81 @@ void spiderbot_die()
        self.movetype           = MOVETYPE_TOSS;
 }
 
-void vewhicle_spiderbot_dinit()
+float spiderbot_impulse(float _imp)
 {
-    if not (vehicle_initialize(
-             "Spiderbot",
-             "models/vehicles/spiderbot.dpm",
-             "models/vehicles/spiderbot_top.dpm",
-             "models/vehicles/spiderbot_cockpit.dpm",
-             "tag_head", "tag_hud", "",
-             HUD_SPIDERBOT,
-             SPIDERBOT_MIN, SPIDERBOT_MAX,
-             FALSE,
-             spiderbot_spawn, autocvar_g_vehicle_spiderbot_respawntime,
-             spiderbot_frame,
-             spiderbot_enter, spiderbot_exit,
-             spiderbot_die,   spiderbot_think,
-             FALSE))
+    switch(_imp)
     {
-        remove(self);
-        return;
-    }
-
-
-    self.gun1               = spawn();
-    self.gun2               = spawn();
+        case 10:
+        case 15:        
+        case 18:
+            self.vehicle.vehicle_weapon2mode += 1;
+            if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
+                self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
+            
+            //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
+            CSQCVehicleSetup(self, 0);
+            return TRUE;
+        case 12:
+        case 16:
+        case 19:
+            self.vehicle.vehicle_weapon2mode -= 1;
+            if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
+                self.vehicle.vehicle_weapon2mode = SBRM_LAST;
+            
+            //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
+            CSQCVehicleSetup(self, 0);
+            return TRUE;
+
+        /*                     
+        case 17: // toss gun, could be used to exit?
+            break;
+        case 20: // Manual minigun reload?
+            break;
+        */
+    }    
+    return FALSE;
+}
 
-    setmodel(self.gun1, "models/vehicles/spiderbot_barrels.dpm");
-    setmodel(self.gun2, "models/vehicles/spiderbot_barrels.dpm");
+void spiderbot_spawn(float _f)
+{
+    if(!self.gun1)
+    {        
+        self.vehicles_impusle   = spiderbot_impulse;
+        self.gun1               = spawn();
+        self.gun2               = spawn();    
+        setmodel(self.gun1, "models/vehicles/spiderbot_barrels.dpm");
+        setmodel(self.gun2, "models/vehicles/spiderbot_barrels.dpm");
+        setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
+        setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
+        self.gravity            = 2;
+        self.mass               = 5000;
+    }
 
-    setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
-    setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
+    self.frame              = 5;
+    self.tur_head.frame     = 1;
+    self.think              = spiderbot_think;
+    self.nextthink          = time;
+    self.vehicle_health     = autocvar_g_vehicle_spiderbot_health;
+    self.vehicle_shield     = autocvar_g_vehicle_spiderbot_shield;
+    self.movetype           = MOVETYPE_WALK;
+    self.solid              = SOLID_SLIDEBOX;
+    self.alpha              = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
+    self.tur_head.angles    = '0 0 0';    
 
-    self.gravity            = 2;
-    self.mass               = 5000;
+    setorigin(self, self.pos1 + '0 0 128');
+    self.angles = self.pos2;
+    self.vehicle_impact = spider_impact;
+    self.damageforcescale = 0.03;
 }
 
 void spawnfunc_vehicle_spiderbot()
 {
+    if(!autocvar_g_vehicle_spiderbot)
+    {
+        remove(self);
+        return;
+    }        
+
     self.vehicle_flags |= VHF_DMGSHAKE;
     //self.vehicle_flags |= VHF_DMGROLL;
     //self.vehicle_flags |= VHF_DMGHEADROLL;
@@ -651,7 +846,6 @@ void spawnfunc_vehicle_spiderbot()
     precache_sound ( "vehicles/spiderbot_walk.wav");
     precache_sound ( "vehicles/spiderbot_land.wav");
 
-    vehicles_configcheck("vehicle_spiderbot.cfg", autocvar_g_vehicle_spiderbot_health);
     if(autocvar_g_vehicle_spiderbot_shield)
         self.vehicle_flags |= VHF_HASSHIELD;
 
@@ -660,12 +854,26 @@ void spawnfunc_vehicle_spiderbot()
 
     if(autocvar_g_vehicle_spiderbot_health_regen)
         self.vehicle_flags |= VHF_HEALTHREGEN;
-    
-    self.think = vewhicle_spiderbot_dinit;
-    
-    if(g_assault)
-        self.nextthink = time + 0.5;
-    else
-        self.nextthink = time + (autocvar_g_vehicles_delayspawn ? autocvar_g_vehicle_spiderbot_respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter) : 0.5);
+        
+    if not (vehicle_initialize(
+             "Spiderbot",
+             "models/vehicles/spiderbot.dpm",
+             "models/vehicles/spiderbot_top.dpm",
+             "models/vehicles/spiderbot_cockpit.dpm",
+             "tag_head", "tag_hud", "",
+             HUD_SPIDERBOT,
+             SPIDERBOT_MIN, SPIDERBOT_MAX,
+             FALSE,
+             spiderbot_spawn, autocvar_g_vehicle_spiderbot_respawntime,
+             spiderbot_frame,
+             spiderbot_enter, spiderbot_exit,
+             spiderbot_die,   spiderbot_think,
+             FALSE, 
+             autocvar_g_vehicle_spiderbot_health,
+             autocvar_g_vehicle_spiderbot_shield))
+    {
+        remove(self);
+        return;
+    }
 }
 #endif // SVQC
index 20c74d3a17e24deb0012882c634c9d527d4747d0..f66c2b925278575cb08235a72394a572aab208de 100644 (file)
@@ -4,6 +4,14 @@ float autocvar_g_vehicles_delayspawn;
 float autocvar_g_vehicles_delayspawn_jitter;
 float autocvar_g_vehicles_allow_flagcarry;
 
+var float autocvar_g_vehicles_nex_damagerate = 0.5;
+var float autocvar_g_vehicles_uzi_damagerate = 0.5;
+var float autocvar_g_vehicles_rifle_damagerate = 0.75;
+var float autocvar_g_vehicles_minstanex_damagerate = 0.001;
+var float autocvar_g_vehicles_tag_damagerate = 5;
+
+float autocvar_g_vehicles;
+
 void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
 void vehicles_return();
 void vehicles_enter();
@@ -39,6 +47,9 @@ float SendAuxiliaryXhair(entity to, float sf)
 
 void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id)
 {
+    if (clienttype(own) != CLIENTTYPE_REAL)
+        return;
+
     entity axh;
 
     axh_id = bound(0, axh_id, MAX_AXH);
@@ -64,7 +75,7 @@ void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id)
 // WriteByte(MSG_ONE, SVC_TEMPENTITY) uses reliable messagess, never use for thinsg that need continous updates.
 void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id)
 {
-       msg_entity = own;
+       msgexntity = own;
 
        WriteByte(MSG_ONE, SVC_TEMPENTITY);
        WriteByte(MSG_ONE, TE_CSQC_AUXILIARYXHAIR);
@@ -84,18 +95,24 @@ void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id)
 // End AuxiliaryXhair
 
 /**
-    Notifies the client that he enterd a vehicle, and sends 
+    Notifies the client that he enterd a vehicle, and sends
     realavent data.
-    
+
     only sends vehicle_id atm (wich is a HUD_* constant, ex. HUD_SPIDERBOT)
 **/
 void CSQCVehicleSetup(entity own, float vehicle_id)
 {
+    if (clienttype(own) != CLIENTTYPE_REAL)
+        return;
+       
        msg_entity = own;
 
        WriteByte(MSG_ONE, SVC_TEMPENTITY);
        WriteByte(MSG_ONE, TE_CSQC_VEHICLESETUP);
-       WriteByte(MSG_ONE, vehicle_id);
+       if(vehicle_id != 0)
+           WriteByte(MSG_ONE, vehicle_id);        
+       else
+        WriteByte(MSG_ONE, 1 + own.vehicle.vehicle_weapon2mode + HUD_VEHICLE_LAST);
 }
 
 /** vehicles_locktarget
@@ -115,6 +132,121 @@ void CSQCVehicleSetup(entity own, float vehicle_id)
 .float  lock_strength;
 .float  lock_time;
 .float  lock_soundtime;
+float  DAMAGE_TARGETDRONE = 10;
+
+vector targetdrone_getnewspot()
+{
+
+       vector spot;
+       float i;
+       for(i = 0; i < 100; ++i)
+       {
+               spot = self.origin + randomvec() * 1024;
+               tracebox(spot, self.mins, self.maxs, spot, MOVE_NORMAL, self);
+               if(trace_fraction == 1.0 && trace_startsolid == 0 && trace_allsolid == 0)
+                       return spot;
+       }
+       return self.origin;
+}
+
+#if 0
+void targetdrone_think();
+void targetdrone_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void targetdrone_renwe()
+{
+       self.think = targetdrone_think;
+       self.nextthink = time + 0.1;
+       setorigin(self, targetdrone_getnewspot());
+       self.health = 200;
+       self.takedamage = DAMAGE_TARGETDRONE;
+       self.event_damage = targetdrone_damage;
+       self.solid = SOLID_BBOX;
+       setmodel(self, "models/runematch/rune.mdl");
+       self.effects = EF_LOWPRECISION;
+       self.scale = 10;
+       self.movetype = MOVETYPE_BOUNCEMISSILE;
+       setsize(self, '-100 -100 -100', '100 100 100');
+
+}
+void targetdrone_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+       self.health -= damage;
+       if(self.health <= 0)
+       {
+               pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
+
+               if(!self.cnt)
+                       remove(self);
+               else
+               {
+                       self.think = targetdrone_renwe;
+                       self.nextthink = time + 1 + random() * 2;
+                       self.solid = SOLID_NOT;
+                       setmodel(self, "");
+               }
+       }
+}
+entity targetdrone_getfear()
+{
+       entity fear;
+       float i;
+
+       for(i = 64; i <= 1024; i += 64)
+       {
+               fear = findradius(self.origin, i);
+               while(fear)
+               {
+                       if(fear.bot_dodge)
+                               return fear;
+
+                       fear = fear.chain;
+               }
+       }
+
+       return world;
+}
+void targetdrone_think()
+{
+       self.nextthink = time + 0.1;
+
+       if(self.wp00)
+       if(self.wp00.deadflag != DEAD_NO)
+               self.wp00 = targetdrone_getfear();
+
+       if(!self.wp00)
+               self.wp00 = targetdrone_getfear();
+
+       vector newdir;
+
+       if(self.wp00)
+               newdir = steerlib_push(self.wp00.origin) + randomvec() * 0.75;
+       else
+               newdir = randomvec() * 0.75;
+
+       newdir = newdir * 0.5 + normalize(self.velocity) * 0.5;
+
+       if(self.wp00)
+               self.velocity = normalize(newdir) * (500 + (1024 / min(vlen(self.wp00.origin - self.origin), 1024)) * 700);
+       else
+               self.velocity = normalize(newdir) * 750;
+
+       tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 2, MOVE_NORMAL, self);
+       if(trace_fraction != 1.0)
+               self.velocity = self.velocity * -1;
+
+       //normalize((normalize(self.velocity) * 0.5 + newdir * 0.5)) * 750;
+}
+
+void targetdrone_spawn(vector _where, float _autorenew)
+{
+       entity drone = spawn();
+       setorigin(drone, _where);
+       drone.think = targetdrone_renwe;
+       drone.nextthink = time + 0.1;
+       drone.cnt = _autorenew;
+}
+#endif
+
 void vehicles_locktarget(float incr, float decr, float _lock_time)
 {
     if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
@@ -132,7 +264,7 @@ void vehicles_locktarget(float incr, float decr, float _lock_time)
             self.lock_soundtime = time + 0.5;
             play2(self.owner, "vehicles/locked.wav");
         }
-        
+
         return;
     }
 
@@ -144,28 +276,30 @@ void vehicles_locktarget(float incr, float decr, float _lock_time)
         if(trace_ent.deadflag != DEAD_NO)
             trace_ent = world;
 
-        if not (trace_ent.vehicle_flags & VHF_ISVEHICLE || trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+        if not (trace_ent.vehicle_flags & VHF_ISVEHICLE ||
+                               trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET ||
+                               trace_ent.takedamage == DAMAGE_TARGETDRONE)
             trace_ent = world;
     }
 
     if(self.lock_target == world && trace_ent != world)
         self.lock_target = trace_ent;
-    
-    if(self.lock_target && trace_ent == self.lock_target) 
-    {            
+
+    if(self.lock_target && trace_ent == self.lock_target)
+    {
         if(self.lock_strength != 1 && self.lock_strength + incr >= 1)
         {
             play2(self.owner, "vehicles/lock.wav");
             self.lock_soundtime = time + 0.8;
-        }        
+        }
         else if (self.lock_strength != 1 && self.lock_soundtime < time)
-        {            
+        {
             play2(self.owner, "vehicles/locking.wav");
             self.lock_soundtime = time + 0.3;
         }
-        
-    }    
-        
+
+    }
+
     // Have a locking target
     // Trace hit current target
     if(trace_ent == self.lock_target && trace_ent != world)
@@ -186,8 +320,8 @@ void vehicles_locktarget(float incr, float decr, float _lock_time)
     }
 }
 
-#define VEHICLE_UPDATE_PLAYER(fld,vhname) \
-self.owner.vehicle_##fld = (self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
+#define VEHICLE_UPDATE_PLAYER(ply,fld,vhname) \
+ply.vehicle_##fld = (self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
 
 #define vehicles_sweap_collision(orig,vel,dt,acm,mult) \
 traceline(orig, orig + vel * dt, MOVE_NORMAL, self); \
@@ -237,8 +371,8 @@ void vehicles_projectile_damage(entity inflictor, entity attacker, float damage,
 {
     // Ignore damage from oterh projectiles from my owner (dont mess up volly's)
     if(inflictor.owner == self.owner)
-        return; 
-    
+        return;
+
     self.health -= damage;
     self.velocity += force;
     if(self.health < 1)
@@ -248,7 +382,6 @@ void vehicles_projectile_damage(entity inflictor, entity attacker, float damage,
         self.think = self.use;
         self.nextthink = time;
     }
-
 }
 
 void vehicles_projectile_explode()
@@ -274,7 +407,7 @@ entity vehicles_projectile(string _mzlfx, string _mzlsound,
                            vector _org, vector _vel,
                            float _dmg, float _radi, float _force,  float _size,
                            float _deahtype, float _projtype, float _health,
-                           float _cull, float _clianim)
+                           float _cull, float _clianim, entity _owner)
 {
     entity proj;
 
@@ -296,7 +429,7 @@ entity vehicles_projectile(string _mzlfx, string _mzlsound,
     proj.touch            = vehicles_projectile_explode;
     proj.use              = vehicles_projectile_explode;
     proj.owner            = self;
-    proj.realowner        = self.owner;
+    proj.realowner        = _owner;
     proj.think            = SUB_Remove;
     proj.nextthink        = time + 30;
 
@@ -359,9 +492,12 @@ void vehicles_spawn()
     setorigin(self, self.pos1 + '0 0 0');
     // Show it
     pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
-
+    
+    if(self.vehicle_controller)
+        self.team = self.vehicle_controller.team;
+       
     vehicles_reset_colors();
-    self.vehicle_spawn();
+    self.vehicle_spawn(VHSF_NORMAL);
 }
 
 // Better way of determening whats crushable needed! (fl_crushable?)
@@ -377,21 +513,21 @@ float vehicles_crushable(entity e)
 }
 
 void vehilces_impact(float _minspeed, float _speedfac, float _maxpain)
-{    
+{
     if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
         return;
-    
+
     if(self.play_time < time)
-    {                    
+    {
         float wc = vlen(self.velocity - self.oldvelocity);
         //dprint("oldvel: ", vtos(self.oldvelocity), "\n");
         //dprint("vel: ", vtos(self.velocity), "\n");
         if(_minspeed < wc)
         {
-            float take = take = min(_speedfac * wc, _maxpain);
+            float take = min(_speedfac * wc, _maxpain);
             Damage (self, world, world, take, DEATH_FALL, self.origin, '0 0 0');
             self.play_time = time + 0.25;
-            
+
             //dprint("wc: ", ftos(wc), "\n");
             //dprint("take: ", ftos(take), "\n");
         }
@@ -409,14 +545,14 @@ void vehicles_touch()
         {
             if(vlen(self.velocity) != 0)
                 Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VHCRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
-            
+
             return; // Dont do selfdamage when hitting "soft targets".
         }
-        
+
         if(self.play_time < time)
         if(self.vehicle_impact)
             self.vehicle_impact();
-        
+
         return;
     }
 
@@ -429,18 +565,18 @@ void vehicles_touch()
     if(other.vehicle != world)
         return;
 
-    // Remove this when bots know how to use vehicles.
-    if (clienttype(other) != CLIENTTYPE_REAL)
-        return;
-
     vehicles_enter();
 }
-
+var float autocvar_g_vehicles_allow_bots = 0;
 void vehicles_enter()
 {
    // Remove this when bots know how to use vehicles
-    if (clienttype(other) != CLIENTTYPE_REAL)
-        return;
+   
+    if (clienttype(other) == CLIENTTYPE_BOT)    
+        if (autocvar_g_vehicles_allow_bots)
+            dprint("Bot enters vehicle\n"); // This is where we need to disconnect (some, all?) normal bot AI and hand over to vehicle's _aiframe()
+        else
+            return;
 
     if(self.phase > time)
         return;
@@ -449,7 +585,7 @@ void vehicles_enter()
     if(self.team)
     if(self.team != other.team)
         return;
-        
+
     RemoveGrapplingHook(other);
 
     self.vehicle_ammo1   = 0;
@@ -497,41 +633,44 @@ void vehicles_enter()
 
     self.team                 = self.owner.team;
     self.flags               -= FL_NOTARGET;
-
-    msg_entity = other;
-    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
-    WriteEntity(MSG_ONE, self.vehicle_viewport);
-
-    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
-    if(self.tur_head)
-    {
-        WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x); // tilt
-        WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y); // yaw
-        WriteAngle(MSG_ONE, 0);                                      // roll
-    }
-    else
+    
+    if (clienttype(other) == CLIENTTYPE_REAL)
     {
-        WriteAngle(MSG_ONE,  self.angles_x * -1); // tilt
-        WriteAngle(MSG_ONE,  self.angles_y);      // yaw
-        WriteAngle(MSG_ONE,  0);                  // roll
+        msg_entity = other;
+        WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+        WriteEntity(MSG_ONE, self.vehicle_viewport);
+                
+        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+        if(self.tur_head)
+        {
+            WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x); // tilt
+            WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y); // yaw
+            WriteAngle(MSG_ONE, 0);                                      // roll
+        }
+        else
+        {
+            WriteAngle(MSG_ONE,  self.angles_x * -1); // tilt
+            WriteAngle(MSG_ONE,  self.angles_y);      // yaw
+            WriteAngle(MSG_ONE,  0);                  // roll
+        }
     }
 
     vehicles_clearrturn();
 
     CSQCVehicleSetup(self.owner, self.hud);
-    
+
     if(other.flagcarried)
     {
         if(!autocvar_g_vehicles_allow_flagcarry)
             DropFlag(other.flagcarried, world, world);
         else
-        {            
+        {
             other.flagcarried.scale = 1;
-            setattachment(other.flagcarried, self, ""); 
-            setorigin(other, '0 0 96');
+            setattachment(other.flagcarried, self, "");
+            setorigin(other.flagcarried, self.maxs_z * '0 0 1');
         }
     }
-    
+
     self.vehicle_enter();
     antilag_clear(other);
 }
@@ -545,17 +684,17 @@ vector vehicles_findgoodexit(vector prefer_spot)
 {
     //vector exitspot;
     float mysize;
-    
+
     tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, self.owner);
     if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
         return prefer_spot;
-    
-    mysize = vlen(self.maxs - self.mins);
+
+    mysize = 1.5 * vlen(self.maxs - self.mins);
     float i;
     vector v, v2;
     v2 = 0.5 * (self.absmin + self.absmax);
     for(i = 0; i < 100; ++i)
-    {        
+    {
         v = randomvec();
         v_z = 0;
         v = v2 + normalize(v) * mysize;
@@ -563,13 +702,13 @@ vector vehicles_findgoodexit(vector prefer_spot)
         if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
             return v;
     }
-    
+
     /*
     exitspot = (self.origin + '0 0 48') + v_forward * mysize;
     tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
     if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
         return exitspot;
-    
+
     exitspot = (self.origin + '0 0 48') - v_forward * mysize;
     tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
     if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
@@ -579,13 +718,13 @@ vector vehicles_findgoodexit(vector prefer_spot)
     tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
     if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
         return exitspot;
-    
+
     exitspot = (self.origin + '0 0 48') - v_right * mysize;
     tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
     if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
         return exitspot;
     */
-    
+
     return self.origin;
 }
 
@@ -593,82 +732,111 @@ vector vehicles_findgoodexit(vector prefer_spot)
     Standarrd vehicle release fucntion.
     custom code goes in self.vehicle_exit
 **/
+float vehicles_exit_running;
 void vehicles_exit(float eject)
-{      
-    entity oldself;
+{
+    entity _vehicle;
+    entity _player;
+    entity _oldself = self;
+    
+    if(vehicles_exit_running)
+    {
+        dprint("^1vehicles_exit allready running! this is not good..\n");
+        return;
+    }
+    
+    vehicles_exit_running = TRUE;
     if(self.flags & FL_CLIENT)
     {
-        oldself = self;
-        self = self.vehicle;
+        _vehicle = self.vehicle;
+            
+        if (_vehicle.vehicle_flags & VHF_PLAYERSLOT)
+        {
+            _vehicle.vehicle_exit(eject);
+            self = _oldself;
+            vehicles_exit_running = FALSE;
+            return;            
+        }
     }
+    else
+        _vehicle = self;
+    
+    _player = _vehicle.owner;
     
-       self.flags |= FL_NOTARGET;
+    self = _vehicle;
 
-    if (self.owner)
+    if (_player)
     {
-        msg_entity = self.owner;
-        WriteByte (MSG_ONE, SVC_SETVIEWPORT);
-        WriteEntity( MSG_ONE, self.owner);
-
-        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
-        WriteAngle(MSG_ONE, 0);                 // pich
-        WriteAngle(MSG_ONE, self.angles_y);     // yaw
-        WriteAngle(MSG_ONE, 0);                 // roll
-
-        setsize(self.owner, PL_MIN,PL_MAX);
-
-        self.owner.takedamage     = DAMAGE_AIM;
-        self.owner.solid          = SOLID_SLIDEBOX;
-        self.owner.movetype       = MOVETYPE_WALK;
-        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.owner.switchweapon   = self.switchweapon;
-        //self.owner.BUTTON_USE     = 0;
+        if (clienttype(_player) == CLIENTTYPE_REAL)
+        {
+            msg_entity = _player;
+            WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+            WriteEntity( MSG_ONE, _player);
+
+            WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+            WriteAngle(MSG_ONE, 0);
+            WriteAngle(MSG_ONE, _vehicle.angles_y);
+            WriteAngle(MSG_ONE, 0);
+        }
         
-        CSQCVehicleSetup(self.owner, HUD_NORMAL);
-    }
-
-    if(self.deadflag == DEAD_NO)
-        self.avelocity          = '0 0 0';
-
-    self.vehicle_hudmodel.viewmodelforclient = self;
-       self.tur_head.nodrawtoclient             = world;
-    vehicles_setreturn();
-
-    self.phase = time + 1;
+        setsize(_player, PL_MIN,PL_MAX);
+
+        _player.takedamage     = DAMAGE_AIM;
+        _player.solid          = SOLID_SLIDEBOX;
+        _player.movetype       = MOVETYPE_WALK;
+        _player.effects        &~= EF_NODRAW;
+        _player.alpha          = 1;
+        _player.PlayerPhysplug = SUB_Null;
+        _player.vehicle        = world;
+        _player.view_ofs       = PL_VIEW_OFS;
+        _player.event_damage   = PlayerDamage;
+        _player.hud            = HUD_NORMAL;
+        _player.switchweapon   = _vehicle.switchweapon;
+
+        if(_player.flagcarried)
+        {
+            _player.flagcarried.scale = 0.6;
+            setattachment(_player.flagcarried, _player, "");
+            setorigin(_player.flagcarried, FLAG_CARRY_POS);
+        }
 
+        CSQCVehicleSetup(_player, HUD_NORMAL);
+    }
+    _vehicle.flags |= FL_NOTARGET;
+    
+    if(_vehicle.deadflag == DEAD_NO)
+        _vehicle.avelocity          = '0 0 0';
+    
+    _vehicle.tur_head.nodrawtoclient             = world;
+    
     if(!teamplay)
-        self.team = 0;
+        _vehicle.team = 0;
     else
-        self.team = self.tur_head.team;
+        _vehicle.team = _vehicle.tur_head.team;
+        
+    sound (_vehicle, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTN_NORM);
+    _vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;   
+    _vehicle.phase = time + 1;
     
-    if(self.owner.flagcarried)
-    {
-        self.owner.flagcarried.scale = 0.6;
-        setattachment(self.owner.flagcarried, self.owner, ""); 
-        setorigin(self.owner.flagcarried, FLAG_CARRY_POS);
-    }
+    _vehicle.vehicle_exit(eject);
     
-    sound (self, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTN_NORM);
-    self.vehicle_exit(eject);
-    self.owner = world;
-    vehicles_reset_colors();
+    vehicles_setreturn();
+    vehicles_reset_colors();        
+    _vehicle.owner = world;
+    self = _oldself;
     
-    if(oldself)
-        self = oldself;
+    vehicles_exit_running = FALSE;
 }
 
 
-void vehicles_regen(.float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time)
+void vehicles_regen(float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale)
 {
     if(self.regen_field < field_max)
-    if(self.timer + rpause < time)
+    if(timer + rpause < time)
     {
+        if(_healthscale)
+            regen = regen * (self.vehicle_health / self.tur_health);
+            
         self.regen_field = min(self.regen_field + regen * delta_time, field_max);
 
         if(self.owner)
@@ -683,6 +851,7 @@ void shieldhit_think()
     {
         //setmodel(self, "");
         self.alpha = -1;
+        self.effects |= EF_NODRAW;
     }
     else
     {
@@ -691,31 +860,48 @@ void shieldhit_think()
 }
 
 void vehicles_painframe()
-{    
+{
     if(self.owner.vehicle_health <= 50)
     if(self.pain_frame < time)
-    {  
-        float _ftmp;  
+    {
+        float _ftmp;
         _ftmp = self.owner.vehicle_health / 50;
         self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp);
         pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
-        
+
         if(self.vehicle_flags & VHF_DMGSHAKE)
             self.velocity += randomvec() * 30;
-        
+
         if(self.vehicle_flags & VHF_DMGROLL)
             if(self.vehicle_flags & VHF_DMGHEADROLL)
                 self.tur_head.angles += randomvec();
             else
                 self.angles += randomvec();
-        
-    }    
+
+    }
 }
 
 void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
     self.dmg_time = time;
+    
+    if(DEATH_ISWEAPON(deathtype, WEP_NEX))
+        damage *= autocvar_g_vehicles_nex_damagerate;
+        
+    if(DEATH_ISWEAPON(deathtype, WEP_UZI))
+        damage *= autocvar_g_vehicles_uzi_damagerate;
+        
+    if(DEATH_ISWEAPON(deathtype, WEP_RIFLE))
+        damage *= autocvar_g_vehicles_rifle_damagerate;
+        
+    if(DEATH_ISWEAPON(deathtype, WEP_MINSTANEX))
+        damage *= autocvar_g_vehicles_minstanex_damagerate;
 
+    if(DEATH_ISWEAPON(deathtype, WEP_SEEKER))
+        damage *= autocvar_g_vehicles_tag_damagerate;
+    
+    self.enemy = attacker;
+    
     if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0))
     {
         if (wasfreed(self.vehicle_shieldent) || self.vehicle_shieldent == world)
@@ -734,6 +920,7 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat
         self.vehicle_shieldent.alpha       = 0.45;
         self.vehicle_shieldent.angles      = vectoangles(normalize(hitloc - (self.origin + self.vehicle_shieldent.origin))) - self.angles;
         self.vehicle_shieldent.nextthink   = time;
+        self.vehicle_shieldent.effects &~= EF_NODRAW;
 
         self.vehicle_shield -= damage;
 
@@ -743,7 +930,7 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat
             self.vehicle_shieldent.colormod = '2 0 0';
             self.vehicle_shield             = 0;
             self.vehicle_shieldent.alpha    = 0.75;
-            
+
                if(sound_allowed(MSG_BROADCAST, attacker))
                 spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM);   // FIXME: PLACEHOLDER
         }
@@ -759,8 +946,11 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat
         if(sound_allowed(MSG_BROADCAST, attacker))
             spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM);  // FIXME: PLACEHOLDER
     }
-
-    self.velocity += force; // * (vlen(force) / self.mass);
+    
+       if(self.damageforcescale < 1 && self.damageforcescale > 0)
+               self.velocity += force * self.damageforcescale;
+       else
+               self.velocity += force;
 
     if(self.vehicle_health <= 0)
     {
@@ -770,6 +960,9 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat
             else
                 vehicles_exit(VHEF_RELESE);
 
+
+        antilag_clear(self);
+
         self.vehicle_die();
         vehicles_setreturn();
     }
@@ -782,15 +975,15 @@ void vehicles_clearrturn()
     ret = findchain(classname, "vehicle_return");
     while(ret)
     {
-        if(ret.enemy == self)
+        if(ret.wp00 == self)
         {
             ret.classname   = "";
             ret.think       = SUB_Remove;
-            ret.nextthink   = time + 0.1;            
-            
+            ret.nextthink   = time + 0.1;
+
             if(ret.waypointsprite_attached)
                 WaypointSprite_Kill(ret.waypointsprite_attached);
-            
+
             return;
         }
         ret = ret.chain;
@@ -799,14 +992,14 @@ void vehicles_clearrturn()
 
 void vehicles_return()
 {
-    pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1);
+    pointparticles(particleeffectnum("teleport"), self.wp00.origin + '0 0 64', '0 0 0', 1);
 
-    self.enemy.think     = vehicles_spawn;
-    self.enemy.nextthink = time;
+    self.wp00.think     = vehicles_spawn;
+    self.wp00.nextthink = time;
 
     if(self.waypointsprite_attached)
         WaypointSprite_Kill(self.waypointsprite_attached);
-            
+
     remove(self);
 }
 
@@ -814,50 +1007,50 @@ void vehicles_showwp_goaway()
 {
     if(self.waypointsprite_attached)
         WaypointSprite_Kill(self.waypointsprite_attached);
-            
+
     remove(self);
-    
+
 }
 
 void vehicles_showwp()
 {
     entity oldself;
     vector rgb;
-    
+
     if(self.cnt)
-    {        
+    {
         self.think      = vehicles_return;
         self.nextthink  = self.cnt;
-    }    
+    }
     else
     {
         self.think      = vehicles_return;
         self.nextthink  = time +1;
-        
+
         oldself = self;
         self = spawn();
         setmodel(self, "null");
-        self.team = oldself.enemy.team;
-        self.enemy = oldself.enemy;
-        setorigin(self, oldself.enemy.pos1);
-        
+        self.team = oldself.wp00.team;
+        self.wp00 = oldself.wp00;
+        setorigin(self, oldself.wp00.pos1);
+
         self.nextthink = time + 5;
         self.think = vehicles_showwp_goaway;
     }
-    
+
     if(teamplay && self.team)
            rgb = TeamColor(self.team);
     else
            rgb = '1 1 1';
     WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
     if(self.waypointsprite_attached)
-    {        
-        WaypointSprite_UpdateRule(self.waypointsprite_attached, self.enemy.team, SPRITERULE_DEFAULT);        
+    {
+        WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT);
         if(oldself == world)
-            WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);        
+            WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
         WaypointSprite_Ping(self.waypointsprite_attached);
-    }    
-    
+    }
+
     if(oldself != world)
         self = oldself;
 }
@@ -865,34 +1058,28 @@ void vehicles_showwp()
 void vehicles_setreturn()
 {
     entity ret;
-    
+
     vehicles_clearrturn();
 
     ret = spawn();
     ret.classname   = "vehicle_return";
-    ret.enemy       = self;    
+    ret.wp00       = self;
     ret.team        = self.team;
     ret.think       = vehicles_showwp;
-    
+
     if(self.deadflag != DEAD_NO)
     {
         ret.cnt         = time + self.vehicle_respawntime;
-        ret.nextthink   = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 5);        
-    }        
+        ret.nextthink   = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 5);
+    }
     else
     {
-        ret.nextthink   = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 1);        
+        ret.nextthink   = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 1);
     }
-    
+
     setmodel(ret, "null");
     setorigin(ret, self.pos1 + '0 0 96');
-       
-}
 
-void vehicles_configcheck(string  configname, float check_cvar)
-{
-    if(check_cvar == 0)
-        localcmd(strcat("exec ", configname, "\n"));
 }
 
 void vehicles_reset_colors()
@@ -940,6 +1127,57 @@ void vehicles_reset_colors()
     self.effects   = _effects;
 }
 
+void vehicle_use()
+{
+    dprint("vehicle ",self.netname, " used by ", activator.classname, "\n");
+
+    self.tur_head.team = activator.team;
+
+    if(self.tur_head.team == 0)
+        self.active = ACTIVE_NOT;
+    else
+        self.active = ACTIVE_ACTIVE;
+    
+    if(self.active == ACTIVE_ACTIVE && self.deadflag == DEAD_NO)
+    {
+        dprint("^3Eat shit yall!\n");
+        vehicles_setreturn();
+        vehicles_reset_colors();
+    }
+    else if(self.active == ACTIVE_NOT && self.deadflag != DEAD_NO)
+    {
+        
+    }
+}
+
+float vehicle_addplayerslot(    entity _owner, 
+                                entity _slot, 
+                                float _hud, 
+                                string _hud_model,
+                                float() _framefunc, 
+                                void(float) _exitfunc)
+{
+    if not (_owner.vehicle_flags & VHF_MULTISLOT)
+        _owner.vehicle_flags |= VHF_MULTISLOT;
+
+    _slot.PlayerPhysplug = _framefunc;
+    _slot.vehicle_exit = _exitfunc;
+    _slot.hud = _hud;
+    _slot.vehicle_flags = VHF_PLAYERSLOT;
+    _slot.vehicle_viewport = spawn();
+    _slot.vehicle_hudmodel = spawn();
+    _slot.vehicle_hudmodel.viewmodelforclient = _slot;
+    _slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
+    
+    setmodel(_slot.vehicle_hudmodel, _hud_model);
+    setmodel(_slot.vehicle_viewport, "null");
+    
+    setattachment(_slot.vehicle_hudmodel, _slot, "");
+    setattachment(_slot.vehicle_viewport, _slot.vehicle_hudmodel, "");
+    
+    return TRUE;
+}
+
 float vehicle_initialize(string  net_name,
                          string  bodymodel,
                          string  topmodel,
@@ -951,24 +1189,55 @@ float vehicle_initialize(string  net_name,
                          vector  min_s,
                          vector  max_s,
                          float   nodrop,
-                         void()  spawnproc,
+                         void(float _spawnflag)  spawnproc,
                          float   _respawntime,
                          float() physproc,
                          void()  enterproc,
                          void(float extflag) exitfunc,
                          void() dieproc,
                          void() thinkproc,
-                         float  use_csqc)
+                         float  use_csqc,
+                         float _max_health,
+                         float _max_shield)
 {
+       if(!autocvar_g_vehicles)
+               return FALSE;
+       
+    if(self.targetname)
+    {
+        self.vehicle_controller = find(world, target, self.targetname);
+        if(!self.vehicle_controller)
+        {
+            bprint("^1WARNING: ^7Vehicle with invalid .targetname\n");
+        }
+        else
+        {
+            self.team = self.vehicle_controller.team;        
+            self.use = vehicle_use;
+            
+            if(teamplay)
+            {
+                if(self.vehicle_controller.team == 0)
+                    self.active = ACTIVE_NOT;
+                else
+                    self.active = ACTIVE_ACTIVE;                
+            }
+        }
+    }
+    
+    precache_sound("onslaught/ons_hit2.wav");
+    precache_sound("onslaught/electricity_explode.wav");
+
+
     addstat(STAT_HUD, AS_INT,  hud);
        addstat(STAT_VEHICLESTAT_HEALTH,  AS_INT, vehicle_health);
        addstat(STAT_VEHICLESTAT_SHIELD,  AS_INT, vehicle_shield);
        addstat(STAT_VEHICLESTAT_ENERGY,  AS_INT, vehicle_energy);
 
-       addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT,   vehicle_ammo1);
+       addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT, vehicle_ammo1);
        addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
 
-       addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT,   vehicle_ammo2);
+       addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT, vehicle_ammo2);
        addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
 
     if(bodymodel == "")
@@ -984,9 +1253,9 @@ float vehicle_initialize(string  net_name,
 
     if(self.team && !teamplay)
         self.team = 0;
-        
+
     self.vehicle_flags |= VHF_ISVEHICLE;
-    
+
     setmodel(self, bodymodel);
 
     self.vehicle_viewport   = spawn();
@@ -998,17 +1267,24 @@ float vehicle_initialize(string  net_name,
     self.iscreature         = TRUE;
     self.damagedbycontents     = TRUE;
     self.hud                = vhud;
-
+    self.tur_health          = _max_health;
+    self.tur_head.tur_health = _max_shield;
     self.vehicle_die         = dieproc;
     self.vehicle_exit        = exitfunc;
     self.vehicle_enter       = enterproc;
     self.PlayerPhysplug      = physproc;
     self.event_damage        = vehicles_damage;
     self.touch               = vehicles_touch;
-    self.think               = vehicles_spawn;    
-    self.nextthink           = time;        
+    self.think               = vehicles_spawn;
+    self.nextthink           = time;
     self.vehicle_respawntime = _respawntime;
     self.vehicle_spawn       = spawnproc;
+    self.effects             = EF_NODRAW;
+    if(g_assault || !autocvar_g_vehicles_delayspawn)
+        self.nextthink = time + 0.5;
+    else
+        self.nextthink = time + _respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter);
+
 
     if(autocvar_g_nodepthtestplayers)
         self.effects = self.effects | EF_NODEPTHTEST;
@@ -1019,7 +1295,6 @@ float vehicle_initialize(string  net_name,
     setmodel(self.vehicle_hudmodel, hudmodel);
     setmodel(self.vehicle_viewport, "null");
 
-
     if(topmodel != "")
     {
         setmodel(self.tur_head, topmodel);
@@ -1041,19 +1316,98 @@ float vehicle_initialize(string  net_name,
         tracebox(self.origin + '0 0 100', min_s, max_s, self.origin - '0 0 10000', MOVE_WORLDONLY, self);
         setorigin(self, trace_endpos);
     }
-
+    
     self.pos1 = self.origin;
     self.pos2 = self.angles;
     self.tur_head.team = self.team;
-    
+
     return TRUE;
 }
 
-void bugmenot()
+vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname, 
+                         float _pichlimit_min, float _pichlimit_max, 
+                         float _rotlimit_min, float _rotlimit_max, float _aimspeed)
+{
+    vector vtmp, vtag;
+    float ftmp;
+    vtag = gettaginfo(_turrret, gettagindex(_turrret, _tagname));
+    vtmp = vectoangles(normalize(_target - vtag));
+    vtmp = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(_vehic.angles), AnglesTransform_FromAngles(vtmp))) - _turrret.angles;
+    vtmp = AnglesTransform_Normalize(vtmp, TRUE);
+    ftmp = _aimspeed * frametime;
+    vtmp_y = bound(-ftmp, vtmp_y, ftmp);
+    vtmp_x = bound(-ftmp, vtmp_x, ftmp);
+    _turrret.angles_y = bound(_rotlimit_min, _turrret.angles_y + vtmp_y, _rotlimit_max);    
+    _turrret.angles_x = bound(_pichlimit_min, _turrret.angles_x + vtmp_x, _pichlimit_max);
+    return vtag;
+}
+
+void vehicles_gib_explode()
+{
+       sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+       pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+       remove(self);
+}
+
+void vehicles_gib_think()
+{
+       self.alpha -= 0.1;
+       if(self.cnt >= time)
+               remove(self);
+       else
+               self.nextthink = time + 0.1;
+}
+
+entity vehicle_tossgib(entity _template, vector _vel, string _tag, float _burn, float _explode, float _maxtime, vector _rot)
+{
+       entity _gib = spawn();
+       setmodel(_gib, _template.model);
+       setorigin(_gib, gettaginfo(self, gettagindex(self, _tag)));
+       _gib.velocity = _vel;
+       _gib.movetype = MOVETYPE_TOSS;
+       _gib.solid = SOLID_CORPSE;
+       _gib.colormod = '-0.5 -0.5 -0.5';
+       _gib.effects = EF_LOWPRECISION; 
+       _gib.avelocity = _rot;
+       
+       if(_burn)
+               _gib.effects |= EF_FLAME;
+       
+       if(_explode)
+       {
+               _gib.think = vehicles_gib_explode; 
+               _gib.nextthink = time + random() * _explode;
+               _gib.touch = vehicles_gib_explode;
+       }
+       else
+       {
+               _gib.cnt = time + _maxtime;
+               _gib.think = vehicles_gib_think; 
+               _gib.nextthink = time + _maxtime - 1;           
+               _gib.alpha = 1;
+       }
+       return _gib;
+}
+
+/*
+vector predict_target(entity _targ, vector _from, float _shot_speed)
 {
-    self.vehicle_exit       = self.vehicle_exit;
-    self.vehicle_enter      = self.vehicle_exit;
-    self.vehicle_die        = self.vehicle_exit;
-    self.vehicle_spawn      = self.vehicle_exit;
-    self.AuxiliaryXhair     = self.AuxiliaryXhair;
+    float i;                // loop
+    float _distance;        // How far to target
+    float _impact_time;     // How long untill projectile impacts
+    vector _predict_pos;    // Predicted enemy location
+    vector _original_origin;// Where target is before predicted
+
+     _original_origin = real_origin(_targ); // Typicaly center of target BBOX
+
+    _predict_pos = _original_origin;
+    for(i = 0; i < 4; ++i)  // Loop a few times to increase prediction accuracy (increase loop count if accuracy is to low)
+    {
+        _distance = vlen(_predict_pos - _from); // Get distance to previos predicted location
+        _impact_time = _distance / _shot_speed; // Calculate impact time
+        _predict_pos = _original_origin + _targ.velocity * _impact_time; // Calculate new predicted location
+    }
+
+    return _predict_pos;
 }
+*/
\ No newline at end of file
index 79fc9cbf9a9ddd9c5d86213d550dab00bf48007d..549dfeab7fffcf16b2e33fc48814ff07e330f706 100644 (file)
@@ -4,5 +4,7 @@
 #include "racer.qc"
 #include "spiderbot.qc"
 #include "raptor.qc"
-//#include "bumblebee.qc"
+#ifndef VEHICLES_NO_UNSTABLE
+#include "bumblebee.qc"
+#endif
 #endif
index dcb1854f368b45803f828bab8a12bfa0e73e86c0..834e6516787ba0411677ea34075cf769adb1bda3 100644 (file)
@@ -2,8 +2,6 @@
 #define VEHICLES_ENABLED
 #ifdef VEHICLES_ENABLED
 
-//#message "with tZork vehicles (experimental)"
-
 .float vehicle_flags;
 float VHF_ISVEHICLE     = 2;    /// Indicates vehicle
 float VHF_HASSHIELD     = 4;    /// Vehicle has shileding
@@ -14,34 +12,40 @@ float VHF_DEATHEJECT    = 64;   /// Vehicle ejects pilot upon fatal damage
 float VHF_MOVE_GROUND   = 128;  /// Vehicle moves on gound
 float VHF_MOVE_HOVER    = 256;  /// Vehicle hover close to gound
 float VHF_MOVE_FLY      = 512;  /// Vehicle is airborn
-float VHF_DMGSHAKE      = 1024;
-float VHF_DMGROLL       = 2048;
-float VHF_DMGHEADROLL   = 4096;
+float VHF_DMGSHAKE      = 1024; /// Add random velocity each frame if health < 50%
+float VHF_DMGROLL       = 2048; /// Add random angles each frame if health < 50%
+float VHF_DMGHEADROLL   = 4096; /// Add random head angles each frame if health < 50%
+float VHF_MULTISLOT     = 8192; /// Vehicle has multiple player slots
+float VHF_PLAYERSLOT    = 16384;    /// This ent is a player slot on a multi-person vehicle
 
 .entity gun1;
 .entity gun2;
+.entity gun3;
+.entity vehicle_shieldent;  /// Entity to disply the shild effect on damage
+.entity vehicle;
+.entity vehicle_viewport;
+.entity vehicle_hudmodel;
+.entity vehicle_controller;
+
+.entity gunner1;
+.entity gunner2;
 
 .float vehicle_health;      /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
 .float vehicle_energy;      /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
 .float vehicle_shield;      /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
-.entity vehicle_shieldent;  /// Entity to disply the shild effect on damage
 
 .float vehicle_ammo1;   /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo1 value.
 .float vehicle_reload1; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload1 value.
 .float vehicle_ammo2;   /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo2 value.
 .float vehicle_reload2; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload2 value.
 
-.entity vehicle;
-.entity vehicle_viewport;
-.entity vehicle_hudmodel;
-
 .float sound_nexttime;
 #define VOL_VEHICLEENGINE 1
 
 .float hud;
 .float dmg_time;
 .float  vehicle_respawntime;
-.void() vehicle_spawn;
+//.void() vehicle_spawn;
 
 void vehicles_exit(float eject);
 var .void(float exit_flags) vehicle_exit;
@@ -55,7 +59,14 @@ float SVC_UPDATEENTITY  = 128; // Net.Protocol 0x80
 
 var .void() vehicle_enter;  /// Vehicles custom funciton to be executed when owner exit it
 var .void() vehicle_die;    /// Vehicles custom function to be executed when vehile die
-var .void() vehicle_spawn;  /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
+#define VHSF_NORMAL 0
+#define VHSF_FACTORY 2
+var .void(float _spawnflag) vehicle_spawn;  /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
+const var .float(float _imp) vehicles_impusle_null;
+var .float(float _imp) vehicles_impusle;
+.float vehicle_weapon2mode = volly_counter;
+
+//§ var .void() vehicle_factory()
 
 #ifdef VEHICLES_USE_ODE
 void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
index bcf12afa9a8c2eda4bfd36b2afdf9dfb602f488f..3780fc71384d987160f8e56c3063166fdbcc1bb3 100644 (file)
@@ -38,6 +38,8 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f
        entity pseudoprojectile;
        float f, ffs;
 
+       pseudoprojectile = world;
+
        railgun_start = start;
        railgun_end = end;
 
@@ -241,31 +243,58 @@ void W_BallisticBullet_LeaveSolid_think()
        UpdateCSQCProjectile(self);
 }
 
-float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant)
+float W_BallisticBullet_LeaveSolid(float eff)
 {
        // move the entity along its velocity until it's out of solid, then let it resume
-
+       vector vel = self.velocity;
        float dt, dst, velfactor, v0, vs;
        float maxdist;
        float E0_m, Es_m;
+       float constant = self.dmg_radius * (other.ballistics_density ? other.ballistics_density : 1);
 
        // outside the world? forget it
        if(self.origin_x > world.maxs_x || self.origin_y > world.maxs_y || self.origin_z > world.maxs_z || self.origin_x < world.mins_x || self.origin_y < world.mins_y || self.origin_z < world.mins_z)
                return 0;
 
+       // special case for zero density and zero bullet constant: 
+
+       if(self.dmg_radius == 0)
+       {
+               if(other.ballistics_density < 0)
+                       constant = 0; // infinite travel distance
+               else
+                       return 0; // no penetration
+       }
+       else
+       {
+               if(other.ballistics_density < 0)
+                       constant = 0; // infinite travel distance
+               else if(other.ballistics_density == 0)
+                       constant = self.dmg_radius;
+               else
+                       constant = self.dmg_radius * other.ballistics_density;
+       }
+
        // E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass
        v0 = vlen(vel);
 
        E0_m = 0.5 * v0 * v0;
-       maxdist = E0_m / constant;
-       // maxdist = 0.5 * v0 * v0 / constant
-       // dprint("max dist = ", ftos(maxdist), "\n");
 
-       if(maxdist <= autocvar_g_ballistics_mindistance)
-               return 0;
+       if(constant)
+       {
+               maxdist = E0_m / constant;
+               // maxdist = 0.5 * v0 * v0 / constant
+               // dprint("max dist = ", ftos(maxdist), "\n");
 
-       traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self);
+               if(maxdist <= autocvar_g_ballistics_mindistance)
+                       return 0;
+       }
+       else
+       {
+               maxdist = vlen(other.maxs - other.mins) + 1; // any distance, as long as we leave the entity
+       }
 
+       traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self, TRUE);
        if(trace_fraction == 1) // 1: we never got out of solid
                return 0;
 
@@ -298,12 +327,19 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant)
        self.flags |= FL_ONGROUND; // prevent moving
        self.W_BallisticBullet_LeaveSolid_velocity = vel;
 
+       if(eff >= 0)
+               if(vlen(trace_endpos - self.origin) > 4)
+               {
+                       endzcurveparticles();
+                       trailparticles(self, eff, self.origin, trace_endpos);
+               }
+
        return 1;
 }
 
 void W_BallisticBullet_Touch (void)
 {
-       float density;
+       //float density;
 
        if(self.think == W_BallisticBullet_LeaveSolid_think) // skip this!
                return;
@@ -311,6 +347,12 @@ void W_BallisticBullet_Touch (void)
        PROJECTILE_TOUCH;
        W_BallisticBullet_Hit ();
 
+       if(self.dmg_radius < 0) // these NEVER penetrate solid
+       {
+               remove(self);
+               return;
+       }
+
        // if we hit "weapclip", bail out
        //
        // rationale of this check:
@@ -331,12 +373,8 @@ void W_BallisticBullet_Touch (void)
                return;
        }
 
-       density = other.ballistics_density;
-       if(density == 0)
-               density = 1;
-
        // go through solid!
-       if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
+       if(!W_BallisticBullet_LeaveSolid(-1))
        {
                remove(self);
                return;
@@ -362,7 +400,7 @@ void fireBallisticBullet_trace_callback(vector start, vector hit, vector end)
 
 void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant)
 {
-       float lag, dt, savetime, density;
+       float lag, dt, savetime; //, density;
        entity pl, oldself;
        float antilagging;
 
@@ -384,7 +422,12 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
        proj.nextthink = time + lifetime; // min(pLifetime, vlen(world.maxs - world.mins) / pSpeed);
        W_SetupProjectileVelocityEx(proj, dir, v_up, pSpeed, 0, 0, spread, antilagging);
        proj.angles = vectoangles(proj.velocity);
-       proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+       if(bulletconstant > 0)
+               proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+       else if(bulletconstant == 0)
+               proj.dmg_radius = 0;
+       else
+               proj.dmg_radius = -1;
        // so: bulletconstant = bullet mass / area of bullet circle
        setorigin(proj, start);
        proj.flags = FL_PROJECTILE;
@@ -468,6 +511,9 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
                                W_BallisticBullet_Hit();
                        }
 
+                       if(proj.dmg_radius < 0) // these NEVER penetrate solid
+                               break;
+
                        // if we hit "weapclip", bail out
                        //
                        // rationale of this check:
@@ -485,15 +531,13 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
                        if not(trace_dphitcontents & DPCONTENTS_OPAQUE)
                                break;
 
-                       density = other.ballistics_density;
-                       if(density == 0)
-                               density = 1;
-
                        // go through solid!
-                       if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
+                       if(!W_BallisticBullet_LeaveSolid((other && (other.solid != SOLID_BSP)) ? eff : -1))
                                break;
 
                        W_BallisticBullet_LeaveSolid_think();
+
+                       self.projectiledeathtype |= HITTYPE_BOUNCE;
                }
                frametime = savetime;
                self = oldself;
@@ -586,7 +630,7 @@ void W_PrepareExplosionByDamage(entity attacker, void() explode)
        self.takedamage = DAMAGE_NO;
        self.event_damage = SUB_Null;
        
-       if not(g_ca)
+       if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner)
        {
                self.owner = attacker;
                self.realowner = attacker;
index 0b3118bb606cea52a6c5115e5bf437ea0a313b6e..1ce463827423fe2d2ca24cfc279772824128f569 100644 (file)
@@ -133,6 +133,7 @@ vector W_Crylink_LinkJoin(entity e, float jspeed, float jtime)
                        p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity);
                        UpdateCSQCProjectile(p);
                }
+               targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE
        }
        else
        {
@@ -335,8 +336,8 @@ void W_Crylink_Attack (void)
 
        shots = autocvar_g_balance_crylink_primary_shots;
        pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
-       proj = world;
-       while (counter < shots)
+       proj = prevproj = firstproj = world;
+       for(counter = 0; counter < shots; ++counter)
        {
                proj = spawn ();
                proj.reset = W_Crylink_Reset;
@@ -408,12 +409,11 @@ void W_Crylink_Attack (void)
                //proj.glow_size = 20;
 
                proj.flags = FL_PROJECTILE;
-
+    proj.missile_flags = MIF_SPLASH;
+    
                CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
 
                other = proj; MUTATOR_CALLHOOK(EditProjectile);
-
-               counter = counter + 1;
        }
        if(autocvar_g_balance_crylink_primary_joinspread != 0 || autocvar_g_balance_crylink_primary_jointime != 0)
        {
@@ -440,8 +440,8 @@ void W_Crylink_Attack2 (void)
 
        shots = autocvar_g_balance_crylink_secondary_shots;
        pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
-       proj = world;
-       while (counter < shots)
+       proj = prevproj = firstproj = world;
+       for(counter = 0; counter < shots; ++counter)
        {
                proj = spawn ();
                proj.reset = W_Crylink_Reset;
@@ -501,12 +501,11 @@ void W_Crylink_Attack2 (void)
                //proj.glow_size = 20;
 
                proj.flags = FL_PROJECTILE;
-
+        proj.missile_flags = MIF_SPLASH;
+        
                CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
 
                other = proj; MUTATOR_CALLHOOK(EditProjectile);
-
-               counter = counter + 1;
        }
        if(autocvar_g_balance_crylink_secondary_joinspread != 0 || autocvar_g_balance_crylink_secondary_jointime != 0)
        {
index 9b1b96e56547abaf3d4bbff42c89a41bde6c781f..7a91cbd89cae366bfde23606899c9fd9807281a9 100644 (file)
@@ -140,6 +140,7 @@ void W_Electro_Attack()
        proj.touch = W_Plasma_TouchExplode;
        setsize(proj, '0 0 -3', '0 0 -3');
        proj.flags = FL_PROJECTILE;
+       proj.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
 
@@ -185,6 +186,7 @@ void W_Electro_Attack2()
 
        proj.bouncefactor = autocvar_g_balance_electro_secondary_bouncefactor;
        proj.bouncestop = autocvar_g_balance_electro_secondary_bouncestop;
+       proj.missile_flags = MIF_SPLASH | MIF_ARC;
 
 #if 0
        entity p2;
index 1c950aca4a58ddc2b3e1eff4092008df91a086a7..67547e3583efef51458b138d926cfda5daf1ed2d 100644 (file)
@@ -159,7 +159,8 @@ void W_Fireball_Attack1()
        proj.touch = W_Fireball_TouchExplode;
        setsize(proj, '-16 -16 -16', '16 16 16');
        proj.flags = FL_PROJECTILE;
-
+    proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+    
        CSQCProjectile(proj, TRUE, PROJECTILE_FIREBALL, TRUE);
 
        other = proj; MUTATOR_CALLHOOK(EditProjectile);
@@ -289,7 +290,8 @@ void W_Fireball_Attack2()
 
        proj.angles = vectoangles(proj.velocity);
        proj.flags = FL_PROJECTILE;
-
+    proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
+    
        CSQCProjectile(proj, TRUE, PROJECTILE_FIREMINE, TRUE);
 
        other = proj; MUTATOR_CALLHOOK(EditProjectile);
index 352ce883bd255fb49c9ebf0ff95bdb9bf40c06f1..5f6c0346f5cf3c11137bf6e5271487fb764b263e 100644 (file)
@@ -200,6 +200,7 @@ void W_Grenade_Attack (void)
        gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale;
        gren.event_damage = W_Grenade_Damage;
        gren.damagedbycontents = TRUE;
+       gren.missile_flags = MIF_SPLASH | MIF_ARC;
        W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
 
        gren.angles = vectoangles (gren.velocity);
@@ -247,6 +248,7 @@ void W_Grenade_Attack2 (void)
        gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale;
        gren.event_damage = W_Grenade_Damage;
        gren.damagedbycontents = TRUE;
+       gren.missile_flags = MIF_SPLASH | MIF_ARC;
        W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary);
 
        gren.angles = vectoangles (gren.velocity);
index 76103f347e34fa50c6d16c849f6ee0dc0c15f2ac..9a4b1ef4495aa95d223d7df5cd15f7e770060f0b 100644 (file)
@@ -101,6 +101,7 @@ void W_Hagar_Attack (void)
 
        missile.angles = vectoangles (missile.velocity);
        missile.flags = FL_PROJECTILE;
+       missile.missile_flags = MIF_SPLASH; 
 
        CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
 
@@ -144,6 +145,7 @@ void W_Hagar_Attack2 (void)
 
        missile.angles = vectoangles (missile.velocity);
        missile.flags = FL_PROJECTILE;
+       missile.missile_flags = MIF_SPLASH; 
 
        CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR_BOUNCING, TRUE);
 
@@ -174,7 +176,7 @@ void W_Hagar_Attack2_Load_Release (void)
 
        shots = self.hagar_load;
        missile = world;
-       while (counter < shots)
+       for(counter = 0; counter < shots; ++counter)
        {
                missile = spawn ();
                missile.owner = missile.realowner = self;
@@ -197,6 +199,7 @@ void W_Hagar_Attack2_Load_Release (void)
                setorigin (missile, w_shotorg);
                setsize(missile, '0 0 0', '0 0 0');
                missile.movetype = MOVETYPE_FLY;
+               missile.missile_flags = MIF_SPLASH; 
                
                // per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar)
                spread_pershot = ((shots - 1) / (autocvar_g_balance_hagar_secondary_load_max - 1)); 
@@ -223,8 +226,6 @@ void W_Hagar_Attack2_Load_Release (void)
                CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
 
                other = missile; MUTATOR_CALLHOOK(EditProjectile);
-
-               counter = counter + 1;
        }
 
        weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_load_animtime, w_ready);
index 62be05f0dcf62a3a8b21bfef514715f9438ca39b..a2697b2f5cb527050677ace98031e52896c6b83e 100644 (file)
@@ -102,6 +102,7 @@ void W_HLAC_Attack2f (void)
     missile.nextthink = time + autocvar_g_balance_hlac_secondary_lifetime;
 
        missile.flags = FL_PROJECTILE;
+       missile.missile_flags = MIF_SPLASH; 
        missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY;
 
        CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
index 695ac381fe55afcaeb750f2890e313addb6ef915..63d02604c4271f11cc808099f148f8946393bbf1 100644 (file)
@@ -100,6 +100,7 @@ void W_Hook_Attack2()
        gren.damageforcescale = autocvar_g_balance_hook_secondary_damageforcescale;
        gren.event_damage = W_Hook_Damage;
        gren.damagedbycontents = TRUE;
+       gren.missile_flags = MIF_SPLASH | MIF_ARC;
 
        gren.velocity = '0 0 1' * autocvar_g_balance_hook_secondary_speed;
        if(autocvar_g_projectiles_newton_style)
index 3da9e422b5c377799d9556013c41a2b2d3dfaaa8..5e2bb075aa5c7ff1a4fd6b258ac2cea9661954a7 100644 (file)
@@ -75,6 +75,7 @@ void W_Laser_Attack (float issecondary)
        missile.touch = W_Laser_Touch;
 
        missile.flags = FL_PROJECTILE;
+       missile.missile_flags = MIF_SPLASH; 
 
        missile.think = W_Laser_Think;
        missile.nextthink = time + autocvar_g_balance_laser_primary_delay;
index 0e73ba71763d0c63dd8d476cf0e671f56142264a..4d98f0c91cd50927abfecdacd53c1b82c6a35dec 100644 (file)
@@ -149,7 +149,7 @@ void W_Mine_ProximityExplode ()
 
 float W_Mine_Count(entity e)
 {
-       float minecount;
+       float minecount = 0;
        entity mine;
        for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
                minecount += 1;
@@ -308,6 +308,7 @@ void W_Mine_Attack (void)
        mine.nextthink = time;
        mine.cnt = time + (autocvar_g_balance_minelayer_lifetime - autocvar_g_balance_minelayer_lifetime_countdown);
        mine.flags = FL_PROJECTILE;
+       mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY;
 
        CSQCProjectile(mine, TRUE, PROJECTILE_MINE, TRUE);
 
@@ -328,7 +329,7 @@ void W_Mine_Attack (void)
 float W_PlacedMines(float detonate)
 {
        entity mine;
-       float minfound;
+       float minfound = 0;
 
        for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self)
        {
index 1fb823da91fcedad865f5cec22a3ebab3008c94d..f95e554b0e9799d78a52108ca39e72f2c7dde053 100644 (file)
@@ -272,7 +272,7 @@ void spawnfunc_weapon_porto (void)
 float w_nexball_weapon(float req);
 float w_porto(float req)
 {
-       vector v_angle_save;
+       //vector v_angle_save;
 
        if (g_nexball) { return w_nexball_weapon(req); }
        if (req == WR_AIM)
@@ -326,7 +326,6 @@ float w_porto(float req)
                                        ClientData_Touch(self);
                                }
                        }
-                       v_angle_save = self.v_angle;
                        if(self.porto_v_angle_held)
                                makevectors(self.porto_v_angle); // override the previously set angles
 
index 42ae90d7466e84c0a46740c9ec2cef614ce873ef..643bf4bd5b5b72b0984365ab6f3f368347b434a2 100644 (file)
@@ -250,6 +250,7 @@ void W_Rocket_Attack (void)
        missile.nextthink = time;
        missile.cnt = time + autocvar_g_balance_rocketlauncher_lifetime;
        missile.flags = FL_PROJECTILE;
+       missile.missile_flags = MIF_SPLASH; 
 
        CSQCProjectile(missile, autocvar_g_balance_rocketlauncher_guiderate == 0 && autocvar_g_balance_rocketlauncher_speedaccel == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound
 
index be58650dc0aa4fdba7f05dfd531af0417ab09ec6..7cf6cfb73634e11be73aba7215de897f8ee7b715 100644 (file)
@@ -78,6 +78,8 @@ void Seeker_Missile_Think()
                newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
                self.velocity = newdir * spd; // make me fly in the new direction at my flight speed
        }
+       else
+               dist = 0;
 
        // Proxy
        if (autocvar_g_balance_seeker_missile_proxy)
@@ -205,6 +207,8 @@ void Seeker_Fire_Missile(vector f_diff, entity m_target)
        setsize (missile, '-4 -4 -4', '4 4 4');
        missile.movetype    = MOVETYPE_FLYMISSILE;
        missile.flags       = FL_PROJECTILE;
+       missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG;
+       
        W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_missile);
 
        missile.angles = vectoangles (missile.velocity);
@@ -277,6 +281,7 @@ void Seeker_Fire_Flac()
        missile.projectiledeathtype = WEP_SEEKER;
        missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
        missile.flags                           = FL_PROJECTILE;
+       missile.missile_flags       = MIF_SPLASH; 
        
        // csqc projectiles
        //missile.angles                                = vectoangles (missile.velocity);       
@@ -308,6 +313,7 @@ void Seeker_Attack()
 {
        entity tracker, closest_target;
        
+       closest_target = world;
        for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self)
        {
                if (closest_target)
@@ -497,6 +503,7 @@ void Seeker_Fire_Tag()
        setsize (missile, '-2 -2 -2', '2 2 2');
 
        missile.flags       = FL_PROJECTILE;
+       //missile.missile_flags = MIF_..?; 
 
        missile.movetype    = MOVETYPE_FLY;
        W_SETUPPROJECTILEVELOCITY(missile, g_balance_seeker_tag);
index a02061e8b80f741a27e419a786940dc157f9b1c3..f19a50208293073f1507fc4bf2beec258456fa13 100644 (file)
@@ -160,6 +160,7 @@ float Tuba_GetNote(entity pl, float hittype)
                case 2: note = -5; break; // G
                case 3: note = -4; break; // G#
                case 4: note = +5; break; // e#
+               default:
                case 5: note =  0; break; // c
                case 6: note = +2; break; // d
                case 7: note = +3; break; // eb
index f09f25bdcd13d320e5b9277da55795865d5c3e88..7bbebdc9c2a707ad0cd5366d2f1de44456db6838 100644 (file)
@@ -334,6 +334,7 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo
 
        o0 = e.origin;
        v0 = e.velocity;
+       g = cvar("sv_gravity") * e.gravity;
 
        WarpZone_trace_forent = forent;
        WarpZone_trace_firstzone = world;
@@ -376,7 +377,6 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo
                e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
        }
        WarpZone_MakeAllSolid();
-       g = cvar("sv_gravity") * e.gravity;
        i = 16;
        for(;;)
        {
index 89c4b72b5f59b15df29024fa07507a3de314d40b..9b94640b5a2319c734a103db57e036b48dd26883 100644 (file)
@@ -259,7 +259,7 @@ float WarpZone_Send(entity to, float sendflags)
 
 float WarpZone_Camera_Send(entity to, float sendflags)
 {
-       float f;
+       float f = 0;
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
 
        if(self.warpzone_fadestart)
diff --git a/scripts/simpleitems.shader b/scripts/simpleitems.shader
new file mode 100644 (file)
index 0000000..69376e8
--- /dev/null
@@ -0,0 +1,478 @@
+////////// AMMO //////////
+
+
+a_cells_simple // cells
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/a_cells_simple
+               blendfunc blend
+       }
+}
+
+a_rockets_simple // rockets
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/a_rockets_simple
+               blendfunc blend
+       }
+}
+
+a_bullets_simple // bullets
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/a_bullets_simple
+               blendfunc blend
+
+       }
+}
+
+a_shells_simple // shells
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/a_shells_simple
+               blendfunc blend
+
+       }
+}
+
+////////// WEAPONS //////////
+
+g_crylink_simple // crylink
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_crylink_simple
+               blendfunc blend
+
+       }
+}
+
+g_electro_simple // electro
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_electro_simple
+               blendfunc blend
+
+       }
+}
+
+g_nex_simple // nex
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_nex_simple
+               blendfunc blend
+
+       }
+}
+
+g_hagar_simple // hagar
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_hagar_simple
+               blendfunc blend
+
+       }
+}
+
+g_gl_simple // mortar
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_gl_simple
+               blendfunc blend
+
+       }
+}
+
+g_rl_simple // rocket launcher
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_rl_simple
+               blendfunc blend
+
+       }
+}
+
+g_shotgun_simple // shotgun
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_shotgun_simple
+               blendfunc blend
+
+       }
+}
+
+g_uzi_simple // machine gun
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_uzi_simple
+               blendfunc blend
+
+       }
+}
+
+g_uzi_simple // machine gun
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_uzi_simple
+               blendfunc blend
+
+       }
+}
+
+g_campingrifle_simple // sniper rifle
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_campingrifle_simple
+               blendfunc blend
+
+       }
+}
+
+g_fireball_simple // fireball
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_fireball_simple
+               blendfunc blend
+
+       }
+}
+
+g_hlac_simple // HLAC
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_hlac_simple
+               blendfunc blend
+
+       }
+}
+
+g_hookgun_simple // hook gun
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_hookgun_simple
+               blendfunc blend
+
+       }
+}
+
+g_laser_simple // laser
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_laser_simple
+               blendfunc blend
+
+       }
+}
+
+g_minelayer_simple // minelayer
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_minelayer_simple
+               blendfunc blend
+
+       }
+}
+
+g_minstanex_simple // minstanex
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_minstanex_simple
+               blendfunc blend
+
+       }
+}
+
+g_porto_simple // portolauncher
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_porto_simple
+               blendfunc blend
+
+       }
+}
+
+g_seeker_simple // tag seeker
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_seeker_simple
+               blendfunc blend
+
+       }
+}
+
+g_tuba_simple // tuba
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/weapons/g_tuba_simple
+               blendfunc blend
+
+       }
+}
+
+////////// ARMOR + HEALTH ITEMS //////////
+
+///// ARMOR /////
+
+item_armor_small_simple // 5a
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/item_armor_small_simple
+               blendfunc blend
+
+       }
+}
+
+item_armor_medium_simple // 25a
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/item_armor_medium_simple
+               blendfunc blend
+
+       }
+}
+
+item_armor_big_simple // 50a
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/item_armor_big_simple
+               blendfunc blend
+
+       }
+}
+
+item_armor_large_simple  // 100a
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/item_armor_large_simple
+               blendfunc blend
+
+       }
+}
+
+///// HEALTH /////
+
+g_h1_simple // 5hp
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_h1_simple
+               blendfunc blend
+
+       }
+}
+
+g_h25_simple // 25hp
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_h25_simple
+               blendfunc blend
+
+       }
+}
+
+g_h50_simple // 50hp
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_h50_simple
+               blendfunc blend
+
+       }
+}
+
+g_h100_simple // 100hp
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_h100_simple
+               blendfunc blend
+
+       }
+}
+
+////////// POWERUPS //////////
+
+g_strength_simple // strength
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_strength_simple
+               blendfunc blend
+
+       }
+}
+
+g_invincible_simple // shield
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_invincible_simple
+               blendfunc blend
+
+       }
+}
+
+g_jetpack_simple // jetpack
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_jetpack_simple
+               blendfunc blend
+
+       }
+}
+
+g_fuel_simple // fuel for jetpack
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_fuel_simple
+               blendfunc blend
+
+       }
+}
+
+g_fuelregen_simple // fuel regen powerup
+{
+       deformVertexes autosprite
+       cull none
+       nopicmip
+
+       {
+               map models/items/g_fuelregen_simple
+               blendfunc blend
+
+       }
+}
\ No newline at end of file
index 9749b51cc2d22f2dcc5781507c20a8a7d7a78411..a6dcfaab86df5c107a1f64fce159d06f98359b1a 100644 (file)
@@ -99,7 +99,7 @@ minelayer
 {
        dpreflectcube cubemaps/default/sky
        {
-               map textures/minelayer.tga
+               map textures/minelayer.tga      
                rgbgen lightingDiffuse
        }
 }
diff --git a/sound/vehicles/missile_alarm.wav b/sound/vehicles/missile_alarm.wav
new file mode 100644 (file)
index 0000000..bf3860a
Binary files /dev/null and b/sound/vehicles/missile_alarm.wav differ
index 2037f7b10be9cef4dff290bed58a7f053a3e7cc4..929805a30f2ef0e4a8b1ba243a9d059d0e04ae44 100644 (file)
Binary files a/textures/raptor.tga and b/textures/raptor.tga differ
diff --git a/textures/raptor_pants.jpg b/textures/raptor_pants.jpg
deleted file mode 100644 (file)
index 5cfa32a..0000000
Binary files a/textures/raptor_pants.jpg and /dev/null differ
diff --git a/textures/raptor_shirt.jpg b/textures/raptor_shirt.jpg
deleted file mode 100644 (file)
index e5bae42..0000000
Binary files a/textures/raptor_shirt.jpg and /dev/null differ
diff --git a/textures/raptor_shirt.tga b/textures/raptor_shirt.tga
new file mode 100644 (file)
index 0000000..5aa36ec
Binary files /dev/null and b/textures/raptor_shirt.tga differ
index 0d4feb3da01b8bed5a8fbba484f2783162805128..705d2a9883341ab2a5904fb1461d16973f6f8af9 100644 (file)
@@ -1,40 +1,64 @@
-set g_vehicle_bumblebee_speed_forward            400
-set g_vehicle_bumblebee_speed_strafe             200
-set g_vehicle_bumblebee_speed_up                 200
-set g_vehicle_bumblebee_speed_down               200
-set g_vehicle_bumblebee_turnspeed                72
-set g_vehicle_bumblebee_pitchspeed               36
-set g_vehicle_bumblebee_pitchlimit               15
-set g_vehicle_bumblebee_friction                 0.75
+set g_vehicle_bumblebee_respawntime              60
+
+set g_vehicle_bumblebee_speed_forward            350
+set g_vehicle_bumblebee_speed_strafe             350
+set g_vehicle_bumblebee_speed_up                 350
+set g_vehicle_bumblebee_speed_down               350
+set g_vehicle_bumblebee_turnspeed                120
+set g_vehicle_bumblebee_pitchspeed               60
+set g_vehicle_bumblebee_pitchlimit               60
+set g_vehicle_bumblebee_friction                 0.5
 
 set g_vehicle_bumblebee_energy                   500
 set g_vehicle_bumblebee_energy_regen             50
 set g_vehicle_bumblebee_energy_regen_pause       1
 
-set g_vehicle_bumblebee_health                   750
-set g_vehicle_bumblebee_health_regen             25
-set g_vehicle_bumblebee_health_regen_pause       5
-
-set g_vehicle_bumblebee_shield                   250
-set g_vehicle_bumblebee_shield_regen             100
-set g_vehicle_bumblebee_shield_regen_pause       2
-
-set g_vehicle_bumblebee_cannon_cost              10
-set g_vehicle_bumblebee_cannon_damage            75
-set g_vehicle_bumblebee_cannon_radius            150
-set g_vehicle_bumblebee_cannon_refire            1.5
-set g_vehicle_bumblebee_cannon_speed             5000
-set g_vehicle_bumblebee_cannon_spread            0.0125
-set g_vehicle_bumblebee_cannon_force             400
-set g_vehicle_bumblebee_cannon_turnspeed         90
-set g_vehicle_bumblebee_cannon_pitchlimit_down   60
-set g_vehicle_bumblebee_cannon_pitchlimit_up     60
-set g_vehicle_bumblebee_cannon_turnlimit_in      5
-set g_vehicle_bumblebee_cannon_turnlimit_out     45
-
-set g_vehicle_bumblebee_respawntime              10
+set g_vehicle_bumblebee_health                   1000
+set g_vehicle_bumblebee_health_regen             65
+set g_vehicle_bumblebee_health_regen_pause       10
+
+set g_vehicle_bumblebee_shield                   400
+set g_vehicle_bumblebee_shield_regen             150
+set g_vehicle_bumblebee_shield_regen_pause       0.75
+
+set g_vehicle_bumblebee_cannon_lock                            0
+set g_vehicle_bumblebee_cannon_cost                            2
+set g_vehicle_bumblebee_cannon_damage                  60
+set g_vehicle_bumblebee_cannon_radius                  225
+set g_vehicle_bumblebee_cannon_refire                  0.2
+set g_vehicle_bumblebee_cannon_speed                   20000
+set g_vehicle_bumblebee_cannon_spread                  0.02
+set g_vehicle_bumblebee_cannon_force                   -35
+set g_vehicle_bumblebee_cannon_turnspeed               160
+set g_vehicle_bumblebee_cannon_pitchlimit_down 60
+set g_vehicle_bumblebee_cannon_pitchlimit_up   60
+set g_vehicle_bumblebee_cannon_turnlimit_in            20
+set g_vehicle_bumblebee_cannon_turnlimit_out   80
+set g_vehicle_bumblebee_cannon_ammo                            100
+set g_vehicle_bumblebee_cannon_ammo_regen              100
+set g_vehicle_bumblebee_cannon_ammo_regen_pause        1
+
+set g_vehicle_bumblebee_raygun_turnspeed 180
+set g_vehicle_bumblebee_raygun_pitchlimit_down 20
+set g_vehicle_bumblebee_raygun_pitchlimit_up 5
+set g_vehicle_bumblebee_raygun_turnlimit_sides 35
+
+set g_vehicle_bumblebee_raygun 0
+set g_vehicle_bumblebee_raygun_range 2048
+set g_vehicle_bumblebee_raygun_dps 250
+set g_vehicle_bumblebee_raygun_aps 100
+set g_vehicle_bumblebee_raygun_fps 100
+
+set g_vehicle_bumblebee_healgun_hps 150
+set g_vehicle_bumblebee_healgun_hmax 100
+set g_vehicle_bumblebee_healgun_aps 75
+set g_vehicle_bumblebee_healgun_amax 100
+set g_vehicle_bumblebee_healgun_sps 100
+set g_vehicle_bumblebee_healgun_smax 100
+set g_vehicle_bumblebee_healgun_locktime 2.5
 
 set g_vehicle_bumblebee_blowup_radius            500
 set g_vehicle_bumblebee_blowup_coredamage        500
 set g_vehicle_bumblebee_blowup_edgedamage        100
-set g_vehicle_bumblebee_blowup_forceintensity    600
\ No newline at end of file
+set g_vehicle_bumblebee_blowup_forceintensity    600
+set g_vehicle_bumblebee_bouncepain "1 100 200"
\ No newline at end of file
index 33fb4140baa7b79a3938cb63029e745f781ab7ef..5c3e06aff1cc9f4db3b590407cecd65beec6db58 100644 (file)
@@ -1,60 +1,61 @@
-set g_vehicle_racer_respawntime                    25
+set g_vehicle_racer_respawntime                    35
 
-set g_vehicle_racer_health              190
+set g_vehicle_racer_health              200
 set g_vehicle_racer_health_regen        0
 set g_vehicle_racer_health_regen_pause  0
 
-set g_vehicle_racer_shield              75
-set g_vehicle_racer_shield_regen        25
+set g_vehicle_racer_shield              100
+set g_vehicle_racer_shield_regen        30
 set g_vehicle_racer_shield_regen_pause  1
 
-set g_vehicle_racer_energy              125
-set g_vehicle_racer_energy_regen        40
+set g_vehicle_racer_energy              100
+set g_vehicle_racer_energy_regen        50
 set g_vehicle_racer_energy_regen_pause  1
 
-set g_vehicle_racer_speed_stop          2000
-set g_vehicle_racer_speed_forward       800
-set g_vehicle_racer_speed_strafe        500
-set g_vehicle_racer_speed_afterburn     2000
-set g_vehicle_racer_friction            0.4
-set g_vehicle_racer_afterburn_cost      60      // energy consumed per second
+set g_vehicle_racer_speed_stop          2500
+set g_vehicle_racer_speed_forward       650
+set g_vehicle_racer_speed_strafe        650
+set g_vehicle_racer_speed_afterburn     3000
+set g_vehicle_racer_friction            0.45
+set g_vehicle_racer_afterburn_cost      100       // energy consumed per second
 
 set g_vehicle_racer_hovertype           0       // 0 = hover, != 0 = maglev
-set g_vehicle_racer_hoverpower          5000    // NOTE!! x 4 (4 engines)
+set g_vehicle_racer_hoverpower          8000    // NOTE!! x 4 (4 engines)
 set g_vehicle_racer_upforcedamper       10
 
 set g_vehicle_racer_downforce            0.01
-set g_vehicle_racer_springlength         65
+set g_vehicle_racer_springlength         70
 set g_vehicle_racer_collision_multiplier 0.05
 set g_vehicle_racer_anglestabilizer      1.75
 
-set g_vehicle_racer_turnspeed          200
-set g_vehicle_racer_pitchspeed         100
+set g_vehicle_racer_turnspeed          220
+set g_vehicle_racer_pitchspeed         125
 set g_vehicle_racer_maxpitch           25
-set g_vehicle_racer_turnroll           32
+set g_vehicle_racer_turnroll           30
 
-set g_vehicle_racer_cannon_speed        9000
-set g_vehicle_racer_cannon_damage       20
+set g_vehicle_racer_cannon_speed        15000
+set g_vehicle_racer_cannon_damage       15
 set g_vehicle_racer_cannon_radius       100
-set g_vehicle_racer_cannon_refire       0.1
-set g_vehicle_racer_cannon_cost         4
+set g_vehicle_racer_cannon_refire       0.05
+set g_vehicle_racer_cannon_cost         2
 set g_vehicle_racer_cannon_spread       0.0125
 set g_vehicle_racer_cannon_force        50
 
-set g_vehicle_racer_rocket_speed       1000
-set g_vehicle_racer_rocket_accel       1400
-set g_vehicle_racer_rocket_turnrate    0.17
-set g_vehicle_racer_rocket_damage      160
+set g_vehicle_racer_rocket_speed       900
+set g_vehicle_racer_rocket_accel       1600
+set g_vehicle_racer_rocket_turnrate    0.2
+set g_vehicle_racer_rocket_damage      100
 set g_vehicle_racer_rocket_force       350
 set g_vehicle_racer_rocket_radius      125
-set g_vehicle_racer_rocket_refire      6
+set g_vehicle_racer_rocket_refire      3
 set g_vehicle_racer_rocket_cost        0
+set g_vehicle_racer_rocket_climbspeed  1600
 
 set g_vehicle_racer_rocket_locktarget           1
-set g_vehicle_racer_rocket_locking_time         0.4
-set g_vehicle_racer_rocket_locking_releasetime  1.6
-set g_vehicle_racer_rocket_locked_time          5
-set g_vehicle_racer_rocket_locked_maxangle      1.46
+set g_vehicle_racer_rocket_locking_time         0.35
+set g_vehicle_racer_rocket_locking_releasetime  0.5
+set g_vehicle_racer_rocket_locked_time          4
+set g_vehicle_racer_rocket_locked_maxangle      1.8
 
 set g_vehicle_racer_blowup_radius           250
 set g_vehicle_racer_blowup_coredamage       250
@@ -63,6 +64,6 @@ set g_vehicle_racer_blowup_forceintensity   250
 
 set g_vehicle_racer_bouncefactor 0.25   // Factor of old velocity to keep after colission
 set g_vehicle_racer_bouncestop 0        // if != 0, New veloctiy after bounce = 0 if new velocity < this
-set g_vehicle_racer_bouncepain "35 2 250" // "minspeed_for_pain speedchange_to_pain_factor max_damage"
+set g_vehicle_racer_bouncepain "60 0.75 300" // "minspeed_for_pain speedchange_to_pain_factor max_damage"
 
 set g_vehicle_racer_mass                    900
index 2a46dd28250be16fad45df4f06cb233780357db2..1efc2f17534f291a1387c90af40bff49acb5fbfc 100644 (file)
@@ -1,65 +1,72 @@
-set g_vehicle_raptor_respawntime 35
+set g_vehicle_raptor_respawntime 40
 
 // 0: go where player aims, +forward etc relative to aim angles
 // 1: ignore aim for up/down movement. +forward always moved forward, +jump always moves up
 set g_vehicle_raptor_movestyle 1
 
-set g_vehicle_raptor_turnroll 0.1
+set g_vehicle_raptor_turnroll 0.4
 
-set g_vehicle_raptor_turnspeed  80
-set g_vehicle_raptor_pitchspeed 40
-set g_vehicle_raptor_pitchlimit 35
+set g_vehicle_raptor_takeofftime 1.5
 
-set g_vehicle_raptor_speed_forward 900
-set g_vehicle_raptor_speed_strafe  700
-set g_vehicle_raptor_speed_up      500
-set g_vehicle_raptor_speed_down    800
-set g_vehicle_raptor_friction      0.7
+set g_vehicle_raptor_turnspeed  200
+set g_vehicle_raptor_pitchspeed 50
+set g_vehicle_raptor_pitchlimit 45
+
+set g_vehicle_raptor_speed_forward 1700
+set g_vehicle_raptor_speed_strafe  900
+set g_vehicle_raptor_speed_up      1700
+set g_vehicle_raptor_speed_down    1700
+set g_vehicle_raptor_friction      2
 
 set g_vehicle_raptor_bomblets           8
 set g_vehicle_raptor_bomblet_alt        750
 set g_vehicle_raptor_bomblet_time       0.5
 set g_vehicle_raptor_bomblet_spread     0.4
-set g_vehicle_raptor_bomblet_damage     50
-set g_vehicle_raptor_bomblet_edgedamage 20
-set g_vehicle_raptor_bomblet_radius     310
+set g_vehicle_raptor_bomblet_damage     55
+set g_vehicle_raptor_bomblet_edgedamage 25
+set g_vehicle_raptor_bomblet_radius     350
 set g_vehicle_raptor_bomblet_force      150
 set g_vehicle_raptor_bomblet_explode_delay 0.4
 set g_vehicle_raptor_bombs_refire       5
 
-set g_vehicle_raptor_cannon_turnspeed 90
+set g_vehicle_raptor_cannon_turnspeed 60
 set g_vehicle_raptor_cannon_turnlimit 20
 set g_vehicle_raptor_cannon_pitchlimit_up   12
 set g_vehicle_raptor_cannon_pitchlimit_down 32
 
 set g_vehicle_raptor_cannon_locktarget          1
-set g_vehicle_raptor_cannon_locking_time        0.4
-set g_vehicle_raptor_cannon_locking_releasetime 1.6
-set g_vehicle_raptor_cannon_locked_time         5
+set g_vehicle_raptor_cannon_locking_time        0.2
+set g_vehicle_raptor_cannon_locking_releasetime 0.45
+set g_vehicle_raptor_cannon_locked_time         1
 set g_vehicle_raptor_cannon_predicttarget       1
 
 set g_vehicle_raptor_cannon_cost     1
-set g_vehicle_raptor_cannon_damage   25
+set g_vehicle_raptor_cannon_damage   10
 set g_vehicle_raptor_cannon_radius   60
-set g_vehicle_raptor_cannon_refire   0.05
+set g_vehicle_raptor_cannon_refire   0.03
 set g_vehicle_raptor_cannon_speed    12000
 set g_vehicle_raptor_cannon_spread   0.01
-set g_vehicle_raptor_cannon_force    50
+set g_vehicle_raptor_cannon_force    25
+
+set g_vehicle_raptor_flare_refire 5
+set g_vehicle_raptor_flare_lifetime 10
+set g_vehicle_raptor_flare_chase 0.9
+set g_vehicle_raptor_flare_range 2000
 
-set g_vehicle_raptor_energy             30
-set g_vehicle_raptor_energy_regen       15
-set g_vehicle_raptor_energy_regen_pause 0.8
+set g_vehicle_raptor_energy             100
+set g_vehicle_raptor_energy_regen       25
+set g_vehicle_raptor_energy_regen_pause 0.25
 
 set g_vehicle_raptor_health             150
 set g_vehicle_raptor_health_regen       0
 set g_vehicle_raptor_health_regen_pause 0
 
-set g_vehicle_raptor_shield             120
+set g_vehicle_raptor_shield             75
 set g_vehicle_raptor_shield_regen       25
 set g_vehicle_raptor_shield_regen_pause 1.5
 
 set g_vehicle_raptor_bouncefactor 0.2
 set g_vehicle_raptor_bouncestop 0
-set g_vehicle_raptor_bouncepain "1 1.5 500"
+set g_vehicle_raptor_bouncepain "1 4 1000"
 
 set g_vehicle_raptor_mass              2200
index bb866037adbd0d4c86b23bd660a9cf8555419aa5..0223b09e897770b09ca9ae84b19fd561041758a9 100644 (file)
@@ -1,59 +1,59 @@
 set g_vehicle_spiderbot_respawntime                      45
 
-set g_vehicle_spiderbot_health                850
-set g_vehicle_spiderbot_health_regen             15
-set g_vehicle_spiderbot_health_regen_pause    10
+set g_vehicle_spiderbot_health                800
+set g_vehicle_spiderbot_health_regen             10
+set g_vehicle_spiderbot_health_regen_pause    5
 
-set g_vehicle_spiderbot_shield                150
+set g_vehicle_spiderbot_shield                200
 set g_vehicle_spiderbot_shield_block          1
 set g_vehicle_spiderbot_shield_regen          25
-set g_vehicle_spiderbot_shield_regen_pause    0.2
+set g_vehicle_spiderbot_shield_regen_pause    0.35
 
 set g_vehicle_spiderbot_energy              0
 set g_vehicle_spiderbot_energy_regen        0
 set g_vehicle_spiderbot_energy_regen_pause  0
 
-set g_vehicle_spiderbot_turnspeed            180
-set g_vehicle_spiderbot_head_turnspeed       120
-set g_vehicle_spiderbot_head_turnlimit       120
-set g_vehicle_spiderbot_head_pitchspeed      70
-set g_vehicle_spiderbot_head_pitchlimit_up   24
-set g_vehicle_spiderbot_head_pitchlimit_down -16
+set g_vehicle_spiderbot_turnspeed            90
+set g_vehicle_spiderbot_turnspeed_strafe     300
+set g_vehicle_spiderbot_head_turnspeed       110
+set g_vehicle_spiderbot_head_turnlimit       90
+set g_vehicle_spiderbot_head_pitchlimit_up   30
+set g_vehicle_spiderbot_head_pitchlimit_down -20
 
 set g_vehicle_spiderbot_speed_stop         50
-set g_vehicle_spiderbot_speed_walk         400
-set g_vehicle_spiderbot_speed_strafe       300
-set g_vehicle_spiderbot_movement_inertia   0.25
-
-set g_vehicle_spiderbot_minigun_damage         16
-set g_vehicle_spiderbot_minigun_spread         0.015
-set g_vehicle_spiderbot_minigun_speed          50000
-set g_vehicle_spiderbot_minigun_refire         0.05
-set g_vehicle_spiderbot_minigun_ammo_cost      1
-set g_vehicle_spiderbot_minigun_ammo_max       200
-set g_vehicle_spiderbot_minigun_ammo_regen     15
+set g_vehicle_spiderbot_speed_walk         500
+set g_vehicle_spiderbot_speed_strafe       400
+set g_vehicle_spiderbot_movement_inertia   0.15
+set g_vehicle_spiderbot_tiltlimit          90
+
+set g_vehicle_spiderbot_minigun_damage          12       // 400 (x2) DPS 
+set g_vehicle_spiderbot_minigun_refire          0.03
+set g_vehicle_spiderbot_minigun_force           9
+set g_vehicle_spiderbot_minigun_spread          0.015
+set g_vehicle_spiderbot_minigun_speed           45000  // ~ 32QU
+set g_vehicle_spiderbot_minigun_bulletconstant  110
+set g_vehicle_spiderbot_minigun_ammo_cost       1
+set g_vehicle_spiderbot_minigun_ammo_max        200
+set g_vehicle_spiderbot_minigun_ammo_regen      40
 set g_vehicle_spiderbot_minigun_ammo_regen_pause 1
 
-set g_vehicle_spiderbot_springlength         150
-set g_vehicle_spiderbot_springup             5
-set g_vehicle_spiderbot_springblend         0.15
+set g_vehicle_spiderbot_springlength        150
+set g_vehicle_spiderbot_springup            20
+set g_vehicle_spiderbot_springblend         0.1
 
 set g_vehicle_spiderbot_rocket_health     100
-set g_vehicle_spiderbot_rocket_damage     75
-set g_vehicle_spiderbot_rocket_edgedamage 15
+set g_vehicle_spiderbot_rocket_damage     50
+set g_vehicle_spiderbot_rocket_edgedamage 25
 set g_vehicle_spiderbot_rocket_force      150
-set g_vehicle_spiderbot_rocket_radius     150
+set g_vehicle_spiderbot_rocket_radius     250
 set g_vehicle_spiderbot_rocket_reload     4
-set g_vehicle_spiderbot_rocket_refire     0.2
-set g_vehicle_spiderbot_rocket_speed      1750
-set g_vehicle_spiderbot_rocket_turnrate   0.2
-set g_vehicle_spiderbot_rocket_noise      0.3
-set g_vehicle_spiderbot_rocket_lifetime   30
-
-set g_vehicle_spiderbot_crush_dmg         50
-set g_vehicle_spiderbot_crush_force       50
-
-set g_vehicle_spiderbot_mass              5000
+set g_vehicle_spiderbot_rocket_refire     0.1
+set g_vehicle_spiderbot_rocket_refire2    0.025  // volly
+set g_vehicle_spiderbot_rocket_speed      3500
+set g_vehicle_spiderbot_rocket_turnrate   0.25
+set g_vehicle_spiderbot_rocket_noise      0.2
+set g_vehicle_spiderbot_rocket_lifetime   20
+set g_vehicle_spiderbot_rocket_spread     0.05
 
 set g_vehicle_spiderbot_bouncefactor 0   // Factor of old velocity to keep after colission
 set g_vehicle_spiderbot_bouncestop 0        // if != 0, New veloctiy after bounce = 0 if new velocity < this
index e002321222044400e78d483c77fab3da2a98ea3d..2a350bf89414cc10aea84603b51ef295d71d17f8 100644 (file)
@@ -5,9 +5,10 @@ exec vehicle_raptor.cfg
 exec vehicle_spiderbot.cfg
 exec vehicle_bumblebee.cfg
 
-//set g_vehicle_racer_respawntime     10
-//set g_vehicle_spiderbot_respawntime 10
-//set g_vehicle_raptor_respawntime    10
+set g_vehicle_racer 1
+set g_vehicle_spiderbot 1
+set g_vehicle_raptor 1
+set g_vehicle_bumblebee 1
 
 set g_vehicles_crush_dmg 70
 set g_vehicles_crush_force 50
@@ -17,3 +18,9 @@ set cl_vehicles_hudscale 0.5way
 set g_vehicles_delayspawn 1
 set g_vehicles_delayspawn_jitter 10
 set g_vehicles_allow_flagcarry 1
+
+set g_vehicles_nex_damagerate 0.5
+set g_vehicles_uzi_damagerate 0.65
+set g_vehicles_rifle_damagerate 1
+set g_vehicles_minstanex_damagerate 0.001
+set g_vehicles_tag_damagerate 2
\ No newline at end of file
index 9129bfc4660cce178bac4c79da14de4c054b98a3..1b0318f21c5a5b515237d088d100575389b530e2 100644 (file)
@@ -141,7 +141,8 @@ SoulKeeper_p
 Stephan "esteel" Stahl
 The player with the unnecessarily long name
 Wolfgang "Blub\0" Bumiller
-
+Erik "Ablu" Schilling
+BlaXpirit
 **Past Contributors
 Alexander "motorsep" Zubov
 Amos "torus" Dudley