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)
// 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)
// 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)
// 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)
// 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
// hit indication animation settings
seta crosshair_hitindication 0.5
-seta crosshair_hitindication_color "10 -10 -10"
+seta crosshair_hitindication_color "10 10 10"
seta crosshair_hitindication_speed 5
// hit testing/tracing for special effects for the crosshair
// reload ring
seta crosshair_ring_reload 1 "main cvar to enable or disable ammo crosshair rings"
seta crosshair_ring_reload_size 2.5 "reload ring size"
-seta crosshair_ring_reload_alpha 0.2 "reload ring alpha"
\ No newline at end of file
+seta crosshair_ring_reload_alpha 0.2 "reload ring alpha"
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_simpleitems_postfix "_simple" "posfix to add fo model name when simple items are enabled"
+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"
//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
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
void CSQC_Init(void)
{
prvm_language = cvar_string("prvm_language");
-
#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()
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))
}
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)
+}
// 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);
// 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
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)
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
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
ATTRIB(XonoticMutatorsDialog, title, string, _("Mutators"))
ATTRIB(XonoticMutatorsDialog, color, vector, SKINCOLOR_DIALOG_MUTATORS)
ATTRIB(XonoticMutatorsDialog, intendedWidth, float, 0.9)
- ATTRIB(XonoticMutatorsDialog, rows, float, 17)
+ ATTRIB(XonoticMutatorsDialog, rows, float, 19)
ATTRIB(XonoticMutatorsDialog, columns, float, 6)
ATTRIB(XonoticMutatorsDialog, refilterEntity, entity, NULL)
ENDCLASS(XonoticMutatorsDialog)
}
}
s = sprintf(_("%s Arena"), substring(s, 3, strlen(s) - 3));
-
+
weaponarenastring = strzone(s);
return weaponarenastring;
me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Gameplay mutators:")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_dodging", _("Dodging")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_dodging", _("Dodging")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_cloaked", _("Cloaked")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_cloaked", _("Cloaked")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_midair", _("Midair")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_midair", _("Midair")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_vampire", _("Vampire")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_vampire", _("Vampire")));
me.TR(me);
me.TDempty(me, 0.2);
s = makeXonoticSlider(10, 50, 1, "g_bloodloss");
- me.TD(me, 1, 2, e = makeXonoticSliderCheckBox(0, 1, s, _("Blood loss")));
+ me.TD(me, 1, 1.8, e = makeXonoticSliderCheckBox(0, 1, s, _("Blood loss")));
setDependent(e, "g_minstagib", 0, 0);
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 1.8, s);
+ me.TD(me, 1, 1.6, s);
me.TR(me);
me.TDempty(me, 0.2);
s = makeXonoticSlider(80, 400, 8, "sv_gravity");
s.valueDigits = 0;
s.valueDisplayMultiplier = 0.125; // show gravity in percent
- me.TD(me, 1, 2, e = makeXonoticSliderCheckBox(800, 1, s, _("Low gravity")));
+ me.TD(me, 1, 1.8, e = makeXonoticSliderCheckBox(800, 1, s, _("Low gravity")));
e.savedValue = 200; // good on silvercity
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 1.8, s);
+ me.TD(me, 1, 1.6, s);
me.TR(me);
me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Weapon & item mutators:")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_grappling_hook", _("Grappling hook")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_grappling_hook", _("Grappling hook")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_jetpack", _("Jet pack")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_jetpack", _("Jet pack")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_invincible_projectiles", _("Invincible Projectiles")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_invincible_projectiles", _("Invincible Projectiles")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_new_toys", _("New Toys")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_new_toys", _("New Toys")));
setDependentWeird(e, checkCompatibility_newtoys);
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_rocket_flying", _("Rocket Flying")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_rocket_flying", _("Rocket Flying")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_pinata", _("Piñata")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_pinata", _("Piñata")));
setDependentWeird(e, checkCompatibility_pinata);
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_weapon_stay", _("Weapons stay")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "g_weapon_stay", _("Weapons stay")));
setDependentWeird(e, checkCompatibility_weaponstay);
me.TR(me);
me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Weapon arenas:")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, string_null, string_null, _("Regular (no arena)")));
+ me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, string_null, string_null, _("Regular (no arena)")));
for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
{
w = get_weaponinfo(i);
str = w.netname;
hstr = w.message;
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_weaponarena", strzone(str), strzone(hstr)));
+ me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_weaponarena", strzone(str), strzone(hstr)));
e.cvarOffValue = "0";
// custom load/save logic that ignores a " laser" suffix, or adds it
e.loadCvars = loadCvarsLaserWeaponArenaWeaponButton;
}
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "menu_weaponarena_with_laser", _("with laser")));
+ me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "menu_weaponarena_with_laser", _("with laser")));
// hook the draw function to gray it out
e.draw_weaponarena = e.draw;
e.draw = preDrawLaserWeaponArenaLaserButton;
me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Special arenas:")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_minstagib", string_null, _("MinstaGib")));
+ me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_minstagib", string_null, _("MinstaGib")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_nix", string_null, _("NIX")));
+ me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_nix", string_null, _("NIX")));
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "g_nix_with_laser", _("with laser")));
+ me.TD(me, 1, 1.6, e = makeXonoticCheckBox(0, "g_nix_with_laser", _("with laser")));
setDependent(e, "g_nix", 1, 1);
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_weaponarena", "most", _("Most weapons")));
+ me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_weaponarena", "most", _("Most weapons")));
e.cvarOffValue = "0";
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", _("No start weapons")));
+ me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", _("No start weapons")));
e.cvarOffValue = "-1";
makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_minelayer g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_rifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba g_start_weapon_minelayer");
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);
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)
{
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;
}
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;
{
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;
return;
sv_notice_join();
+
+ MUTATOR_CALLHOOK(ClientConnect);
}
/*
=============
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)
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.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x) // prevent crouching if using melee attack
+ if (!self.vehicle)
+ if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen) // 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))
{
}
PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
}
}
- else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO))
+ else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO) && !self.freezetag_frozen)
{
//makevectors(self.v_angle_y * '0 1 0');
makevectors(self.v_angle);
else if (self.flags & FL_ONGROUND)
{
// we get here if we ran out of ammo
- if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32))
+ if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01)
sprint(self, "You don't have any fuel for the ^2Jetpack\n");
// walking
{
float wishspeed0;
// we get here if we ran out of ammo
- if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32))
+ if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01)
sprint(self, "You don't have any fuel for the ^2Jetpack\n");
if(maxspd_mod < 1)
.entity pusher;
.float pushltime;
+.float istypefrag;
.float CopyBody_nextthink;
.void(void) CopyBody_think;
if (!self.animstate_override)
{
- if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
+ if (self.freezetag_frozen)
+ setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
+ else if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
{
if (self.crouch)
{
self.alpha = -1;
self.solid = SOLID_NOT; // restore later
self.takedamage = DAMAGE_NO; // restore later
+ self.damagedbycontents = FALSE;
}
}
// 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);
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))
{
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);
}
{
if(argv(1) != "")
{
- float tokens;
+ //float tokens;
string s;
if(argc == 2) // undefined cvar: use the default value on the server then
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
+}
{
if(argv(2))
{
- entity client = GetIndexedEntity(argc, 1));
+ entity client = GetIndexedEntity(argc, 1);
float accepted = VerifyClientEntity(client, TRUE, FALSE);
if(accepted > 0)
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":
if (!other.flagcarried)
if (!other.ctf_captureshielded)
{
+ if(MUTATOR_CALLHOOK(ItemTouch))
+ return;
+
if (other.next_take_time > time)
return;
.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;
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.killcount = attacker.killcount + 1;
- if (attacker.killcount > 2) {
- Send_KillNotification(a, ftos(attacker.killcount), "", KILL_SPREE, MSG_SPREE);
- }
- else if (attacker.killcount == 3)
+ if (attacker.killcount == 3)
{
Send_KillNotification(a, "", "", KILL_SPREE_3, MSG_SPREE);
AnnounceTo(attacker, "03kills");
AnnounceTo(attacker, "30kills");
PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30, 1);
}
+ else if (attacker.killcount > 2) {
+ Send_KillNotification(a, ftos(attacker.killcount), "", KILL_SPREE, MSG_SPREE);
+ }
LogDeath("frag", deathtype, attacker, targ);
}
}
if(autocvar_g_mirrordamage_virtual)
{
- vector v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
+ 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(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;
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;
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");
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
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)
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)
#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(v.flags & FL_CLIENT)
#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(v.classname == STR_PLAYER)
+#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if(v.classname != STR_PLAYER)
#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(v.classname == STR_PLAYER)
#endif
float warmup_start_health;
float warmup_start_armorvalue;
float g_weapon_stay;
-float g_ghost_items;
entity get_weaponinfo(float w);
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");
+++ /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")
- {
- 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 (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 other; // weapon info
// IN+OUT
string ret_string;
+
+MUTATOR_HOOKABLE(ItemTouch);
+ // called at when a item is touched. Called early, can edit item properties.
+ entity self; // item
+ entity other; // player
+
+MUTATOR_HOOKABLE(ClientConnect);
+ // called at when a player connect
+ entity self; // player
FOR_EACH_PLAYER(e)
{
- if(e.freezetag_frozen == 0 && e.classname == "player" && e.health >= 1) // here's one player from the winning team... good
+ if(e.freezetag_frozen == 0 && e.health >= 1) // here's one player from the winning team... good
{
winner = e;
break; // break, we found the winner
MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
{
- if(self.freezetag_frozen == 0)
+ if(self.freezetag_frozen == 0 && self.health >= 1)
{
if(self.team == COLOR_TEAM1)
--redalive;
--pinkalive;
--totalalive;
- freezetag_Freeze(frag_attacker);
+ freezetag_Freeze(frag_attacker);
}
- if(frag_attacker.classname == STR_PLAYER)
- centerprint(frag_attacker, strcat("^2You froze ^7", frag_target.netname, ".\n"));
-
if(frag_attacker == frag_target || frag_attacker == world)
{
- if(frag_target.classname == STR_PLAYER)
- centerprint(frag_target, "^1You froze yourself.\n");
+ if(frag_target.classname == STR_PLAYER)
+ centerprint(frag_target, "^1You froze yourself.\n");
bprint("^7", frag_target.netname, "^1 froze himself.\n");
}
else
{
- if(frag_target.classname == STR_PLAYER)
- centerprint(frag_target, strcat("^1You were frozen by ^7", frag_attacker.netname, ".\n"));
+ if(frag_target.classname == STR_PLAYER)
+ centerprint(frag_target, strcat("^1You were frozen by ^7", frag_attacker.netname, ".\n"));
+ if(frag_attacker.classname == STR_PLAYER)
+ centerprint(frag_attacker, strcat("^2You froze ^7", frag_target.netname, ".\n"));
bprint("^7", frag_target.netname, "^1 was frozen by ^7", frag_attacker.netname, ".\n");
}
MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
{
- freezetag_Unfreeze(world); // start by making sure that all ice blocks are removed
+ freezetag_Unfreeze(world); // start by making sure that all ice blocks are removed
if(total_players == 1 && time > game_starttime) // only one player active on server, start a new match immediately
if(!next_round && warmup && (time < warmup - autocvar_g_freezetag_warmup || time > warmup)) // not awaiting next round
--- /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;
--- /dev/null
+#define _SSMAGIX "SUPERSPEC_OPTIONSFILE_V1"
+#define _ISLOCAL ((edict_num(1) == self) ? TRUE : FALSE)
+
+#define ASF_STRENGTH 1
+#define ASF_SHIELD 2
+#define ASF_MEGA_AR 4
+#define ASF_MEGA_HP 8
+#define ASF_FLAG_GRAB 16
+#define ASF_OBSERVER_ONLY 32
+#define ASF_SHOWWHAT 64
+#define ASF_SSIM 128
+#define ASF_ALL 0xFFFFFF
+.float autospec_flags;
+
+#define SSF_SILENT 1
+#define SSF_VERBOSE 2
+#define SSF_ITEMMSG 4
+.float superspec_flags;
+
+.string superspec_itemfilter; //"classname1 classname2 ..."
+
+float _spectate(entity _player)
+{
+ if(SpectateNext(_player) == 1)
+ {
+ PutObserverInServer();
+ self.classname = "spectator";
+ }
+
+ return TRUE;
+}
+
+void superspec_save_client_conf()
+{
+ string fn = "superspec-local.options";
+ float fh;
+
+
+ if not(_ISLOCAL)
+ {
+ if(self.crypto_idfp == "")
+ return;
+
+ fn = sprintf("superspec-%s.options", uri_escape(self.crypto_idfp));
+ }
+
+ if((fh = fopen(fn, FILE_WRITE)) < 0)
+ {
+ dprint("^1ERROR: ^7 superspec can not open ", fn, " for writing.\n");
+ }
+ else
+ {
+ fputs(fh, _SSMAGIX);
+ fputs(fh, "\n");
+ fputs(fh, ftos(self.autospec_flags));
+ fputs(fh, "\n");
+ fputs(fh, ftos(self.superspec_flags));
+ fputs(fh, "\n");
+ fputs(fh, self.superspec_itemfilter);
+ fputs(fh, "\n");
+ fclose(fh);
+ }
+}
+
+void superspec_msg(string _center_title, string _con_title, entity _to, string _msg, float _spamlevel)
+{
+
+ sprint(_to, strcat(_con_title, _msg));
+
+ if(_to.superspec_flags & SSF_SILENT)
+ return;
+
+ if(_spamlevel > 1)
+ if not(_to.superspec_flags & SSF_VERBOSE)
+ return;
+
+ centerprint(_to, strcat(_center_title, _msg));
+}
+
+float superspec_filteritem(entity _for, entity _item)
+{
+ float i;
+
+ if(!_for.superspec_itemfilter)
+ return TRUE;
+
+ if(_for.superspec_itemfilter == "")
+ return TRUE;
+
+ float l = tokenize_console(_for.superspec_itemfilter);
+ for(i = 0; i < l; ++i)
+ {
+ if(argv(i) == _item.classname)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_ItemTouch)
+{
+ entity _oldself = self;
+ entity _item = self;
+
+ FOR_EACH_SPEC(self)
+ {
+ if(self.superspec_flags & SSF_ITEMMSG)
+ if(superspec_filteritem(self, _item))
+ {
+ if(self.superspec_flags & SSF_VERBOSE)
+ superspec_msg("", "", self, sprintf("Player %s^7 just picked up ^3%s\n", other.netname, _item.netname), 1);
+ else
+ superspec_msg("", "", self, sprintf("Player %s^7 just picked up ^3%s\n^8(%s^8)\n", other.netname, _item.netname, _item.classname), 1);
+ if(self.autospec_flags& ASF_SSIM && self.enemy != other)
+ {
+ _spectate(other);
+
+ self = _oldself;
+ return FALSE;
+ }
+ }
+
+
+ if((self.autospec_flags & ASF_SHIELD && _item.invincible_finished) ||
+ (self.autospec_flags & ASF_STRENGTH && _item.strength_finished) ||
+ (self.autospec_flags& ASF_MEGA_AR && _item.classname == "item_armor_large") ||
+ (self.autospec_flags& ASF_MEGA_HP && _item.classname == "item_health_mega") ||
+ (self.autospec_flags& ASF_FLAG_GRAB && _item.classname == "item_flag_team"))
+ {
+
+ if((self.enemy != other) || self.classname == "observer")
+ {
+ if(self.autospec_flags & ASF_OBSERVER_ONLY && self.classname != "observer")
+ {
+ if(self.superspec_flags & SSF_VERBOSE)
+ superspec_msg("", "", self, sprintf("^8Ignored that %s^8 grabbed %s^8 since the observer_only option is ON\n", other.netname, _item.netname), 2);
+ }
+ else
+ {
+ if(self.autospec_flags & ASF_SHOWWHAT)
+ superspec_msg("", "", self, sprintf("^7Following %s^7 due to picking up %s\n", other.netname, _item.netname), 2);
+
+ _spectate(other);
+ }
+ }
+ }
+ }
+
+ self = _oldself;
+
+ return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
+{
+#define OPTIONINFO(flag,var,test,text,long,short) \
+ var = strcat(var, ((flag & test) ? "^2[ON] ^7" : "^1[OFF] ^7")); \
+ var = strcat(var, text," ^7(^3 ", long, "^7 | ^3", short, " ^7)\n")
+
+ if(MUTATOR_RETURNVALUE) // command was already handled?
+ return FALSE;
+
+ if(self.classname == "player")
+ return FALSE;
+
+ if(cmd_name == "superspec_itemfilter")
+ {
+ if(argv(1) == "help")
+ {
+ string _aspeco;
+ _aspeco = strcat(_aspeco, "^7 superspec_itemfilter ^3\"item_classname1 item_classname2\"^7 only show thise items when ^2superspec ^3item_message^7 is on\n");
+ _aspeco = strcat(_aspeco, "^3 clear^7 Remove the filter (show all pickups)\n");
+ _aspeco = strcat(_aspeco, "^3 show ^7 Display current filter\n");
+ superspec_msg("^3superspec_itemfilter help:\n\n\n", "\n^3superspec_itemfilter help:\n", self, _aspeco, 1);
+ }
+ else if(argv(1) == "clear")
+ {
+ if(self.superspec_itemfilter != "")
+ strunzone(self.superspec_itemfilter);
+
+ self.superspec_itemfilter = "";
+ }
+ else if(argv(1) == "show" || argv(1) == "")
+ {
+ if(self.superspec_itemfilter == "")
+ {
+ superspec_msg("^3superspec_itemfilter^7 is ^1not^7 set", "\n^3superspec_itemfilter^7 is ^1not^7 set\n", self, "", 1);
+ return TRUE;
+ }
+ float i;
+ float l = tokenize_console(self.superspec_itemfilter);
+ string _msg;
+ for(i = 0; i < l; ++i)
+ _msg = strcat(_msg, "^3#", ftos(i), " ^7", argv(i), "\n");
+ //_msg = sprintf("^3#%d^7 %s\n%s", i, _msg, argv(i));
+
+ _msg = strcat(_msg,"\n");
+
+ superspec_msg("^3superspec_itemfilter is:\n\n\n", "\n^3superspec_itemfilter is:\n", self, _msg, 1);
+ }
+ else
+ {
+ if(self.superspec_itemfilter != "")
+ strunzone(self.superspec_itemfilter);
+
+ self.superspec_itemfilter = strzone(argv(1));
+ }
+
+
+ return TRUE;
+ }
+
+ if(cmd_name == "superspec")
+ {
+ string _aspeco;
+
+ if(cmd_argc > 1)
+ {
+ float i, _bits, _start = 1;
+ if(argv(1) == "help")
+ {
+ _aspeco = "";
+ _aspeco = strcat(_aspeco, "use cmd superspec [option] [on|off] to set options\n\n");
+ _aspeco = strcat(_aspeco, "^3 silent ^7(short^5 si^7) supress ALL mesagess from superspectate.\n");
+ _aspeco = strcat(_aspeco, "^3 verrbose ^7(short^5 ve^7) makes superspectate print some additional information.\n");
+ _aspeco = strcat(_aspeco, "^3 item_message ^7(short^5 im^7) makes superspectate print items that was picked up.\n");
+ _aspeco = strcat(_aspeco, "^7 Use cmd superspec_itemfilter \"item_class1 item_class2\" to set up a filter of what to show with ^3item_message.\n");
+ superspec_msg("^2Available Super Spectate ^3options:\n\n\n", "\n^2Available Super Spectate ^3options:\n", self, _aspeco, 1);
+ return TRUE;
+ }
+
+ if(argv(1) == "clear")
+ {
+ self.superspec_flags = 0;
+ _start = 2;
+ }
+
+ for(i = _start; i < cmd_argc; ++i)
+ {
+ if(argv(i) == "on" || argv(i) == "1")§
+ {
+ self.superspec_flags |= _bits;
+ _bits = 0;
+ }
+ else if(argv(i) == "off" || argv(i) == "0")
+ {
+ if(_start == 1)
+ self.superspec_flags &~= _bits;
+
+ _bits = 0;
+ }
+ else
+ {
+ if((argv(i) == "silent") || (argv(i) == "si"§)) _bits |= SSF_SILENT ;
+ if((argv(i) == "verbose") || (argv(i) == "ve")) _bits |= SSF_VERBOSE;
+ if((argv(i) == "item_message") || (argv(i) == "im")) _bits |= SSF_ITEMMSG;
+ }
+ }
+ }
+
+
+ OPTIONINFO(self.superspec_flags, _aspeco, SSF_SILENT, "Silent", "silent", "si");
+ OPTIONINFO(self.superspec_flags, _aspeco, SSF_VERBOSE, "Verbose", "verbose", "ve");
+ OPTIONINFO(self.superspec_flags, _aspeco, SSF_ITEMMSG, "Item pickup messages", "item_message", "im");
+
+ superspec_msg("^3Current Super Spectate options are:\n\n\n\n\n", "\n^3Current Super Spectate options are:\n", self, _aspeco, 1);
+ return TRUE;
+
+ }
+
+/////////////////////
+
+ if(cmd_name == "autospec")
+ {
+ string _aspeco;
+ if(cmd_argc > 1)
+ {
+ if(argv(1) == "help")
+ {
+ _aspeco = "";
+ _aspeco = strcat(_aspeco, "use cmd autospec [option] [on|off] to set options\n\n");
+ _aspeco = strcat(_aspeco, "^3 strength ^7(short^5 st^7) for automatic spectate on strength powerup\n");
+ _aspeco = strcat(_aspeco, "^3 shield ^7(short^5 sh^7) for automatic spectate on shield powerup\n");
+ _aspeco = strcat(_aspeco, "^3 mega_health ^7(short^5 mh^7) for automatic spectate on mega health\n");
+ _aspeco = strcat(_aspeco, "^3 mega_armor ^7(short^5 ma^7) for automatic spectate on mega armor\n");
+ _aspeco = strcat(_aspeco, "^3 flag_grab ^7(short^5 fg^7) for automatic spectate on CTF flag grab\n");
+ _aspeco = strcat(_aspeco, "^3 observer_only (short^5 oo^7) for automatic spectate only if in observer mode\n");
+ _aspeco = strcat(_aspeco, "^3 show_what (short^5 sw^7) to display what event triggerd autospectate\n");
+ _aspeco = strcat(_aspeco, "^3 item_msg ^7(short^5 im^7) to autospec when item_message in superspectate is triggerd\n");
+ _aspeco = strcat(_aspeco, "^3 all ^7(short ^5aa^7) turn everything on/off\n");
+ superspec_msg("^2Available Auto Spectate ^3options:\n\n\n", "\n^2Available Auto Spectate ^3options:\n", self, _aspeco, 1);
+ return TRUE;
+ }
+
+ float i, _bits, _start = 1;
+ if(argv(1) == "clear")
+ {
+ self.autospec_flags = 0;
+ _start = 2;
+ }
+
+ for(i = _start; i < cmd_argc; ++i)
+ {
+ if(argv(i) == "on" || argv(i) == "1")
+ {
+ self.autospec_flags |= _bits;
+ _bits = 0;
+ }
+ else if(argv(i) == "off" || argv(i) == "0")
+ {
+ if(_start == 1)
+ self.autospec_flags &~= _bits;
+
+ _bits = 0;
+ }
+ else
+ {
+ if((argv(i) == "strength") || (argv(i) == "st")) _bits |= ASF_STRENGTH;
+ if((argv(i) == "shield") || (argv(i) == "sh")) _bits |= ASF_SHIELD;
+ if((argv(i) == "mega_health") || (argv(i) == "mh")) _bits |= ASF_MEGA_HP;
+ if((argv(i) == "mega_armor") || (argv(i) == "ma")) _bits |= ASF_MEGA_AR;
+ if((argv(i) == "flag_grab") || (argv(i) == "fg")) _bits |= ASF_FLAG_GRAB;
+ if((argv(i) == "observer_only") || (argv(i) == "oo")) _bits |= ASF_OBSERVER_ONLY;
+ if((argv(i) == "show_what") || (argv(i) == "sw")) _bits |= ASF_SHOWWHAT;
+ if((argv(i) == "item_msg") || (argv(i) == "im")) _bits |= ASF_SSIM;
+ if((argv(i) == "all") || (argv(i) == "aa")) _bits |= ASF_ALL;
+ }
+ }
+ }
+
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_STRENGTH, "Strength", "strength", "st");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_SHIELD, "Shiled", "shield", "sh");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_HP, "Mega Health", "mega_health", "mh");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_AR, "Mega Armor", "mega_armor", "ma");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_FLAG_GRAB, "Flag grab", "flag_grab","fg");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_OBSERVER_ONLY, "Only switch if Observer", "observer_only", "oo");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_SHOWWHAT, "Show what item triggered spectate", "show_what", "sw");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_SSIM, "Switch on superspec item message", "item_msg", "im");
+
+ superspec_msg("^3Current auto spectate options are:\n\n\n\n\n", "\n^3Current auto spectate options are:\n", self, _aspeco, 1);
+ return TRUE;
+ }
+
+ if(cmd_name == "followpowerup")
+ {
+ entity _player;
+ FOR_EACH_PLAYER(_player)
+ {
+ if(_player.strength_finished > time || _player.invincible_finished > time)
+ return _spectate(_player);
+ }
+
+ superspec_msg("", "", self, "No active powerups\n", 1);
+ return TRUE;
+ }
+
+ if(cmd_name == "followstrength")
+ {
+ entity _player;
+ FOR_EACH_PLAYER(_player)
+ {
+ if(_player.strength_finished > time)
+ return _spectate(_player);
+ }
+
+ superspec_msg("", "", self, "No active Strength\n", 1);
+ return TRUE;
+ }
+
+ if(cmd_name == "followstshield")
+ {
+ entity _player;
+ FOR_EACH_PLAYER(_player)
+ {
+ if(_player.invincible_finished > time)
+ return _spectate(_player);
+ }
+
+ superspec_msg("", "", self, "No active Shield\n", 1);
+ 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);
+ }
+
+ superspec_msg("", "", self, "No active flag carrier\n", 1);
+ return TRUE;
+ }
+
+ return FALSE;
+#undef OPTIONINFO
+}
+
+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;
+}
+*/
+
+void superspec_hello()
+{
+ if(self.enemy.crypto_idfp == "")
+ centerprint(self.enemy, "Your clinet have/allow no crypto id, superspec options will not be saved/restored.");
+ else
+ centerprint(self.enemy, sprintf("Hello %s\nSince your client has a Crypto ID, your superspec preferenses will be presisted on this server.", self.enemy.netname));
+
+ remove(self);
+}
+
+MUTATOR_HOOKFUNCTION(superspec_ClientConnect)
+{
+ string fn = "superspec-local.options";
+ float fh;
+
+ self.superspec_flags = SSF_VERBOSE;
+ self.superspec_itemfilter = "";
+
+ entity _hello = spawn();
+ _hello.enemy = self;
+ _hello.think = superspec_hello;
+ _hello.nextthink = time + 5;
+
+ if not(_ISLOCAL)
+ {
+ if(self.crypto_idfp == "")
+ return FALSE;
+
+ fn = sprintf("superspec-%s.options", uri_escape(self.crypto_idfp));
+ }
+
+ if((fh = fopen(fn, FILE_READ)) < 0)
+ {
+ dprint("^1ERROR: ^7 superspec can not open ", fn, " for reading.\n");
+ }
+ else
+ {
+ string _magic = fgets(fh);
+ if(_magic != _SSMAGIX)
+ {
+ dprint("^1ERROR^7 While reading superspec options file: unkown magic\n");
+ }
+ else
+ {
+ self.autospec_flags = stof(fgets(fh));
+ self.superspec_flags = stof(fgets(fh));
+ self.superspec_itemfilter = strzone(fgets(fh));
+ }
+ fclose(fh);
+ }
+
+ return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(superspec_ClientDisconnect)
+{
+ superspec_save_client_conf();
+ return FALSE;
+}
+
+
+/*
+MUTATOR_HOOKFUNCTION(superspec_MakePlayerObserver)
+{
+ 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(ItemTouch, superspec_ItemTouch, 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(MakePlayerObserver, superspec_MakePlayerObserver, 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);
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
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';
+var float autocvar_cl_fullbright_items = 0;
+var vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
+var float autocvar_cl_weapon_stay_alpha = 0.75;
+var float autocvar_cl_simple_items = 0;
+var string autocvr_cl_simpleitems_postfix = "_simple";
+.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;
+ }
+}
+
+void ItemRead(float _IsNew)
+{
+ 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 (autocvar_cl_ghost_items_color)
+ {
+ 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(autocvar_cl_simple_items && (self.ItemStatus & ITS_ALLOWSI))
+ {
+ string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
+ self.draw = ItemDrawSimple;
+
+
+
+ if(fexists(sprintf("%s%s.md3", _fn2, autocvr_cl_simpleitems_postfix)))
+ self.mdl = strzone(sprintf("%s%s.md3", _fn2, autocvr_cl_simpleitems_postfix));
+ else if(fexists(sprintf("%s%s.dpm", _fn2, autocvr_cl_simpleitems_postfix)))
+ self.mdl = strzone(sprintf("%s%s.dpm", _fn2, autocvr_cl_simpleitems_postfix));
+ else if(fexists(sprintf("%s%s.iqm", _fn2, autocvr_cl_simpleitems_postfix)))
+ self.mdl = strzone(sprintf("%s%s.iqm", _fn2, autocvr_cl_simpleitems_postfix));
+ else if(fexists(sprintf("%s%s.obj", _fn2, autocvr_cl_simpleitems_postfix)))
+ self.mdl = strzone(sprintf("%s%s.obj", _fn2, autocvr_cl_simpleitems_postfix));
+ 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)
void Item_Touch (void)
{
entity e, head;
-
+
// remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
if(self.classname == "droppedweapon")
{
return;
if (self.owner == other)
return;
+ if(MUTATOR_CALLHOOK(ItemTouch))
+ return;
if (self.classname == "droppedweapon")
{
}
}
e = RandomSelection_chosen_ent;
+
}
else
e = self;
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
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)
{
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)
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)
- {
- dcount = c1;
- dbotcount = cb1;
- }
- else if(dteam == 2 && c2 >= 0)//dcolor == COLOR_TEAM2 - 1)
+ GetTeamCounts(self);
+ if(!TeamSmallerEqThanTeam(dteam, steam, self))
{
- 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");
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)
{
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;
}
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;
}
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 = 0, 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
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;
//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);
//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);
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);
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));
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;
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_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)
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
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);
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);
--- /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