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"
// 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
// 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
// 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
// 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
// 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
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
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"
// 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
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"
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"
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)"
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
//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
cl_decals 1
-cl_decals_models 1
+cl_decals_models 0
cl_decals_time 10
cl_particles_quality 1
cl_damageeffect 1
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"
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"
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"
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"
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"
--- /dev/null
+Plane,a_bullets_simple
\ No newline at end of file
--- /dev/null
+Plane,a_cells_simple
\ No newline at end of file
--- /dev/null
+Plane,a_rockets_simple
\ No newline at end of file
--- /dev/null
+Plane,a_shells_simple
\ No newline at end of file
--- /dev/null
+Plane,g_h100_simple
\ No newline at end of file
--- /dev/null
+Plane,g_h1_simple
\ No newline at end of file
--- /dev/null
+Plane,g_h25_simple
\ No newline at end of file
--- /dev/null
+Plane,g_h50_simple
\ No newline at end of file
--- /dev/null
+Plane,g_invincible_simple
\ No newline at end of file
--- /dev/null
+Plane,g_strength_simple
\ No newline at end of file
--- /dev/null
+Plane,item_armor_big_simple
\ No newline at end of file
--- /dev/null
+Plane,item_armor_large_simple
\ No newline at end of file
--- /dev/null
+Plane,item_armor_medium_simple
\ No newline at end of file
--- /dev/null
+Plane,item_armor_small_simple
\ No newline at end of file
--- /dev/null
+Plane,g_crylink_simple
\ No newline at end of file
--- /dev/null
+# 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
--- /dev/null
+Plane,g_electro_simple
\ No newline at end of file
--- /dev/null
+Plane,g_gl_simple
\ No newline at end of file
--- /dev/null
+Plane,g_hagar_simple
\ No newline at end of file
--- /dev/null
+Plane,g_nex_simple
\ No newline at end of file
--- /dev/null
+Plane,g_rl_simple
\ No newline at end of file
--- /dev/null
+Plane,g_shotgun_simple
\ No newline at end of file
--- /dev/null
+Plane,g_uzi_simple
\ No newline at end of file
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 ?=
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");
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;
DamageInfo_Precache();
Vehicles_Precache();
turrets_precache();
- Announcer_Precache();
+ Announcer_Precache();
Tuba_Precache();
if(autocvar_cl_reticle)
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));
CSQC_RAPTOR_HUD();
else if(hud == HUD_BUMBLEBEE)
CSQC_BUMBLE_HUD();
+ else if(hud == HUD_BUMBLEBEE_GUN)
+ CSQC_BUMBLE_GUN_HUD();
}
cl_notice_run();
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;
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;
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;
{
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;
+ }
}
}
}
// 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;
}
// 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;
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);
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;
}
}
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)
{
++column;
}
}
+
+ draw_endBoldFont();
}
// Ammo (#1)
HUD_Panel_UpdateCvars(ammo);
HUD_Panel_ApplyFadeAlpha();
+
+ draw_beginBoldFont();
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
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)
HUD_Panel_UpdateCvars(powerups);
HUD_Panel_ApplyFadeAlpha();
+
+ draw_beginBoldFont();
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
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)
} 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)
} 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)
} 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)
HUD_Panel_UpdateCvars(timer);
HUD_Panel_ApplyFadeAlpha();
+
+ draw_beginBoldFont();
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
}
drawstring_aspect(pos, timer, mySize, timer_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ draw_endBoldFont();
}
// Radar (#6)
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]);
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)
{
string distribution_str;
distribution_str = ftos(distribution);
+ draw_beginBoldFont();
if (distribution >= 0)
{
if (distribution > 0)
}
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
float max_fragcount;
max_fragcount = -99;
+ draw_beginBoldFont();
for(tm = teams.sort_next; tm; tm = tm.sort_next) {
if(tm.team == COLOR_SPECTATOR)
continue;
++rows;
}
}
+ draw_endBoldFont();
}
}
HUD_Panel_UpdateCvars(racetimer);
HUD_Panel_ApplyFadeAlpha();
+
+ draw_beginBoldFont();
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
}
}
}
+
+ draw_endBoldFont();
}
// Vote window (#9)
HUD_Panel_UpdateCvars(modicons);
HUD_Panel_ApplyFadeAlpha();
+
+ draw_beginBoldFont();
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
HUD_Mod_Dom(pos, mySize);
else if(gametype == MAPINFO_TYPE_KEEPAWAY)
HUD_Mod_Keepaway(pos, mySize);
+
+ draw_endBoldFont();
}
// Draw pressed keys (#11)
}
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);
HUD_Panel_UpdateCvars(physics);
HUD_Panel_ApplyFadeAlpha();
+ draw_beginBoldFont();
+
HUD_Panel_DrawBg(1);
if(panel_bg_padding)
{
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)
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:
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);
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;
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;
+}
sortlist.qc
miscfunctions.qc
teamplay.qc
+../server/t_items.qc
teamradar.qc
hud_config.qc
target_music.qc
vehicles/vehicles.qc
+../server/vehicles/bumblebee.qc
shownames.qh
shownames.qc
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;
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;
}
hud_fontsize = HUD_GetFontsize("hud_fontsize");
+ draw_beginBoldFont();
for(i = 0; i < argc - 1; ++i)
{
float nocomplain;
}
hud_field[hud_num_fields] = SP_END;
+ draw_endBoldFont();
}
// MOVEUP::
}
// 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)
pos_x -= hud_fontsize_x;
}
}
+ draw_endBoldFont();
pos_x = xmin;
pos_y += 1.25 * hud_fontsize_y; // skip the header
// 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;
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);
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);
}
}
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;
}
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);
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
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;
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;
+ }
}
}
#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];
.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;
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;
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)
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;
}
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()
{
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;
alarm2time = 0;
}
}
-
// Minigun bar
picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
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;
}
}
-#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)
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
}
}
-#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()
{
/*
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");
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);
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);
{
o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
}
+ draw_endBoldFont();
}
void Ent_RemoveWaypointSprite()
{
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.
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)
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));
{
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));
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));
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)
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)
return;
}
}
-}
\ No newline at end of file
+}
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;
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
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';
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;
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;
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 = "";
# 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)
# 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))
spawnpoints = 0;
spawnplaces = 0;
_MapInfo_Map_worldspawn_music = "";
+ mapMins = '0 0 0';
+ mapMaxs = '0 0 0';
for(;;)
{
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;
-var float MAPINFO_TYPE_ALL = 0;
+float MAPINFO_TYPE_ALL;
entity MapInfo_Type_first;
entity MapInfo_Type_last;
.entity enemy; // internal next pointer
{
float created_saved_value;
entity e;
+
+ created_saved_value = FALSE;
if not(tmp_cvar || tmp_value)
{
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"))
while(acl)
{
t = car(acl); acl = cdr(acl);
+
d = 1;
if(substring(t, 0, 1) == "-")
{
}
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;
}
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)
+}
// 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);
// 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);
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);
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)
{
// 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.
//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
--- /dev/null
+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));
+}
other.parent = me;
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
other.parent = NULL;
- entity n, p, f, l;
- f = me.firstChild;
- l = me.lastChild;
+ entity n, p;
n = other.nextSibling;
p = other.prevSibling;
other.parent = me;
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
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)
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);
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)
{
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;
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
{
other.Container_size = theSize;
me.setAlphaOf(me, other, theAlpha);
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
other.parent = NULL;
- entity n, p, f, l;
- f = me.firstChild;
- l = me.lastChild;
+ entity n, p;
n = other.nextSibling;
p = other.prevSibling;
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;
void Dialog_configureDialog(entity me)
{
- entity closebutton;
float absWidth, absHeight;
me.frame = spawnBorderImage();
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)
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
}
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;
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)
float spaceAvail;
spaceAvail = 1 - me.keepspaceLeft - me.keepspaceRight;
+ if(me.isBold)
+ draw_beginBoldFont();
+
float spaceUsed;
spaceUsed = draw_TextWidth(t, me.allowColors, me.realFontSize);
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)
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;
draw_Text(me.realOrigin, t, fs, me.colorL, me.alpha, me.allowColors);
draw_fontscale = dfs;
+
+ if(me.isBold)
+ draw_endBoldFont();
}
SUPER(Label).draw(me);
}
float ListBox_mouseRelease(entity me, vector pos)
{
- vector absSize;
if(me.pressed == 1)
{
// slider dragging mode
// 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));
}
}
vector fs;
animating = 0;
+ front = world;
for(e = me.firstChild; e; e = e.nextSibling)
if(e.ModalController_state)
{
}
switch(me.animationState)
{
+ default:
case 0:
case 3:
nexposeeKey = ((scan == K_SPACE) || (scan == K_ENTER) || (scan == K_KP_ENTER));
{
switch(me.animationState)
{
+ default:
case 0:
case 3:
me.animationState = 1;
scalemode = SCALEMODE_CROP;
+ l = 0;
for(i = 0; i < strlen(algn); ++i)
{
c = substring(algn, i, 1);
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
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");
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");
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'));
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:")));
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);
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");
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");
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");
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));
buf = buf_create();
fh = fopen("languages.txt", FILE_READ);
+ i = 0;
while((s = fgets(fh)))
{
n = tokenize_console(s);
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)
{
s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
m = tokenizebyseparator(s, ":");
+ typestr = "";
if(m >= 2)
{
typestr = argv(0);
freeslots = -1;
sflags = -1;
modname = "";
+ pure = 0;
for(j = 2; j < m; ++j)
{
if(argv(j) == "")
#define GAMETYPE(id) if(i++ == cnt) return id;
GAMETYPES
#undef GAMETYPE
+
+ unused_float = i;
return 0;
}
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);
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);
void antilag_restore(entity e)
{
+ if (e.vehicle && e.vehicle.vehicle_flags == VHF_PLAYERSLOT)
+ return;
+
if(e.vehicle)
antilag_restore(e.vehicle);
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
}
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;
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;
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;
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();
{
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)
{
self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
- for(;;)
+ for(i = 0; ; ++i)
{
while (head)
{
self.dphitcontentsmask |= DPCONTENTS_OPAQUE;
head = head2;
- ++i;
}
// Restore hit flags
// 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
if not(teamplay)
return 0;
- float c;
+ float c = 0;
entity head;
FOR_EACH_PLAYER(head)
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)
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)
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
float havocbot_ons_teamcount(entity bot, float role)
{
- float c;
+ float c = 0;
entity head;
FOR_EACH_PLAYER(head)
// We'll consider only the best case
bestvalue = 99999999999;
+ cp = world;
for (; cp1; cp1 = cp1.chain)
{
if not(cp1.wpconsidered)
dir = normalize(move);
stepdist = 32;
ignorehazards = FALSE;
+ swimming = FALSE;
// Analyze starting point
traceline(start, start, MOVE_NORMAL, e);
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)
{
{
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;
entity find_bot_by_number(float number)
{
entity bot;
- float c;
+ float c = 0;
if(!number)
return world;
float lost;
string savevar;
- won = 0;
+ won = lost = 0;
head = findchain(classname, "player");
while(head)
float drag;
crosshair_trace_plusvisibletriggers(self);
+ drag = FALSE;
if(vlen(self.origin - trace_ent.origin) <= autocvar_g_grab_range)
{
switch(trace_ent.grab)
}
if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
+ vehicles_exit(VHEF_RELESE);
if(self.flagcarried)
DropFlag(self.flagcarried, world, world);
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;
vector m1, m2;
defaultmodel = "";
+ defaultskin = 0;
+ chmdl = FALSE;
if(autocvar_sv_defaultcharacter == 1)
{
- defaultskin = 0;
-
if(teamplay)
{
string s;
{
if(self.killindicator_teamchange == -1)
{
- self.team = -1;
- JoinBestTeam( self, FALSE, FALSE );
+ JoinBestTeam( self, FALSE, TRUE );
}
else if(self.killindicator_teamchange == -2)
{
return;
}
- if (self.owner.alpha < 0)
+ if (self.owner.alpha < 0 && !self.owner.vehicle)
{
self.owner.killindicator = world;
remove(self);
} 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;
rr = CTS_RECORD;
else
rr = RACE_RECORD;
- t = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
msg_entity = self;
race_send_recordtime(MSG_ONE);
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;
}
/*
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;
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);*/
}
}
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);
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);
if(!SpectateUpdate())
PutObserverInServer();
- }
+ //}
return 1;
} else {
return 0;
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)
// TODO simplify this
entity e;
- float totalClients;
+ float totalClients = 0;
FOR_EACH_CLIENT(e)
if(e != ignore)
totalClients += 1;
if (!autocvar_g_maxplayers)
return maxclients - totalClients;
- float currentlyPlaying;
+ float currentlyPlaying = 0;
FOR_EACH_REALPLAYER(e)
currentlyPlaying += 1;
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 {
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";
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)
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))
{
}
.entity pusher;
.float pushltime;
+.float istypefrag;
.float CopyBody_nextthink;
.void(void) CopyBody_think;
// 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)
{
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)
// 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) == " ")
else if(teamplay)
colorstr = Team_ColorCode(source.team);
else
+ {
+ colorstr = "";
teamsay = FALSE;
+ }
if(intermission_running)
teamsay = FALSE;
// FLOOD CONTROL
flood = 0;
+ flood_field = floodcontrol_chat;
if(floodcontrol)
{
float flood_spl;
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))
{
// 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;
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;
{
vector mdirection;
float mspeed;
- float outspeed;
- float nstyle;
vector outvelocity;
mvelocity = mvelocity * g_weaponspeedfactor;
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;
}
// 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);
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)
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);
}
}
}
-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)
case "pink": selection = COLOR_TEAM4; break;
case "auto": selection = (-1); break;
- default: break;
+ default: selection = 0; break;
}
if(selection)
{
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);
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") \
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
next_token = -1;
index = start_index;
+ selection = world;
if(argc > start_index)
{
tmp_number = stof(argv(index));
++index;
}
+ else
+ tmp_number = 0;
}
else // maybe it's ONLY a number?
{
}
else
{
+ selection = world;
FOR_EACH_CLIENT(tmp_player)
if (strdecolorize(tmp_player.netname) == strdecolorize(input))
selection = tmp_player;
entity selection = GetFilteredEntity(input);
float output;
- if(selection) { output = num_for_edict(selection); }
+ output = num_for_edict(selection);
return output;
}
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);
#undef COMMON_COMMAND
return;
-}
\ No newline at end of file
+}
{
float rec = 0, r, i;
string h, s;
+
+ s = "";
if (g_ctf)
{
map = GetMapname();
+ s = "";
for (i = 1; i <= RANKINGS_CNT; ++i)
{
t = race_readTime(map, i);
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)
return "No ladder on this server!\n";
else
return strcat("Top ", ftos(LADDER_SIZE), " ladder rankings:\n", s);
-}
\ No newline at end of file
+}
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;
}
return FALSE;
-}
\ No newline at end of file
+}
float infobartime = stof(argv(3));
string successful, t;
+ successful = string_null;
if((targets) && (admin_message))
{
{
entity client;
string reason = argv(1);
- float i;
+ float i = 0;
FOR_EACH_REALPLAYER(client)
{
case CMD_REQUEST_COMMAND:
{
entity client;
- float i;
+ float i = 0;
float argc;
FOR_EACH_CLIENT(client)
string notify = argv(3);
string successful, t;
+ successful = string_null;
// lets see if the target(s) even actually exist.
if((targets) && (destination))
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);
{
if(argv(2))
{
- entity client = GetIndexedEntity(argc, 1));
+ entity client = GetIndexedEntity(argc, 1);
float accepted = VerifyClientEntity(client, TRUE, FALSE);
if(accepted > 0)
{
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)
{
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
+}
|| ((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;
{
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)
{
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;
}
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":
|| ((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);
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;
else
e.gravity = 0;
- e.csqcprojectile_type = type;
if(!sound_allowed(MSG_BROADCAST, e))
type |= 0x80;
+ e.csqcprojectile_type = type;
}
void UpdateCSQCProjectile(entity e)
.float t_length, t_width;
.vector destvec; // for rain
+.vector destvec2; // for train
.float cnt; // for rain
.float count;
//.float cnt2;
.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
.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)
-// 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.
*/
.float teamkill_soundtime;
.entity teamkill_soundsource;
.entity pusher;
+.float istypefrag;
.float taunt_soundtime;
// 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)
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))
{
{
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);
if (targ.killcount > 2)
msg = ftos(targ.killcount);
+ else
+ msg = "";
if(teamplay && deathtype == DEATH_MIRRORDAMAGE)
{
if(attacker.team == COLOR_TEAM1)
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);
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 {
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");
msg = inflictor.message;
else if (deathtype == DEATH_CUSTOM)
msg = deathmessage;
+ else
+ msg = "";
if(strstrofs(msg, "%", 0) < 0)
msg = strcat("%s ", msg);
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;
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;
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;
self.aiment.flags &~= FL_ONGROUND;
self.aiment.pusher = self.realowner;
self.aiment.pushltime = time + autocvar_g_maxpushtime;
+ self.aiment.istypefrag = self.aiment.BUTTON_CHAT;
}
}
{
self.realowner.pusher = attacker;
self.realowner.pushltime = time + autocvar_g_maxpushtime;
+ self.realowner.istypefrag = self.realowner.BUTTON_CHAT;
}
RemoveGrapplingHook(self.realowner);
}
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
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;
}
}
-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;
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;
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;
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)
{
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;
dprint(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
}
+ stopentity = trace_ent;
+
if(trace_startsolid)
{
// we started inside solid.
// 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
{
}
}
-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);
}
/*
if (other.iscreature)
{
if (other.takedamage)
+ if (!other.deadflag)
if (other.triggerhealtime < time)
{
EXACTTRIGGER_TOUCH;
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)
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");
print(s, "\n");
if(to_eventlog)
GameLogEcho(s);
+
+ file = -1;
if(to_file)
{
file = fopen(autocvar_sv_logscores_filename, FILE_APPEND);
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
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)
{
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)
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]);
print("^2Listing all existing active bans:\n");
+ n = 0;
for(i = 0; i < ban_count; ++i)
{
if(time > ban_expire[i])
if ((keylist & (keylist-1)) != 0)
return strcat("the ", item_keys_names[lowestbit(keylist)]);
+ n = "";
+ base = 0;
while (keylist) {
l = lowestbit(keylist);
if (n)
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;
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)
}
void GetCvars(float f)
{
- string s;
+ string s = string_null;
if (f > 0)
s = strcat1(argv(f));
float warmup_start_health;
float warmup_start_armorvalue;
float g_weapon_stay;
-float g_ghost_items;
entity get_weaponinfo(float w);
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")
{
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);
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?
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");
{
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)))
e.initialize_entity_order = order;
cur = initialize_entity_first;
+ prev = world;
for (;;)
{
if (!cur || cur.initialize_entity_order > order)
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)
org = world.mins;
delta = world.maxs - world.mins;
+ start = end = org;
+
for (i = 0; i < attempts; ++i)
{
start_x = org_x + random() * delta_x;
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;
+++ /dev/null
-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);
-}
**/
#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;
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;
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)
{
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.");
}
{
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.");
}
.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)
{
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")
i += 4;
if(key.netname == "^6pink key")
i += 8;
- test[key.owner.playerid] = i;
+ kh_keystatus[key.owner.playerid] = i;
kh_Key_Attach(key);
first = TRUE;
midpoint = '0 0 0';
+ firstorigin = '0 0 0';
+ lastorigin = '0 0 0';
FOR_EACH_KH_KEY(key)
{
vector thisorigin;
{
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)
{
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.");
}
if(nb_teams == 2)
otherteam = OtherTeam(ball.team);
+ else
+ otherteam = 0;
if((isclient = ball.pusher.flags & FL_CLIENT))
pname = ball.pusher.netname;
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"));)
{
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
--- /dev/null
+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;
+}
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;
}
}
-
-
if (dodge_detected == 1) {
self.last_dodging_time = time;
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);
--- /dev/null
+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;
+}
MUTATOR_DECLARATION(gamemode_freezetag);
MUTATOR_DECLARATION(gamemode_keepaway);
MUTATOR_DECLARATION(gamemode_nexball);
+MUTATOR_DECLARATION(gamemode_onslaught);
MUTATOR_DECLARATION(mutator_dodging);
MUTATOR_DECLARATION(mutator_invincibleprojectiles);
MUTATOR_DECLARATION(mutator_rocketflying);
MUTATOR_DECLARATION(mutator_spawn_near_teammate);
MUTATOR_DECLARATION(mutator_vampire);
+MUTATOR_DECLARATION(mutator_superspec);
MUTATOR_DECLARATION(sandbox);
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;
}
// 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])
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)
{
pathlib_expandnode = pathlib_expandnode_box;
pathlib_movenode = pathlib_swimnode;
+ doedge = 0;
}
else
{
{
pathlib_expandnode = pathlib_expandnode_box;
pathlib_movenode = pathlib_swimnode;
+ doedge = 0;
}
else
{
plib_points2[0] = plib_points[0];
vector bp;
bp = plib_points[0];
+ fc2 = 0;
for(i = 0; i < 8; ++i)
{
c = 0;
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;
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
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)
ctf.qc
domination.qc
-mode_onslaught.qc
+//mode_onslaught.qc
//nexball.qc
g_hook.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
mutators/mutator_vampire.qc
mutators/mutator_spawn_near_teammate.qc
mutators/sandbox.qc
+mutators/mutator_superspec.qc
../warpzonelib/anglestransform.qc
../warpzonelib/mathlib.qc
newpos = race_readPos(map, t);
float i;
+ player_prevpos = 0;
for(i = 1; i <= RANKINGS_CNT; ++i)
{
if(race_readUID(map, i) == myuid)
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
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
{
}
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;
vector RuneColormod(float r)
{
- vector _color;
+ vector _color = '255 0 255';
+
if(r == RUNE_STRENGTH)
_color = '255 0 0';
if(r == RUNE_DEFENSE)
// count runes my owner holds
rcount = 0;
rune = find(world, classname, "rune");
+ rnum = -1;
while(rune)
{
if(rune.owner == self.owner)
entity curse1, rune1, curse2, rune2;
- rune = curse = world;
rcount = ccount = r = c = 0;
rune = find(rune, classname, "rune");
while(rune)
numtodrop = autocvar_g_runematch_drop_runes_max;
prevent_same = !autocvar_g_runematch_allow_same;
- rune = curse = world;
do
{
rune = find(rune, classname, "rune");
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;
{
if(!t1 || !t2) return (!t2) - !t1;
- vector result;
+ vector result = '0 0 0';
float i;
for(i = 0; i < MAX_TEAMSCORE; ++i)
{
{
if(!t1 || !t2) return (!t2) - !t1;
- vector result;
+ vector result = '0 0 0';
float i;
for(i = 0; i < MAX_SCORE; ++i)
{
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)
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)
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);
CreatureFrame ();
CheckRules_World ();
- AuditTeams();
-
RuneMatchGivePoints();
bot_serverframe();
+#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
.float max_armorvalue;
.float pickup_anyway;
-
+/*
float Item_Customize()
{
if(self.spawnshieldtime)
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)
if(self.count == 1)
{
string name;
- vector rgb;
+ vector rgb = '1 0 1';
name = string_null;
if(g_minstagib)
{
}
}
e = RandomSelection_chosen_ent;
+
}
else
e = self;
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;
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;
if(weaponid)
WEPSET_COPY_EW(self, weaponid);
+
self.flags = FL_ITEM | itemflags;
if(MUTATOR_CALLHOOK(FilterItem)) // error means we do not want the item
remove (self);
return;
}
+
+ if(self.angles != '0 0 0')
+ self.SendFlags |= ISF_ANGLES;
self.reset = Item_Reset;
// it's a level item
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));
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
* 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)
void spawnfunc_item_minst_cells (void) {
if (g_minstagib)
{
- minst_no_auto_cells = 1;
+ minst_no_auto_cells = TRUE;
minstagib_items(IT_CELLS);
}
else
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;
return got;
}
+#endif
float PUSH_SILENT = 2;
.float pushltime;
+.float istypefrag;
.float height;
void() SUB_UseTargets;
// reset tracking of who pushed you into a hazard (for kill credit)
other.pushltime = 0;
+ other.istypefrag = 0;
}
if(self.enemy.target)
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
{
{
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;
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);
{
ActivateTeamplay();
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_onslaught);
}
if(g_race)
c1 = c2 = c3 = c4 = -1;
cb1 = cb2 = cb3 = cb4 = 0;
+ teament_name = string_null;
if(g_onslaught)
{
// onslaught is special
float PlayerValue(entity p)
{
- if(IsTeamBalanceForced() == 1)
- return 1;
return 1;
// FIXME: it always returns 1...
}
}
}
+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
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;
}
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");
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;
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)
{
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);
vector real_origin(entity ent)
{
entity e;
- vector v;
+ vector v = ((ent.absmin + ent.absmax) * 0.5);
e = ent.tag_entity;
while(e)
v = v + ((e.absmin + e.absmax) * 0.5);
e = e.tag_entity;
}
- v = v + ((ent.absmin + ent.absmax) * 0.5);
+
return v;
}
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;
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;
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;
}
}
else
{
+ edist = 0;
+ ve = '0 0 0';
fe = 0;
}
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;
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);
}
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;
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;
}
entity toast(entity from, float range, float damage)
{
entity e;
- entity etarget;
+ entity etarget = world;
float d,dd;
float r;
rocket.tur_shotorg = randomvec() * 512;
rocket.cnt = time + 1;
rocket.enemy = self.enemy;
-
+
if (random() < 0.01)
rocket.think = walker_rocket_loop;
else
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
}
--- /dev/null
+#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
void racer_enter();
// Auto cvars
+float autocvar_g_vehicle_racer;
+
float autocvar_g_vehicle_racer_speed_afterburn;
float autocvar_g_vehicle_racer_afterburn_cost;
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;
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);
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)
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);
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)
{
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;
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;
player = self;
racer = self.vehicle;
self = racer;
-
+
player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
-
+
vehicles_painframe();
-
+
if(racer.deadflag != DEAD_NO)
{
self = player;
return 1;
}
- racer_align4point();
+ racer_align4point(frametime);
crosshair_trace(player);
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)
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)
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;
}
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');
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()
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;
}
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,
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;
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");
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;
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
-#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;
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;
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();
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()
void raptor_enter()
{
+ self.vehicle_weapon2mode = RSM_BOMB;
self.owner.PlayerPhysplug = raptor_takeoff;
self.movetype = MOVETYPE_BOUNCEMISSILE;
self.solid = SOLID_SLIDEBOX;
if(self.owner.flagcarried)
setorigin(self.owner.flagcarried, '-20 0 96');
-
+
+ CSQCVehicleSetup(self.owner, 0);
}
void raptor_land()
if not (self.owner)
return;
-
+
makevectors(self.angles);
if(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;
}
// 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;
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)
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,
}
}
- // 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;
}
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;
{
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;
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);
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);
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;
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;
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
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;
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;
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()
{
}
}
+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;
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
//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)
{
}
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;
}
}
- 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)
{
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;
}
}
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;
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;
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;
e = e.chain;
}
- self.velocity = '0 0 0';
+ //self.velocity = '0 0 0';
self.think = spiderbot_think;
self.nextthink = time;
self.frame = 5;
}
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()
{
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;
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;
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;
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
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();
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);
// 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);
// 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
.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)
self.lock_soundtime = time + 0.5;
play2(self.owner, "vehicles/locked.wav");
}
-
+
return;
}
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)
}
}
-#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); \
{
// 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)
self.think = self.use;
self.nextthink = time;
}
-
}
void vehicles_projectile_explode()
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;
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;
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?)
}
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");
}
{
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;
}
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;
if(self.team)
if(self.team != other.team)
return;
-
+
RemoveGrapplingHook(other);
self.vehicle_ammo1 = 0;
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);
}
{
//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;
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)
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;
}
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)
{
//setmodel(self, "");
self.alpha = -1;
+ self.effects |= EF_NODRAW;
}
else
{
}
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)
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;
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
}
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)
{
else
vehicles_exit(VHEF_RELESE);
+
+ antilag_clear(self);
+
self.vehicle_die();
vehicles_setreturn();
}
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;
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);
}
{
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;
}
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()
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,
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 == "")
if(self.team && !teamplay)
self.team = 0;
-
+
self.vehicle_flags |= VHF_ISVEHICLE;
-
+
setmodel(self, bodymodel);
self.vehicle_viewport = spawn();
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;
setmodel(self.vehicle_hudmodel, hudmodel);
setmodel(self.vehicle_viewport, "null");
-
if(topmodel != "")
{
setmodel(self.tur_head, topmodel);
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
#include "racer.qc"
#include "spiderbot.qc"
#include "raptor.qc"
-//#include "bumblebee.qc"
+#ifndef VEHICLES_NO_UNSTABLE
+#include "bumblebee.qc"
+#endif
#endif
#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
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;
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
entity pseudoprojectile;
float f, ffs;
+ pseudoprojectile = world;
+
railgun_start = start;
railgun_end = end;
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;
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;
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:
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;
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;
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;
W_BallisticBullet_Hit();
}
+ if(proj.dmg_radius < 0) // these NEVER penetrate solid
+ break;
+
// if we hit "weapclip", bail out
//
// rationale of this check:
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;
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;
p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity);
UpdateCSQCProjectile(p);
}
+ targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE
}
else
{
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;
//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)
{
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;
//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)
{
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);
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;
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);
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);
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);
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);
missile.angles = vectoangles (missile.velocity);
missile.flags = FL_PROJECTILE;
+ missile.missile_flags = MIF_SPLASH;
CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
missile.angles = vectoangles (missile.velocity);
missile.flags = FL_PROJECTILE;
+ missile.missile_flags = MIF_SPLASH;
CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR_BOUNCING, TRUE);
shots = self.hagar_load;
missile = world;
- while (counter < shots)
+ for(counter = 0; counter < shots; ++counter)
{
missile = spawn ();
missile.owner = missile.realowner = self;
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));
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);
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);
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)
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;
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;
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);
float W_PlacedMines(float detonate)
{
entity mine;
- float minfound;
+ float minfound = 0;
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self)
{
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)
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
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
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)
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);
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);
{
entity tracker, closest_target;
+ closest_target = world;
for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self)
{
if (closest_target)
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);
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
o0 = e.origin;
v0 = e.velocity;
+ g = cvar("sv_gravity") * e.gravity;
WarpZone_trace_forent = forent;
WarpZone_trace_firstzone = world;
e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
}
WarpZone_MakeAllSolid();
- g = cvar("sv_gravity") * e.gravity;
i = 16;
for(;;)
{
float WarpZone_Camera_Send(entity to, float sendflags)
{
- float f;
+ float f = 0;
WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
if(self.warpzone_fadestart)
--- /dev/null
+////////// 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
{
dpreflectcube cubemaps/default/sky
{
- map textures/minelayer.tga
+ map textures/minelayer.tga
rgbgen lightingDiffuse
}
}
-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
-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
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
-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
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
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
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
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