--- /dev/null
+// hud variables
+set _hud_configure 0 "1 = configure the HUD"
+seta hud_configure_teamcolorforced 0 "1 = force display of team colors in configure mode"
+seta hud_configure_checkcollisions 1 "check for collisions against other panels when in hud configure mode"
+seta hud_configure_bg_minalpha 0.25 "minimum panel background alpha when in hud configure mode"
+seta hud_configure_grid_alpha 0.15 "alpha for visible grid when in configure mode"
+
+seta hud_fontsize 11 "text fontsize for the hud"
+seta hud_width 560 "2D virtual width for the hud"
+
+// general hud panel cvars (i.e. shouldn't be adjusted by a skin config)
+seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count"
+seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count"
+seta hud_panel_weapons_ammo_full_cells 180 "show 100% of the status bar at this ammo count"
+seta hud_panel_weapons_ammo_full_rockets 160 "show 100% of the status bar at this ammo count"
+seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count"
+
+seta hud_panel_ammo_maxammo "40" "when you have this much ammo, the ammo status bar is full"
+
+seta hud_panel_healtharmor_maxhealth "200" "when you have this much health, the health status bar is full"
+seta hud_panel_healtharmor_maxarmor "200" "when you have this much armor, the armor status bar is full"
+seta hud_panel_healtharmor_progressbar_gfx_damage 5 "show damage effect when damaged at least by this amount; 0 disables the effect"
+seta hud_panel_healtharmor_progressbar_gfx_lowhealth 40 "health progressbar blinks when health is lower than this amount"
+
+seta hud_panel_engineinfo_framecounter_exponentialmovingaverage 1 "use an averaging method for calculating fps instead of counting frametime like engine does"
+seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point"
+seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster"
+
+// hud panel aliases
+alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4"
+alias +hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized 1"
+alias -hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized 0"
+alias hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized"
+
+// other hud cvars
+seta hud_showbinds 1 "what to show in the HUD to indicate certain keys to press: 0 display commands, 1 bound keys, 2 both"
+seta hud_showbinds_limit 2 "maximum number of bound keys to show for a command. 0 for unlimited"
+
+seta hud_colorflash_alpha 0.5 "starting alpha of the color flash"
+
+seta hud_damage 0.55 "an improved version of gl_polyblend for damage, draw an image instead when hurt"
+seta hud_damage_blur 10 "Use postprocessing to blur the screen when you have taken damage. This can be paired with current hud damage or just used alone. Higher values = more blur"
+seta hud_damage_blur_alpha 0.5 "Amount of alpha to use when merging the blurred layers back into the render. Turning this up higher will remove bloom, so it's best to find a balance"
+seta hud_damage_gentle_alpha_multiplier 0.10 "how much to multiply alpha of flash when using the cl_gentle version, it's much more opaque than the non-gentle version"
+seta hud_damage_gentle_color "1 0.7 1" "color of flash for cl_gentle version"
+seta hud_damage_color "1 0 0" "color of flash"
+seta hud_damage_factor 0.025 "(damage * factor) = how much to add to the alpha value"
+seta hud_damage_fade_rate 0.75 "how much to subtract from the alpha value each second"
+seta hud_damage_maxalpha 1.5 "how much to limit the alpha value to"
+seta hud_damage_pain_threshold 0.1 "how much alpha to ignore (must be bigger than the hud_damage_factor so that e.g. rot is ignored)"
+seta hud_damage_pain_threshold_lower 1.25 "how much we lower pain_threshold with when nearing 0 health (if pain_threshold gets negative then we always draw a flash at alpha = fabs(pain_threshold)"
+seta hud_damage_pain_threshold_lower_health 50 "at which health we start lowering pain_threshold"
+seta hud_damage_pain_threshold_pulsating_min 0.6 "minimum value when calculating the pulse: max(pulsating_min, fabs(sin(PI * time / period))"
+seta hud_damage_pain_threshold_pulsating_period 0.8 "one pulse every X seconds"
+
+seta hud_powerup 0 "power of the sharpen effect when owning the shield or strength powerups, default is 0.5"
+
+seta hud_postprocessing 1 "enables the ability for effects such as hud_damage_blur and hud_contents to apply a postprocessing method upon the screen - enabling this disables manual editing of the postprocess cvars"
+seta hud_postprocessing_maxbluralpha 0 "maximum alpha which the blur postprocess can be, default is 0.5"
+seta hud_postprocessing_maxblurradius 8 "maximum radius which the blur postprocess can be, default is 8"
+
+seta hud_contents 1 "an improved version of gl_polyblend for liquids such as water/lava/slime, draw a filler when inside the liquid"
+seta hud_contents_blur 10 "Use postprocessing to blur the screen when you are inside a liquid. Higher values = more blur"
+seta hud_contents_blur_alpha 0.5 "Amount of alpha to use when merging the blurred layers back into the render. Turning this up higher will remove bloom, so it's best to find a balance"
+seta hud_contents_factor 1 "factor at which to multiply the current faded value."
+seta hud_contents_fadeintime 0.02 "factor of time it takes for the alpha level to reach normal value when entering the liquid"
+seta hud_contents_fadeouttime 0.1 "factor of time it takes for the alpha level to reach normal value when leaving the liquid"
+seta hud_contents_lava_alpha 0.7 "alpha of the lava"
+seta hud_contents_lava_color "0.8 0.1 0" "color blend when inside lava"
+seta hud_contents_slime_alpha 0.7 "alpha of the slime"
+seta hud_contents_slime_color "0 0.4 0.1" "color blend when inside slime"
+seta hud_contents_water_alpha 0.5 "alpha of the water"
+seta hud_contents_water_color "0.4 0.3 0.3" "color blend when inside water"
+
+seta hud_shownames 1 "draw names and health/armor of nearby players"
+seta hud_shownames_enemies 1 "show tags for enemies as well"
+seta hud_shownames_crosshairdistance 0 "if set, only draw tags which came within this distance of your crosshair (25 recommended)"
+seta hud_shownames_crosshairdistance_time 5 "how many seconds the tag is still visible after pointing at them"
+seta hud_shownames_crosshairdistance_antioverlap 0 "allow antioverlap to work as normal even with crosshairdistance on"
+seta hud_shownames_self 0 "also include your own name to be shown when third person camera mode is on (chase_active/cl_eventchase)"
+seta hud_shownames_status 1 "1 = draw health/armor status of teammates"
+seta hud_shownames_statusbar_height 4 "height of status bar"
+seta hud_shownames_aspect 8 "aspect ratio of total drawing area per name"
+seta hud_shownames_fontsize 12 "font size"
+seta hud_shownames_decolorize 1 "1 = decolorize name in team games, 2 = decolorize always"
+seta hud_shownames_alpha 0.7 "alpha"
+seta hud_shownames_resize 1 "enable resizing of the names, then the size cvars will correspond to the maximum size"
+seta hud_shownames_mindistance 1000 "start fading alpha/size at this distance"
+seta hud_shownames_maxdistance 5000 "alpha/size is 0 at this distance"
+seta hud_shownames_antioverlap 1 "if two tags get too close to each other, fade out the one further away from you"
+seta hud_shownames_antioverlap_distance 50 "2d distance to other tag after which to fade out"
+seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units"
\ No newline at end of file
seta hud_panel_weapons_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
seta hud_panel_weapons_aspect "" "use this aspect on the items"
seta hud_panel_weapons_complainbubble "" "complain bubble (out of ammo, weapon not available etc)"
+seta hud_panel_weapons_complainbubble_time "" "time that a new entry stays until it fades out"
+seta hud_panel_weapons_complainbubble_fadetime "" "fade out time"
seta hud_panel_weapons_complainbubble_padding "" "padding for the complainbubble"
seta hud_panel_weapons_complainbubble_color_outofammo "" "color of the complainbubble when showing out of ammo message"
seta hud_panel_weapons_complainbubble_color_donthave "" "color of the complainbubble when showing don't have weapon message"
seta hud_panel_weapons_ammo_alpha "" "alpha of status bar"
seta hud_panel_weapons_timeout "" "panel disappears if you don't switch weapon for this amount of seconds"
seta hud_panel_weapons_timeout_effect "" "disappearance effect: 0) no effect; 1) panel moves out of screen; 2) panel fades out"
+seta hud_panel_weapons_label "" "1 = show number of weapon, 2 = show bound key of weapon"
+seta hud_panel_weapons_accuracy "" "show accuracy color as the weapon icon background; colors can be configured with accuracy_color* cvars"
+seta hud_panel_weapons_accuracy_color "" "low accuracy color"
+seta hud_panel_weapons_accuracy_color "" "medium accuracy color"
+seta hud_panel_weapons_accuracy_color "" "high accuracy color"
+seta hud_panel_weapons_accuracy_color_levels "" "levels of accuracy (normally 3)"
+seta hud_panel_weapons_ammo "" "show ammo as a status bar"
+seta hud_panel_weapons_onlyowned "" "show only owned weapons"
seta hud_panel_ammo "" "enable/disable this panel"
seta hud_panel_ammo_pos "" "position of this panel"
seta hud_panel_healtharmor_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
seta hud_panel_healtharmor_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_healtharmor_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_healtharmor_text "" "show text/icons in the healtharmor panel"
seta hud_panel_healtharmor_progressbar "" "enable progressbar in panel"
seta hud_panel_healtharmor_progressbar_health "" "progressbar image for health"
seta hud_panel_healtharmor_progressbar_armor "" "progressbar image for armor"
-seta hud_panel_healtharmor_text "" "show text/icons in the healtharmor panel"
+seta hud_panel_healtharmor_progressbar_gfx "" "enable graphic effects on the progressbars"
+seta hud_panel_healtharmor_progressbar_gfx_smooth "" "smooth changes of the progressbar when health/armor change at least by this amount; 0 disables the effect"
seta hud_panel_notify "" "enable/disable this panel"
seta hud_panel_notify_pos "" "position of this base of the panel"
seta hud_panel_notify_flip "" "order the list top to bottom instead of bottom to top"
seta hud_panel_notify_fontsize "" "multiplier for the font size used for player names in the panel"
seta hud_panel_notify_print "" "also con_notify print the messages that are shown on the notify panel"
+seta hud_panel_notify_fadetime "" "fade out time"
+seta hud_panel_notify_time "" "time that a new entry stays until it fades out"
seta hud_panel_timer "" "enable/disable this panel"
seta hud_panel_timer_pos "" "position of this base of the panel"
seta hud_panel_timer_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
seta hud_panel_timer_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_timer_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_timer_increment "" "show elapsed time instead of remaining time"
seta hud_panel_radar "" "enable/disable this panel, 2 = also enable in non-teambased gamemodes"
seta hud_panel_radar_pos "" "position of this base of the panel"
seta hud_panel_radar_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_radar_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
seta hud_panel_radar_foreground_alpha "" "alpha of the map"
+seta hud_panel_radar_rotation "" "rotation mode: you set what points up. 0 = player, 1 = west, 2 = south, 3 = east, 4 = north"
+seta hud_panel_radar_zoommode "" "zoom mode: 0 = zoomed by default, 1 = zoomed when +zoom, 2 = always zoomed, 3 = always zoomed out"
+seta hud_panel_radar_scale "" "distance you can see on the team radar"
+seta hud_panel_radar_maximized_scale "" "distance you can see on the radar when maximized"
+seta hud_panel_radar_maximized_size "" "size of the radar when maximized"
seta hud_panel_score "" "enable/disable this panel"
seta hud_panel_score_pos "" "position of this base of the panel"
seta hud_panel_score_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
seta hud_panel_score_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_score_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_score_rankings "" "show rankings: 1 always show my own score; 2 pure rankings"
seta hud_panel_racetimer "" "enable/disable this panel"
seta hud_panel_racetimer_pos "" "position of this base of the panel"
seta hud_panel_modicons_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
seta hud_panel_modicons_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_modicons_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_modicons_dom_layout "" "3 possible layouts: 0) only icons; 1) icons and percentage of average pps (points per second); 2) icons and average pps"
seta hud_panel_pressedkeys "" "enable/disable this panel, 1 = show only when spectating other players, 2 = show always"
seta hud_panel_pressedkeys_pos "" "position of this base of the panel"
seta hud_panel_engineinfo_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
seta hud_panel_engineinfo_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_engineinfo_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_engineinfo_framecounter_decimals "" "amount of decimals to show"
+seta hud_panel_engineinfo_framecounter_time "" "time between framerate display updates"
seta hud_panel_infomessages "" "enable/disable this panel"
seta hud_panel_infomessages_pos "" "position of this base of the panel"
seta hud_panel_physics_baralign "" "0 = align bars to the left, 1 = align bars to the right, 2 = align only left bar to the right, 3 = align only right bar to the right, 4 = align bars to the center"
seta hud_panel_physics_flip "" "flip speed/acceleration positions"
seta hud_panel_physics_progressbar "" "enable progressbar in panel (2 = only for speed; 3 = only for acceleration)"
-seta hud_panel_physics_acceleration_progressbar_mode "" "0 = progressbar increases from the center to the right if the acceleration is positive, to the left if it's negative; 1 = progressbar increases from the border in the same direction for both positive and negative accelerations"
+seta hud_panel_physics_acceleration_max "" "acceleration progressbar gets completely filled up by this value (in g)"
+seta hud_panel_physics_acceleration_mode "" "0 = progressbar increases from the center to the right if the acceleration is positive, to the left if it's negative; 1 = progressbar increases from the border in the same direction for both positive and negative accelerations"
+seta hud_panel_physics_acceleration_vertical "" "include the acceleration on the Z-axis"
seta hud_panel_physics_text "" "show text in panel (2 = only for speed; 3 = only for acceleration)"
+seta hud_panel_physics_speed_unit "" "speed unit (1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots)"
+seta hud_panel_physics_speed_unit_show "" "also show speed unit"
+seta hud_panel_physics_speed_max "" "speed progressbar gets filled up completely by this value (in qu/s)"
+seta hud_panel_physics_speed_vertical "" "include the speed on the Z-axis"
+seta hud_panel_physics_topspeed "" "also show top speed"
+seta hud_panel_physics_topspeed_time "" "how many seconds the top speed takes to fade out"
seta hud_panel_centerprint "" "enable/disable this panel"
seta hud_panel_centerprint_pos "" "position of this base of the panel"
seta hud_panel_centerprint_flip "" "invert messages order"
seta hud_panel_centerprint_fontscale "" "scale the text font by this amount"
seta hud_panel_centerprint_time "" "message duration (NOTE: certain messages have a fixed duration)"
-seta hud_panel_centerprint_fadetime "" "how long a message takes to fade out (this time is included in the message duration and can't be > 1)"
+seta hud_panel_centerprint_fade_in "" "how long a message takes to fade in"
+seta hud_panel_centerprint_fade_out "" "how long a message takes to fade out (this time is included in the message duration and can't be > 5)"
+seta hud_panel_centerprint_fade_subsequent "" "enable extra fading effects for each additional message, so that the more messages you have the more they become faded out"
+seta hud_panel_centerprint_fade_subsequent_passone "" "division factor for the first pass for alpha fading, with 2 all messages after the first have half alpha"
+seta hud_panel_centerprint_fade_subsequent_passone_minalpha "" "minimum factor that the first pass can fade to"
+seta hud_panel_centerprint_fade_subsequent_passtwo "" "division factor for the second pass for alpha fading, it applies another fade on top of the first pass to make it more transitioned"
+seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "" "minimum factor that the second pass can fade to"
+seta hud_panel_centerprint_fade_subsequent_minfontsize "" "minimum factor for the font size from the subsequent fading effects"
+seta hud_panel_centerprint_fade_minfontsize "" "minimum factor for the font size from the fading in/out effects"
set g_balance_firetransfer_damage 0.8
set g_throughfloor_damage 1
set g_throughfloor_force 1
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines)
+// 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_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
set g_balance_falldamage_factor 0.15
set g_balance_falldamage_maxdamage 25
set g_balance_damagepush_speedfactor 0
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
// }}}
// {{{ powerups
set g_balance_grapplehook_stretch 50
set g_balance_grapplehook_airfriction 0.2
set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
// }}}
// {{{ weapon properties
set g_balance_shotgun_primary_speed 12000
set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu
set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim
-set g_balance_shotgun_secondary_melee_range 60
-set g_balance_shotgun_secondary_melee_swing 50
-set g_balance_shotgun_secondary_melee_time 0.1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 0
+set g_balance_shotgun_secondary_melee_multihit 1
set g_balance_shotgun_secondary_damage 115
set g_balance_shotgun_secondary_force 150
set g_balance_shotgun_secondary_refire 1.1
set g_balance_electro_secondary_ammo 2
set g_balance_electro_secondary_health 5
set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 0
set g_balance_electro_secondary_count 1
set g_balance_electro_secondary_bouncefactor 0.5
set g_balance_electro_secondary_bouncestop 0.075
set g_balance_nex_charge_animlimit 0.5
set g_balance_nex_charge_limit 0.5
set g_balance_nex_charge_rot_rate 0
-set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button
+set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
set g_balance_nex_charge_shot_multiplier 0.5
set g_balance_nex_charge_velocity_rate 0.2
set g_balance_nex_charge_minspeed 400
set g_balance_hagar_primary_damage 37
set g_balance_hagar_primary_edgedamage 15
set g_balance_hagar_primary_force 100
+set g_balance_hagar_primary_health 0
+set g_balance_hagar_primary_damageforcescale 0
set g_balance_hagar_primary_radius 65
set g_balance_hagar_primary_spread 0.010
set g_balance_hagar_primary_speed 3000
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
set g_balance_hagar_secondary_damage 37
set g_balance_hagar_secondary_edgedamage 15
set g_balance_hagar_secondary_force 100
+set g_balance_hagar_secondary_health 0
+set g_balance_hagar_secondary_damageforcescale 0
set g_balance_hagar_secondary_radius 65
set g_balance_hagar_secondary_spread 0.015
set g_balance_hagar_secondary_speed 1400
set g_balance_hook_secondary_animtime 0.3 // good shoot anim
set g_balance_hook_secondary_power 3 // effect behaves like a square function
set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 0
+set g_balance_hook_secondary_damageforcescale 0
// }}}
// {{{ hlac
set g_balance_hlac_primary_spread_min 0.01
set g_balance_firetransfer_damage 0.8
set g_throughfloor_damage 0.7
set g_throughfloor_force 0.8
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines)
+// 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_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
set g_balance_falldamage_factor 0.20
set g_balance_falldamage_maxdamage 15
set g_balance_damagepush_speedfactor 2.5
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
// }}}
// {{{ powerups
set g_balance_grapplehook_stretch 50
set g_balance_grapplehook_airfriction 0.2
set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
// }}}
// {{{ weapon properties
set g_balance_shotgun_primary_speed 12000
set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu
set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim
-set g_balance_shotgun_secondary_melee_range 85
-set g_balance_shotgun_secondary_melee_swing 50
-set g_balance_shotgun_secondary_melee_time 0.1
-set g_balance_shotgun_secondary_melee_no_doubleslap 0
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 0
+set g_balance_shotgun_secondary_melee_multihit 1
set g_balance_shotgun_secondary_damage 110
set g_balance_shotgun_secondary_force 150
set g_balance_shotgun_secondary_refire 1.1
set g_balance_electro_secondary_ammo 2
set g_balance_electro_secondary_health 10
set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 0
set g_balance_electro_secondary_count 3
set g_balance_electro_secondary_bouncefactor 0.5
set g_balance_electro_secondary_bouncestop 0.075
set g_balance_hagar_primary_damage 14
set g_balance_hagar_primary_edgedamage 6
set g_balance_hagar_primary_force 70
+set g_balance_hagar_primary_health 0
+set g_balance_hagar_primary_damageforcescale 0
set g_balance_hagar_primary_radius 110
set g_balance_hagar_primary_spread 0.1
set g_balance_hagar_primary_speed 1800
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
set g_balance_hagar_secondary_damage 14 // default for _load: 32
set g_balance_hagar_secondary_edgedamage 6 // default for _load: 10
set g_balance_hagar_secondary_force 70 // default for _load: 160
+set g_balance_hagar_secondary_health 0
+set g_balance_hagar_secondary_damageforcescale 0
set g_balance_hagar_secondary_radius 125
set g_balance_hagar_secondary_spread 0.15 // default for _load: 0.08
set g_balance_hagar_secondary_speed 1800
set g_balance_hook_secondary_animtime 0.2 // good shoot anim
set g_balance_hook_secondary_power 3 // effect behaves like a square function
set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 0
+set g_balance_hook_secondary_damageforcescale 0
// }}}
// {{{ hlac
set g_balance_hlac_primary_spread_min 0.01
set g_balance_firetransfer_damage 0.8
set g_throughfloor_damage 0.4
set g_throughfloor_force 0.7
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines)
+// 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_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
set g_balance_falldamage_factor 0.15
set g_balance_falldamage_maxdamage 25
set g_balance_damagepush_speedfactor 0
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
// }}}
// {{{ powerups
set g_balance_grapplehook_stretch 50
set g_balance_grapplehook_airfriction 0.2
set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
// }}}
// {{{ weapon properties
set g_balance_shotgun_primary_speed 12000
set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu
set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim
-set g_balance_shotgun_secondary_melee_range 85
-set g_balance_shotgun_secondary_melee_swing 50
-set g_balance_shotgun_secondary_melee_time 0.1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 0
+set g_balance_shotgun_secondary_melee_multihit 1
set g_balance_shotgun_secondary_damage 84
set g_balance_shotgun_secondary_force 147
set g_balance_shotgun_secondary_refire 1.1
set g_balance_electro_secondary_ammo 2
set g_balance_electro_secondary_health 10
set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 0
set g_balance_electro_secondary_count 3
set g_balance_electro_secondary_bouncefactor 0.5
set g_balance_electro_secondary_bouncestop 0.075
set g_balance_nex_charge_animlimit 0.5
set g_balance_nex_charge_limit 0.5
set g_balance_nex_charge_rot_rate 0
-set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button
+set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
set g_balance_nex_charge_shot_multiplier 0
set g_balance_nex_charge_velocity_rate 0.2
set g_balance_nex_charge_minspeed ""
set g_balance_hagar_primary_damage 43
set g_balance_hagar_primary_edgedamage 15
set g_balance_hagar_primary_force 94
+set g_balance_hagar_primary_health 0
+set g_balance_hagar_primary_damageforcescale 0
set g_balance_hagar_primary_radius 70
set g_balance_hagar_primary_spread 0.010
set g_balance_hagar_primary_speed 3000
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
set g_balance_hagar_secondary_damage 43
set g_balance_hagar_secondary_edgedamage 15
set g_balance_hagar_secondary_force 100
+set g_balance_hagar_secondary_health 0
+set g_balance_hagar_secondary_damageforcescale 0
set g_balance_hagar_secondary_radius 70
set g_balance_hagar_secondary_spread 0.015
set g_balance_hagar_secondary_speed 1400
set g_balance_hook_secondary_animtime 0.3 // good shoot anim
set g_balance_hook_secondary_power 3 // effect behaves like a square function
set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 0
+set g_balance_hook_secondary_damageforcescale 0
// }}}
// {{{ hlac
set g_balance_hlac_primary_spread_min 0.01
set g_weaponspreadfactor 1 "weapon spread multiplier"
set g_balance_firetransfer_time 0.9
set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.4
-set g_throughfloor_force 0.7
+set g_throughfloor_damage 0.75
+set g_throughfloor_force 0.75
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines)
+// 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_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
set g_balance_falldamage_factor 0.20
set g_balance_falldamage_maxdamage 40
set g_balance_damagepush_speedfactor 2.5
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
// }}}
// {{{ powerups
set g_balance_grapplehook_length_min 50
set g_balance_grapplehook_stretch 50
set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 130
+set g_balance_grapplehook_health 50
+set g_balance_grapplehook_damagedbycontents 1
// }}}
// {{{ weapon properties
// {{{ laser
set g_balance_laser_primary_damage 25
set g_balance_laser_primary_edgedamage 12.5
-set g_balance_laser_primary_force 250
+set g_balance_laser_primary_force 300
set g_balance_laser_primary_radius 70
set g_balance_laser_primary_speed 6000
set g_balance_laser_primary_spread 0
set g_balance_laser_primary_shotangle 0
set g_balance_laser_primary_delay 0
set g_balance_laser_primary_gauntlet 0
-set g_balance_laser_primary_force_zscale 1.5
+set g_balance_laser_primary_force_zscale 1.25
set g_balance_laser_primary_force_velocitybias 0
set g_balance_laser_primary_force_other_scale 1
set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
set g_balance_shotgun_secondary 1
set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing 50
-set g_balance_shotgun_secondary_melee_time 0.1
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_damage 110
+set g_balance_shotgun_secondary_melee_nonplayerdamage 40
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_damage 100
set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_refire 1.1
+set g_balance_shotgun_secondary_refire 1.25
set g_balance_shotgun_secondary_animtime 1
set g_balance_shotgun_reload_ammo 0 //default: 5
set g_balance_shotgun_reload_time 2
// {{{ uzi
set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary
set g_balance_uzi_spread_min 0.02
-set g_balance_uzi_spread_max 0.06
+set g_balance_uzi_spread_max 0.05
set g_balance_uzi_spread_add 0.012
set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more)
set g_balance_uzi_burst_animtime 0.3
set g_balance_uzi_burst_refire 0.06 // refire between burst bullets
set g_balance_uzi_burst_refire2 0.45 // refire after burst
-set g_balance_uzi_burst_spread 0.03
+set g_balance_uzi_burst_spread 0.02
set g_balance_uzi_burst_damage 25
set g_balance_uzi_burst_force 20
set g_balance_uzi_burst_ammo 3
set g_balance_uzi_first_damage 14
set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.03
-set g_balance_uzi_first_refire 0.4
+set g_balance_uzi_first_refire 0.2
set g_balance_uzi_first_ammo 1
-set g_balance_uzi_sustained_damage 12
+set g_balance_uzi_sustained_damage 10 // 100 dps
set g_balance_uzi_sustained_force 5
-set g_balance_uzi_sustained_spread 0.04
+set g_balance_uzi_sustained_spread 0.03
set g_balance_uzi_sustained_refire 0.1
set g_balance_uzi_sustained_ammo 1
set g_balance_grenadelauncher_primary_refire 0.8
set g_balance_grenadelauncher_primary_animtime 0.3
set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_primary_health 0
+set g_balance_grenadelauncher_primary_health 15
set g_balance_grenadelauncher_primary_damageforcescale 0
set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
set g_balance_grenadelauncher_secondary_refire 0.7
set g_balance_grenadelauncher_secondary_animtime 0.3
set g_balance_grenadelauncher_secondary_ammo 2
-set g_balance_grenadelauncher_secondary_health 0
+set g_balance_grenadelauncher_secondary_health 30
set g_balance_grenadelauncher_secondary_damageforcescale 4
set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
// }}}
// {{{ electro
set g_balance_electro_lightning 0
-set g_balance_electro_primary_damage 55
-set g_balance_electro_primary_edgedamage 27.5
+set g_balance_electro_primary_damage 40
+set g_balance_electro_primary_edgedamage 20
set g_balance_electro_primary_force 200
set g_balance_electro_primary_force_up 0
set g_balance_electro_primary_radius 100
set g_balance_electro_secondary_ammo 2
set g_balance_electro_secondary_health 5
set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 1
set g_balance_electro_secondary_count 3
set g_balance_electro_secondary_bouncefactor 0.4
set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_combo_damage 40
-set g_balance_electro_combo_edgedamage 20
+set g_balance_electro_combo_damage 50
+set g_balance_electro_combo_edgedamage 25
set g_balance_electro_combo_force 120
set g_balance_electro_combo_radius 175
set g_balance_electro_combo_comboradius 275
set g_balance_nex_charge_animlimit 0.5
set g_balance_nex_charge_limit 1
set g_balance_nex_charge_rot_rate 0
-set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button
+set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
set g_balance_nex_charge_shot_multiplier 0
set g_balance_nex_charge_velocity_rate 0
set g_balance_nex_charge_minspeed 400
// {{{ hagar
set g_balance_hagar_primary_damage 25
set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 50
-set g_balance_hagar_primary_radius 60
+set g_balance_hagar_primary_force 100
+set g_balance_hagar_primary_health 15
+set g_balance_hagar_primary_damageforcescale 0
+set g_balance_hagar_primary_radius 65
set g_balance_hagar_primary_spread 0.04
-set g_balance_hagar_primary_speed 2000
+set g_balance_hagar_primary_speed 2200
set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_refire 0.15
+set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second
set g_balance_hagar_primary_ammo 1
set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_load 1
set g_balance_hagar_secondary_load_spread 0.075
set g_balance_hagar_secondary_load_spread_bias 0.5
set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_hold 1
+set g_balance_hagar_secondary_load_hold 4
set g_balance_hagar_secondary_load_releasedeath 0
set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
set g_balance_hagar_secondary_damage 40
set g_balance_hagar_secondary_edgedamage 20
-set g_balance_hagar_secondary_force 50
+set g_balance_hagar_secondary_force 75
+set g_balance_hagar_secondary_health 15
+set g_balance_hagar_secondary_damageforcescale 0
set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_spread 0.06
+set g_balance_hagar_secondary_spread 0.05
set g_balance_hagar_secondary_speed 2000
set g_balance_hagar_secondary_lifetime_min 10
set g_balance_hagar_secondary_lifetime_rand 0
set g_balance_rocketlauncher_refire 1.1
set g_balance_rocketlauncher_animtime 0.3
set g_balance_rocketlauncher_ammo 4
-set g_balance_rocketlauncher_health 0 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
+set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn
set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
set g_balance_rocketlauncher_guiderate 110 // max degrees per second
// {{{ porto
set g_balance_porto_primary_refire 1.5
set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_speed 5000
+set g_balance_porto_primary_speed 1000
set g_balance_porto_primary_lifetime 5
set g_balance_portal_health 200 // these get recharged whenever the portal is used
set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
set g_balance_hook_secondary_edgedamage 5 // not much
set g_balance_hook_secondary_radius 500 // LOTS
set g_balance_hook_secondary_force -2000 // LOTS
-set g_balance_hook_secondary_ammo 50 // a whole pack
+set g_balance_hook_secondary_ammo 30 // a whole pack
set g_balance_hook_secondary_lifetime 5 // infinite
set g_balance_hook_secondary_speed 0 // not much throwing
set g_balance_hook_secondary_gravity 5 // fast falling
set g_balance_hook_secondary_animtime 0.3 // good shoot anim
set g_balance_hook_secondary_power 3 // effect behaves like a square function
set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 15
+set g_balance_hook_secondary_damageforcescale 0
// }}}
// {{{ hlac // TO BE REMOVED
set g_balance_hlac_primary_spread_min 0.01
set g_balance_firetransfer_damage 0.8
set g_throughfloor_damage 0.5
set g_throughfloor_force 0.7
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines)
+// 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_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
set g_balance_falldamage_factor 0.02 // maxspeed = minspeed + maxdamage / factor = 4550
set g_balance_falldamage_maxdamage 75
set g_balance_damagepush_speedfactor 0
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
// }}}
// {{{ powerups
set g_balance_grapplehook_stretch 50
set g_balance_grapplehook_airfriction 0.2
set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
// }}}
// {{{ weapon properties
set g_balance_shotgun_primary_speed 12000
set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu
set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim
-set g_balance_shotgun_secondary_melee_range 85
-set g_balance_shotgun_secondary_melee_swing 50
-set g_balance_shotgun_secondary_melee_time 0.1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 0
+set g_balance_shotgun_secondary_melee_multihit 1
set g_balance_shotgun_secondary_damage 110
set g_balance_shotgun_secondary_force 150
set g_balance_shotgun_secondary_refire 1.1
set g_balance_electro_secondary_ammo 2
set g_balance_electro_secondary_health 10
set g_balance_electro_secondary_damageforcescale 2
+set g_balance_electro_secondary_damagedbycontents 0
set g_balance_electro_secondary_count 3
set g_balance_electro_secondary_bouncefactor 0.5
set g_balance_electro_secondary_bouncestop 0.075
set g_balance_nex_charge_animlimit 0.5
set g_balance_nex_charge_limit 0.5
set g_balance_nex_charge_rot_rate 0.1
-set g_balance_nex_charge_rot_pause 1 // Dont rot down untill this long after release of charge button
+set g_balance_nex_charge_rot_pause 1 // Dont rot down until this long after release of charge button
set g_balance_nex_charge_shot_multiplier 0
set g_balance_nex_charge_velocity_rate 0
set g_balance_nex_charge_minspeed 400
set g_balance_hagar_primary_damage 25
set g_balance_hagar_primary_edgedamage 5
set g_balance_hagar_primary_force 70
+set g_balance_hagar_primary_health 0
+set g_balance_hagar_primary_damageforcescale 0
set g_balance_hagar_primary_radius 60
set g_balance_hagar_primary_spread 0.010
set g_balance_hagar_primary_speed 2500
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
set g_balance_hagar_secondary_damage 30
set g_balance_hagar_secondary_edgedamage 15
set g_balance_hagar_secondary_force 50
+set g_balance_hagar_secondary_health 0
+set g_balance_hagar_secondary_damageforcescale 0
set g_balance_hagar_secondary_radius 65
set g_balance_hagar_secondary_spread 0.015
set g_balance_hagar_secondary_speed 1400
set g_balance_hook_secondary_animtime 0.3 // good shoot anim
set g_balance_hook_secondary_power 3 // effect behaves like a square function
set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 0
+set g_balance_hook_secondary_damageforcescale 0
// }}}
// {{{ hlac
set g_balance_hlac_primary_spread_min 0.01
set g_forced_respawn 1 // no delaying/cheating a match by not spawning
// info
-set sv_fragmessage_information_stats 0 // don't reveal how much health/armor the attacker had
+set sv_fraginfo_stats 0 // don't reveal how much health/armor the attacker had
alias +hook +button6
alias -hook -button6
alias use "impulse 21"
-alias +use use // always send that impulse AND press the key (+use is engine internal command and executes anyway)
-set cl_newusekeysupported 1 // indicates that we always send the use impulse too, so they do not need to be synthesized
alias ready "cmd ready"
alias lockteams "sv_cmd lockteams"
alias unlockteams "sv_cmd unlockteams"
seta crosshair_ring_reload_size 2.5 "reload ring size"
seta crosshair_ring_reload_alpha 0.2 "reload ring alpha"
+seta cl_reticle 1 "control for toggling whether ANY zoom reticles are shown"
seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (brakes image proportions)"
seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha"
fov 90
seta cl_velocityzoom 0 "velocity based zooming of fov, negative values zoom out"
-seta cl_velocityzoomtime 0.3 "time value for averaging speed values"
+seta cl_velocityzoom_type 3 "how to factor in speed, 1 = all velocity in all directions, 2 = velocity only in forward direction (can be negative), 3 = velocity only in forward direction (limited to forward only)"
+seta cl_velocityzoom_speed 1000 "target speed for fov factoring"
+seta cl_velocityzoom_time 0.2 "time value for averaging speed values"
seta cl_zoomfactor 5 "how much +zoom will zoom (1-16)"
seta cl_zoomspeed 8 "how fast it will zoom (0.5-16), negative values mean instant zoom"
seta cl_zoomsensitivity 0 "how zoom changes sensitivity (0 = weakest, 1 = strongest)"
set g_allow_oldnexbeam 0 "If enabled, clients are allowed to use old v2.3 Nexgun beam"
seta cl_particles_oldnexbeam 0 "Uses the old v2.3 Nexgun beam instead of the new beam, only works if server allows it (g_allow_oldnexbeam 1)"
-set sv_qcweaponanimation 0
set g_telefrags 1 "telefragging, i.e. killing someone who stands in the way of someone who is teleporting"
set g_telefrags_teamplay 1 "never telefrag team mates"
set sv_gibhealth 100 "Minus health a dead body must have in order to get gibbed"
// fragmessage: This allows extra information to be displayed with the frag centerprints.
-set sv_fragmessage_information_ping 1 "Enable ping display information, 0 = Never display; 1 = Always display (If the player is a bot, it will say bot instead of the ping.)"
-set sv_fragmessage_information_handicap 1 "Enable handicap display information, 0 = Never display; 1 = Only when the player has handicap on; 2 = Always display (Displays Off if off)"
-set sv_fragmessage_information_stats 1 "Enable statistics (health/armor) display information, 0 = Never display; 1 = Always display (Only available for the person who was killed)"
-set sv_fragmessage_information_typefrag 1 "Enable typefrag display information, 0 = Never display; 1 = Always display"
+set sv_fraginfo_ping 1 "Enable ping display information, 0 = Never display; 1 = Always display (If the player is a bot, it will say bot instead of the ping.)"
+set sv_fraginfo_handicap 1 "Enable handicap display information, 0 = Never display; 1 = Only when the player has handicap on; 2 = Always display (Displays Off if off)"
+set sv_fraginfo_stats 1 "Enable statistics (health/armor) display information, 0 = Never display; 1 = Always display (Only available for the person who was killed)"
+set sv_fraginfo_typefrag 1 "Enable typefrag display information, 0 = Never display; 1 = Always display"
// use default physics
set sv_friction_on_land 0
set sv_jumpspeedcap_min "" "lower bound on the baseline velocity of a jump; final velocity will be >= (jumpheight * min + jumpheight)"
set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)"
set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style"
+set sv_player_jumpanim_minfall 48 "minimum distance player has to have below their feet before the jump animation will be activated (only when falling, +jump will play anim instantly)"
seta sv_precacheplayermodels 1
seta sv_precacheweapons 0
locs_enable 0
pausable 0
-seta g_spawnshieldtime 1.000000 "number of seconds you are invincible after you spawned, this shield is lost after you fire"
-seta g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)"
+set g_spawnshieldtime 1 "number of seconds you are invincible after you spawned, this shield is lost after you fire"
+set g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)"
set g_trueaim_minrange 44 "TrueAim minimum range (TrueAim adjusts shots so they hit the crosshair point even though the gun is not at the screen center)"
set g_antilag_nudge 0 "don't touch"
set g_antilag_bullets 1 "Bullets AntiLag (0 = no AntiLag, 1 = server side hit scan in the past) - DO NOT TOUCH (severely changes weapon balance)"
seta g_maplist_shuffle 1 "new randomization method: like selectrandom, but avoid playing the same maps in short succession. This works by taking out the first element and inserting it into g_maplist with a bias to the end of the list"
set g_maplist_check_waypoints 0 "when 1, maps are skipped if there currently are bots, but the map has no waypoints"
set samelevel 0 "when 1, always play the same level over and over again"
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
set g_cloaked 0 "display all players mostly invisible"
set g_player_alpha 1
set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
+set g_invincible_projectiles 0 "set to 1 to disable any damage to projectiles in all balance configs, regardless of g_projectiles_damage"
set g_dodging 0 "set to 1 to enable dodging in games"
set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs"
bind r reload
bind BACKSPACE dropweapon
bind g dropweapon
-bind f use
+bind f +use
// misc
bind e +hook
bind y messagemode2
bind z messagemode2
bind u "+con_chat_maximize"
+bind m +hud_panel_radar_maximized
bind i +show_info
bind PAUSE pause
bind F10 quit
set g_nick_flood_penalty_yellow 3 "number of changes to allow before warning and movement blocking"
set g_nick_flood_penalty_red 30 "number of changes to allow before totally disorienting the player"
+set sv_waypointsprite_deployed_lifetime 10
+set sv_waypointsprite_deadlifetime 1
+set sv_waypointsprite_limitedrange 5120
+
seta g_waypointsprite_uppercase 1
set g_waypointsprite_normdistance 512
set g_waypointsprite_minscale 0.5
set g_waypointsprite_minalpha 0.4
set g_waypointsprite_distancealphaexponent 2
set g_waypointsprite_timealphaexponent 1
-set g_waypointsprite_deployed_lifetime 10
-set g_waypointsprite_deadlifetime 1
-set g_waypointsprite_limitedrange 5120
set g_waypointsprite_stuffbinds 0
seta g_waypointsprite_scale 1
seta g_waypointsprite_fontsize 12
alias -userbind "_userbind_call userbind${1}_release"
// we must change its default from 1.0 to 1 to be consistent with menuqc
-seta slowmo 1
+set slowmo 1
seta menu_skin "luminos"
set menu_slowmo 1
con_notifysize 10
con_notifyalign 0
-// hud variables
-set _hud_configure 0 "1 = configure the HUD"
-seta hud_configure_teamcolorforced 0 "1 = force display of team colors in configure mode"
-seta hud_configure_checkcollisions 1 "check for collisions against other panels when in hud configure mode"
-seta hud_configure_bg_minalpha 0.25 "minimum panel background alpha when in hud configure mode"
-seta hud_configure_grid_alpha 0.15 "alpha for visible grid when in configure mode"
-
seta sbar_info_pos 0 "Y-axis distance from lower right corner for engine info prints"
-// user preference cvars (i.e. shouldn't be adjusted by a skin config)
-seta hud_panel_weapons_label 1 "1 = show number of weapon, 2 = show bound key of weapon"
-seta hud_panel_weapons_complainbubble_time 1 "time that a new entry stays until it fades out"
-seta hud_panel_weapons_complainbubble_fadetime 0.25 "fade out time"
-seta hud_panel_weapons_accuracy 1 "show accuracy color as the weapon icon background; colors can be configured with accuracy_color* cvars"
-seta hud_panel_weapons_ammo 1 "show ammo as a status bar"
-seta hud_panel_weapons_ammo_full_shells 50 "show 100% of the status bar at this ammo count"
-seta hud_panel_weapons_ammo_full_nails 200 "show 100% of the status bar at this ammo count"
-seta hud_panel_weapons_ammo_full_cells 80 "show 100% of the status bar at this ammo count"
-seta hud_panel_weapons_ammo_full_rockets 80 "show 100% of the status bar at this ammo count"
-seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count"
-seta hud_panel_weapons_onlyowned 1 "show only owned weapons"
-
-seta hud_panel_ammo_maxammo "40" "when you have this much ammo, the ammo status bar is full"
-
-seta hud_panel_healtharmor_maxhealth "200" "when you have this much health, the health status bar is full"
-seta hud_panel_healtharmor_maxarmor "200" "when you have this much armor, the armor status bar is full"
-seta hud_panel_healtharmor_progressbar_gfx 1 "enable graphic effects on the progressbars"
-seta hud_panel_healtharmor_progressbar_gfx_damage 5 "show damage effect when damaged at least by this amount; 0 disables the effect"
-seta hud_panel_healtharmor_progressbar_gfx_lowhealth 40 "health progressbar blinks when health is lower than this amount"
-seta hud_panel_healtharmor_progressbar_gfx_smooth 2 "smooth changes of the progressbar when health/armor change at least by this amount; 0 disables the effect"
-
-seta hud_panel_notify_time 10 "time that a new entry stays until it fades out"
-seta hud_panel_notify_fadetime 3 "fade out time"
-
-seta hud_panel_modicons_dom_layout 1 "3 possible layouts: 0) only icons; 1) icons and percentage of average pps (points per second); 2) icons and average pps"
-
-seta hud_panel_timer_increment 0 "show elapsed time instead of remaining time"
-
-seta hud_panel_radar_scale 4096 "distance you can see on the team radar"
-seta hud_panel_radar_rotation 0 "rotation mode: you set what points up. 0 = player, 1 = west, 2 = south, 3 = east, 4 = north"
-seta hud_panel_radar_zoommode 0 "zoom mode: 0 = zoomed by default, 1 = zoomed when +zoom, 2 = always zoomed, 3 = always zoomed out"
-alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4"
-
-seta hud_panel_score_rankings 0 "show rankings: 1 always show my own score; 2 pure rankings"
-
-seta hud_panel_engineinfo_framecounter_time 0.1 "time between framerate display updates"
-seta hud_panel_engineinfo_framecounter_decimals 0 "amount of decimals to show"
-seta hud_panel_engineinfo_framecounter_exponentialmovingaverage 1 "use an averaging method for calculating fps instead of counting frametime like engine does"
-seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point"
-seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster"
-
-seta hud_panel_physics_speed_unit 3 "speed unit (1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots)"
-seta hud_panel_physics_speed_unit_show 1 "also show speed unit"
-seta hud_panel_physics_speed_max 1800 "speed progressbar gets filled up completely by this value (in qu/s)"
-seta hud_panel_physics_speed_vertical 0 "include the speed on the Z-axis"
-seta hud_panel_physics_topspeed 1 "also show top speed"
-seta hud_panel_physics_topspeed_time 4 "how many seconds the top speed takes to fade out"
-seta hud_panel_physics_acceleration_max 1.5 "acceleration progressbar gets completely filled up by this value (in g)"
-seta hud_panel_physics_acceleration_vertical 0 "include the acceleration on the Z-axis"
-
-seta hud_showbinds 1 "what to show in the HUD to indicate certain keys to press: 0 display commands, 1 bound keys, 2 both"
-seta hud_showbinds_limit 2 "maximum number of bound keys to show for a command. 0 for unlimited"
-
-seta hud_colorflash_alpha 0.5 "starting alpha of the color flash"
-
-seta hud_damage 0.55 "an improved version of gl_polyblend for damage, draw an image instead when hurt"
-seta hud_damage_blur 10 "Use postprocessing to blur the screen when you have taken damage. This can be paired with current hud damage or just used alone. Higher values = more blur"
-seta hud_damage_blur_alpha 0.5 "Amount of alpha to use when merging the blurred layers back into the render. Turning this up higher will remove bloom, so it's best to find a balance"
-seta hud_damage_gentle_alpha_multiplier 0.10 "how much to multiply alpha of flash when using the cl_gentle version, it's much more opaque than the non-gentle version"
-seta hud_damage_gentle_color "1 0.7 1" "color of flash for cl_gentle version"
-seta hud_damage_color "1 0 0" "color of flash"
-seta hud_damage_factor 0.025 "(damage * factor) = how much to add to the alpha value"
-seta hud_damage_fade_rate 0.75 "how much to subtract from the alpha value each second"
-seta hud_damage_maxalpha 1.5 "how much to limit the alpha value to"
-seta hud_damage_pain_threshold 0.1 "how much alpha to ignore (must be bigger than the hud_damage_factor so that e.g. rot is ignored)"
-seta hud_damage_pain_threshold_lower 1.25 "how much we lower pain_threshold with when nearing 0 health (if pain_threshold gets negative then we always draw a flash at alpha = fabs(pain_threshold)"
-seta hud_damage_pain_threshold_lower_health 50 "at which health we start lowering pain_threshold"
-seta hud_damage_pain_threshold_pulsating_min 0.6 "minimum value when calculating the pulse: max(pulsating_min, fabs(sin(PI * time / period))"
-seta hud_damage_pain_threshold_pulsating_period 0.8 "one pulse every X seconds"
-
-seta hud_powerup 0 "power of the sharpen effect when owning the shield or strength powerups, default is 0.5"
-
-seta hud_postprocessing 1 "enables the ability for effects such as hud_damage_blur and hud_contents to apply a postprocessing method upon the screen - enabling this disables manual editing of the postprocess cvars"
-seta hud_postprocessing_maxbluralpha 0 "maximum alpha which the blur postprocess can be, default is 0.5"
-seta hud_postprocessing_maxblurradius 8 "maximum radius which the blur postprocess can be, default is 8"
-
-seta hud_contents 1 "an improved version of gl_polyblend for liquids such as water/lava/slime, draw a filler when inside the liquid"
-seta hud_contents_blur 10 "Use postprocessing to blur the screen when you are inside a liquid. Higher values = more blur"
-seta hud_contents_blur_alpha 0.5 "Amount of alpha to use when merging the blurred layers back into the render. Turning this up higher will remove bloom, so it's best to find a balance"
-seta hud_contents_factor 1 "factor at which to multiply the current faded value."
-seta hud_contents_fadeintime 0.02 "factor of time it takes for the alpha level to reach normal value when entering the liquid"
-seta hud_contents_fadeouttime 0.1 "factor of time it takes for the alpha level to reach normal value when leaving the liquid"
-seta hud_contents_lava_alpha 0.7 "alpha of the lava color blend when inside it"
-seta hud_contents_lava_color "0.8 0.1 0"
-seta hud_contents_slime_alpha 0.7 "alpha of the slime color blend when inside it"
-seta hud_contents_slime_color "0 0.4 0.1"
-seta hud_contents_water_alpha 0.5 "alpha of the water color blend when inside it"
-seta hud_contents_water_color "0.4 0.3 0.3"
-
-seta hud_shownames 1 "draw names and health/armor of nearby players"
-seta hud_shownames_enemies 2 "1 = draw names of enemies you point at (TODO), 2 = draw names of all enemies in view"
-seta hud_shownames_self 0 "also include your own name to be shown when third person camera mode is on (chase_active/cl_eventchase)"
-seta hud_shownames_status 1 "1 = draw health/armor status of teammates"
-seta hud_shownames_statusbar_height 4 "height of status bar"
-seta hud_shownames_aspect 8 "aspect ratio of total drawing area per name"
-seta hud_shownames_fontsize 12 "font size"
-seta hud_shownames_decolorize 1 "1 = decolorize name in team games, 2 = decolorize always"
-seta hud_shownames_alpha 0.7 "alpha"
-seta hud_shownames_resize 1 "enable resizing of the names, then the size cvars will correspond to the maximum size"
-seta hud_shownames_mindistance 1000 "start fading alpha/size at this distance"
-seta hud_shownames_maxdistance 2500 "alpha/size is 0 at this distance"
-seta hud_shownames_antioverlap 1 "if two tags get too close to each other, fade out the one further away from you"
-seta hud_shownames_antioverlap_distance 125 "2d distance to other tag after which to fade out"
-seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units"
-
// scoreboard
seta scoreboard_columns default
seta scoreboard_border_thickness 1 "scoreboard border thickness"
seta scoreboard_highlight 1 "enable highlighting for rows and columns in the scoreboard"
seta scoreboard_highlight_alpha 0.10 "highlight alpha value (depends on hud_scoreboard_highlight 1)"
seta scoreboard_highlight_alpha_self 0.25 "self highlight alpha value"
-seta scoreboard_offset_left 0.15 "how many pixels the scoreboard is offset from the left screen edge"
-seta scoreboard_offset_right 0.15 "how many pixels the scoreboard is offset from the right screen edge"
+seta scoreboard_offset_left 0.15 "how far (by percent) the scoreboard is offset from the left screen edge"
+seta scoreboard_offset_right 0.15 "how far (by percent) the scoreboard is offset from the right screen edge"
+seta scoreboard_offset_vertical 0.05 "how far (by percent) the scoreboard is offset from the top and bottom of the screen"
seta scoreboard_bg_scale 0.25 "scale for the tiled scoreboard background"
seta accuracy_color_levels "0 20 100" "accuracy values at which a specified color (accuracy_color<X>) will be used. If your accuracy is between 2 of these values then a mix of the Xth and X+1th colors will be used. You can specify up to 10 values, in increasing order"
// CTF capture limit placeholder cvar
set capturelimit 0
-// hud: font size
-seta hud_fontsize 11
-seta hud_width 560
-
// these entities are not referenced by anything directly, they just represent
// teams and are found by find() when needed
prvm_leaktest_ignore_classnames "ctf_team dom_team tdm_team"
sv_allowdownloads_inarchive 1 // for csprogs.dat
+sv_allowdownloads 0 // download protocol is evil
set g_jump_grunt 0 "Do you make a grunting noise every time you jump? Is it the same grunting noise every time?"
if_client set g_start_delay 0 "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server"
if_dedicated set g_start_delay 15 "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server"
-alias ons_map "cl_cmd radar" // legacy alias
-alias radar "cl_cmd radar"
+alias radar "cl_cmd hud_panel_radar_maximized"
alias scoreboard_columns_set "" // aliased later
alias scoreboard_columns_help "cl_cmd scoreboard_columns_help $*"
seta cl_clippedspectating 1 "movement collision for spectators so that you can't pass through walls and such. (client setting) NOTE: reconnect or use sendcvar command to update the choice."
+seta cl_autoscreenshot 0 "client option to automatically take a screenshot once the map has ended (see also sv_autoscreenshot)"
+
// must be at the bottom of this file:
// alias for switching the teamselect menu
alias menu_showteamselect "menu_cmd directmenu TeamSelect"
// create this cvar in case the engine did not
set snd_soundradius 1200
+set snd_softclip 1
+set snd_maxchannelvolume 0
+set snd_streaming_length 2
+seta menu_snd_attenuation_method 1 "Use exponential instead of linear falloff for sound attenuation"
+alias snd_attenuation_method_0 "set menu_snd_attenuation_method 0; set snd_soundradius 1200; set snd_attenuation_exponent 1; set snd_attenuation_decibel 0" // Quake default
+alias snd_attenuation_method_1 "set menu_snd_attenuation_method 1; set snd_soundradius 2400; set snd_attenuation_exponent 4; set snd_attenuation_decibel 0" // nice approximation for method 2
+alias snd_attenuation_method_2 "set menu_snd_attenuation_method 2; set snd_soundradius 1200; set snd_attenuation_exponent 0; set snd_attenuation_decibel 10" // warning: plays sounds within up to 6000qu
+snd_attenuation_method_1
// declare the channels we use
seta snd_channel8volume 1 "QuakeC controlled background music volume"
seta snd_channel9volume 1 "QuakeC controlled ambient sound volume"
+// sound randomization
+snd_identicalsoundrandomization_time -0.1
+snd_identicalsoundrandomization_tics 1
+
// loading screen
scr_loadingscreen_background 0
scr_loadingscreen_barcolor "0 0.5 1"
exec turrets.cfg
exec vehicles.cfg
-// hud cvar descriptions
+// hud cvar descriptions and common settings
+exec _hud_common.cfg
exec _hud_descriptions.cfg
// exec the default skin config
-// please add any new cvars into the hud_save script in qcsrc/client/hud.qc for consistency
+// please add any new cvars into the hud_save script in qcsrc/client/hud_config.qc for consistency
exec hud_luminos.cfg
// enable menu syncing
type static
color 0xffdf72 0x811200
tex 48 55
-size 1 2
+size 5 2
sizeincrease -15
alpha 100 144 988
airfriction 8
r_glsl_deluxemapping 1
r_glsl_offsetmapping 1
r_glsl_offsetmapping_reliefmapping 0
-r_hdr 0
r_motionblur 0.5
r_shadow_gloss 1
r_shadow_realtime_dlight 1
r_glsl_deluxemapping 0
r_glsl_offsetmapping 0
r_glsl_offsetmapping_reliefmapping 0
-r_hdr 0
r_motionblur 0
r_shadow_gloss 0
r_shadow_realtime_dlight 0
r_glsl_deluxemapping 0
r_glsl_offsetmapping 0
r_glsl_offsetmapping_reliefmapping 0
-r_hdr 0
r_motionblur 0
r_shadow_gloss 0
r_shadow_realtime_dlight 1
r_glsl_deluxemapping 1
r_glsl_offsetmapping 0
r_glsl_offsetmapping_reliefmapping 0
-r_hdr 0
r_motionblur 0
r_shadow_gloss 1
r_shadow_realtime_dlight 1
r_glsl_deluxemapping 0
r_glsl_offsetmapping 0
r_glsl_offsetmapping_reliefmapping 0
-r_hdr 0
r_motionblur 0
r_shadow_gloss 0
r_shadow_realtime_dlight 0
r_glsl_deluxemapping 1
r_glsl_offsetmapping 1
r_glsl_offsetmapping_reliefmapping 1
-r_hdr 2
r_motionblur 0.5
r_shadow_gloss 1
r_shadow_realtime_dlight 1
r_glsl_deluxemapping 1
r_glsl_offsetmapping 1
r_glsl_offsetmapping_reliefmapping 0
-r_hdr 0
r_motionblur 0.5
r_shadow_gloss 1
r_shadow_realtime_dlight 1
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
seta hud_progressbar_nexball_color "0.7 0.1 0"
-seta hud_progressbar_speed_color "1 0.75 0"
-seta hud_progressbar_acceleration_color "0.5 0.75 1"
-seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
+seta hud_progressbar_speed_color "1 0.75 0"
+seta hud_progressbar_acceleration_color "0.5 0.75 1"
+seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
seta _hud_panelorder "15 12 9 10 5 6 14 0 7 4 11 2 1 3 8 13 16 "
seta hud_configure_grid_ysize "0.010000"
seta hud_panel_weapons 1
-seta hud_panel_weapons_pos "0.940000 0.180000"
-seta hud_panel_weapons_size "0.060000 0.610000"
+seta hud_panel_weapons_pos "0.930000 0.170000"
+seta hud_panel_weapons_size "0.070000 0.650000"
seta hud_panel_weapons_bg "border_small_weapons"
seta hud_panel_weapons_bg_color ""
seta hud_panel_weapons_bg_color_team ""
seta hud_panel_weapons_bg_alpha ""
seta hud_panel_weapons_bg_border ""
-seta hud_panel_weapons_bg_padding ""
+seta hud_panel_weapons_bg_padding "4"
+seta hud_panel_weapons_accuracy "1"
+seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "-10"
+seta hud_panel_weapons_complainbubble_padding "2"
+seta hud_panel_weapons_complainbubble_time "4"
+seta hud_panel_weapons_complainbubble_fadetime "2"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
+seta hud_panel_weapons_ammo "1"
seta hud_panel_weapons_ammo_color "0 1 0"
seta hud_panel_weapons_ammo_alpha "1"
seta hud_panel_weapons_aspect "2"
-seta hud_panel_weapons_timeout "3"
-seta hud_panel_weapons_timeout_effect "2"
+seta hud_panel_weapons_timeout "5"
+seta hud_panel_weapons_timeout_effect "3"
+seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_ammo_pos "0.330000 0.960000"
seta hud_panel_healtharmor_progressbar "1"
seta hud_panel_healtharmor_progressbar_health "progressbar"
seta hud_panel_healtharmor_progressbar_armor "progressbar"
+seta hud_panel_healtharmor_progressbar_gfx "1"
+seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
seta hud_panel_notify 1
seta hud_panel_notify_flip "0"
seta hud_panel_notify_fontsize "0.8"
seta hud_panel_notify_print "1"
+seta hud_panel_notify_time "10"
+seta hud_panel_notify_fadetime "3"
seta hud_panel_timer 1
seta hud_panel_timer_pos "0.800000 0.040000"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
+seta hud_panel_timer_increment "0"
seta hud_panel_radar 2
seta hud_panel_radar_pos "0 0"
seta hud_panel_radar_bg_border ""
seta hud_panel_radar_bg_padding "-1"
seta hud_panel_radar_foreground_alpha "0.800000"
+seta hud_panel_radar_rotation "0"
+seta hud_panel_radar_zoommode "0"
+seta hud_panel_radar_scale "4096"
+seta hud_panel_radar_maximized_scale "8192"
+seta hud_panel_radar_maximized_size "0.5 0.5"
seta hud_panel_score 1
seta hud_panel_score_pos "0.890000 0.030000"
seta hud_panel_score_bg_alpha ""
seta hud_panel_score_bg_border ""
seta hud_panel_score_bg_padding "0"
+seta hud_panel_score_rankings "1"
seta hud_panel_racetimer 1
seta hud_panel_racetimer_pos "0.360000 0.110000"
seta hud_panel_vote 1
seta hud_panel_vote_pos "0.710000 0.660000"
seta hud_panel_vote_size "0.210000 0.100000"
-seta hud_panel_vote_bg "border_vote"
+seta hud_panel_vote_bg ""
seta hud_panel_vote_bg_color ""
seta hud_panel_vote_bg_color_team ""
seta hud_panel_vote_bg_alpha ""
seta hud_panel_modicons_bg_alpha ""
seta hud_panel_modicons_bg_border ""
seta hud_panel_modicons_bg_padding "0"
+seta hud_panel_modicons_dom_layout "1"
seta hud_panel_pressedkeys 1
seta hud_panel_pressedkeys_pos "0.450000 0.720000"
seta hud_panel_engineinfo_bg_alpha ""
seta hud_panel_engineinfo_bg_border ""
seta hud_panel_engineinfo_bg_padding ""
+seta hud_panel_engineinfo_framecounter_time "0.1"
+seta hud_panel_engineinfo_framecounter_decimals "0"
seta hud_panel_infomessages 1
seta hud_panel_infomessages_pos "0.720000 0.100000"
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
+seta hud_panel_physics_speed_unit "3"
+seta hud_panel_physics_speed_unit_show "1"
+seta hud_panel_physics_speed_max "1800"
+seta hud_panel_physics_speed_vertical "0"
+seta hud_panel_physics_topspeed "1"
+seta hud_panel_physics_topspeed_time "4"
+seta hud_panel_physics_acceleration_max "1.5"
+seta hud_panel_physics_acceleration_vertical "0"
seta hud_panel_physics_flip "0"
seta hud_panel_physics_baralign "0"
-seta hud_panel_physics_acceleration_progressbar_mode "0"
seta hud_panel_physics_progressbar "1"
+seta hud_panel_physics_acceleration_mode "0"
seta hud_panel_physics_text "1"
seta hud_panel_centerprint 1
-seta hud_panel_centerprint_pos "0.175000 0.260000"
-seta hud_panel_centerprint_size "0.650000 0.210000"
+seta hud_panel_centerprint_pos "0.175000 0.220000"
+seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_bg_color ""
seta hud_panel_centerprint_bg_color_team ""
seta hud_panel_centerprint_bg_border ""
seta hud_panel_centerprint_bg_padding ""
seta hud_panel_centerprint_align "0.5"
-seta hud_panel_centerprint_flip "1"
+seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
seta hud_panel_centerprint_time "3"
-seta hud_panel_centerprint_fadetime "0.25"
+seta hud_panel_centerprint_fade_in "0.2"
+seta hud_panel_centerprint_fade_out "0.5"
+seta hud_panel_centerprint_fade_subsequent "1"
+seta hud_panel_centerprint_fade_subsequent_passone "3"
+seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_passtwo "10"
+seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
+seta hud_panel_centerprint_fade_minfontsize "0"
menu_sync
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
seta hud_progressbar_nexball_color "0.7 0.1 0"
-seta hud_progressbar_speed_color "1 0.75 0"
-seta hud_progressbar_acceleration_color "0.5 0.75 1"
-seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
+seta hud_progressbar_speed_color "1 0.75 0"
+seta hud_progressbar_acceleration_color "0.5 0.75 1"
+seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
seta _hud_panelorder "10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 15 16 "
seta hud_panel_weapons_bg_alpha ""
seta hud_panel_weapons_bg_border ""
seta hud_panel_weapons_bg_padding ""
+seta hud_panel_weapons_accuracy "1"
+seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
seta hud_panel_weapons_complainbubble_padding "-10"
+seta hud_panel_weapons_complainbubble_time "1"
+seta hud_panel_weapons_complainbubble_fadetime "0.25"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
+seta hud_panel_weapons_ammo "1"
seta hud_panel_weapons_ammo_color "0 1 0"
seta hud_panel_weapons_ammo_alpha "1"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "0"
seta hud_panel_weapons_timeout_effect "0"
+seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_ammo_pos "0.650000 0.890000"
seta hud_panel_ammo_onlycurrent "0"
seta hud_panel_ammo_iconalign "0"
seta hud_panel_ammo_progressbar "0"
-seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_progressbar_name "progressbar"
+seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
seta hud_panel_powerups 1
seta hud_panel_healtharmor_progressbar "1"
seta hud_panel_healtharmor_progressbar_health "progressbar"
seta hud_panel_healtharmor_progressbar_armor "progressbar"
+seta hud_panel_healtharmor_progressbar_gfx "1"
+seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
seta hud_panel_notify 1
seta hud_panel_notify_flip "1"
seta hud_panel_notify_fontsize "0.8"
seta hud_panel_notify_print "0"
+seta hud_panel_notify_time "10"
+seta hud_panel_notify_fadetime "3"
seta hud_panel_timer 1
seta hud_panel_timer_pos "0.435000 0"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
+seta hud_panel_timer_increment "0"
seta hud_panel_radar 2
seta hud_panel_radar_pos "0.810000 0"
seta hud_panel_radar_bg_border "0"
seta hud_panel_radar_bg_padding "0"
seta hud_panel_radar_foreground_alpha "0.500000"
+seta hud_panel_radar_rotation "0"
+seta hud_panel_radar_zoommode "0"
+seta hud_panel_radar_scale "4096"
+seta hud_panel_radar_maximized_scale "8192"
+seta hud_panel_radar_maximized_size "0.5 0.5"
seta hud_panel_score 1
seta hud_panel_score_pos "0.465000 0.045000"
seta hud_panel_score_bg_alpha ""
seta hud_panel_score_bg_border ""
seta hud_panel_score_bg_padding ""
+seta hud_panel_score_rankings "1"
seta hud_panel_racetimer 1
seta hud_panel_racetimer_pos "0.360000 0.090000"
seta hud_panel_modicons_bg_alpha ""
seta hud_panel_modicons_bg_border ""
seta hud_panel_modicons_bg_padding ""
+seta hud_panel_modicons_dom_layout "1"
seta hud_panel_pressedkeys 1
seta hud_panel_pressedkeys_pos "0.450000 0.650000"
seta hud_panel_engineinfo_bg_alpha ""
seta hud_panel_engineinfo_bg_border ""
seta hud_panel_engineinfo_bg_padding ""
+seta hud_panel_engineinfo_framecounter_time "0.1"
+seta hud_panel_engineinfo_framecounter_decimals "0"
seta hud_panel_infomessages 1
seta hud_panel_infomessages_pos "0.710000 0"
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
+seta hud_panel_physics_speed_unit "3"
+seta hud_panel_physics_speed_unit_show "1"
+seta hud_panel_physics_speed_max "1800"
+seta hud_panel_physics_speed_vertical "0"
+seta hud_panel_physics_topspeed "1"
+seta hud_panel_physics_topspeed_time "4"
+seta hud_panel_physics_acceleration_max "1.5"
+seta hud_panel_physics_acceleration_vertical "0"
seta hud_panel_physics_flip "0"
seta hud_panel_physics_baralign "0"
-seta hud_panel_physics_acceleration_progressbar_mode "0"
seta hud_panel_physics_progressbar "3"
-seta hud_panel_physics_text "2"
+seta hud_panel_physics_acceleration_mode "0"
+seta hud_panel_physics_text "1"
seta hud_panel_centerprint 1
-seta hud_panel_centerprint_pos "0.175000 0.260000"
-seta hud_panel_centerprint_size "0.650000 0.210000"
+seta hud_panel_centerprint_pos "0.175000 0.220000"
+seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_bg_color ""
seta hud_panel_centerprint_bg_color_team ""
seta hud_panel_centerprint_bg_border ""
seta hud_panel_centerprint_bg_padding ""
seta hud_panel_centerprint_align "0.5"
-seta hud_panel_centerprint_flip "1"
+seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
seta hud_panel_centerprint_time "3"
-seta hud_panel_centerprint_fadetime "0.25"
+seta hud_panel_centerprint_fade_in "0.2"
+seta hud_panel_centerprint_fade_out "0.5"
+seta hud_panel_centerprint_fade_subsequent "1"
+seta hud_panel_centerprint_fade_subsequent_passone "3"
+seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_passtwo "10"
+seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
+seta hud_panel_centerprint_fade_minfontsize "0"
menu_sync
--- /dev/null
+seta hud_skin "luminos_xhair"
+seta hud_panel_bg "0"
+seta hud_panel_bg_color "1 0.4375 0"
+seta hud_panel_bg_color_team "0"
+seta hud_panel_bg_alpha "1"
+seta hud_panel_bg_border "8"
+seta hud_panel_bg_padding "2"
+seta hud_panel_fg_alpha "1"
+
+seta hud_dock "0"
+seta hud_dock_color "0 0.449576 0.860796"
+seta hud_dock_color_team "0.700000"
+seta hud_dock_alpha "1"
+
+seta hud_progressbar_alpha "0.3"
+seta hud_progressbar_strength_color "0 0 0.6"
+seta hud_progressbar_shield_color "0.6 0 0.6"
+seta hud_progressbar_health_color "0.6 0 0"
+seta hud_progressbar_armor_color "0 0.6 0"
+seta hud_progressbar_fuel_color "0.6 0.6 0"
+seta hud_progressbar_nexball_color "0.7 0.1 0"
+seta hud_progressbar_speed_color "1 0.75 0"
+seta hud_progressbar_acceleration_color "0.5 0.75 1"
+seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
+
+seta _hud_panelorder "15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 "
+
+seta hud_configure_grid "1"
+seta hud_configure_grid_xsize "0.010000"
+seta hud_configure_grid_ysize "0.010000"
+
+seta hud_panel_weapons 1
+seta hud_panel_weapons_pos "0.350000 0.940000"
+seta hud_panel_weapons_size "0.300000 0.060000"
+seta hud_panel_weapons_bg ""
+seta hud_panel_weapons_bg_color ""
+seta hud_panel_weapons_bg_color_team ""
+seta hud_panel_weapons_bg_alpha ""
+seta hud_panel_weapons_bg_border ""
+seta hud_panel_weapons_bg_padding ""
+seta hud_panel_weapons_accuracy "1"
+seta hud_panel_weapons_label "1"
+seta hud_panel_weapons_complainbubble "1"
+seta hud_panel_weapons_complainbubble_padding "-10"
+seta hud_panel_weapons_complainbubble_time "1"
+seta hud_panel_weapons_complainbubble_fadetime "0.25"
+seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
+seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
+seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
+seta hud_panel_weapons_ammo "1"
+seta hud_panel_weapons_ammo_color "0 1 0"
+seta hud_panel_weapons_ammo_alpha "1"
+seta hud_panel_weapons_aspect "2"
+seta hud_panel_weapons_timeout "0"
+seta hud_panel_weapons_timeout_effect "0"
+seta hud_panel_weapons_onlyowned "1"
+
+seta hud_panel_ammo 1
+seta hud_panel_ammo_pos "0.450000 0.630000"
+seta hud_panel_ammo_size "0.080000 0.040000"
+seta hud_panel_ammo_bg ""
+seta hud_panel_ammo_bg_color ""
+seta hud_panel_ammo_bg_color_team ""
+seta hud_panel_ammo_bg_alpha ""
+seta hud_panel_ammo_bg_border ""
+seta hud_panel_ammo_bg_padding ""
+seta hud_panel_ammo_onlycurrent "1"
+seta hud_panel_ammo_iconalign "0"
+seta hud_panel_ammo_progressbar "1"
+seta hud_panel_ammo_progressbar_name "progressbar_ammo"
+seta hud_panel_ammo_progressbar_xoffset "0.32"
+seta hud_panel_ammo_text "1"
+
+seta hud_panel_powerups 1
+seta hud_panel_powerups_pos "0.270000 0.940000"
+seta hud_panel_powerups_size "0.080000 0.060000"
+seta hud_panel_powerups_bg "0"
+seta hud_panel_powerups_bg_color ""
+seta hud_panel_powerups_bg_color_team ""
+seta hud_panel_powerups_bg_alpha ""
+seta hud_panel_powerups_bg_border ""
+seta hud_panel_powerups_bg_padding "-3"
+seta hud_panel_powerups_flip "1"
+seta hud_panel_powerups_iconalign "1"
+seta hud_panel_powerups_baralign "1"
+seta hud_panel_powerups_progressbar "1"
+seta hud_panel_powerups_progressbar_strength "progressbar"
+seta hud_panel_powerups_progressbar_shield "progressbar"
+seta hud_panel_powerups_text "1"
+
+seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor_pos "0.350000 0.380000"
+seta hud_panel_healtharmor_size "0.070000 0.240000"
+seta hud_panel_healtharmor_bg "border_healtharmor"
+seta hud_panel_healtharmor_bg_color "0.464391 0.464391 0.464391"
+seta hud_panel_healtharmor_bg_color_team ""
+seta hud_panel_healtharmor_bg_alpha "0.600000"
+seta hud_panel_healtharmor_bg_border "-1"
+seta hud_panel_healtharmor_bg_padding "0"
+seta hud_panel_healtharmor_flip "0"
+seta hud_panel_healtharmor_iconalign "1"
+seta hud_panel_healtharmor_baralign "1"
+seta hud_panel_healtharmor_progressbar "1"
+seta hud_panel_healtharmor_progressbar_health "progressbar_health"
+seta hud_panel_healtharmor_progressbar_armor "progressbar_armor"
+seta hud_panel_healtharmor_progressbar_gfx "1"
+seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
+seta hud_panel_healtharmor_text "0"
+
+seta hud_panel_notify 1
+seta hud_panel_notify_pos "0 0"
+seta hud_panel_notify_size "0.210000 0.260000"
+seta hud_panel_notify_bg "0"
+seta hud_panel_notify_bg_color ""
+seta hud_panel_notify_bg_color_team ""
+seta hud_panel_notify_bg_alpha ""
+seta hud_panel_notify_bg_border ""
+seta hud_panel_notify_bg_padding ""
+seta hud_panel_notify_flip "1"
+seta hud_panel_notify_fontsize "0.8"
+seta hud_panel_notify_print "0"
+seta hud_panel_notify_time "10"
+seta hud_panel_notify_fadetime "3"
+
+seta hud_panel_timer 1
+seta hud_panel_timer_pos "0.435000 0"
+seta hud_panel_timer_size "0.135000 0.060000"
+seta hud_panel_timer_bg "0"
+seta hud_panel_timer_bg_color ""
+seta hud_panel_timer_bg_color_team ""
+seta hud_panel_timer_bg_alpha ""
+seta hud_panel_timer_bg_border ""
+seta hud_panel_timer_bg_padding "0"
+seta hud_panel_timer_increment "0"
+
+seta hud_panel_radar 2
+seta hud_panel_radar_pos "0.810000 0"
+seta hud_panel_radar_size "0.190000 0.250000"
+seta hud_panel_radar_bg "border_radar"
+seta hud_panel_radar_bg_color ""
+seta hud_panel_radar_bg_color_team ""
+seta hud_panel_radar_bg_alpha "0.500000"
+seta hud_panel_radar_bg_border "0"
+seta hud_panel_radar_bg_padding "0"
+seta hud_panel_radar_foreground_alpha "0.500000"
+seta hud_panel_radar_rotation "0"
+seta hud_panel_radar_zoommode "0"
+seta hud_panel_radar_scale "4096"
+seta hud_panel_radar_maximized_scale "8192"
+seta hud_panel_radar_maximized_size "0.5 0.5"
+
+seta hud_panel_score 1
+seta hud_panel_score_pos "0.465000 0.045000"
+seta hud_panel_score_size "0.090000 0.060000"
+seta hud_panel_score_bg ""
+seta hud_panel_score_bg_color ""
+seta hud_panel_score_bg_color_team ""
+seta hud_panel_score_bg_alpha ""
+seta hud_panel_score_bg_border ""
+seta hud_panel_score_bg_padding ""
+seta hud_panel_score_rankings "1"
+
+seta hud_panel_racetimer 1
+seta hud_panel_racetimer_pos "0.360000 0.090000"
+seta hud_panel_racetimer_size "0.280000 0.090000"
+seta hud_panel_racetimer_bg "0"
+seta hud_panel_racetimer_bg_color ""
+seta hud_panel_racetimer_bg_color_team ""
+seta hud_panel_racetimer_bg_alpha ""
+seta hud_panel_racetimer_bg_border ""
+seta hud_panel_racetimer_bg_padding ""
+
+seta hud_panel_vote 1
+seta hud_panel_vote_pos "0 0.890000"
+seta hud_panel_vote_size "0.170000 0.110000"
+seta hud_panel_vote_bg ""
+seta hud_panel_vote_bg_color ""
+seta hud_panel_vote_bg_color_team ""
+seta hud_panel_vote_bg_alpha ""
+seta hud_panel_vote_bg_border ""
+seta hud_panel_vote_bg_padding ""
+seta hud_panel_vote_alreadyvoted_alpha "0.800000"
+
+seta hud_panel_modicons 1
+seta hud_panel_modicons_pos "0.560000 0"
+seta hud_panel_modicons_size "0.050000 0.100000"
+seta hud_panel_modicons_bg ""
+seta hud_panel_modicons_bg_color ""
+seta hud_panel_modicons_bg_color_team ""
+seta hud_panel_modicons_bg_alpha ""
+seta hud_panel_modicons_bg_border ""
+seta hud_panel_modicons_bg_padding ""
+seta hud_panel_modicons_dom_layout "1"
+
+seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys_pos "0.450000 0.690000"
+seta hud_panel_pressedkeys_size "0.100000 0.110000"
+seta hud_panel_pressedkeys_bg "0"
+seta hud_panel_pressedkeys_bg_color ""
+seta hud_panel_pressedkeys_bg_color_team ""
+seta hud_panel_pressedkeys_bg_alpha ""
+seta hud_panel_pressedkeys_bg_border ""
+seta hud_panel_pressedkeys_bg_padding ""
+seta hud_panel_pressedkeys_aspect "1.600000"
+
+seta hud_panel_chat 1
+seta hud_panel_chat_pos "0 0.775000"
+seta hud_panel_chat_size "0.460000 0.110000"
+seta hud_panel_chat_bg "0"
+seta hud_panel_chat_bg_color ""
+seta hud_panel_chat_bg_color_team ""
+seta hud_panel_chat_bg_alpha ""
+seta hud_panel_chat_bg_border ""
+seta hud_panel_chat_bg_padding ""
+
+seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo_pos "0.910000 0.970000"
+seta hud_panel_engineinfo_size "0.090000 0.030000"
+seta hud_panel_engineinfo_bg "0"
+seta hud_panel_engineinfo_bg_color ""
+seta hud_panel_engineinfo_bg_color_team ""
+seta hud_panel_engineinfo_bg_alpha ""
+seta hud_panel_engineinfo_bg_border ""
+seta hud_panel_engineinfo_bg_padding ""
+seta hud_panel_engineinfo_framecounter_time "0.1"
+seta hud_panel_engineinfo_framecounter_decimals "0"
+
+seta hud_panel_infomessages 1
+seta hud_panel_infomessages_pos "0.710000 0"
+seta hud_panel_infomessages_size "0.290000 0.100000"
+seta hud_panel_infomessages_bg "0"
+seta hud_panel_infomessages_bg_color ""
+seta hud_panel_infomessages_bg_color_team ""
+seta hud_panel_infomessages_bg_alpha ""
+seta hud_panel_infomessages_bg_border ""
+seta hud_panel_infomessages_bg_padding "0"
+seta hud_panel_infomessages_flip "1"
+
+seta hud_panel_physics 3
+seta hud_panel_physics_pos "0.270000 0.730000"
+seta hud_panel_physics_size "0.170000 0.030000"
+seta hud_panel_physics_bg ""
+seta hud_panel_physics_bg_color ""
+seta hud_panel_physics_bg_color_team ""
+seta hud_panel_physics_bg_alpha ""
+seta hud_panel_physics_bg_border ""
+seta hud_panel_physics_bg_padding ""
+seta hud_panel_physics_speed_unit "3"
+seta hud_panel_physics_speed_unit_show "1"
+seta hud_panel_physics_speed_max "1800"
+seta hud_panel_physics_speed_vertical "0"
+seta hud_panel_physics_topspeed "1"
+seta hud_panel_physics_topspeed_time "4"
+seta hud_panel_physics_acceleration_max "1.5"
+seta hud_panel_physics_acceleration_vertical "0"
+seta hud_panel_physics_flip "0"
+seta hud_panel_physics_baralign "0"
+seta hud_panel_physics_progressbar "3"
+seta hud_panel_physics_acceleration_mode "0"
+seta hud_panel_physics_text "1"
+
+seta hud_panel_centerprint 1
+seta hud_panel_centerprint_pos "0.175000 0.220000"
+seta hud_panel_centerprint_size "0.650000 0.220000"
+seta hud_panel_centerprint_bg "0"
+seta hud_panel_centerprint_bg_color ""
+seta hud_panel_centerprint_bg_color_team ""
+seta hud_panel_centerprint_bg_alpha ""
+seta hud_panel_centerprint_bg_border ""
+seta hud_panel_centerprint_bg_padding ""
+seta hud_panel_centerprint_align "0.5"
+seta hud_panel_centerprint_flip "0"
+seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_time "3"
+seta hud_panel_centerprint_fade_in "0.2"
+seta hud_panel_centerprint_fade_out "0.5"
+seta hud_panel_centerprint_fade_subsequent "1"
+seta hud_panel_centerprint_fade_subsequent_passone "3"
+seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_passtwo "10"
+seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
+seta hud_panel_centerprint_fade_minfontsize "0"
+
+menu_sync
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
seta hud_progressbar_nexball_color "0.7 0.1 0"
-seta hud_progressbar_speed_color "1 0.75 0"
-seta hud_progressbar_acceleration_color "0.5 0.75 1"
-seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
+seta hud_progressbar_speed_color "1 0.75 0"
+seta hud_progressbar_acceleration_color "0.5 0.75 1"
+seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
seta _hud_panelorder "15 10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 16 "
seta hud_panel_weapons_bg_alpha ""
seta hud_panel_weapons_bg_border ""
seta hud_panel_weapons_bg_padding ""
+seta hud_panel_weapons_accuracy "1"
+seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
seta hud_panel_weapons_complainbubble_padding "-10"
+seta hud_panel_weapons_complainbubble_time "1"
+seta hud_panel_weapons_complainbubble_fadetime "0.25"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
+seta hud_panel_weapons_ammo "1"
seta hud_panel_weapons_ammo_color "0 1 0"
seta hud_panel_weapons_ammo_alpha "1"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "3"
seta hud_panel_weapons_timeout_effect "1"
+seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_ammo_pos "0.190000 0.920000"
seta hud_panel_ammo_onlycurrent "0"
seta hud_panel_ammo_iconalign "0"
seta hud_panel_ammo_progressbar "0"
-seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_progressbar_name "progressbar"
+seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
seta hud_panel_powerups 1
seta hud_panel_healtharmor_progressbar "1"
seta hud_panel_healtharmor_progressbar_health "progressbar"
seta hud_panel_healtharmor_progressbar_armor "progressbar"
+seta hud_panel_healtharmor_progressbar_gfx "1"
+seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
seta hud_panel_notify 1
seta hud_panel_notify_flip "0"
seta hud_panel_notify_fontsize "0.8"
seta hud_panel_notify_print "1"
+seta hud_panel_notify_time "10"
+seta hud_panel_notify_fadetime "3"
seta hud_panel_timer 1
seta hud_panel_timer_pos "0.870000 0"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
+seta hud_panel_timer_increment "0"
-seta hud_panel_radar 2 // enabled for keepaway and to make the HUD consistent throughout game modes
+seta hud_panel_radar 2
seta hud_panel_radar_pos "0.030000 0.020000"
seta hud_panel_radar_size "0.170000 0.220000"
seta hud_panel_radar_bg ""
seta hud_panel_radar_bg_border ""
seta hud_panel_radar_bg_padding "-3"
seta hud_panel_radar_foreground_alpha "0.800000"
+seta hud_panel_radar_rotation "0"
+seta hud_panel_radar_zoommode "0"
+seta hud_panel_radar_scale "4096"
+seta hud_panel_radar_maximized_scale "8192"
+seta hud_panel_radar_maximized_size "0.5 0.5"
seta hud_panel_score 1
seta hud_panel_score_pos "0.020000 0.920000"
seta hud_panel_score_bg_alpha ""
seta hud_panel_score_bg_border ""
seta hud_panel_score_bg_padding ""
+seta hud_panel_score_rankings "1"
seta hud_panel_racetimer 1
seta hud_panel_racetimer_pos "0.360000 0.090000"
seta hud_panel_modicons_bg_alpha ""
seta hud_panel_modicons_bg_border ""
seta hud_panel_modicons_bg_padding ""
+seta hud_panel_modicons_dom_layout "1"
seta hud_panel_pressedkeys 1
seta hud_panel_pressedkeys_pos "0.410000 0.710000"
seta hud_panel_engineinfo_bg_alpha ""
seta hud_panel_engineinfo_bg_border ""
seta hud_panel_engineinfo_bg_padding ""
+seta hud_panel_engineinfo_framecounter_time "0.1"
+seta hud_panel_engineinfo_framecounter_decimals "0"
seta hud_panel_infomessages 1
seta hud_panel_infomessages_pos "0.510000 0"
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
+seta hud_panel_physics_speed_unit "3"
+seta hud_panel_physics_speed_unit_show "1"
+seta hud_panel_physics_speed_max "1800"
+seta hud_panel_physics_speed_vertical "0"
+seta hud_panel_physics_topspeed "1"
+seta hud_panel_physics_topspeed_time "4"
+seta hud_panel_physics_acceleration_max "1.5"
+seta hud_panel_physics_acceleration_vertical "0"
seta hud_panel_physics_flip "0"
seta hud_panel_physics_baralign "0"
-seta hud_panel_physics_acceleration_progressbar_mode "0"
seta hud_panel_physics_progressbar "1"
+seta hud_panel_physics_acceleration_mode "0"
seta hud_panel_physics_text "1"
seta hud_panel_centerprint 1
-seta hud_panel_centerprint_pos "0.175000 0.260000"
-seta hud_panel_centerprint_size "0.650000 0.210000"
+seta hud_panel_centerprint_pos "0.175000 0.220000"
+seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_bg_color ""
seta hud_panel_centerprint_bg_color_team ""
seta hud_panel_centerprint_bg_border ""
seta hud_panel_centerprint_bg_padding ""
seta hud_panel_centerprint_align "0.5"
-seta hud_panel_centerprint_flip "1"
+seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
seta hud_panel_centerprint_time "3"
-seta hud_panel_centerprint_fadetime "0.25"
+seta hud_panel_centerprint_fade_in "0.2"
+seta hud_panel_centerprint_fade_out "0.5"
+seta hud_panel_centerprint_fade_subsequent "1"
+seta hud_panel_centerprint_fade_subsequent_passone "3"
+seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_passtwo "10"
+seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
+seta hud_panel_centerprint_fade_minfontsize "0"
menu_sync
+++ /dev/null
-seta hud_skin "luminos_xhair"
-seta hud_panel_bg "0"
-seta hud_panel_bg_color "1 0.4375 0"
-seta hud_panel_bg_color_team "0"
-seta hud_panel_bg_alpha "1"
-seta hud_panel_bg_border "8"
-seta hud_panel_bg_padding "2"
-seta hud_panel_fg_alpha "1"
-
-seta hud_dock "0"
-seta hud_dock_color "0 0.449576 0.860796"
-seta hud_dock_color_team "0.700000"
-seta hud_dock_alpha "1"
-
-seta hud_progressbar_alpha "0.3"
-seta hud_progressbar_strength_color "0 0 0.6"
-seta hud_progressbar_shield_color "0.6 0 0.6"
-seta hud_progressbar_health_color "0.6 0 0"
-seta hud_progressbar_armor_color "0 0.6 0"
-seta hud_progressbar_fuel_color "0.6 0.6 0"
-seta hud_progressbar_nexball_color "0.7 0.1 0"
-seta hud_progressbar_speed_color "1 0.75 0"
-seta hud_progressbar_acceleration_color "0.5 0.75 1"
-seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
-
-seta _hud_panelorder "15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 "
-
-seta hud_configure_grid "1"
-seta hud_configure_grid_xsize "0.010000"
-seta hud_configure_grid_ysize "0.010000"
-
-seta hud_panel_weapons 1
-seta hud_panel_weapons_pos "0.350000 0.940000"
-seta hud_panel_weapons_size "0.300000 0.060000"
-seta hud_panel_weapons_bg ""
-seta hud_panel_weapons_bg_color ""
-seta hud_panel_weapons_bg_color_team ""
-seta hud_panel_weapons_bg_alpha ""
-seta hud_panel_weapons_bg_border ""
-seta hud_panel_weapons_bg_padding ""
-seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "-10"
-seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
-seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
-seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
-seta hud_panel_weapons_ammo_color "0 1 0"
-seta hud_panel_weapons_ammo_alpha "1"
-seta hud_panel_weapons_aspect "2"
-seta hud_panel_weapons_timeout "0"
-seta hud_panel_weapons_timeout_effect "0"
-
-seta hud_panel_ammo 1
-seta hud_panel_ammo_pos "0.450000 0.630000"
-seta hud_panel_ammo_size "0.080000 0.040000"
-seta hud_panel_ammo_bg ""
-seta hud_panel_ammo_bg_color ""
-seta hud_panel_ammo_bg_color_team ""
-seta hud_panel_ammo_bg_alpha ""
-seta hud_panel_ammo_bg_border ""
-seta hud_panel_ammo_bg_padding ""
-seta hud_panel_ammo_onlycurrent "1"
-seta hud_panel_ammo_iconalign "0"
-seta hud_panel_ammo_progressbar "1"
-seta hud_panel_ammo_progressbar_name "progressbar_ammo"
-seta hud_panel_ammo_progressbar_xoffset "0.32"
-seta hud_panel_ammo_text "1"
-
-seta hud_panel_powerups 1
-seta hud_panel_powerups_pos "0.270000 0.940000"
-seta hud_panel_powerups_size "0.080000 0.060000"
-seta hud_panel_powerups_bg "0"
-seta hud_panel_powerups_bg_color ""
-seta hud_panel_powerups_bg_color_team ""
-seta hud_panel_powerups_bg_alpha ""
-seta hud_panel_powerups_bg_border ""
-seta hud_panel_powerups_bg_padding "-3"
-seta hud_panel_powerups_flip "1"
-seta hud_panel_powerups_iconalign "1"
-seta hud_panel_powerups_baralign "1"
-seta hud_panel_powerups_progressbar "1"
-seta hud_panel_powerups_progressbar_strength "progressbar"
-seta hud_panel_powerups_progressbar_shield "progressbar"
-seta hud_panel_powerups_text "0"
-
-seta hud_panel_healtharmor 1
-seta hud_panel_healtharmor_pos "0.350000 0.380000"
-seta hud_panel_healtharmor_size "0.070000 0.240000"
-seta hud_panel_healtharmor_bg "border_healtharmor"
-seta hud_panel_healtharmor_bg_color "0.464391 0.464391 0.464391"
-seta hud_panel_healtharmor_bg_color_team ""
-seta hud_panel_healtharmor_bg_alpha "0.600000"
-seta hud_panel_healtharmor_bg_border "-1"
-seta hud_panel_healtharmor_bg_padding "0"
-seta hud_panel_healtharmor_flip "0"
-seta hud_panel_healtharmor_iconalign "1"
-seta hud_panel_healtharmor_baralign "1"
-seta hud_panel_healtharmor_progressbar "1"
-seta hud_panel_healtharmor_progressbar_health "progressbar_health"
-seta hud_panel_healtharmor_progressbar_armor "progressbar_armor"
-seta hud_panel_healtharmor_text "0"
-
-seta hud_panel_notify 1
-seta hud_panel_notify_pos "0 0"
-seta hud_panel_notify_size "0.210000 0.260000"
-seta hud_panel_notify_bg "0"
-seta hud_panel_notify_bg_color ""
-seta hud_panel_notify_bg_color_team ""
-seta hud_panel_notify_bg_alpha ""
-seta hud_panel_notify_bg_border ""
-seta hud_panel_notify_bg_padding ""
-seta hud_panel_notify_flip "1"
-seta hud_panel_notify_fontsize "0.8"
-seta hud_panel_notify_print "0"
-
-seta hud_panel_timer 1
-seta hud_panel_timer_pos "0.435000 0"
-seta hud_panel_timer_size "0.135000 0.060000"
-seta hud_panel_timer_bg "0"
-seta hud_panel_timer_bg_color ""
-seta hud_panel_timer_bg_color_team ""
-seta hud_panel_timer_bg_alpha ""
-seta hud_panel_timer_bg_border ""
-seta hud_panel_timer_bg_padding "0"
-
-seta hud_panel_radar 2
-seta hud_panel_radar_pos "0.810000 0"
-seta hud_panel_radar_size "0.190000 0.250000"
-seta hud_panel_radar_bg "border_radar"
-seta hud_panel_radar_bg_color ""
-seta hud_panel_radar_bg_color_team ""
-seta hud_panel_radar_bg_alpha "0.500000"
-seta hud_panel_radar_bg_border "0"
-seta hud_panel_radar_bg_padding "0"
-seta hud_panel_radar_foreground_alpha "0.500000"
-
-seta hud_panel_score 1
-seta hud_panel_score_pos "0.465000 0.045000"
-seta hud_panel_score_size "0.090000 0.060000"
-seta hud_panel_score_bg ""
-seta hud_panel_score_bg_color ""
-seta hud_panel_score_bg_color_team ""
-seta hud_panel_score_bg_alpha ""
-seta hud_panel_score_bg_border ""
-seta hud_panel_score_bg_padding ""
-
-seta hud_panel_racetimer 1
-seta hud_panel_racetimer_pos "0.360000 0.090000"
-seta hud_panel_racetimer_size "0.280000 0.090000"
-seta hud_panel_racetimer_bg "0"
-seta hud_panel_racetimer_bg_color ""
-seta hud_panel_racetimer_bg_color_team ""
-seta hud_panel_racetimer_bg_alpha ""
-seta hud_panel_racetimer_bg_border ""
-seta hud_panel_racetimer_bg_padding ""
-
-seta hud_panel_vote 1
-seta hud_panel_vote_pos "0 0.890000"
-seta hud_panel_vote_size "0.170000 0.110000"
-seta hud_panel_vote_bg ""
-seta hud_panel_vote_bg_color ""
-seta hud_panel_vote_bg_color_team ""
-seta hud_panel_vote_bg_alpha ""
-seta hud_panel_vote_bg_border ""
-seta hud_panel_vote_bg_padding ""
-seta hud_panel_vote_alreadyvoted_alpha "0.800000"
-
-seta hud_panel_modicons 1
-seta hud_panel_modicons_pos "0.560000 0"
-seta hud_panel_modicons_size "0.050000 0.100000"
-seta hud_panel_modicons_bg ""
-seta hud_panel_modicons_bg_color ""
-seta hud_panel_modicons_bg_color_team ""
-seta hud_panel_modicons_bg_alpha ""
-seta hud_panel_modicons_bg_border ""
-seta hud_panel_modicons_bg_padding ""
-
-seta hud_panel_pressedkeys 1
-seta hud_panel_pressedkeys_pos "0.450000 0.690000"
-seta hud_panel_pressedkeys_size "0.100000 0.110000"
-seta hud_panel_pressedkeys_bg "0"
-seta hud_panel_pressedkeys_bg_color ""
-seta hud_panel_pressedkeys_bg_color_team ""
-seta hud_panel_pressedkeys_bg_alpha ""
-seta hud_panel_pressedkeys_bg_border ""
-seta hud_panel_pressedkeys_bg_padding ""
-seta hud_panel_pressedkeys_aspect "1.600000"
-
-seta hud_panel_chat 1
-seta hud_panel_chat_pos "0 0.775000"
-seta hud_panel_chat_size "0.460000 0.110000"
-seta hud_panel_chat_bg "0"
-seta hud_panel_chat_bg_color ""
-seta hud_panel_chat_bg_color_team ""
-seta hud_panel_chat_bg_alpha ""
-seta hud_panel_chat_bg_border ""
-seta hud_panel_chat_bg_padding ""
-
-seta hud_panel_engineinfo 0
-seta hud_panel_engineinfo_pos "0.910000 0.970000"
-seta hud_panel_engineinfo_size "0.090000 0.030000"
-seta hud_panel_engineinfo_bg "0"
-seta hud_panel_engineinfo_bg_color ""
-seta hud_panel_engineinfo_bg_color_team ""
-seta hud_panel_engineinfo_bg_alpha ""
-seta hud_panel_engineinfo_bg_border ""
-seta hud_panel_engineinfo_bg_padding ""
-
-seta hud_panel_infomessages 1
-seta hud_panel_infomessages_pos "0.710000 0"
-seta hud_panel_infomessages_size "0.290000 0.100000"
-seta hud_panel_infomessages_bg "0"
-seta hud_panel_infomessages_bg_color ""
-seta hud_panel_infomessages_bg_color_team ""
-seta hud_panel_infomessages_bg_alpha ""
-seta hud_panel_infomessages_bg_border ""
-seta hud_panel_infomessages_bg_padding "0"
-seta hud_panel_infomessages_flip "1"
-
-seta hud_panel_physics 3
-seta hud_panel_physics_pos "0.270000 0.730000"
-seta hud_panel_physics_size "0.170000 0.030000"
-seta hud_panel_physics_bg ""
-seta hud_panel_physics_bg_color ""
-seta hud_panel_physics_bg_color_team ""
-seta hud_panel_physics_bg_alpha ""
-seta hud_panel_physics_bg_border ""
-seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_flip "0"
-seta hud_panel_physics_baralign "0"
-seta hud_panel_physics_acceleration_progressbar_mode "0"
-seta hud_panel_physics_progressbar "3"
-seta hud_panel_physics_text "2"
-
-seta hud_panel_centerprint 1
-seta hud_panel_centerprint_pos "0.175000 0.260000"
-seta hud_panel_centerprint_size "0.650000 0.210000"
-seta hud_panel_centerprint_bg "0"
-seta hud_panel_centerprint_bg_color ""
-seta hud_panel_centerprint_bg_color_team ""
-seta hud_panel_centerprint_bg_alpha ""
-seta hud_panel_centerprint_bg_border ""
-seta hud_panel_centerprint_bg_padding ""
-seta hud_panel_centerprint_align "0.5"
-seta hud_panel_centerprint_flip "1"
-seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_time "3"
-seta hud_panel_centerprint_fadetime "0.25"
-
-menu_sync
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
seta hud_progressbar_nexball_color "0.7 0.1 0"
-seta hud_progressbar_speed_color "0.25 0.25 1"
-seta hud_progressbar_acceleration_color "0.25 1 0.25"
-seta hud_progressbar_acceleration_neg_color "1 0.25 0.25"
+seta hud_progressbar_speed_color "1 0.75 0"
+seta hud_progressbar_acceleration_color "0.5 0.75 1"
+seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
seta _hud_panelorder "15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 "
seta hud_configure_grid_ysize "0.01"
seta hud_panel_weapons 1
-seta hud_panel_weapons_pos "0.370000 0.870000"
-seta hud_panel_weapons_size "0.340000 0.060000"
+seta hud_panel_weapons_pos "0.375000 0.870000"
+seta hud_panel_weapons_size "0.300000 0.060000"
seta hud_panel_weapons_bg "0"
seta hud_panel_weapons_bg_color ""
seta hud_panel_weapons_bg_color_team ""
seta hud_panel_weapons_bg_alpha ""
seta hud_panel_weapons_bg_border ""
seta hud_panel_weapons_bg_padding "-5"
+seta hud_panel_weapons_accuracy "1"
+seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
seta hud_panel_weapons_complainbubble_padding "-10"
+seta hud_panel_weapons_complainbubble_time "1"
+seta hud_panel_weapons_complainbubble_fadetime "0.25"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
+seta hud_panel_weapons_ammo "1"
seta hud_panel_weapons_ammo_color "0 1 0"
seta hud_panel_weapons_ammo_alpha "1"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "0"
seta hud_panel_weapons_timeout_effect "0"
+seta hud_panel_weapons_onlyowned "0"
seta hud_panel_ammo 1
seta hud_panel_ammo_pos "0.160000 0.910000"
seta hud_panel_ammo_onlycurrent "0"
seta hud_panel_ammo_iconalign "0"
seta hud_panel_ammo_progressbar "0"
-seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_progressbar_name "progressbar"
+seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
seta hud_panel_powerups 1
seta hud_panel_healtharmor_progressbar "0"
seta hud_panel_healtharmor_progressbar_health "progressbar"
seta hud_panel_healtharmor_progressbar_armor "progressbar"
+seta hud_panel_healtharmor_progressbar_gfx "1"
+seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
seta hud_panel_notify 0
seta hud_panel_notify_flip "0"
seta hud_panel_notify_fontsize "1"
seta hud_panel_notify_print "1"
+seta hud_panel_notify_time "10"
+seta hud_panel_notify_fadetime "3"
seta hud_panel_timer 1
seta hud_panel_timer_pos "0.850000 0"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
+seta hud_panel_timer_increment "0"
seta hud_panel_radar 2
-seta hud_panel_radar_pos "0.800000 0"
+seta hud_panel_radar_pos "0 0"
seta hud_panel_radar_size "0.200000 0.260000"
seta hud_panel_radar_bg "border_radar"
seta hud_panel_radar_bg_color ""
seta hud_panel_radar_bg_border "0"
seta hud_panel_radar_bg_padding "0"
seta hud_panel_radar_foreground_alpha "1"
+seta hud_panel_radar_rotation "0"
+seta hud_panel_radar_zoommode "0"
+seta hud_panel_radar_scale "4096"
+seta hud_panel_radar_maximized_scale "8192"
+seta hud_panel_radar_maximized_size "0.5 0.5"
seta hud_panel_score 1
seta hud_panel_score_pos "0.760000 0.910000"
-seta hud_panel_score_size "0.240000 0.090000"
+seta hud_panel_score_size "0.200000 0.080000"
seta hud_panel_score_bg "0"
seta hud_panel_score_bg_color ""
seta hud_panel_score_bg_color_team ""
seta hud_panel_score_bg_alpha ""
seta hud_panel_score_bg_border ""
seta hud_panel_score_bg_padding ""
+seta hud_panel_score_rankings "0"
seta hud_panel_racetimer 1
seta hud_panel_racetimer_pos "0.360000 0.140000"
seta hud_panel_modicons_bg_alpha ""
seta hud_panel_modicons_bg_border ""
seta hud_panel_modicons_bg_padding ""
+seta hud_panel_modicons_dom_layout "1"
seta hud_panel_pressedkeys 1
seta hud_panel_pressedkeys_pos "0.440000 0.760000"
seta hud_panel_engineinfo_bg_alpha ""
seta hud_panel_engineinfo_bg_border ""
seta hud_panel_engineinfo_bg_padding ""
+seta hud_panel_engineinfo_framecounter_time "0.1"
+seta hud_panel_engineinfo_framecounter_decimals "0"
seta hud_panel_infomessages 1
seta hud_panel_infomessages_pos "0.700000 0.620000"
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
+seta hud_panel_physics_speed_unit "3"
+seta hud_panel_physics_speed_unit_show "1"
+seta hud_panel_physics_speed_max "1800"
+seta hud_panel_physics_speed_vertical "0"
+seta hud_panel_physics_topspeed "1"
+seta hud_panel_physics_topspeed_time "4"
+seta hud_panel_physics_acceleration_max "1.5"
+seta hud_panel_physics_acceleration_vertical "0"
seta hud_panel_physics_flip "0"
seta hud_panel_physics_baralign "0"
-seta hud_panel_physics_acceleration_progressbar_mode "0"
seta hud_panel_physics_progressbar "3"
-seta hud_panel_physics_text "2"
+seta hud_panel_physics_acceleration_mode "0"
+seta hud_panel_physics_text "1"
seta hud_panel_centerprint 1
seta hud_panel_centerprint_pos "0.175000 0.260000"
-seta hud_panel_centerprint_size "0.650000 0.210000"
+seta hud_panel_centerprint_size "0.650000 0.200000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_bg_color ""
seta hud_panel_centerprint_bg_color_team ""
seta hud_panel_centerprint_bg_border ""
seta hud_panel_centerprint_bg_padding ""
seta hud_panel_centerprint_align "0.5"
-seta hud_panel_centerprint_flip "1"
+seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
seta hud_panel_centerprint_time "3"
-seta hud_panel_centerprint_fadetime "0.25"
+seta hud_panel_centerprint_fade_in "0.2"
+seta hud_panel_centerprint_fade_out "0.5"
+seta hud_panel_centerprint_fade_subsequent "1"
+seta hud_panel_centerprint_fade_subsequent_passone "3"
+seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_passtwo "10"
+seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5"
+seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
+seta hud_panel_centerprint_fade_minfontsize "0"
menu_sync
"togglezoom" "toggle zoom"
"+showscores" "show scores"
"screenshot" "screen shot"
+"+hud_panel_radar_maximized" "maximize radar"
"" ""
"" "Communicate"
"messagemode" "public chat"
cvar_set(e.netname, e.message);
}
-void() menu_show_error =
+void menu_show_error()
{
drawstring('0 200 0', _("ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!"), '8 8 0', '1 0 0', 1, 0);
-};
+}
// CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
// Useful for precaching things
-void() menu_sub_null =
+void menu_sub_null()
{
-};
+}
#ifdef USE_FTE
float __engine_check;
break;
maxclients = i;
- //ctf_temp_1 = "";
- // localcmd("alias order \"cmd order $*\""); enable if ctf-command thingy is used
- //registercmd("ctf_menu");
- registercmd("ons_map");
registercmd("hud_configure");
registercmd("hud_save");
//registercmd("menu_action");
cl_announcer_prev = strzone(autocvar_cl_announcer);
}
Tuba_Precache();
-
- if(autocvar_cl_reticle_item_normal) precache_pic("gfx/reticle_normal");
- if(autocvar_cl_reticle_item_nex) precache_pic("gfx/reticle_nex");
-
+
+ if(autocvar_cl_reticle)
+ {
+ if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); }
+ if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); }
+ }
+
get_mi_min_max_texcoords(1); // try the CLEVER way first
minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
shortmapname = mi_shortname;
{
float argc;
// Tokenize String
- //argc = tokenize(strMessage);
argc = tokenize_console(strMessage);
// Acquire Command
- local string strCmd;
+ string strCmd;
strCmd = argv(0);
if(strCmd == "hud_configure") { // config hud
if(cmd == "mv_download") {
Cmd_MapVote_MapDownload(argc);
}
+ else if(cmd == "hud_panel_radar_maximized")
+ {
+ if(argc == 1)
+ hud_panel_radar_maximized = !hud_panel_radar_maximized;
+ else
+ hud_panel_radar_maximized = (stof(argv(1)) != 0);
+ }
else if(cmd == "settemp") {
cvar_clientsettemp(argv(1), argv(2));
}
{
vote_active = 0; // force the panel to disappear right as we have selected the value (to prevent it from fading out in the normal vote panel pos)
vote_prev = 0;
- cvar_set("cl_allow_uid2name", "1");
+ localcmd("setreport cl_allow_uid2name 1\n");
vote_change = -9999;
uid2name_dialog = 0;
}
{
vote_active = 0;
vote_prev = 0;
- cvar_set("cl_allow_uid2name", "0");
+ localcmd("setreport cl_allow_uid2name 0\n");
vote_change = -9999;
uid2name_dialog = 0;
}
// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
{
- local float bSkipKey;
+ float bSkipKey;
bSkipKey = false;
if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
void Ent_RadarLink();
void Ent_Init();
void Ent_ScoresInfo();
-void(float bIsNewEntity) CSQC_Ent_Update =
+void CSQC_Ent_Update(float bIsNewEntity)
{
float t;
float savetime;
#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
if(self.enttype)
- if(t != self.enttype)
+ {
+ if(t != self.enttype || bIsNewEntity)
{
//print(_("A CSQC entity changed its type!\n"));
- print(sprintf(_("A CSQC entity changed its type! (edict: %d, classname: %s)\n"), num_for_edict(self), self.classname));
+ print(sprintf(_("A CSQC entity changed its type! (edict: %d, type: %d -> %d)\n"), num_for_edict(self), self.enttype, t));
Ent_Remove();
bIsNewEntity = 1;
}
+ }
+ else
+ {
+ if(!bIsNewEntity)
+ {
+ print(sprintf(_("A CSQC entity appeared out of nowhere! (edict: %d, type: %d)\n"), num_for_edict(self), t));
+ bIsNewEntity = 1;
+ }
+ }
#endif
self.enttype = t;
switch(t)
}
time = savetime;
-};
+}
// Destructor, but does NOT deallocate the entity by calling remove(). Also
// used when an entity changes its type. For an entity that someone interacts
// with others, make sure it can no longer do so.
// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
float CSQC_Parse_TempEntity()
{
- local float bHandled;
+ float bHandled;
bHandled = true;
// Acquire TE ID
- local float nTEID;
+ float nTEID;
nTEID = ReadByte();
// NOTE: Could just do return instead of break...
float avgspeed;
vector GetCurrentFov(float fov)
{
- float zoomsensitivity, zoomspeed, zoomfactor, zoomdir, velocityzoom;
+ float zoomsensitivity, zoomspeed, zoomfactor, zoomdir;
+ float velocityzoom, curspeed;
zoomsensitivity = autocvar_cl_zoomsensitivity;
zoomfactor = autocvar_cl_zoomfactor;
setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
else
setsensitivityscale(1);
+
+ makevectors(view_angles);
- if (autocvar_cl_velocityzoom)
+ if(autocvar_cl_velocityzoom)
{
- velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoomtime), 1);
- avgspeed = avgspeed * (1 - velocityzoom) + (vlen(pmove_vel) / 1000) * velocityzoom;
+ switch(autocvar_cl_velocityzoom_type)
+ {
+ case 3: curspeed = max(0, v_forward * pmove_vel); break;
+ case 2: curspeed = (v_forward * pmove_vel); break;
+ case 1: default: curspeed = vlen(pmove_vel); break;
+ }
+
+ velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoom_time), 1); // speed at which the zoom adapts to player velocity
+ avgspeed = avgspeed * (1 - velocityzoom) + (curspeed / autocvar_cl_velocityzoom_speed) * velocityzoom;
velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom / 1) * 1);
- //print(ftos(avgspeed), " avgspeed, ", ftos(autocvar_cl_velocityzoom), " cvar, ", ftos(velocityzoom), " return\n"); // for debugging
+
+ //print(ftos(avgspeed), " avgspeed, ", ftos(curspeed), " curspeed, ", ftos(velocityzoom), " return\n"); // for debugging
}
else
velocityzoom = 1;
else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_RIFLE && button_attack2)
reticle_type = 2; // nex zoom
- if (reticle_type)
+ if(reticle_type && autocvar_cl_reticle)
{
if(autocvar_cl_reticle_stretch)
{
}
}
- if(autocvar_hud_damage && !autocvar_chase_active)
+ if(autocvar_hud_damage)
{
splash_size_x = max(vid_conwidth, vid_conheight);
splash_size_y = max(vid_conwidth, vid_conheight);
myhealth_prev = myhealth;
- if(autocvar_cl_gentle_damage || autocvar_cl_gentle)
+ // IDEA: change damage color/picture based on player model for robot/alien species?
+ // pro: matches model better
+ // contra: it's not red because blood is red, but because red is an alarming color, so red should stay
+ // maybe different reddish pics?
+ if(autocvar_chase_active >= 0) // not while the event chase camera is active
{
- if(autocvar_cl_gentle_damage == 2)
+ if(autocvar_cl_gentle_damage || autocvar_cl_gentle)
{
- if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
+ if(autocvar_cl_gentle_damage == 2)
{
- myhealth_gentlergb = eX * random() + eY * random() + eZ * random();
+ if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
+ {
+ myhealth_gentlergb = eX * random() + eY * random() + eZ * random();
+ }
}
+ else
+ myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
+
+ drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
}
else
- myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
-
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
+ drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
}
- else
- drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
- if(autocvar_hud_postprocessing)
+ if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on.
{
if(autocvar_hud_damage_blur && myhealth_flash_temp)
{
wcross_color = stov(cvar_string(strcat("crosshair_", wcross_wep, "_color")));
else if(autocvar_crosshair_color_by_health)
{
- local float x = getstati(STAT_HEALTH);
+ float x = getstati(STAT_HEALTH);
//x = red
//y = green
if(acc_color_levels)
strunzone(acc_color_levels);
acc_color_levels = strzone(autocvar_accuracy_color_levels);
- acc_levels = tokenize(acc_color_levels);
+ acc_levels = tokenize_console(acc_color_levels);
if (acc_levels > MAX_ACCURACY_LEVELS)
acc_levels = MAX_ACCURACY_LEVELS;
if(autocvar_camera_look_player)
{
- local vector dir;
- local float n;
+ vector dir;
+ float n;
dir = normalize(view_origin - current_position);
n = mouse_angles_z;
float autocvar_cl_particles_quality;
float autocvar_cl_projectiles_sloppy;
float autocvar_cl_readpicture_force;
+var float autocvar_cl_reticle = 1;
float autocvar_cl_reticle_item_nex;
float autocvar_cl_reticle_item_normal;
float autocvar_cl_reticle_stretch;
var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
float autocvar_cl_velocityzoom;
-var float autocvar_cl_velocityzoomtime = 0.3;
+float autocvar_cl_velocityzoom_type;
+float autocvar_cl_velocityzoom_speed;
+float autocvar_cl_velocityzoom_time;
string autocvar_cl_weaponpriority;
float autocvar_cl_zoomfactor;
float autocvar_cl_zoomsensitivity;
float autocvar_g_balance_tuba_volume;
float autocvar_g_balance_tuba_pitchstep;
float autocvar_g_warmup_limit;
-var float autocvar_g_waypointsprite_uppercase = 1;
-var float autocvar_g_waypointsprite_alpha = 1;
-var float autocvar_g_waypointsprite_crosshairfadealpha = 1;
+float autocvar_g_waypointsprite_uppercase;
+float autocvar_g_waypointsprite_alpha;
+float autocvar_g_waypointsprite_crosshairfadealpha;
float autocvar_g_waypointsprite_crosshairfadedistance;
-var float autocvar_g_waypointsprite_crosshairfadescale = 1;
+float autocvar_g_waypointsprite_crosshairfadescale;
float autocvar_g_waypointsprite_distancealphaexponent;
-var float autocvar_g_waypointsprite_distancefadealpha = 1;
-var float autocvar_g_waypointsprite_distancefadedistancemultiplier = 1;
-var float autocvar_g_waypointsprite_distancefadescale = 1;
-var float autocvar_g_waypointsprite_edgefadealpha = 1;
+float autocvar_g_waypointsprite_distancefadealpha;
+float autocvar_g_waypointsprite_distancefadedistancemultiplier;
+float autocvar_g_waypointsprite_distancefadescale;
+float autocvar_g_waypointsprite_edgefadealpha;
float autocvar_g_waypointsprite_edgefadedistance;
-var float autocvar_g_waypointsprite_edgefadescale = 1;
-var float autocvar_g_waypointsprite_edgeoffset_bottom = 0;
-var float autocvar_g_waypointsprite_edgeoffset_left = 0;
-var float autocvar_g_waypointsprite_edgeoffset_right = 0;
-var float autocvar_g_waypointsprite_edgeoffset_top = 0;
-var float autocvar_g_waypointsprite_fontsize = 12;
+float autocvar_g_waypointsprite_edgefadescale;
+float autocvar_g_waypointsprite_edgeoffset_bottom;
+float autocvar_g_waypointsprite_edgeoffset_left;
+float autocvar_g_waypointsprite_edgeoffset_right;
+float autocvar_g_waypointsprite_edgeoffset_top;
+float autocvar_g_waypointsprite_fontsize;
float autocvar_g_waypointsprite_minalpha;
float autocvar_g_waypointsprite_minscale;
float autocvar_g_waypointsprite_normdistance;
-var float autocvar_g_waypointsprite_scale = 1;
+float autocvar_g_waypointsprite_scale;
float autocvar_g_waypointsprite_spam;
float autocvar_g_waypointsprite_timealphaexponent;
-var float autocvar_hud_colorflash_alpha = 0.5;
+float autocvar_hud_colorflash_alpha;
float autocvar_hud_configure_bg_minalpha;
float autocvar_hud_configure_checkcollisions;
float autocvar_hud_configure_grid;
vector autocvar_hud_panel_bg_color;
float autocvar_hud_panel_bg_color_team;
float autocvar_hud_panel_bg_padding;
+float autocvar_hud_panel_centerprint;
+string autocvar_hud_panel_centerprint_pos;
+string autocvar_hud_panel_centerprint_size;
+string autocvar_hud_panel_centerprint_bg;
+string autocvar_hud_panel_centerprint_bg_color;
+string autocvar_hud_panel_centerprint_bg_color_team;
+string autocvar_hud_panel_centerprint_bg_alpha;
+string autocvar_hud_panel_centerprint_bg_border = "";
+string autocvar_hud_panel_centerprint_bg_padding = "";
+float autocvar_hud_panel_centerprint_align;
+var float autocvar_hud_panel_centerprint_fade_in = 0.2;
+var float autocvar_hud_panel_centerprint_fade_out = 0.5;
+var float autocvar_hud_panel_centerprint_fade_subsequent = 1;
+var float autocvar_hud_panel_centerprint_fade_subsequent_passone = 3;
+var float autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha = 0.5;
+var float autocvar_hud_panel_centerprint_fade_subsequent_passtwo = 10;
+var float autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha = 0.5;
+var float autocvar_hud_panel_centerprint_fade_subsequent_minfontsize = 0.75;
+var float autocvar_hud_panel_centerprint_fade_minfontsize = 0;
+float autocvar_hud_panel_centerprint_flip;
+float autocvar_hud_panel_centerprint_fontscale;
+float autocvar_hud_panel_centerprint_time;
float autocvar_hud_panel_chat;
float autocvar_hud_panel_engineinfo;
float autocvar_hud_panel_engineinfo_framecounter_decimals;
float autocvar_hud_panel_healtharmor_progressbar_gfx_damage;
float autocvar_hud_panel_healtharmor_progressbar_gfx_lowhealth;
float autocvar_hud_panel_healtharmor_progressbar_gfx_smooth;
-
-// TEMPORARY hard coded default for compatibility - remove after 0.2 release
-var float autocvar_hud_panel_centerprint = 1;
-noref var string autocvar_hud_panel_centerprint_pos = "0.180000 0.260000";
-noref var string autocvar_hud_panel_centerprint_size = "0.650000 0.210000";
-noref var string autocvar_hud_panel_centerprint_bg = "";
-noref var string autocvar_hud_panel_centerprint_bg_color = "";
-noref var string autocvar_hud_panel_centerprint_bg_color_team = "";
-noref var string autocvar_hud_panel_centerprint_bg_alpha = "";
-noref var string autocvar_hud_panel_centerprint_bg_border = "";
-noref var string autocvar_hud_panel_centerprint_bg_padding = "";
-var float autocvar_hud_panel_centerprint_align = 0.5;
-var float autocvar_hud_panel_centerprint_fadetime = 0.25;
-var float autocvar_hud_panel_centerprint_flip = 1;
-var float autocvar_hud_panel_centerprint_fontscale = 1;
-var float autocvar_hud_panel_centerprint_time = 3;
float autocvar_hud_panel_healtharmor_text;
float autocvar_hud_panel_infomessages;
float autocvar_hud_panel_infomessages_flip;
float autocvar_hud_panel_notify_print;
float autocvar_hud_panel_notify_time;
float autocvar_hud_panel_physics;
-float autocvar_hud_panel_physics_acceleration_progressbar_mode;
+float autocvar_hud_panel_physics_acceleration_mode;
float autocvar_hud_panel_physics_acceleration_max;
float autocvar_hud_panel_physics_progressbar;
float autocvar_hud_panel_physics_acceleration_vertical;
float autocvar_hud_panel_racetimer;
float autocvar_hud_panel_radar;
float autocvar_hud_panel_radar_foreground_alpha;
+float autocvar_hud_panel_radar_maximized_scale;
+vector autocvar_hud_panel_radar_maximized_size;
float autocvar_hud_panel_radar_rotation;
float autocvar_hud_panel_radar_scale;
float autocvar_hud_panel_radar_zoommode;
float autocvar_hud_showbinds_limit;
float autocvar_hud_shownames;
float autocvar_hud_shownames_enemies;
+float autocvar_hud_shownames_crosshairdistance;
+float autocvar_hud_shownames_crosshairdistance_time;
+float autocvar_hud_shownames_crosshairdistance_antioverlap;
float autocvar_hud_shownames_self;
float autocvar_hud_shownames_status;
float autocvar_hud_shownames_statusbar_height;
var float autocvar_scoreboard_highlight_alpha_self = 0.25;
float autocvar_scoreboard_offset_left;
float autocvar_scoreboard_offset_right;
+float autocvar_scoreboard_offset_vertical;
float autocvar_v_flipped;
float autocvar_vid_conheight;
float autocvar_vid_conwidth;
string ctf_temp_1;
float order_page;
-void() menu_close =
+void menu_close()
{
menu_visible = false;
menu_show = menu_show_error;
strunzone(ctf_temp_1);*/
localcmd("\nin_bindmap 0 0;");
-};
+}
-void() order_menu_render =
+void order_menu_render()
{
- local vector ps, po;
- local float i, p, n;
- local string frags, color;
+ vector ps, po;
+ float i, p, n;
+ string frags, color;
ps = '0 200 0';
po = '0 8 0';
} else {
menu_close();
}
-};
+}
-float(float bInputType, float nPrimary, float nSecondary) order_menu_action =
+float order_menu_action(float bInputType, float nPrimary, float nSecondary)
{
- local string arg;
- local float p, i, n, chose;
- local string frags, color;
+ string arg;
+ float p, i, n, chose;
+ string frags, color;
if(bInputType != 0) // key down wanted
return FALSE;
return FALSE;
}
return TRUE;
-};
+}
-void() order_menu_show =
+void order_menu_show()
{
order_page = 0;
menu_show = order_menu_render;
menu_action = order_menu_action;
-};
+}
-void() ctf_menu_render =
+void ctf_menu_render()
{
- local vector ps, po;
+ vector ps, po;
ps = '0 200 0';
po = '0 8 0';
} else {
menu_close();
}
-};
+}
-float(float bInputType, float nPrimary, float nSecondary) ctf_menu_action =
+float ctf_menu_action(float bInputType, float nPrimary, float nSecondary)
{
- local string arg;
+ string arg;
if(bInputType != 0) // key down wanted
return FALSE;
return FALSE;
}
return TRUE;
-};
+}
-void() ctf_menu_show =
+void ctf_menu_show()
{
if(getstati(STAT_CTF_STATE) < 0)
return;
menu_action = ctf_menu_action;
menu_visible = TRUE;
//menu_default_binds();
-};
+}
-void() ctf_view =
+void ctf_view()
{
- local float stat;
+ float stat;
stat = getstati(STAT_CTF_STATE);
if(stat == CTF_STATE_ATTACK) {
drawpic('0 0 0', "gfx/ctf_ic_atk.tga", '64 64 0', '1 1 1', 1, 0);
} else {
drawstring('0 0 0', _("Awaiting orders..."), '8 8 0', '1 1 1', 0.5, 0);
}
-};
+}
#endif
if(DEATH_ISTURRET(w_deathtype))
{
+ string _snd;
traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world);
if(trace_plane_normal != '0 0 0')
w_backoff = trace_plane_normal;
{
case DEATH_TURRET_EWHEEL:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN);
- pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1);
+ pointparticles(particleeffectnum("laser_impact"), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_FLAC:
- vector org2;
- org2 = w_org + w_backoff * 6;
- pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
- if (w_random<0.15)
- sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM);
- else if (w_random<0.7)
- sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM);
- else
- sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
-
+ pointparticles(particleeffectnum("hagar_explode"), w_org, '0 0 0', 1);
+ _snd = strcat("weapons/hagexp", ftos(1 + rint(random() * 2)), ".waw");
+ sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM);
break;
case DEATH_TURRET_MLRS:
case DEATH_TURRET_MACHINEGUN:
case DEATH_TURRET_WALKER_GUN:
- string _snd;
_snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw");
sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("machinegun_impact"), self.origin, w_backoff * 1000, 1);
void HUD_Weapons(void)
{
- float i, f, screen_ar;
- float center_x, center_y;
- if(hud != HUD_NORMAL) return;
+ // declarations
+ float weapons_stat = getstati(STAT_WEAPONS);
+ float i, f, a, j, factor;
+ float screen_ar, center_x, center_y;
+ float weapon_count, weapon_id, weapon_alpha;
+ float row, column, rows, columns;
+ float aspect = autocvar_hud_panel_weapons_aspect;
+
+ float show_accuracy, panel_weapon_accuracy;
+
+ float timeout = autocvar_hud_panel_weapons_timeout;
+ float timein_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.375 : 0);
+ float timeout_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.75 : 0);
+
+ float ammo_type, ammo_full, ammo_alpha;
+ float barsize_x, barsize_y, baroffset_x, baroffset_y;
+
+ float when = autocvar_hud_panel_weapons_complainbubble_time;
+ float fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime;
+
+ vector weapon_pos, weapon_size;
+ vector old_panel_size;
+ vector color, ammo_color;
+
+ // check to see if we want to continue
+ if(hud != HUD_NORMAL) { return; }
+
if(!autocvar__hud_configure)
- {
- if(!autocvar_hud_panel_weapons) return;
- if(spectatee_status == -1) return;
- }
+ if((!autocvar_hud_panel_weapons) || (spectatee_status == -1))
+ return;
+ else if(timeout && time >= weapontime + timeout + timeout_effect_length)
+ {
+ weaponprevtime = time;
+ return;
+ }
else
hud_configure_active_panel = HUD_PANEL_WEAPONS;
- float timeout = autocvar_hud_panel_weapons_timeout;
- float timeout_effect_length, timein_effect_length;
- if (autocvar_hud_panel_weapons_timeout_effect == 0)
+ // update generic hud functions
+ HUD_Panel_UpdateCvars(weapons);
+ HUD_Panel_ApplyFadeAlpha();
+
+ // calculate fading effect to weapon images for when the panel is idle
+ if(autocvar_hud_panel_weapons_fade)
{
- timeout_effect_length = 0;
- timein_effect_length = 0;
+ weapon_alpha = 3.2 - 2 * (time - weapontime);
+ weapon_alpha = bound(0.7, weapon_alpha, 1) * panel_fg_alpha;
}
else
- {
- timeout_effect_length = 0.75;
- timein_effect_length = 0.375;
- }
+ weapon_alpha = panel_fg_alpha;
- if (timeout && time >= weapontime + timeout + timeout_effect_length && !autocvar__hud_configure)
- {
- weaponprevtime = time;
- return;
- }
-
- HUD_Panel_UpdateCvars(weapons);
- HUD_Panel_ApplyFadeAlpha();
-
- // TODO make this configurable
+ // figure out weapon order (how the weapons are sorted) // TODO make this configurable
if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
{
float weapon_cnt;
weaponorder_cmp_str = string_null;
}
-
- float when, fadetime;
- when = autocvar_hud_panel_weapons_complainbubble_time;
- fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime;
- float weapons_st = getstati(STAT_WEAPONS);
- float weapon_count;
+
+ // determine which weapons are going to be shown
if (autocvar_hud_panel_weapons_onlyowned)
{
if(autocvar__hud_configure)
{
- if (weapons_st == 0)
+ if (weapons_stat == 0) // create some fake weapons anyway
for(i = 0; i <= WEP_LAST-WEP_FIRST; i += floor((WEP_LAST-WEP_FIRST)/5))
- weapons_st |= power2of(i);
+ weapons_stat |= power2of(i);
+
if(menu_enabled != 2)
HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
}
-
- vector old_panel_size;
+
+ // do we own this weapon?
for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
- {
- if(weapons_st & weaponorder[i].weapons)
+ if(weapons_stat & weaponorder[i].weapons)
++weapon_count;
- }
- if(!autocvar__hud_configure && (autocvar_hud_panel_weapons_complainbubble && time - complain_weapon_time < when + fadetime))// && complain_weapon >= 0
- ++weapon_count;
- if (weapon_count == 0)
- return;
+
+ // add it anyway if weaponcomplain is shown
+ if((!autocvar__hud_configure)
+ && (autocvar_hud_panel_weapons_complainbubble
+ && time - complain_weapon_time < when + fadetime))
+ ++weapon_count;
+
+ // might as well commit suicide now, no reason to live ;)
+ if (weapon_count == 0) { return; }
+
// reduce size of the panel
if (panel_size_y > panel_size_x)
{
else
weapon_count = WEP_COUNT;
- if (timeout && time >= weapontime + timeout && !autocvar__hud_configure)
+ // animation for fading in/out the panel respectively when not in use
+ if(!autocvar__hud_configure)
{
- f = (time - (weapontime + timeout)) / timeout_effect_length;
- if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
- {
- panel_bg_alpha *= (1 - f);
- panel_fg_alpha *= (1 - f);
- }
- if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
+ if (timeout && time >= weapontime + timeout) // apply timeout effect if needed
{
- f *= f; // for a cooler movement
- center_x = panel_pos_x + panel_size_x/2;
- center_y = panel_pos_y + panel_size_y/2;
- screen_ar = vid_conwidth/vid_conheight;
- if (center_x/center_y < screen_ar) //bottom left
+ f = (time - (weapontime + timeout)) / timeout_effect_length;
+ if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
{
- if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom
- panel_pos_y += f * (vid_conheight - panel_pos_y);
- else //left
- panel_pos_x -= f * (panel_pos_x + panel_size_x);
+ panel_bg_alpha *= (1 - f);
+ panel_fg_alpha *= (1 - f);
}
- else //top right
+ if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
{
- if ((vid_conwidth - center_x)/center_y < screen_ar) //right
- panel_pos_x += f * (vid_conwidth - panel_pos_x);
- else //top
- panel_pos_y -= f * (panel_pos_y + panel_size_y);
+ f *= f; // for a cooler movement
+ center_x = panel_pos_x + panel_size_x/2;
+ center_y = panel_pos_y + panel_size_y/2;
+ screen_ar = vid_conwidth/vid_conheight;
+ if (center_x/center_y < screen_ar) //bottom left
+ {
+ if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom
+ panel_pos_y += f * (vid_conheight - panel_pos_y);
+ else //left
+ panel_pos_x -= f * (panel_pos_x + panel_size_x);
+ }
+ else //top right
+ {
+ if ((vid_conwidth - center_x)/center_y < screen_ar) //right
+ panel_pos_x += f * (vid_conwidth - panel_pos_x);
+ else //top
+ panel_pos_y -= f * (panel_pos_y + panel_size_y);
+ }
}
+ weaponprevtime = time - (1 - f) * timein_effect_length;
}
- weaponprevtime = time - (1 - f) * timein_effect_length;
- }
- else if (timeout && time < weaponprevtime + timein_effect_length && !autocvar__hud_configure)
- {
- f = (time - weaponprevtime) / timein_effect_length;
- if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
- {
- panel_bg_alpha *= (f);
- panel_fg_alpha *= (f);
- }
- if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
+ else if (timeout && time < weaponprevtime + timein_effect_length) // apply timein effect if needed
{
- f *= f; // for a cooler movement
- f = 1 - f;
- center_x = panel_pos_x + panel_size_x/2;
- center_y = panel_pos_y + panel_size_y/2;
- screen_ar = vid_conwidth/vid_conheight;
- if (center_x/center_y < screen_ar) //bottom left
+ f = (time - weaponprevtime) / timein_effect_length;
+ if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
{
- if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom
- panel_pos_y += f * (vid_conheight - panel_pos_y);
- else //left
- panel_pos_x -= f * (panel_pos_x + panel_size_x);
+ panel_bg_alpha *= (f);
+ panel_fg_alpha *= (f);
}
- else //top right
+ if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
{
- if ((vid_conwidth - center_x)/center_y < screen_ar) //right
- panel_pos_x += f * (vid_conwidth - panel_pos_x);
- else //top
- panel_pos_y -= f * (panel_pos_y + panel_size_y);
+ f *= f; // for a cooler movement
+ f = 1 - f;
+ center_x = panel_pos_x + panel_size_x/2;
+ center_y = panel_pos_y + panel_size_y/2;
+ screen_ar = vid_conwidth/vid_conheight;
+ if (center_x/center_y < screen_ar) //bottom left
+ {
+ if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom
+ panel_pos_y += f * (vid_conheight - panel_pos_y);
+ else //left
+ panel_pos_x -= f * (panel_pos_x + panel_size_x);
+ }
+ else //top right
+ {
+ if ((vid_conwidth - center_x)/center_y < screen_ar) //right
+ panel_pos_x += f * (vid_conwidth - panel_pos_x);
+ else //top
+ panel_pos_y -= f * (panel_pos_y + panel_size_y);
+ }
}
}
}
+ // draw the background, then change the virtual size of it to better fit other items inside
HUD_Panel_DrawBg(1);
if(panel_bg_padding)
{
panel_pos += '1 1 0' * panel_bg_padding;
- panel_size -= '2 2 0' * panel_bg_padding;
+ panel_size -= '1 1 0' * panel_bg_padding;
}
- float weapid, wpnalpha;
-
- if(autocvar_hud_panel_weapons_fade)
- {
- wpnalpha = 3.2 - 2 * (time - weapontime);
- wpnalpha = bound(0.7, wpnalpha, 1) * panel_fg_alpha;
- }
- else
- wpnalpha = panel_fg_alpha;
-
- float rows, columns;
- float aspect = autocvar_hud_panel_weapons_aspect;
+ // after the sizing and animations are done, update the other values
rows = panel_size_y/panel_size_x;
rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count);
-
columns = ceil(weapon_count/rows);
- float row, column;
-
- float a, type, fullammo;
-
- vector color;
- vector wpnpos;
- vector wpnsize;
-
- vector ammo_color;
- float ammo_alpha;
- wpnsize = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows);
- float barsize_x, barsize_y, baroffset_x, baroffset_y;
+ weapon_size = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows);
+
+ // calculate position/size for visual bar displaying ammount of ammo status
if (autocvar_hud_panel_weapons_ammo)
{
ammo_color = stov(autocvar_hud_panel_weapons_ammo_color);
ammo_alpha = panel_fg_alpha * autocvar_hud_panel_weapons_ammo_alpha;
-
- if(wpnsize_x/wpnsize_y > aspect)
+ if(weapon_size_x/weapon_size_y > aspect)
{
- barsize_x = aspect * wpnsize_y;
- barsize_y = wpnsize_y;
- baroffset_x = (wpnsize_x - barsize_x) / 2;
+ barsize_x = aspect * weapon_size_y;
+ barsize_y = weapon_size_y;
+ baroffset_x = (weapon_size_x - barsize_x) / 2;
}
else
{
- barsize_y = 1/aspect * wpnsize_x;
- barsize_x = wpnsize_x;
- baroffset_y = (wpnsize_y - barsize_y) / 2;
+ barsize_y = 1/aspect * weapon_size_x;
+ barsize_x = weapon_size_x;
+ baroffset_y = (weapon_size_y - barsize_y) / 2;
}
}
- float show_accuracy;
- float weapon_stats;
if(autocvar_hud_panel_weapons_accuracy && acc_levels)
{
show_accuracy = true;
for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
{
+ // retrieve information about the current weapon to be drawn
self = weaponorder[i];
- if (!self || self.impulse < 0)
- continue;
- if (autocvar_hud_panel_weapons_onlyowned)
- if (!((weapons_st & self.weapons) || (self.weapon == complain_weapon && time - complain_weapon_time < when + fadetime && autocvar_hud_panel_weapons_complainbubble)))
- continue;
- wpnpos = panel_pos + eX * column * wpnsize_x + eY * row * wpnsize_y;
-
- weapid = self.impulse;
+ weapon_id = self.impulse;
+
+ // skip if this weapon doesn't exist
+ if (!self || self.impulse < 0) { continue; }
+
+ // skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
+ if (autocvar_hud_panel_weapons_onlyowned
+ && !((weapons_stat & self.weapons)
+ || (self.weapon == complain_weapon
+ && time - complain_weapon_time < when + fadetime
+ && autocvar_hud_panel_weapons_complainbubble)))
+ continue;
+
+ // figure out the drawing position of weapon
+ weapon_pos = (panel_pos
+ + eX * column * weapon_size_x
+ + eY * row * weapon_size_y);
// draw background behind currently selected weapon
if(self.weapon == switchweapon)
- drawpic_aspect_skin(wpnpos, "weapon_current_bg", wpnsize, '1 1 1', wpnalpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
// draw the weapon accuracy
if(show_accuracy)
{
- weapon_stats = weapon_accuracy[self.weapon-WEP_FIRST];
- if(weapon_stats >= 0)
+ panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST];
+ if(panel_weapon_accuracy >= 0)
{
- // find the max level lower than weapon_stats
- float j;
+ // find the max level lower than weapon_accuracy
j = acc_levels-1;
- while ( j && weapon_stats < acc_lev[j] )
+ while ( j && panel_weapon_accuracy < acc_lev[j] )
--j;
- // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
- float factor;
- factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
+ // inject color j+1 in color j, how much depending on how much weapon_accuracy is higher than level j
+ factor = (panel_weapon_accuracy - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
color = acc_col[j];
color = color + factor * (acc_col[j+1] - color);
- drawpic_aspect_skin(wpnpos, "weapon_accuracy", wpnsize, color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, "weapon_accuracy", weapon_size, color, panel_fg_alpha, DRAWFLAG_NORMAL);
}
}
- // draw the weapon icon
- if(weapons_st & self.weapons)
+ // drawing all the weapon items
+ if(weapons_stat & self.weapons)
{
- drawpic_aspect_skin(wpnpos, strcat("weapon", self.netname), wpnsize, '1 1 1', wpnalpha, DRAWFLAG_NORMAL);
-
- if(autocvar_hud_panel_weapons_label == 1) // weapon number
- drawstring(wpnpos, ftos(weapid), '1 1 0' * 0.5 * wpnsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- else if(autocvar_hud_panel_weapons_label == 2) // bind
- drawstring(wpnpos, getcommandkey(ftos(weapid), strcat("impulse ", ftos(weapid))), '1 1 0' * 0.5 * wpnsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ // draw the weapon image
+ drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+ // draw weapon label string
+ switch(autocvar_hud_panel_weapons_label)
+ {
+ case 1: // weapon number
+ drawstring(weapon_pos, ftos(weapon_id), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ break;
+
+ case 2: // bind
+ drawstring(weapon_pos, getcommandkey(ftos(weapon_id), strcat("impulse ", ftos(weapon_id))), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ break;
+
+ case 3: // weapon name
+ drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ break;
+
+ default: // nothing
+ break;
+ }
+
// draw ammo status bar
if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO)
{
a = 0;
- type = GetAmmoTypeForWep(self.weapon);
- if(type != -1)
- a = getstati(GetAmmoStat(type)); // how much ammo do we have?
+ ammo_type = GetAmmoTypeForWep(self.weapon);
+ if(ammo_type != -1)
+ a = getstati(GetAmmoStat(ammo_type)); // how much ammo do we have?
if(a > 0)
{
- switch(type) {
- case 0: fullammo = autocvar_hud_panel_weapons_ammo_full_shells; break;
- case 1: fullammo = autocvar_hud_panel_weapons_ammo_full_nails; break;
- case 2: fullammo = autocvar_hud_panel_weapons_ammo_full_rockets; break;
- case 3: fullammo = autocvar_hud_panel_weapons_ammo_full_cells; break;
- case 4: fullammo = autocvar_hud_panel_weapons_ammo_full_fuel; break;
- default: fullammo = 60;
+ switch(ammo_type) {
+ case 0: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
+ case 1: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
+ case 2: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
+ case 3: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
+ case 4: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
+ default: ammo_full = 60;
}
drawsetcliparea(
- wpnpos_x + baroffset_x,
- wpnpos_y + baroffset_y,
- barsize_x * bound(0, a/fullammo, 1),
+ weapon_pos_x + baroffset_x,
+ weapon_pos_y + baroffset_y,
+ barsize_x * bound(0, a/ammo_full, 1),
barsize_y);
- drawpic_aspect_skin(wpnpos, "weapon_ammo", wpnsize, ammo_color, ammo_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, "weapon_ammo", weapon_size, ammo_color, ammo_alpha, DRAWFLAG_NORMAL);
drawresetcliparea();
}
}
}
-
- // draw a "ghost weapon icon" if you don't have the weapon
- else
+ else // draw a "ghost weapon icon" if you don't have the weapon
{
- drawpic_aspect_skin(wpnpos, strcat("weapon", self.netname), wpnsize, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
}
-
+
// draw the complain message
if(time - complain_weapon_time < when + fadetime && self.weapon == complain_weapon && autocvar_hud_panel_weapons_complainbubble)
{
if(fadetime)
- {
- if(complain_weapon_time + when > time)
- a = 1;
- else
- a = bound(0, (complain_weapon_time + when + fadetime - time) / fadetime, 1);
- }
+ a = ((complain_weapon_time + when > time) ? 1 : bound(0, (complain_weapon_time + when + fadetime - time) / fadetime, 1));
else
- {
- if(complain_weapon_time + when > time)
- a = 1;
- else
- a = 0;
- }
+ a = ((complain_weapon_time + when > time) ? 1 : 0);
+
string s;
if(complain_weapon_type == 0) {
color = stov(autocvar_hud_panel_weapons_complainbubble_color_unavailable);
}
float padding = autocvar_hud_panel_weapons_complainbubble_padding;
- drawpic_aspect_skin(wpnpos + '1 1 0' * padding, "weapon_complainbubble", wpnsize - '2 2 0' * padding, color, a * panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(wpnpos + '1 1 0' * padding, s, wpnsize - '2 2 0' * padding, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos + '1 1 0' * padding, "weapon_complainbubble", weapon_size - '2 2 0' * padding, color, a * panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(weapon_pos + '1 1 0' * padding, s, weapon_size - '2 2 0' * padding, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
}
+ // continue with new position for the next weapon
++row;
if(row >= rows)
{
++column;
}
}
-
}
// Ammo (#1)
else
print (sprintf(_("^1%s^1 is now conserved for centuries to come\n"), s1));
}
- } else if(type == DEATH_TURRET) {
+ } else if(DEATH_ISTURRET(type)) {
HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
if(alsoprint)
- print (sprintf(_("^1%s^1 was mowed down by a turret \n"), s1));
+ {
+ if(gentle)
+ print (sprintf(_("^1%s^1 ran into a turret\n"), s1));
+ else
+ {
+ switch(type)
+ {
+ case DEATH_TURRET_EWHEEL:
+ print (sprintf(_("^1%s^1 was laserd down by a eWheel turret \n"), s1));
+ break;
+ case DEATH_TURRET_FLAC:
+ print (sprintf(_("^1%s^1 got caught in the flac \n"), s1));
+ break;
+ case DEATH_TURRET_MACHINEGUN:
+ print (sprintf(_("^1%s^1 was riddeld full of riddled by a machinegun turret \n"), s1));
+ break;
+ case DEATH_TURRET_WALKER_GUN:
+ print (sprintf(_("^1%s^1 got served a led enrichment by a walker turret \n"), s1));
+ break;
+ case DEATH_TURRET_WALKER_MEELE:
+ print (sprintf(_("^1%s^1 was impaled by a walker turret \n"), s1));
+ break;
+ case DEATH_TURRET_WALKER_ROCKET:
+ print (sprintf(_("^1%s^1 was rocketed to hell by a walker turret \n"), s1));
+ break;
+ case DEATH_TURRET_HELLION:
+ print (sprintf(_("^1%s^1 was blasted away hellion turret \n"), s1));
+ break;
+ case DEATH_TURRET_HK:
+ print (sprintf(_("^1%s^1 could not hide from the hunter turret \n"), s1));
+ break;
+ case DEATH_TURRET_MLRS:
+ print (sprintf(_("^1%s^1 got turned into smoldering gibs by a mlrs turret \n"), s1));
+ break;
+ case DEATH_TURRET_PLASMA:
+ print (sprintf(_("^1%s^1 got served some superheated plasma from a plasma turret \n"), s1));
+ break;
+ case DEATH_TURRET_PHASER:
+ print (sprintf(_("^1%s^1 was phased out \n"), s1));
+ break;
+ case DEATH_TURRET_TESLA:
+ print (sprintf(_("^1%s^1 was electrocuted by a tesla turret \n"), s1));
+ break;
+ }
+ }
+ }
} else if (type == DEATH_CUSTOM) {
HUD_KillNotify_Push(s1, "", 0, DEATH_CUSTOM);
if(alsoprint)
{
if (!autocvar__hud_configure)
{
- if (autocvar_hud_panel_radar == 0) return;
- if (autocvar_hud_panel_radar != 2 && !teamplay) return;
+ if (hud_panel_radar_maximized)
+ {
+ if (!hud_draw_maximized) return;
+ }
+ else
+ {
+ if (autocvar_hud_panel_radar == 0) return;
+ if (autocvar_hud_panel_radar != 2 && !teamplay) return;
+ }
}
else
hud_configure_active_panel = HUD_PANEL_RADAR;
HUD_Panel_UpdateCvars(radar);
HUD_Panel_ApplyFadeAlpha();
+
+ if (hud_panel_radar_maximized && !autocvar__hud_configure)
+ {
+ panel_size = autocvar_hud_panel_radar_maximized_size;
+ panel_size_x = bound(0.2, panel_size_x, 1) * vid_conwidth;
+ panel_size_y = bound(0.2, panel_size_y, 1) * vid_conheight;
+ panel_pos_x = (vid_conwidth - panel_size_x) / 2;
+ panel_pos_y = (vid_conheight - panel_size_y) / 2;
+
+ panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized
+ if(precache_pic(panel_bg) == "") { panel_bg = "gfx/hud/default/border_default"; } // fallback
+ }
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
mySize -= '2 2 0' * panel_bg_padding;
}
- local float color2;
- local entity tm;
+ float color2;
+ entity tm;
float scale2d, normalsize, bigsize;
float f;
void HUD_VoteWindow(void)
{
- if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE))
+ if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE || (serverflags & SERVERFLAG_PLAYERSTATS)))
{
vote_active = 1;
if (autocvar__hud_configure)
print(_("^1You must answer before entering hud configure mode\n"));
cvar_set("_hud_configure", "0");
}
- vote_called_vote = strzone(_("^2Name ^7instead of \"^1Unregistered player^7\" in stats"));
+ if(vote_called_vote)
+ strunzone(vote_called_vote);
+ vote_called_vote = strzone(_("^2Name ^7instead of \"^1Anonymous player^7\" in stats"));
uid2name_dialog = 1;
}
cvar_set("con_chatrect", "0");
return;
}
+ if(autocvar__con_chat_maximized)
+ if(!hud_draw_maximized) return;
}
else
hud_configure_active_panel = HUD_PANEL_CHAT;
speed_baralign = (autocvar_hud_panel_physics_baralign == 2);
acceleration_baralign = (autocvar_hud_panel_physics_baralign == 3);
}
- if (autocvar_hud_panel_physics_acceleration_progressbar_mode == 0)
+ if (autocvar_hud_panel_physics_acceleration_mode == 0)
acceleration_baralign = 3; //override hud_panel_physics_baralign value for acceleration
//draw speed
float centerprint_time[CENTERPRINT_MAX_MSGS];
float centerprint_expire_time[CENTERPRINT_MAX_MSGS];
float centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
-float centerprint_fadetime;
float centerprint_showing;
void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
if (!centerprint_showing)
centerprint_showing = TRUE;
- centerprint_fadetime = bound(0, autocvar_hud_panel_centerprint_fadetime, 1);
-
for (i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j)
{
if (j == CENTERPRINT_MAX_MSGS)
if (strMessage == "" && centerprint_messages[j] != "" && centerprint_countdown_num[j] == 0)
{
// fade out the current msg (duration and countdown_num are ignored)
- centerprint_time[j] = centerprint_fadetime;
- if (centerprint_expire_time[j] > time + centerprint_fadetime || centerprint_expire_time[j] < time)
- centerprint_expire_time[j] = time + centerprint_fadetime;
+ centerprint_time[j] = min(5, autocvar_hud_panel_centerprint_fade_out);
+ if (centerprint_expire_time[j] > time + min(5, autocvar_hud_panel_centerprint_fade_out) || centerprint_expire_time[j] < time)
+ centerprint_expire_time[j] = time + min(5, autocvar_hud_panel_centerprint_fade_out);
return;
}
break; // found a msg with the same id, at position j
if (scoreboard_bottom >= 0.96 * vid_conheight)
return;
vector target_pos;
+
target_pos = eY * scoreboard_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
- panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha);
- panel_size_y = min(panel_size_y, vid_conheight - scoreboard_bottom);
+
+ if(target_pos_y > panel_pos_y)
+ {
+ panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha);
+ panel_size_y = min(panel_size_y, vid_conheight - scoreboard_bottom);
+ }
}
HUD_Panel_DrawBg(1);
else
continue;
}
- if (centerprint_time[j] < 0 || centerprint_expire_time[j] - centerprint_fadetime > time)
- {
- a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / centerprint_fadetime, 1);
- sz = 0.8 + a * (1 - 0.8);
- }
+
+ // fade the centerprint in/out
+ if (centerprint_time[j] < 0 || centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
+ a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
else if (centerprint_expire_time[j] > time)
+ a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
+
+ // set the size from fading in/out before subsequent fading
+ sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
+
+ // also fade it based on positioning
+ if(autocvar_hud_panel_centerprint_fade_subsequent)
{
- a = (centerprint_expire_time[j] - time) / centerprint_fadetime;
- sz = 0.8 + a * (1 - 0.8);
+ a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (i / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half alpha
+ a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (i / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower alpha even more for each message
}
-
+
+ // finally set the size based on the new alpha from subsequent fading
+ sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize));
drawfontscale = sz * '1 1 0';
+
if (centerprint_countdown_num[j])
n = tokenizebyseparator(sprintf(centerprint_messages[j], centerprint_countdown_num[j]), "\n");
else
n = tokenizebyseparator(centerprint_messages[j], "\n");
+
if (autocvar_hud_panel_centerprint_flip)
{
// check if the message can be entirely shown
pos_y -= fontsize_y;
else
pos_y -= fontsize_y * CENTERPRINT_SPACING/2;
- // NOTE: uncommented so as to not reject messages whenever they are "too large" -- This just continues drawing it anyway.
- //if (pos_y < panel_pos_y) // check if the next line can be shown
- //{
- // drawfontscale = '1 1 0';
- // return;
- //}
}
}
current_msg_pos_y = pos_y; // save starting pos (first line) of the current message
}
else
pos_y += fontsize_y * CENTERPRINT_SPACING/2;
- // NOTE: uncommented so as to not reject messages whenever they are "too large" -- This just continues drawing it anyway.
- //if (!autocvar_hud_panel_centerprint_flip && pos_y > panel_pos_y + panel_size_y - fontsize_y) // check if the next line can be shown
- //{
- // drawfontscale = '1 1 0';
- // return;
- //}
}
}
msg_size = pos_y - msg_size;
{
pos_y = current_msg_pos_y - CENTERPRINT_SPACING * fontsize_y;
if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
- pos_y += (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(a));
+ pos_y += (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz));
+
+ if (pos_y < panel_pos_y) // check if the next message can be shown
+ {
+ drawfontscale = '1 1 0';
+ return;
+ }
}
else
{
pos_y += CENTERPRINT_SPACING * fontsize_y;
if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
- pos_y -= (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(a));
+ pos_y -= (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz));
+
+ if(pos_y > panel_pos_y + panel_size_y - fontsize_y) // check if the next message can be shown
+ {
+ drawfontscale = '1 1 0';
+ return;
+ }
}
}
drawfontscale = '1 1 0';
}
}
+ hud_draw_maximized = 0;
// draw panels in order specified by panel_order array
- for(i = HUD_PANEL_NUM - 1; i >= 0; --i) {
- if(i != HUD_PANEL_CHAT || !autocvar__con_chat_maximized) // don't draw maximized chat panel twice!
- HUD_DrawPanel(panel_order[i]);
- }
+ for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
+ HUD_DrawPanel(panel_order[i]);
- // draw chat panel on top if it is maximized
+ hud_draw_maximized = 1; // panels that may be maximized must check this var
+ // draw maximized panels on top
+ if(hud_panel_radar_maximized)
+ HUD_Radar();
if(autocvar__con_chat_maximized)
- HUD_Chat(); // HUD_DrawPanel(HUD_PANEL_CHAT);
+ HUD_Chat();
if(autocvar__hud_configure)
{
float panel_order[HUD_PANEL_NUM];
string hud_panelorder_prev;
+float hud_draw_maximized;
+float hud_panel_radar_maximized;
+
vector mousepos;
vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
vector panel_click_resizeorigin; // coordinates for opposite point when resizing
HUD_Write_Cvar_q("hud_progressbar_armor_color");
HUD_Write_Cvar_q("hud_progressbar_fuel_color");
HUD_Write_Cvar_q("hud_progressbar_nexball_color");
+ HUD_Write_Cvar_q("hud_progressbar_speed_color");
+ HUD_Write_Cvar_q("hud_progressbar_acceleration_color");
+ HUD_Write_Cvar_q("hud_progressbar_acceleration_neg_color");
HUD_Write("\n");
HUD_Write_Cvar_q("_hud_panelorder");
HUD_Write_PanelCvar_q("_bg_border");
HUD_Write_PanelCvar_q("_bg_padding");
switch(i) {
- case HUD_PANEL_WEAPONS:
+ case HUD_PANEL_WEAPONS:
+ HUD_Write_PanelCvar_q("_accuracy");
+ HUD_Write_PanelCvar_q("_label");
HUD_Write_PanelCvar_q("_complainbubble");
HUD_Write_PanelCvar_q("_complainbubble_padding");
+ HUD_Write_PanelCvar_q("_complainbubble_time");
+ HUD_Write_PanelCvar_q("_complainbubble_fadetime");
HUD_Write_PanelCvar_q("_complainbubble_color_outofammo");
HUD_Write_PanelCvar_q("_complainbubble_color_donthave");
HUD_Write_PanelCvar_q("_complainbubble_color_unavailable");
+ HUD_Write_PanelCvar_q("_ammo");
HUD_Write_PanelCvar_q("_ammo_color");
HUD_Write_PanelCvar_q("_ammo_alpha");
HUD_Write_PanelCvar_q("_aspect");
HUD_Write_PanelCvar_q("_timeout");
HUD_Write_PanelCvar_q("_timeout_effect");
+ HUD_Write_PanelCvar_q("_onlyowned");
break;
case HUD_PANEL_AMMO:
HUD_Write_PanelCvar_q("_onlycurrent");
HUD_Write_PanelCvar_q("_progressbar");
HUD_Write_PanelCvar_q("_progressbar_strength");
HUD_Write_PanelCvar_q("_progressbar_shield");
+ HUD_Write_PanelCvar_q("_text");
break;
case HUD_PANEL_HEALTHARMOR:
HUD_Write_PanelCvar_q("_flip");
HUD_Write_PanelCvar_q("_progressbar");
HUD_Write_PanelCvar_q("_progressbar_health");
HUD_Write_PanelCvar_q("_progressbar_armor");
+ HUD_Write_PanelCvar_q("_progressbar_gfx");
+ HUD_Write_PanelCvar_q("_progressbar_gfx_smooth");
HUD_Write_PanelCvar_q("_text");
break;
case HUD_PANEL_NOTIFY:
HUD_Write_PanelCvar_q("_flip");
HUD_Write_PanelCvar_q("_fontsize");
HUD_Write_PanelCvar_q("_print");
+ HUD_Write_PanelCvar_q("_time");
+ HUD_Write_PanelCvar_q("_fadetime");
+ break;
+ case HUD_PANEL_TIMER:
+ HUD_Write_PanelCvar_q("_increment");
break;
case HUD_PANEL_RADAR:
HUD_Write_PanelCvar_q("_foreground_alpha");
+ HUD_Write_PanelCvar_q("_rotation");
+ HUD_Write_PanelCvar_q("_zoommode");
+ HUD_Write_PanelCvar_q("_scale");
+ HUD_Write_PanelCvar_q("_maximized_scale");
+ HUD_Write_PanelCvar_q("_maximized_size");
+ break;
+ case HUD_PANEL_SCORE:
+ HUD_Write_PanelCvar_q("_rankings");
break;
case HUD_PANEL_VOTE:
HUD_Write_PanelCvar_q("_alreadyvoted_alpha");
break;
+ case HUD_PANEL_MODICONS:
+ HUD_Write_PanelCvar_q("_dom_layout");
+ break;
case HUD_PANEL_PRESSEDKEYS:
HUD_Write_PanelCvar_q("_aspect");
break;
+ case HUD_PANEL_ENGINEINFO:
+ HUD_Write_PanelCvar_q("_framecounter_time");
+ HUD_Write_PanelCvar_q("_framecounter_decimals");
+ break;
case HUD_PANEL_INFOMESSAGES:
HUD_Write_PanelCvar_q("_flip");
break;
case HUD_PANEL_PHYSICS:
+ HUD_Write_PanelCvar_q("_speed_unit");
+ HUD_Write_PanelCvar_q("_speed_unit_show");
+ HUD_Write_PanelCvar_q("_speed_max");
+ HUD_Write_PanelCvar_q("_speed_vertical");
+ HUD_Write_PanelCvar_q("_topspeed");
+ HUD_Write_PanelCvar_q("_topspeed_time");
+ HUD_Write_PanelCvar_q("_acceleration_max");
+ HUD_Write_PanelCvar_q("_acceleration_vertical");
HUD_Write_PanelCvar_q("_flip");
HUD_Write_PanelCvar_q("_baralign");
HUD_Write_PanelCvar_q("_progressbar");
HUD_Write_PanelCvar_q("_acceleration_mode");
+ HUD_Write_PanelCvar_q("_text");
break;
case HUD_PANEL_CENTERPRINT:
HUD_Write_PanelCvar_q("_align");
HUD_Write_PanelCvar_q("_flip");
HUD_Write_PanelCvar_q("_fontscale");
HUD_Write_PanelCvar_q("_time");
- HUD_Write_PanelCvar_q("_fadetime");
+ HUD_Write_PanelCvar_q("_fade_in");
+ HUD_Write_PanelCvar_q("_fade_out");
+ HUD_Write_PanelCvar_q("_fade_subsequent");
+ HUD_Write_PanelCvar_q("_fade_subsequent_passone");
+ HUD_Write_PanelCvar_q("_fade_subsequent_passone_minalpha");
+ HUD_Write_PanelCvar_q("_fade_subsequent_passtwo");
+ HUD_Write_PanelCvar_q("_fade_subsequent_passtwo_minalpha");
+ HUD_Write_PanelCvar_q("_fade_subsequent_minfontsize");
+ HUD_Write_PanelCvar_q("_fade_minfontsize");
break;
}
HUD_Write("\n");
string con_keys;
float keys;
con_keys = findkeysforcommand("toggleconsole");
- keys = tokenize(con_keys);
+ keys = tokenize(con_keys); // findkeysforcommand returns data for this
float hit_con_bind, i;
for (i = 0; i < keys; ++i)
case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
- case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(""); break;
+ case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break;
- case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.4; break;
- case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.4; break;
+ case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.75; break;
+ case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.75; break;
case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough
case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough
case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break;
entity pl, tm;
string str;
- xmin = autocvar_scoreboard_offset_left * vid_conwidth;
- ymin = autocvar_con_notify * autocvar_con_notifysize;
+ xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
+ ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
- xmax = (1 - autocvar_scoreboard_offset_right) * vid_conwidth;
- ymax = vid_conheight - ymin;
+ xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
+ ymax = (vid_conheight - ymin);
sbwidth = xmax - xmin;
// self.armorvalue
// self.sameteam = player is on same team as local client
// self.fadedelay = time to wait before name tag starts fading in for enemies
+// self.pointtime = last time you pointed at this player
//
const float SHOWNAMES_FADESPEED = 4;
-const float SHOWNAMES_FADEDELAY = 0.5;
+const float SHOWNAMES_FADEDELAY = 0.4;
void Draw_ShowNames(entity ent)
{
if(!autocvar_hud_shownames)
if(ent.sameteam || (!ent.sameteam && autocvar_hud_shownames_enemies))
{
ent.origin_z += autocvar_hud_shownames_offset;
-
+
float hit;
- if(ent.sameteam)
+ if(ent.sameteam && !autocvar_hud_shownames_crosshairdistance)
{
hit = 1;
}
hit = 1;
}
+ // handle tag fading
+ float overlap, onscreen, crosshairdistance;
vector o, eo;
+
o = project_3d_to_2d(ent.origin);
- float overlap, onscreen;
-
+
if(autocvar_hud_shownames_antioverlap)
{
// fade tag out if another tag that is closer to you overlaps
}
onscreen = (o_z >= 0 && o_x >= 0 && o_y >= 0 && o_x <= vid_conwidth && o_y <= vid_conheight);
+ crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
+
+ if(autocvar_hud_shownames_crosshairdistance)
+ {
+ if(autocvar_hud_shownames_crosshairdistance > crosshairdistance)
+ ent.pointtime = time;
+
+ if not(ent.pointtime + autocvar_hud_shownames_crosshairdistance_time > time)
+ overlap = TRUE;
+ else
+ overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : FALSE); // override what antioverlap says unless allowed by cvar.
+ }
if(!ent.fadedelay)
ent.fadedelay = time + SHOWNAMES_FADEDELAY;
.float armorvalue;
.float sameteam;
.float fadedelay;
-
+.float pointtime;
}
}
-void(vector coord3d, vector pangles, vector rgb) draw_teamradar_player =
+void draw_teamradar_player(vector coord3d, vector pangles, vector rgb)
{
vector coord, rgb2;
R_PolygonVertex(coord-v_forward, '1 0 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord-v_right*3-v_forward*2, '1 1 0', rgb, panel_fg_alpha);
R_EndPolygon();
-};
+}
void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a)
{
{
v_flipped = autocvar_v_flipped;
hud_panel_radar_scale = autocvar_hud_panel_radar_scale;
+ if (hud_panel_radar_maximized && !autocvar__hud_configure)
+ {
+ if (autocvar_hud_panel_radar_maximized_scale > 0)
+ hud_panel_radar_scale = autocvar_hud_panel_radar_maximized_scale;
+ }
hud_panel_radar_foreground_alpha = autocvar_hud_panel_radar_foreground_alpha * panel_fg_alpha;
hud_panel_radar_rotation = autocvar_hud_panel_radar_rotation;
hud_panel_radar_zoommode = autocvar_hud_panel_radar_zoommode;
{
if (!turret_is_precache[TID_COMMON])
{
- dprint("turret_precache TID_COMMON\n");
precache_sound ("weapons/rocket_impact.wav");
precache_model ("models/turrets/base-gib1.md3");
precache_model ("models/turrets/base-gib2.md3");
}
turret_tid2info(_tid);
if(turret_is_precache[_tid])
- {
- dprint("turret_precache: ", tid2info_name, " allready precachd, skipping.\n");
return;
- }
- else
- dprint("turret_precache: ", tid2info_name, " precaching.\n");
switch(_tid)
{
}
void turret_remove()
-{
- turret_tid2info(self.turret_type);
- dprint("Removing ", tid2info_name, " turrret.\n");
-
+{
remove(self.tur_head);
self.tur_head = world;
}
+.vector glowmod;
void turret_changeteam()
-{
- self.colormod = '0 0 0';
-
- switch(self.team)
+{
+ switch(self.team - 1)
{
case COLOR_TEAM1: // Red
- self.colormod = '2 0.5 0.5';
+ self.glowmod = '2 0 0';
break;
case COLOR_TEAM2: // Blue
- self.colormod = '0.5 0.5 2';
+ self.glowmod = '0 0 2';
break;
case COLOR_TEAM3: // Yellow
- self.colormod = '1.4 1.4 0.6';
+ self.glowmod = '1 1 0';
break;
case COLOR_TEAM4: // Pink
- self.colormod = '1.4 0.6 1.4';
+ self.glowmod = '1 0 1';
break;
}
- self.tur_head.colormod = self.colormod;
+ if(self.team)
+ self.colormap = 1024 + (self.team - 1) * 17;
+
+ self.tur_head.colormap = self.colormap;
+ self.tur_head.glowmod = self.glowmod;
+
}
void turret_head_draw()
{
dt = random();
- if(dt < 0.25)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-
+ if(dt < 0.03)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
}
- if(self.health < 85)
- if(dt < 0.1)
- pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+ if(self.health < 85)
+ if(dt < 0.01)
+ pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
if(self.health < 32)
- if(dt < 0.1)
- pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
-
+ if(dt < 0.015)
+ pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
}
void turret_walker_draw()
self.angles_y = self.move_angles_y;
if (self.health < 127)
- if(random() < 0.25)
+ if(random() < 0.15)
te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
}
self.angles_y = self.move_angles_y;
if (self.health < 127)
- if(random() < 0.25)
+ if(random() < 0.05)
te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
}
self.tur_head = spawn();
turret_tid2info(self.turret_type);
- dprint("Constructing ", tid2info_name , " turret (", ftos(self.turret_type), ")\n");
setorigin(self, self.origin);
setmodel(self, tid2info_base);
setmodel(self.tur_head, tid2info_head);
setsize(self, tid2info_min, tid2info_max);
setsize(self.tur_head, '0 0 0', '0 0 0');
- setorigin(self.tur_head, gettaginfo(self, gettagindex(self, "tag_head")));
+
+ if(self.turret_type == TID_EWHEEL)
+ setorigin(self.tur_head, '0 0 0');
+ else if (self.turret_type == TID_WALKER)
+ setorigin(self.tur_head, '0 0 0');
+ else
+ setorigin(self.tur_head, gettaginfo(self, gettagindex(self, "tag_head")));
self.tur_head.classname = "turret_head";
self.tur_head.owner = self;
self.tur_head.movetype = MOVETYPE_NOCLIP;
self.draw = turret_draw;
self.entremove = turret_remove;
- self.drawmask = MASK_NORMAL;
- self.tur_head.drawmask = MASK_NORMAL;
-
+ self.drawmask = MASK_NORMAL;
+ self.tur_head.drawmask = MASK_NORMAL;
+ self.anim_start_time = 0;
if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
{
self.gravity = 1;
Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
self.drawmask = MASK_NORMAL;
-
+
if(self.cnt)
{
if(time >= self.nextthink)
pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
for (i = 1; i < 5; i = i + 1)
- turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin, self.velocity + randomvec() * 700, '0 0 0', FALSE);
+ turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', FALSE);
}
entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
{
entity gib;
-
+
+ traceline(_from, _to, MOVE_NOMONSTERS, world);
+ if(trace_startsolid)
+ return world;
+
gib = spawn();
setorigin(gib, _from);
setmodel(gib, _model);
gib.solid = SOLID_CORPSE;
gib.draw = turret_gib_draw;
gib.cnt = _explode;
-
+ setsize(gib, '-1 -1 -1', '1 1 1');
if(_explode)
{
gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
gib.move_avelocity = prandomvec() * 32;
gib.move_time = time;
gib.damageforcescale = 1;
+ gib.classname = "turret_gib";
return gib;
}
{
entity headgib;
- setmodel(self, "");
- setmodel(self.tur_head, "");
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);
- dprint("Turret ", tid2info_name, " dies.\n");
// Base
if(self.turret_type == TID_EWHEEL)
- turret_gibtoss(tid2info_base, self.origin, self.velocity, '-1 -1 -1', FALSE);
+ 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, self.velocity, '-1 -1 -1', FALSE);
+ 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, self.velocity, '-1 -1 -1', FALSE);
+ 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 2', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
- turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 2', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
- turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 2', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+ {
+ 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 4', '0 0 0', '0 0 0', TRUE);
+ 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;
+ }
}
- headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
- 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;
+ setmodel(self, "null");
+ setmodel(self.tur_head, "null");
}
void ent_turret()
turret_precache(self.turret_type);
turret_construct();
+ self.colormap = 1024;
+ self.glowmod = '0 1 1';
+ self.tur_head.colormap = self.colormap;
+ self.tur_head.glowmod = self.glowmod;
}
if(sf & TNSF_ANG)
if(sf & TNSF_STATUS)
{
- float _team;
- _team = ReadByte();
- _team -= 1; // /&)=(%&#)&%)/#&)=½!!!½!!". thanks.
- self.health = ReadByte();
- if(_team != self.team)
- {
- self.team = _team;
- turret_changeteam();
+ float _tmp;
+ _tmp = ReadByte();
+ if(_tmp != self.team)
+ {
+ self.team = _tmp;
+ turret_changeteam();
}
- if(self.health == 0)
+ _tmp = ReadByte();
+ if(_tmp == 0 && self.health != 0)
turret_die();
+
+ self.health = _tmp;
}
}
#define TUBA_MIN -18
#define TUBA_MAX 27
-#define TUBA_INSTRUMENTS 1
+#define TUBA_INSTRUMENTS 2
#define TUBA_STARTNOTE(i,n) strcat("weapons/tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n), ".wav")
.float note; // note
void Ent_TubaNote(float bIsNew)
{
- float f, n, i, att;
+ float f, n, i, att, upd;
f = ReadByte();
+ upd = 0;
+
if(f & 1)
{
n = ReadChar();
{
self.note = n;
self.tuba_instrument = i;
- Ent_TubaNote_UpdateSound();
+ upd = 1;
}
}
self.entremove = Ent_TubaNote_StopSound;
self.enemy.think = Ent_TubaNote_Think;
self.enemy.nextthink = time + 10;
+
+ if(upd)
+ Ent_TubaNote_UpdateSound();
}
void Tuba_Precache()
float DEATH_WEAPONMASK = 0xFF;
float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths
float HITTYPE_SECONDARY = 0x100;
-float HITTYPE_SPLASH = 0x200;
+float HITTYPE_SPLASH = 0x200; // automatically set by RadiusDamage
float HITTYPE_BOUNCE = 0x400;
-float HITTYPE_HEADSHOT = 0x800;
+float HITTYPE_HEADSHOT = 0x800; // automatically set by Damage (if headshotbonus is set)
float HITTYPE_RESERVED = 0x1000; // unused yet
// macros to access these
#define SERVERFLAG_ALLOW_FULLBRIGHT 1
#define SERVERFLAG_TEAMPLAY 2
+#define SERVERFLAG_PLAYERSTATS 4
-// files (-1 for URL)
+// files
.float url_fh;
+#define URL_FH_CURL -1
+#define URL_FH_STDOUT -2
// URLs
.string url_url;
url_fromid[id] = world;
// if we get here, we MUST have both buffers cleared
- if(e.url_rbuf != -1 || e.url_wbuf != -1 || e.url_fh != -1)
+ if(e.url_rbuf != -1 || e.url_wbuf != -1 || e.url_fh != URL_FH_CURL)
error("url_URI_Get_Callback: not a request waiting for data");
if(status == 0)
}
}
-void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
+void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass)
{
entity e;
float i;
// create a writing end that does nothing yet
e = spawn();
- e.classname = "url_fopen_file";
+ e.classname = "url_single_fopen_file";
e.url_url = strzone(url);
- e.url_fh = -1;
+ e.url_fh = URL_FH_CURL;
e.url_wbuf = buf_create();
if(e.url_wbuf < 0)
{
- print("url_fopen: out of memory in buf_create\n");
+ print("url_single_fopen: out of memory in buf_create\n");
rdy(e, pass, URL_READY_ERROR);
strunzone(e.url_url);
remove(e);
}
e.url_wbufpos = 0;
e.url_rbuf = -1;
+ e.url_ready = rdy;
+ e.url_ready_pass = pass;
rdy(e, pass, URL_READY_CANWRITE);
break;
break;
if(i >= autocvar__urllib_nextslot)
{
- print("url_fopen: too many concurrent requests\n");
+ print("url_single_fopen: too many concurrent requests\n");
rdy(world, pass, URL_READY_ERROR);
return;
}
// GET the data
if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0))
{
- print("url_fopen: failure in crypto_uri_postbuf\n");
+ print("url_single_fopen: failure in crypto_uri_postbuf\n");
rdy(world, pass, URL_READY_ERROR);
return;
}
// all). Wait for data to come from the
// server, then call the callback
e = spawn();
- e.classname = "url_fopen_file";
+ e.classname = "url_single_fopen_file";
e.url_url = strzone(url);
- e.url_fh = -1;
+ e.url_fh = URL_FH_CURL;
e.url_rbuf = -1;
e.url_wbuf = -1;
e.url_ready = rdy;
break;
}
}
+ else if(url == "-")
+ {
+ switch(mode)
+ {
+ case FILE_WRITE:
+ case FILE_APPEND:
+ e = spawn();
+ e.classname = "url_single_fopen_stdout";
+ e.url_fh = URL_FH_STDOUT;
+ e.url_ready = rdy;
+ e.url_ready_pass = pass;
+ rdy(e, pass, URL_READY_CANWRITE);
+ break;
+ case FILE_READ:
+ print("url_single_fopen: cannot open '-' for reading\n");
+ rdy(world, pass, URL_READY_ERROR);
+ break;
+ }
+ }
else
{
float fh;
else
{
e = spawn();
- e.classname = "url_fopen_file";
+ e.classname = "url_single_fopen_file";
e.url_fh = fh;
+ e.url_ready = rdy;
+ e.url_ready_pass = pass;
if(mode == FILE_READ)
rdy(e, pass, URL_READY_CANREAD);
else
}
// close a file
-void url_fclose(entity e, url_ready_func rdy, entity pass)
+void url_fclose(entity e)
{
float i;
- if(e.url_fh < 0)
+ if(e.url_fh == URL_FH_CURL)
{
if(e.url_rbuf == -1 || e.url_wbuf != -1) // not(post GET/POST request)
if(e.url_rbuf != -1 || e.url_wbuf == -1) // not(pre POST request)
if(i >= autocvar__urllib_nextslot)
{
print("url_fclose: too many concurrent requests\n");
- rdy(e, pass, URL_READY_ERROR);
+ e.url_ready(e,e.url_ready_pass, URL_READY_ERROR);
buf_del(e.url_wbuf);
strunzone(e.url_url);
remove(e);
if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0))
{
print("url_fclose: failure in crypto_uri_postbuf\n");
- rdy(e, pass, URL_READY_ERROR);
+ e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
buf_del(e.url_wbuf);
strunzone(e.url_url);
remove(e);
// call the callback
buf_del(e.url_wbuf);
e.url_wbuf = -1;
- e.url_ready = rdy;
- e.url_ready_pass = pass;
e.url_id = i;
url_fromid[i] = e;
else
{
// we have READ all data, just close
- rdy(e, pass, URL_READY_CLOSED);
+ e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED);
buf_del(e.url_rbuf);
strunzone(e.url_url);
remove(e);
}
}
+ else if(e.url_fh == URL_FH_STDOUT)
+ {
+ e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle
+ remove(e);
+ }
else
{
// file
fclose(e.url_fh);
- rdy(e, pass, URL_READY_CLOSED); // closing creates no reading handle
+ e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle
remove(e);
}
}
// with \n (blame FRIK_FILE)
string url_fgets(entity e)
{
- if(e.url_fh < 0)
+ if(e.url_fh == URL_FH_CURL)
{
if(e.url_rbuf == -1)
error("url_fgets: not readable in current state");
e.url_rbufpos += 1;
return s;
}
+ else if(e.url_fh == URL_FH_STDOUT)
+ {
+ // stdout
+ return string_null;
+ }
else
{
// file
// without \n (blame FRIK_FILE)
void url_fputs(entity e, string s)
{
- if(e.url_fh < 0)
+ if(e.url_fh == URL_FH_CURL)
{
if(e.url_wbuf == -1)
error("url_fputs: not writable in current state");
bufstr_set(e.url_wbuf, e.url_wbufpos, s);
e.url_wbufpos += 1;
}
+ else if(e.url_fh == URL_FH_STDOUT)
+ {
+ // stdout
+ print(s);
+ }
else
{
// file
fputs(e.url_fh, s);
}
}
+
+// multi URL object, tries URLs separated by space in sequence
+void url_multi_ready(entity fh, entity me, float status)
+{
+ float n;
+ if(status == URL_READY_ERROR)
+ {
+ me.cnt += 1;
+ n = tokenize_console(me.url_url);
+ if(n <= me.cnt)
+ {
+ me.url_ready(fh, me.url_ready_pass, status);
+ strunzone(me.url_url);
+ remove(me);
+ return;
+ }
+ url_single_fopen(argv(me.cnt), me.lip, url_multi_ready, me);
+ return;
+ }
+ me.url_ready(fh, me.url_ready_pass, status);
+}
+void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass)
+{
+ float n;
+ n = tokenize_console(url);
+ if(n <= 0)
+ {
+ print("url_multi_fopen: need at least one URL\n");
+ rdy(world, pass, URL_READY_ERROR);
+ return;
+ }
+
+ entity me;
+ me = spawn();
+ me.classname = "url_multi";
+ me.url_url = strzone(url);
+ me.cnt = 0;
+ me.lip = mode;
+ me.url_ready = rdy;
+ me.url_ready_pass = pass;
+ url_single_fopen(argv(0), mode, url_multi_ready, me);
+}
// errors: -1, or negative HTTP status code
typedef void(entity handle, entity pass, float status) url_ready_func;
-void url_fopen(string url, float mode, url_ready_func rdy, entity pass);
-void url_fclose(entity e, url_ready_func rdy, entity pass);
+void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass);
+void url_fclose(entity e);
string url_fgets(entity e);
void url_fputs(entity e, string s);
float url_URI_Get_Callback(float id, float status, string data);
#define MIN_URL_ID 128
#define NUM_URL_ID 64
+
+void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass);
string unescape(string in)
{
- local float i, len;
- local string str, s;
+ float i, len;
+ string str, s;
// but it doesn't seem to be necessary in my tests at least
in = strzone(in);
void wordwrap_cb(string s, float l, void(string) callback)
{
- local string c;
- local float lleft, i, j, wlen;
+ string c;
+ float lleft, i, j, wlen;
s = strzone(s);
lleft = l;
}
// requires that m2>m1 in all coordinates, and that m4>m3
-float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;};
+float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
// requires the same, but is a stronger condition
-float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins_x >= bmins_x && smaxs_x <= bmaxs_x && smins_y >= bmins_y && smaxs_y <= bmaxs_y && smins_z >= bmins_z && smaxs_z <= bmaxs_z;};
+float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins_x >= bmins_x && smaxs_x <= bmaxs_x && smins_y >= bmins_y && smaxs_y <= bmaxs_y && smins_z >= bmins_z && smaxs_z <= bmaxs_z;}
#ifndef MENUQC
#endif
float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
{
- float ICanHasKallerz;
-
- // detect color codes support in the width function
- ICanHasKallerz = (w("^7", theSize) == 0);
-
// STOP.
// The following function is SLOW.
// For your safety and for the protection of those around you...
}
while(left < right - 1);
- if(ICanHasKallerz)
+ if(w("^7", theSize) == 0) // detect color codes support in the width function
{
// NOTE: when color codes are involved, this binary search is,
// mathematically, BROKEN. However, it is obviously guaranteed to
float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_lenFunction_t w)
{
- float ICanHasKallerz;
-
- // detect color codes support in the width function
- ICanHasKallerz = (w("^7") == 0);
-
// STOP.
// The following function is SLOW.
// For your safety and for the protection of those around you...
}
while(left < right - 1);
- if(ICanHasKallerz)
+ if(w("^7") == 0) // detect color codes support in the width function
{
// NOTE: when color codes are involved, this binary search is,
// mathematically, BROKEN. However, it is obviously guaranteed to
return left;
}
+string find_last_color_code(string s)
+{
+ float start, len, i, carets;
+ start = strstrofs(s, "^", 0);
+ if (start == -1) // no caret found
+ return "";
+ len = strlen(s)-1;
+ for(i = len; i >= start; --i)
+ {
+ if(substring(s, i, 1) != "^")
+ continue;
+
+ carets = 1;
+ while (i-carets >= start && substring(s, i-carets, 1) == "^")
+ ++carets;
+
+ // check if carets aren't all escaped
+ if (carets == 1 || mod(carets, 2) == 1) // first check is just an optimization
+ {
+ if(i+1 <= len)
+ if(strstrofs("0123456789", substring(s, i+1, 1), 0) >= 0)
+ return substring(s, i, 2);
+
+ if(i+4 <= len)
+ if(substring(s, i+1, 1) == "x")
+ if(strstrofs("0123456789abcdefABCDEF", substring(s, i+2, 1), 0) >= 0)
+ if(strstrofs("0123456789abcdefABCDEF", substring(s, i+3, 1), 0) >= 0)
+ if(strstrofs("0123456789abcdefABCDEF", substring(s, i+4, 1), 0) >= 0)
+ return substring(s, i, 5);
+ }
+ i -= carets; // this also skips one char before the carets
+ }
+
+ return "";
+}
+
string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
{
float cantake;
string s;
s = getWrappedLine_remaining;
+
+ if(w <= 0)
+ {
+ getWrappedLine_remaining = string_null;
+ return s; // the line has no size ANYWAY, nothing would be displayed.
+ }
cantake = textLengthUpToWidth(s, w, theFontSize, tw);
if(cantake > 0 && cantake < strlen(s))
getWrappedLine_remaining = substring(s, cantake, strlen(s) - cantake);
if(getWrappedLine_remaining == "")
getWrappedLine_remaining = string_null;
+ else if (tw("^7", theFontSize) == 0)
+ getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, cantake)), getWrappedLine_remaining);
return substring(s, 0, cantake);
}
else
getWrappedLine_remaining = substring(s, take + 1, strlen(s) - take);
if(getWrappedLine_remaining == "")
getWrappedLine_remaining = string_null;
+ else if (tw("^7", theFontSize) == 0)
+ getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, take)), getWrappedLine_remaining);
return substring(s, 0, take);
}
}
string s;
s = getWrappedLine_remaining;
+
+ if(w <= 0)
+ {
+ getWrappedLine_remaining = string_null;
+ return s; // the line has no size ANYWAY, nothing would be displayed.
+ }
cantake = textLengthUpToLength(s, w, tw);
if(cantake > 0 && cantake < strlen(s))
getWrappedLine_remaining = substring(s, cantake, strlen(s) - cantake);
if(getWrappedLine_remaining == "")
getWrappedLine_remaining = string_null;
+ else if (tw("^7") == 0)
+ getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, cantake)), getWrappedLine_remaining);
return substring(s, 0, cantake);
}
else
getWrappedLine_remaining = substring(s, take + 1, strlen(s) - take);
if(getWrappedLine_remaining == "")
getWrappedLine_remaining = string_null;
+ else if (tw("^7") == 0)
+ getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, take)), getWrappedLine_remaining);
return substring(s, 0, take);
}
}
return -1;
return ((a * 22 + b) * 22 + c) * 22 + d;
}
+
+float lowestbit(float f)
+{
+ f &~= f * 2;
+ f &~= f * 4;
+ f &~= f * 16;
+ f &~= f * 256;
+ f &~= f * 65536;
+ return f;
+}
float GameCommand_Generic(string cmd);
// returns TRUE if handled, FALSE otherwise
-// uses tokenize on its argument!
+// tokenizes its input!
// iterative depth-first search, with fields that go "up", "down left" and "right" in a tree
// for each element, funcPre is called first, then funcPre and funcPost for all its children, and funcPost last
if(argv(0) == "sync")
{
- loadAllCvars(main);
- updateCompression();
+ m_sync();
return;
}
return;
}
- if(argv(0) == "setresolution")
- {
- updateConwidths();
- return;
- }
-
- if(argv(0) == "setcompression")
- {
- updateCompression();
- return;
- }
-
if(argv(0) == "curl")
{
float do_exec;
return;
}
-#if 0
- if(argv(0) == "tokentest")
- {
- string s;
- float i, n;
-
- print("SANE tokenizer:\n");
- s = cvar_string("tokentest");
- n = tokenize_console_force_builtin(s);
- for(i = -n; i < n; ++i)
- {
- print("token ", ftos(i), ": '", argv(i), "' = ");
- print(ftos(argv_start_index(i)), " to ", ftos(argv_end_index(i)), "\n");
- }
- print(".\n");
-
- print("INSANE tokenizer:\n");
- s = cvar_string("tokentest");
- n = tokenize(s);
- for(i = -n; i < n; ++i)
- {
- print("token ", ftos(i), ": '", argv(i), "' = ");
- print(ftos(argv_start_index(i)), " to ", ftos(argv_end_index(i)), "\n");
- }
- print(".\n");
-
- print("EMULATED tokenizer:\n");
- s = cvar_string("tokentest");
- n = tokenize_console_force_emulation(s);
- for(i = -n; i < n; ++i)
- {
- print("token ", ftos(i), ": '", argv(i), "' = ");
- print(ftos(argv_start_index(i)), " to ", ftos(argv_end_index(i)), "\n");
- }
- print(".\n");
- return;
- }
-#endif
-
print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n"));
}
draw_fontscale = df;
}
}
-};
+}
#endif
e.draw(e);
me.leaveSubitem(me);
}
-};
+}
void Container_focusLeave(entity me)
{
draw_Picture( '0 0 0', strcat( "/", me.texturePath ),
drawSize, '1 1 1', 1.0 );
} else {
- local vector fontsize;
+ vector fontsize;
fontsize_x = fontsize_y = 1.0 / 30.0;
fontsize_z = 0.0;
draw_Text( '0 0 0', _("Browser not initialized!"), fontsize, '1 1 1', 1.0, 0 );
else
me.setFocus(me, front);
SUPER(ModalController).draw(me);
-};
+}
void ModalController_addTab(entity me, entity other, entity tabButton)
{
}
SUPER(Nexposee).draw(me);
-};
+}
float Nexposee_mousePress(entity me, vector pos)
{
float menuNotTheFirstFrame;
float menuMouseMode;
-void SUB_Null() { };
+void SUB_Null() { }
-void() m_init =
+void m_sync()
+{
+ updateCompression();
+ updateConwidths();
+
+ loadAllCvars(main);
+}
+
+void m_init()
{
cvar_set("_menu_alpha", "0");
prvm_language = strzone(cvar_string("prvm_language"));
}
}
-void() m_init_delayed =
+void m_init_delayed()
{
float fh, glob, n, i;
string s;
menuShiftState = 0;
menuMousePos = '0.5 0.5 0';
+ m_sync();
+
if(Menu_Active)
m_display(); // delayed menu display
-};
+}
-void(float key, float ascii) m_keyup =
+void m_keyup (float key, float ascii)
{
if(!menuInitialized)
return;
if(key == K_ALT) menuShiftState -= (menuShiftState & S_ALT);
if(key == K_CTRL) menuShiftState -= (menuShiftState & S_CTRL);
if(key == K_SHIFT) menuShiftState -= (menuShiftState & S_SHIFT);
-};
+}
-void(float key, float ascii) m_keydown =
+void m_keydown(float key, float ascii)
{
if(!menuInitialized)
return;
if(key == K_ALT) menuShiftState |= S_ALT;
if(key == K_CTRL) menuShiftState |= S_CTRL;
if(key == K_SHIFT) menuShiftState |= S_SHIFT;
-};
+}
float SCALEMODE_CROP = 0;
float SCALEMODE_LETTERBOX = 1;
draw_Picture(org, img, isz, '1 1 1', a);
}
-void(string img, float a, string algn, float force1) drawBackground =
+void drawBackground(string img, float a, string algn, float force1)
{
if(main.mainNexposee.ModalController_state == 0)
return;
}
}
-void() m_draw =
+void m_draw()
{
float t;
float realFrametime;
postMenuDraw();
frametime = 0;
-};
+}
-void() m_display =
+void m_display()
{
Menu_Active = true;
setkeydest(KEY_MENU);
main.focusEnter(main);
main.showNotify(main);
-};
+}
-void() m_hide =
+void m_hide()
{
Menu_Active = false;
setkeydest(KEY_GAME);
main.focusLeave(main);
main.hideNotify(main);
-};
+}
-void() m_toggle =
+void m_toggle()
{
if(Menu_Active)
m_hide();
else
m_display();
-};
+}
-void() m_shutdown =
+void m_shutdown()
{
entity e;
if(e.destroy)
e.destroy(e);
}
-};
+}
void m_focus_item_chain(entity outermost, entity innermost)
{
}
}
-void(string itemname) m_goto =
+void m_goto(string itemname)
{
entity e;
if(!menuInitialized)
}
}
-void() m_goto_skin_selector =
+void m_goto_skin_selector()
{
if(!menuInitialized)
return;
m_goto("skinselector");
}
-void() m_goto_language_selector =
+void m_goto_language_selector()
{
if(!menuInitialized)
return;
m_goto("languageselector");
}
-void() m_goto_video_settings =
+void m_goto_video_settings()
{
if(!menuInitialized)
return;
float preMenuInit(); // you have to define this for pre-menu initialization. Return 0 if initialization needs to be retried a frame later, 1 if it succeeded.
void preMenuDraw(); // this is run before the menu is drawn. You may put some stuff there that has to be done every frame.
void postMenuDraw(); // this is run just after the menu is drawn (or not). Useful to draw something over everything else.
+
+void m_sync();
s = strcat(s, ", ", _("NIX"));
if(cvar("g_rocket_flying"))
s = strcat(s, ", ", _("Rocket Flying"));
+ if(cvar("g_invincible_projectiles"))
+ s = strcat(s, ", ", _("Invincible Projectiles"));
if(cvar_string("g_weaponarena") != "0")
s = strcat(s, ", ", WeaponArenaString());
if(cvar("g_start_weapon_laser") == 0)
me.TR(me);
me.TDempty(me, 0.4);
me.TD(me, 1, 1.8, s);
- me.TR(me);
me.TR(me);
me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Weapon & item mutators:")));
me.TR(me);
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2, 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.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_rocket_flying", _("Rocket Flying")));
me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "hud_damage"));
me.gotoRC(me, me.rows - 1, 0);
- me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "color -1 -1;name \"$_cl_name\";cl_cmd sendcvar cl_weaponpriority;sendcvar cl_zoomfactor;sendcvar cl_zoomspeed;sendcvar cl_autoswitch;sendcvar cl_shownames;sendcvar cl_forceplayermodelsfromxonotic;sendcvar cl_forceplayermodels;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY));
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "color -1 -1;name \"$_cl_name\";cl_cmd sendcvar cl_weaponpriority;sendcvar cl_zoomfactor;sendcvar cl_zoomspeed;sendcvar cl_autoswitch;sendcvar cl_forceplayermodelsfromxonotic;sendcvar cl_forceplayermodels;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY));
}
void HUDSetup_Join_Click(entity me, entity btn)
{
ATTRIB(XonoticWaypointDialog, title, string, _("Waypoints"))
ATTRIB(XonoticWaypointDialog, color, vector, SKINCOLOR_DIALOG_WAYPOINTS)
ATTRIB(XonoticWaypointDialog, intendedWidth, float, 0.5)
- ATTRIB(XonoticWaypointDialog, rows, float, 6)
+ ATTRIB(XonoticWaypointDialog, rows, float, 5)
ATTRIB(XonoticWaypointDialog, columns, float, 3)
ENDCLASS(XonoticWaypointDialog)
#endif
me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1, 0.05, "g_waypointsprite_alpha"));
setDependent(e, "cl_hidewaypoints", 0, 0);
me.TR(me);
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Show names:")));
- me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_shownames"));
- e.addValue(e, _("Never"), "0");
- e.addValue(e, _("Teammates"), "1");
- e.addValue(e, _("All players"), "2");
- e.configureXonoticTextSliderValues(e);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "hud_shownames", _("Show names above players")));
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
e.onClick = Dialog_Close;
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "snd_spatialization_control", _("Headphone friendly mode")));
setDependent(e, "snd_channels", 1.5, 0.5);
me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation")));
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Spatial voices:")));
me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "0", ZCTX(_("VOCS^None"))));
me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "menu_sounds", _("Menu sounds")));
me.gotoRC(me, me.rows - 1, 0);
- me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY));
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; snd_attenuation_method_$menu_snd_attenuation_method; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY));
}
#endif
me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_coronas", _("Coronas")));
me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "r_coronas_occlusionquery", _("Use Occlusion Queries")));
me.TR(me);
- me.TD(me, 1, 1.2, e = makeXonoticCheckBox(0, "r_bloom", _("Bloom")));
- setDependent(e, "r_hdr", 0, 0);
- me.TD(me, 1, 1.8, e = makeXonoticCheckBoxEx(2, 0, "r_hdr", _("High Dynamic Range (HDR)")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "r_bloom", _("High Dynamic Range (HDR)")));
me.TR(me);
s = makeXonoticSlider(0.1, 1, 0.1, "r_motionblur");
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "vid_fullscreen", _("Full screen")));
me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "vid_vsync", _("Vertical Synchronization")));
- me.TR(me);
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_gl20", _("Use OpenGL 2.0 shaders (GLSL)")));
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "v_glslgamma", _("Use GLSL to handle color control")));
setDependent(e, "vid_gl20", 1, 1);
- me.TR(me);
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Vertex Buffer Objects (VBOs)")));
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "gl_vbo", "2", _("Vertices")));
me.TD(me, 1, 1.9, e = makeXonoticRadioButton(1, "gl_vbo", "1", _("Vertices and Triangles")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Frame Buffer Objects (FBOs)")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "r_viewfbo", "0", _("None")));
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "r_viewfbo", "1", _("8bit")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "r_viewfbo", "2", _("16bit HDR")));
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "r_viewfbo", "3", _("32bit HDR")));
me.TR(me);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Depth first:")));
e.addValue(e, ZCTX(_("DF^World")), "1");
e.addValue(e, ZCTX(_("DF^All")), "2");
e.configureXonoticTextSliderValues(e);
- me.TR(me);
- if(cvar_type("apple_multithreadedgl") & CVAR_TYPEFLAG_ENGINE)
- me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "apple_multithreadedgl", _("Disable multithreaded OpenGL")));
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "gl_finish", _("Wait for GPU to finish each frame")));
me.TD(me, 1, 2, e = makeXonoticSlider(0.5, 2.0, 0.05, "r_hdr_scenebrightness"));
me.gotoRC(me, me.rows - 1, 0);
- me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "menu_cmd setresolution; vid_restart; menu_restart; togglemenu; defer 0.1 \"menu_cmd videosettings\"", COMMANDBUTTON_APPLY));
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "menu_cmd sync; vid_restart; menu_restart; togglemenu; defer 0.1 \"menu_cmd videosettings\"", COMMANDBUTTON_APPLY));
}
#endif
}
else */
{
- float m, o;
+ float m, o, i, n; // moin moin
string s, typestr, modstr;
s = me.filterString;
// ping: reject negative ping (no idea why this happens in the first place, engine bug)
sethostcachemasknumber(++m, SLIST_FIELD_PING, 0, SLIST_TEST_GREATEREQUAL);
+ // show full button
if(!me.filterShowFull)
{
sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); // legacy
sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, ":S0:", SLIST_TEST_NOTCONTAIN); // g_maxplayers support
}
+
+ // show empty button
if(!me.filterShowEmpty)
sethostcachemasknumber(++m, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
+
+ // gametype filtering
if(typestr != "")
sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(typestr, ":"), SLIST_TEST_STARTSWITH);
+
+ // mod filtering
if(modstr != "")
{
if(substring(modstr, 0, 1) == "!")
else
sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(modstr), SLIST_TEST_EQUAL);
}
+
+ // server banning
+ n = tokenizebyseparator(_Nex_ExtResponseSystem_BannedServers, " ");
+ for(i = 0; i < n; ++i)
+ if(argv(i) != "")
+ sethostcachemaskstring(++m, SLIST_FIELD_CNAME, argv(i), SLIST_TEST_NOTSTARTSWITH);
+
m = SLIST_MASK_OR - 1;
if(s != "")
{
{
float i, found, owned;
+ if(_Nex_ExtResponseSystem_BannedServersNeedsRefresh)
+ {
+ if(!me.needsRefresh)
+ me.needsRefresh = 2;
+ _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 0;
+ }
+
if(me.currentSortField == -1)
{
me.setSortOrder(me, SLIST_FIELD_PING, +1);
}
_Nex_ExtResponseSystem_UpdateTo = strzone(_Nex_ExtResponseSystem_UpdateTo);
+
+ if(n >= 4)
+ {
+ _Nex_ExtResponseSystem_BannedServers = strzone(argv(3));
+ _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 1;
+ }
}
}
me.TR(me); \
me.TD(me, 1, 4, e = makeXonoticCheckBox(0, strzone(strcat("hud_panel_", panelname)), _("Enable panel"))); \
DIALOG_HUDPANEL_COMMON_NOTOGGLE()
+
+string _Nex_ExtResponseSystem_BannedServers;
+float _Nex_ExtResponseSystem_BannedServersNeedsRefresh;
void antilag_record(entity e, float t)
{
+ if(e.vehicle)
+ antilag_record(e.vehicle, t);
+
if(time < e.(antilag_times[e.antilag_index]))
return;
e.antilag_index = e.antilag_index + 1;
if(e.antilag_debug)
te_spark(antilag_takebackorigin(e, t - e.antilag_debug), '0 0 0', 32);
+
}
// finds the index BEFORE t
vector antilag_takebackavgvelocity(entity e, float t0, float t1)
{
vector o0, o1;
+
if(t0 >= t1)
return '0 0 0';
o0 = antilag_takebackorigin(e, t0);
void antilag_takeback(entity e, float t)
{
+ if(e.vehicle)
+ antilag_takeback(e.vehicle, t);
+
e.antilag_saved_origin = e.origin;
setorigin(e, antilag_takebackorigin(e, t));
}
void antilag_restore(entity e)
{
+ if(e.vehicle)
+ antilag_restore(e.vehicle);
+
setorigin(e, e.antilag_saved_origin);
}
void antilag_record(entity e, float t);
-float antilag_find(entity e, float t);
vector antilag_takebackorigin(entity e, float t);
vector antilag_takebackavgvelocity(entity e, float t0, float t1);
void antilag_takeback(entity e, float t);
void assault_setenemytoobjective()
{
- local entity objective;
+ entity objective;
for(objective = world; (objective = find(objective, targetname, self.target)); ) {
if(objective.classname == "target_objective") {
if(self.enemy == world)
}
- local entity ent;
+ entity ent;
for(ent = world; (ent = nextent(ent)); )
{
if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)
--- /dev/null
+void() movetarget_f;
+void() t_movetarget;
+void() FoundTarget;
+
+float MONSTER_WANDER = 64; // disable wandering around
+float MONSTER_APPEAR = 128; // spawn invisible, and appear when triggered
+
+.float ismonster;
+.float monsterawaitingteleport; // avoid awaking monsters in teleport rooms
+
+// when a monster becomes angry at a player, that monster will be used
+// as the sight target the next frame so that monsters near that one
+// will wake up even if they wouldn't have noticed the player
+//
+entity sight_entity;
+float sight_entity_time;
+
+/*
+
+.enemy
+Will be world if not currently angry at anyone.
+
+.movetarget
+The next path spot to walk toward. If .enemy, ignore .movetarget.
+When an enemy is killed, the monster will try to return to it's path.
+
+.huntt_ime
+Set to time + something when the player is in sight, but movement straight for
+him is blocked. This causes the monster to use wall following code for
+movement direction instead of sighting on the player.
+
+.ideal_yaw
+A yaw angle of the intended direction, which will be turned towards at up
+to 45 deg / state. If the enemy is in view and hunt_time is not active,
+this will be the exact line towards the enemy.
+
+.pausetime
+A monster will leave it's stand state and head towards it's .movetarget when
+time > .pausetime.
+
+walkmove(angle, speed) primitive is all or nothing
+*/
+
+
+//
+// globals
+//
+//float current_yaw;
+
+float(float v) anglemod =
+{
+ v = v - 360 * floor(v / 360);
+ return v;
+}
+
+/*
+==============================================================================
+
+MOVETARGET CODE
+
+The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways heads to the next target.
+
+targetname
+must be present. The name of this movetarget.
+
+target
+the next spot to move to. If not present, stop here for good.
+
+pausetime
+The number of seconds to spend standing or bowing for path_stand or path_bow
+
+==============================================================================
+*/
+
+
+void() movetarget_f =
+{
+ if (!self.targetname)
+ objerror ("monster_movetarget: no targetname");
+
+ self.solid = SOLID_TRIGGER;
+ self.touch = t_movetarget;
+ setsize (self, '-8 -8 -8', '8 8 8');
+}
+
+/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8)
+Monsters will continue walking towards the next target corner.
+*/
+void() path_corner =
+{
+ movetarget_f ();
+}
+
+/*
+=============
+t_movetarget
+
+Something has bumped into a movetarget. If it is a monster
+moving towards it, change the next destination and continue.
+==============
+*/
+void() t_movetarget =
+{
+ entity temp;
+
+ if (other.health < 1)
+ return;
+ if (other.movetarget != self)
+ return;
+
+ if (other.enemy)
+ return; // fighting, not following a path
+
+ temp = self;
+ self = other;
+ other = temp;
+
+ /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+ if (self.classname == "monster_ogre")
+ sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
+ */
+
+//dprint ("t_movetarget\n");
+ self.goalentity = self.movetarget = find (world, targetname, other.target);
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ if (!self.movetarget)
+ {
+ self.pausetime = time + 999999;
+ self.th_stand ();
+ return;
+ }
+}
+
+void() monster_wanderpaththink =
+{
+ vector v, v1;
+ float b, c;
+ self.nextthink = time + random() * 10 + 1;
+ if (self.owner.health < 1) // dead, also handled in death code
+ {
+ self.owner.movetarget = world;
+ remove(self);
+ return;
+ }
+ b = -1;
+ c = 10;
+ while (c > 0)
+ {
+ c = c - 1;
+ v = randomvec();
+ traceline(self.owner.origin, v * 1024 + self.owner.origin, FALSE, self);
+ v = trace_endpos - (normalize(v) * 16) - self.owner.origin;
+ if (vlen(v) > b)
+ {
+ b = vlen(v);
+ v1 = v;
+ }
+ }
+ setorigin(self, v1 + self.owner.origin);
+ self.owner.ideal_yaw = vectoyaw(self.origin - self.owner.origin);
+}
+
+void() monster_wanderpathtouch =
+{
+ if (other.health < 1)
+ return;
+ if (other.movetarget != self)
+ return;
+
+ if (other.enemy)
+ return; // fighting, not following a path
+
+ /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+ if (other.classname == "monster_ogre")
+ sound (other, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
+ */
+ monster_wanderpaththink();
+}
+
+void() monster_spawnwanderpath =
+{
+ newmis = spawn();
+ newmis.classname = "monster_wanderpath";
+ newmis.solid = SOLID_TRIGGER;
+ newmis.touch = monster_wanderpathtouch;
+ setsize (newmis, '-8 -8 -8', '8 8 8');
+ newmis.think = monster_wanderpaththink;
+ newmis.nextthink = time + random() * 10 + 1;
+ newmis.owner = self;
+ self.goalentity = self.movetarget = newmis;
+}
+
+void() monster_checkbossflag =
+{
+//#NO AUTOCVARS START
+#if 0
+ float healthboost;
+ float r;
+
+ // monsterbosses cvar or spawnflag 64 causes a monster to be a miniboss
+ if ((self.spawnflags & 64) || (random() * 100 < cvar("monsterbosspercent")))
+ {
+ self.radsuit_finished = time + 1000000000;
+ r = random() * 4;
+ if (r < 2)
+ {
+ self.super_damage_finished = time + 1000000000;
+ healthboost = 30 + self.health * 0.5;
+ self.effects = self.effects | (EF_FULLBRIGHT | EF_BLUE);
+ }
+ if (r >= 1)
+ {
+ healthboost = 30 + self.health * bound(0.5, skill * 0.5, 1.5);
+ self.effects = self.effects | (EF_FULLBRIGHT | EF_RED);
+ self.healthregen = max(self.healthregen, min(skill * 10, 30));
+ }
+ self.health = self.health + healthboost;
+ self.max_health = self.health;
+ self.bodyhealth = self.bodyhealth * 2 + healthboost;
+ do
+ {
+ self.colormod_x = random();
+ self.colormod_y = random();
+ self.colormod_z = random();
+ self.colormod = normalize(self.colormod);
+ }
+ while (self.colormod_x > 0.6 && self.colormod_y > 0.6 && self.colormod_z > 0.6);
+ }
+#endif
+//#NO AUTOCVARS END
+}
+
+
+//============================================================================
+
+/*
+=============
+range
+
+returns the range catagorization of an entity reletive to self
+0 melee range, will become hostile even if back is turned
+1 visibility and infront, or visibility and show hostile
+2 infront and show hostile
+3 only triggered by damage
+=============
+*/
+float(entity targ) range =
+{
+ float r;
+ r = vlen ((self.origin + self.view_ofs) - (targ.origin + targ.view_ofs));
+ if (r < 120)
+ return RANGE_MELEE;
+ if (r < 500)
+ return RANGE_NEAR;
+ if (r < 2000) // increased from 1000 for DP
+ return RANGE_MID;
+ return RANGE_FAR;
+}
+
+/*
+=============
+visible
+
+returns 1 if the entity is visible to self, even if not infront ()
+=============
+*/
+float (entity targ) visible =
+{
+ if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
+ return FALSE;
+
+ traceline ((self.origin + self.view_ofs), (targ.origin + targ.view_ofs), TRUE, self); // see through other monsters
+
+ if (trace_inopen && trace_inwater)
+ return FALSE; // sight line crossed contents
+
+ if (trace_fraction == 1)
+ return TRUE;
+ return FALSE;
+}
+
+
+/*
+=============
+infront
+
+returns 1 if the entity is in front (in sight) of self
+=============
+*/
+float(entity targ) infront =
+{
+ float dot;
+
+ makevectors (self.angles);
+ dot = normalize (targ.origin - self.origin) * v_forward;
+
+ return (dot > 0.3);
+}
+// returns 0 if not infront, or the dotproduct if infront
+float(vector dir, entity targ) infront2 =
+{
+ float dot;
+
+ dir = normalize(dir);
+ dot = normalize (targ.origin - self.origin) * dir;
+
+ if (dot >= 0.3) return dot; // infront
+ return 0;
+}
+
+
+//============================================================================
+
+/*
+===========
+ChangeYaw
+
+Turns towards self.ideal_yaw at self.yaw_speed
+Sets the global variable current_yaw
+Called every 0.1 sec by monsters
+============
+*/
+/*
+
+void() ChangeYaw =
+{
+ float ideal, move;
+
+//current_yaw = self.ideal_yaw;
+// mod down the current angle
+ current_yaw = anglemod( self.angles_y );
+ ideal = self.ideal_yaw;
+
+ if (current_yaw == ideal)
+ return;
+
+ move = ideal - current_yaw;
+ if (ideal > current_yaw)
+ {
+ if (move > 180)
+ move = move - 360;
+ }
+ else
+ {
+ if (move < -180)
+ move = move + 360;
+ }
+
+ if (move > 0)
+ {
+ if (move > self.yaw_speed)
+ move = self.yaw_speed;
+ }
+ else
+ {
+ if (move < 0-self.yaw_speed )
+ move = 0-self.yaw_speed;
+ }
+
+ current_yaw = anglemod (current_yaw + move);
+
+ self.angles_y = current_yaw;
+}
+
+*/
+
+
+//============================================================================
+
+void() HuntTarget =
+{
+ self.goalentity = self.enemy;
+ self.think = self.th_run;
+ self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
+ self.nextthink = time + 0.1;
+ SUB_AttackFinished (1); // wait a while before first attack
+}
+
+.void() th_sightsound;
+
+void() SightSound =
+{
+ if (self.health < 1)
+ return;
+ // skill 5 does not play sight sounds, instead you only hear the appear sound as they are about to attack
+ if (skill >= 5)
+ if (self.classname != "monster_hellfish")
+ return;
+
+ if (self.th_sightsound)
+ self.th_sightsound();
+}
+
+void() FoundTarget =
+{
+ if (self.health < 1 || !self.th_run)
+ return;
+ if (self.enemy.health < 1 || !self.enemy.takedamage)
+ return;
+ if (self.enemy.classname == "player")
+ {
+ // let other monsters see this monster for a while
+ sight_entity = self;
+ sight_entity_time = time + 0.1;
+ }
+
+ self.show_hostile = time + 1; // wake up other monsters
+
+ SightSound ();
+ HuntTarget ();
+}
+
+/*
+//float checkplayertime;
+entity lastcheckplayer;
+entity havocbot_list;
+
+
+entity() checkplayer =
+{
+ entity check;
+ float worldcount;
+ // we can just fallback on checkclient if there are no bots
+ if (!havocbot_list)
+ return checkclient();
+*/
+ /*
+ if (time < checkplayertime)
+ {
+ traceline(self.origin + self.view_ofs, lastcheckplayer.origin + lastcheckplayer.view_ofs, TRUE, self);
+ if (trace_fraction == 1)
+ return lastcheckplayer;
+ if (trace_ent == lastcheckplayer)
+ return lastcheckplayer;
+ }
+ checkplayertime = time + 0.1;
+ */
+/*
+ check = lastcheckplayer;
+ worldcount = 0;
+ c = 0;
+ do
+ {
+ c = c + 1;
+ check = findfloat(check, havocattack, TRUE);
+ if (check.classname == "player" || check.classname == "turretbase")
+ {
+ traceline(self.origin + self.view_ofs, check.origin + check.view_ofs, TRUE, self);
+ if (trace_fraction == 1)
+ return lastcheckplayer = check;
+ if (trace_ent == check)
+ return lastcheckplayer = check;
+ }
+ else if (check == world)
+ {
+ worldcount = worldcount + 1;
+ if (worldcount >= 2)
+ return lastcheckplayer = check;
+ }
+ }
+ while(check != lastcheckplayer && c < 100);
+ return world;
+}
+*/
+
+/*
+===========
+FindTarget
+
+Self is currently not attacking anything, so try to find a target
+
+Returns TRUE if an enemy was sighted
+
+When a player fires a missile, the point of impact becomes a fakeplayer so
+that monsters that see the impact will respond as if they had seen the
+player.
+
+To avoid spending too much time, only a single client (or fakeclient) is
+checked each frame. This means multi player games will have slightly
+slower noticing monsters.
+============
+*/
+.float findtarget;
+float() FindTarget =
+{
+ entity client;
+ float r;
+
+ if (self.health < 1)
+ return FALSE;
+
+ // if the first or second spawnflag bit is set, the monster will only
+ // wake up on really seeing the player, not another monster getting angry
+
+ if (self.spawnflags & 3)
+ {
+ // don't wake up on seeing another monster getting angry
+ client = checkclient ();
+ if (!client)
+ return FALSE; // current check entity isn't in PVS
+ }
+ else
+ {
+ if (sight_entity_time >= time)
+ {
+ client = sight_entity;
+ if (client.enemy == self.enemy)
+ return TRUE;
+ }
+ else
+ {
+ client = checkclient ();
+ if (!client)
+ return FALSE; // current check entity isn't in PVS
+ }
+ }
+
+ if (client == self.enemy)
+ return FALSE;
+
+ if (client.flags & FL_NOTARGET)
+ return FALSE;
+
+#if 0
+ if (client.items & IT_INVISIBILITY)
+ return FALSE;
+#endif
+
+ // on skill 5 the monsters usually ignore the player and remain ghostlike
+ if (skill >= 5)
+ if (self.classname != "monster_hellfish")
+ if (random() < 0.99)
+ return FALSE;
+
+ r = range(client);
+ if (r == RANGE_FAR)
+ return FALSE;
+
+ if (!visible (client))
+ return FALSE;
+
+ if (r == RANGE_NEAR)
+ {
+ if (client.show_hostile < time && !infront (client))
+ return FALSE;
+ }
+ else if (r == RANGE_MID)
+ {
+ // LordHavoc: was if ( /* client.show_hostile < time || */ !infront (client))
+ if (client.show_hostile < time && !infront (client))
+ return FALSE;
+ }
+
+ //
+ // got one
+ //
+
+ if (client.model == "")
+ return FALSE;
+ self.enemy = client;
+ if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
+ {
+ self.enemy = self.enemy.enemy;
+ if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
+ {
+ self.enemy = world;
+ return FALSE;
+ }
+ }
+
+ FoundTarget ();
+
+ return TRUE;
+}
+
+
+//=============================================================================
+
+void(float dist) ai_forward =
+{
+ walkmove (self.angles_y, dist);
+}
+
+void(float dist) ai_back =
+{
+ walkmove ( (self.angles_y+180), dist);
+}
+
+
+void(float a) monster_setalpha;
+
+/*
+=============
+ai_pain
+
+stagger back a bit
+=============
+*/
+void(float dist) ai_pain =
+{
+ if (self.health < 1)
+ return;
+ ai_back (dist);
+}
+
+/*
+=============
+ai_painforward
+
+stagger back a bit
+=============
+*/
+void(float dist) ai_painforward =
+{
+ if (self.health < 1)
+ return;
+ walkmove (self.ideal_yaw, dist);
+}
+
+/*
+=============
+ai_walk
+
+The monster is walking it's beat
+=============
+*/
+void(float dist) ai_walk =
+{
+ if (self.health < 1)
+ return;
+
+ movedist = dist;
+
+ // check for noticing a player
+ if (self.oldenemy.takedamage)
+ if (self.oldenemy.health >= 1)
+ {
+ self.enemy = self.oldenemy;
+ self.oldenemy = world;
+ FoundTarget();
+ monster_setalpha(0);
+ return;
+ }
+ if (self.enemy)
+ {
+ if (self.enemy.takedamage)
+ {
+ if (self.enemy.health >= 1)
+ {
+ FoundTarget();
+ monster_setalpha(0);
+ return;
+ }
+ else
+ self.enemy = world;
+ }
+ else
+ self.enemy = world;
+ }
+
+ self.findtarget = TRUE;
+
+ movetogoal (dist);
+ monster_setalpha(0);
+}
+
+
+/*
+=============
+ai_stand
+
+The monster is staying in one place for a while, with slight angle turns
+=============
+*/
+void() ai_stand =
+{
+ if (self.health < 1)
+ return;
+ if (self.enemy)
+ {
+ if (self.enemy.takedamage)
+ {
+ if (self.enemy.health >= 1)
+ {
+ FoundTarget();
+ monster_setalpha(0);
+ return;
+ }
+ else
+ self.enemy = world;
+ }
+ else
+ self.enemy = world;
+ }
+ self.findtarget = TRUE;
+
+ if (time > self.pausetime)
+ {
+ self.th_walk ();
+ monster_setalpha(0);
+ return;
+ }
+
+// change angle slightly
+
+ monster_setalpha(0);
+}
+
+/*
+=============
+ai_turn
+
+don't move, but turn towards ideal_yaw
+=============
+*/
+void() ai_turn =
+{
+ if (self.enemy)
+ {
+ if (self.enemy.takedamage)
+ {
+ if (self.enemy.health >= 1)
+ {
+ FoundTarget();
+ monster_setalpha(0);
+ return;
+ }
+ else
+ self.enemy = world;
+ }
+ else
+ self.enemy = world;
+ }
+ self.findtarget = TRUE;
+
+ ChangeYaw ();
+ monster_setalpha(0);
+}
+
+//=============================================================================
+
+/*
+=============
+ChooseTurn
+=============
+*/
+void(vector pDestvec) ChooseTurn =
+{
+ vector dir, newdir;
+
+ dir = self.origin - pDestvec;
+
+ newdir_x = trace_plane_normal_y;
+ newdir_y = 0 - trace_plane_normal_x;
+ newdir_z = 0;
+
+ if (dir * newdir > 0)
+ {
+ dir_x = 0 - trace_plane_normal_y;
+ dir_y = trace_plane_normal_x;
+ }
+ else
+ {
+ dir_x = trace_plane_normal_y;
+ dir_y = 0 - trace_plane_normal_x;
+ }
+
+ dir_z = 0;
+ self.ideal_yaw = vectoyaw(dir);
+}
+
+/*
+============
+FacingIdeal
+
+============
+*/
+float() FacingIdeal =
+{
+ float delta;
+
+ delta = anglemod(self.angles_y - self.ideal_yaw);
+ if (delta > 45 && delta < 315)
+ return FALSE;
+ return TRUE;
+}
+
+
+//=============================================================================
+
+.float() th_checkattack;
+
+
+
+/*
+=============
+ai_run
+
+The monster has an enemy it is trying to kill
+=============
+*/
+void(float dist) ai_run =
+{
+ float ofs;
+ if (self.health < 1)
+ return;
+ movedist = dist;
+ // see if the enemy is dead
+ if (self.enemy.health < 1 || self.enemy.takedamage == DAMAGE_NO)
+ {
+ self.enemy = world;
+ // FIXME: look all around for other targets
+ if (self.oldenemy.health >= 1 && self.oldenemy.takedamage)
+ {
+ self.enemy = self.oldenemy;
+ self.oldenemy = world;
+ HuntTarget ();
+ }
+ else
+ {
+ if (self.movetarget)
+ self.th_walk ();
+ else
+ self.th_stand ();
+ return;
+ }
+ }
+
+ // wake up other monsters
+ self.show_hostile = time + 1;
+
+ // check knowledge of enemy
+ enemy_range = range(self.enemy);
+
+ self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
+ ChangeYaw ();
+
+ if (self.attack_state == AS_MELEE)
+ {
+ //dprint ("ai_run_melee\n");
+ //Turn and close until within an angle to launch a melee attack
+ if (FacingIdeal())
+ {
+ self.th_melee ();
+ self.attack_state = AS_STRAIGHT;
+ }
+ return;
+ }
+ else if (self.attack_state == AS_MISSILE)
+ {
+ //dprint ("ai_run_missile\n");
+ //Turn in place until within an angle to launch a missile attack
+ if (FacingIdeal())
+ if (self.th_missile ())
+ self.attack_state = AS_STRAIGHT;
+ return;
+ }
+
+ if (self.th_checkattack())
+ return; // beginning an attack
+
+ if (visible(self.enemy))
+ self.search_time = time + 5;
+ else if (coop)
+ {
+ // look for other coop players
+ if (self.search_time < time)
+ self.findtarget = TRUE;
+ }
+
+ if (self.attack_state == AS_SLIDING)
+ {
+ //dprint ("ai_run_slide\n");
+ //Strafe sideways, but stay at aproximately the same range
+ if (self.lefty)
+ ofs = 90;
+ else
+ ofs = -90;
+
+ if (walkmove (self.ideal_yaw + ofs, movedist))
+ return;
+
+ self.lefty = !self.lefty;
+
+ walkmove (self.ideal_yaw - ofs, movedist);
+ }
+
+ // head straight in
+ movetogoal (dist); // done in C code...
+}
+
--- /dev/null
+.entity movetarget;
+.float pausetime;
+
+.void() th_stand;
+.void() th_walk;
+.void() th_run;
+.float() th_missile; // LordHavoc: changed from void() to float(), returns true if attacking
+.void() th_melee;
+//.void(entity attacker, float damage, float damgtype, string dethtype) th_pain; // TODO Xonotic uses event_damage
+//.void() th_die; // TODO never called directly by Xonotic
+.entity oldenemy; // mad at this player before taking damage
+entity newmis; // launch_spike sets this after spawning it
+
+// range values
+float RANGE_MELEE = 0;
+float RANGE_NEAR = 1;
+float RANGE_MID = 2;
+float RANGE_FAR = 3;
+
+float DMG_KNIGHT_MELEE_BASE = 0;
+float DMG_KNIGHT_MELEE_RANDOM1 = 3;
+float DMG_KNIGHT_MELEE_RANDOM2 = 3;
+float DMG_KNIGHT_MELEE_RANDOM3 = 3;
+
+.float show_hostile;
+ // set to time+0.2 whenever a client fires a
+ // weapon or takes damage. Used to alert
+ // monsters that otherwise would let the player go
+
+float movedist;
+.float lefty;
+.float search_time;
+.float attack_state;
+
+float AS_STRAIGHT = 1;
+float AS_SLIDING = 2;
+float AS_MELEE = 3;
+float AS_MISSILE = 4;
+
+float SKILL4_MINALPHA = 0.4;
+
+float monsterwander;
+//#NO AUTOCVARS START
+/*
+ monsterwander = cvar("monsterwander");
+ // monsterwander is always on in skill 5
+ if (skill >= 5)
+ monsterwander = TRUE;
+*/
+//#NO AUTOCVARS END
+
+.float candrown;
+
+.void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc;
+void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc;
--- /dev/null
+
+/*
+
+A monster is in fight mode if it thinks it can effectively attack its
+enemy.
+
+When it decides it can't attack, it goes into hunt mode.
+
+*/
+
+void SUB_AttackFinished (float normal)
+{
+ self.cnt = 0; // refire count for nightmare
+ if (skill < 3)
+ ATTACK_FINISHED(self) = time + normal;
+}
+
+float CanDamage(entity targ, entity inflictor)
+{
+ if (targ.movetype == MOVETYPE_PUSH)
+ {
+ traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
+ if (trace_fraction == 1)
+ return TRUE;
+ if (trace_ent == targ)
+ return TRUE;
+ return FALSE;
+ }
+
+ traceline(inflictor.origin, targ.origin, TRUE, self);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
+ if (trace_fraction == 1)
+ return TRUE;
+
+ return FALSE;
+}
+
+float(float v) anglemod;
+
+void(vector dest) ChooseTurn;
+
+void() ai_face;
+
+
+float enemy_range;
+
+
+//=============================================================================
+
+/*
+===========
+GenericCheckAttack
+
+The player is in view, so decide to move or launch an attack
+Returns FALSE if movement should continue
+============
+*/
+float() GenericCheckAttack =
+{
+ vector spot1, spot2;
+ entity targ;
+ float chance;
+
+ if (self.health < 1)
+ return FALSE;
+ targ = self.enemy;
+
+ if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
+ return FALSE;
+
+// see if any entities are in the way of the shot
+ spot1 = self.origin + self.view_ofs;
+ spot2 = targ.origin + targ.view_ofs;
+
+ traceline (spot1, spot2, FALSE, self);
+
+ if (trace_ent != targ)
+ return FALSE; // don't have a clear shot
+
+ if (trace_inopen && trace_inwater)
+ return FALSE; // sight line crossed contents
+
+ if (enemy_range == RANGE_MELEE)
+ { // melee attack
+ if (self.th_melee)
+ {
+ self.th_melee ();
+ return TRUE;
+ }
+ }
+
+// missile attack
+ if (time < ATTACK_FINISHED(self))
+ return FALSE;
+
+ if (!self.th_missile)
+ return FALSE;
+
+ if (enemy_range == RANGE_FAR)
+ return FALSE;
+
+ if (enemy_range == RANGE_MELEE)
+ {
+ chance = 0.9;
+ ATTACK_FINISHED(self) = 0;
+ }
+ else if (enemy_range == RANGE_NEAR)
+ {
+ if (self.th_melee)
+ chance = 0.2;
+ else
+ chance = 0.4;
+ }
+ else if (enemy_range == RANGE_MID)
+ {
+ if (self.th_melee)
+ chance = 0.05;
+ else
+ chance = 0.1;
+ }
+ else
+ chance = 0;
+
+ if (random () < chance)
+ if (self.th_missile ())
+ {
+ SUB_AttackFinished (2*random());
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+=============
+ai_face
+
+Stay facing the enemy
+=============
+*/
+void() ai_face =
+{
+ self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
+ ChangeYaw ();
+}
+
+/*
+=============
+ai_charge
+
+The monster is in a melee attack, so get as close as possible to .enemy
+=============
+*/
+float (entity targ) visible;
+float(entity targ) infront;
+float(entity targ) range;
+
+void(float d) ai_charge =
+{
+ if (self.health < 1)
+ return;
+ ai_face ();
+ movetogoal (d); // done in C code...
+}
+
+void() ai_charge_side =
+{
+ if (self.health < 1)
+ return;
+ vector dtemp;
+ float heading;
+
+// aim to the left of the enemy for a flyby
+
+ self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
+ ChangeYaw ();
+
+ makevectors (self.angles);
+ dtemp = self.enemy.origin - 30*v_right;
+ heading = vectoyaw(dtemp - self.origin);
+
+ walkmove(heading, 20);
+}
+
+
+/*
+=============
+ai_melee
+
+=============
+*/
+void() ai_melee =
+{
+ vector delta;
+ float ldmg;
+
+ if (self.health < 1)
+ return;
+ if (!self.enemy)
+ return; // removed before stroke
+
+ delta = self.enemy.origin - self.origin;
+
+ if (vlen(delta) > 60)
+ return;
+
+ ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
+ ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
+ ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
+ traceline(self.origin, self.enemy.origin, FALSE, self);
+
+ Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); // TODO add force to monster melee attacks?
+}
+
+
+void() ai_melee_side =
+{
+ vector delta;
+ float ldmg;
+
+ if (self.health < 1)
+ return;
+ if (!self.enemy)
+ return; // removed before stroke
+
+ ai_charge_side();
+
+ delta = self.enemy.origin - self.origin;
+
+ if (vlen(delta) > 60)
+ return;
+ if (!CanDamage (self.enemy, self))
+ return;
+ ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
+ ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
+ ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
+ traceline(self.origin, self.enemy.origin, FALSE, self);
+ Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0');
+}
+
--- /dev/null
+/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
+
+// name =[framenum, nexttime, nextthink] {code}
+// expands to:
+// name ()
+// {
+// self.frame=framenum;
+// self.nextthink = time + nexttime;
+// self.think = nextthink
+// <code>
+// }
+
+.float ismonster;
+
+.float modelindex2;
+
+/*
+================
+monster_use
+
+Using a monster makes it angry at the current activator
+LordHavoc: using a monster with the spawnflag 'Appear' makes it appear
+================
+*/
+void() monster_use =
+{
+ if (self.enemy)
+ return;
+ if (self.health < 1)
+ return;
+ if (self.mdl)
+ if (self.spawnflags & MONSTER_APPEAR)
+ {
+ self.nextthink = time + 0.1;
+ self.spawnflags = self.spawnflags - MONSTER_APPEAR;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ //self.movetype = MOVETYPE_STEP;
+ self.model = self.mdl;
+ self.mdl = "";
+ self.modelindex = self.modelindex2;
+ self.modelindex2 = 0;
+ //setorigin(self, self.origin + '0 0 1');
+ spawn_tdeath(self.origin, self, self.origin);
+ return;
+ }
+
+#if 0
+ if (activator.items & IT_INVISIBILITY)
+ return;
+#endif
+ if (activator.flags & FL_NOTARGET)
+ return;
+ if (activator.classname != "player")
+ return;
+
+ // delay reaction so if the monster is teleported, its sound is still heard
+ self.enemy = activator;
+ self.nextthink = time + 0.1;
+ self.think = FoundTarget;
+}
+
+void() monster_appearsetup =
+{
+ if ((self.spawnflags & MONSTER_APPEAR) == 0)
+ return;
+ self.mdl = self.model;
+ self.modelindex2 = self.modelindex;
+ self.modelindex = 0;
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ //self.movetype = MOVETYPE_NONE;
+ self.nextthink = -1;
+ self.model = "";
+}
+
+/*
+================
+monster_setalpha
+
+Sets relative alpha of monster in skill 4 mode.
+================
+*/
+void(float a) monster_setalpha =
+{
+ if (skill < 4 || self.classname == "monster_hellfish")
+ {
+ self.alpha = 1.0;
+ return;
+ }
+
+ if (skill >= 5)
+ {
+ // randomly forget enemy, this makes monsters randomly return to their normal ghostlike state
+ if (a == 0)
+ if (self.enemy)
+ if (random() < 0.1)
+ self.enemy = world;
+ // randomly blink (playing the same alarming sound as if attacking)
+ if (self.enemy == world)
+ {
+ a = 0;
+ if (time >= 0.3) // don't blink during the init process because it might become permanent
+ if (random() < 0.005)
+ {
+ // blink for an instant, this causes the appear sound, alarming the player as if under attack
+ /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+ sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
+ */
+ a = 1;
+ }
+ }
+ // if ghosted, become non-solid and immune to damage
+ if (a <= 0 || self.enemy == world)
+ {
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ }
+ else
+ {
+ // if unghosting, make sure we have an enemy, otherwise stay ghosted (even if blinking) so we can't be shot while blinking
+ /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+ if (self.solid != SOLID_SLIDEBOX)
+ sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
+ */
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ }
+ }
+ self.alpha = SKILL4_MINALPHA + (1 - SKILL4_MINALPHA) * bound(0, a, 1);
+}
+
+/*
+================
+monster_death_use
+
+When a mosnter dies, it fires all of its targets with the current
+enemy as activator.
+================
+*/
+void() monster_death_use =
+{
+// fall to ground
+ if (self.flags & FL_FLY)
+ self.flags = self.flags - FL_FLY;
+ if (self.flags & FL_SWIM)
+ self.flags = self.flags - FL_SWIM;
+
+ if (!self.target)
+ return;
+
+ activator = self.enemy;
+ SUB_UseTargets ();
+}
+
+
+void() monsterinwall =
+{
+ entity e;
+ if (!autocvar_developer)
+ return;
+ // this is handy for level designers,
+ // puts a spikey ball where the error is...
+ e = spawn();
+ setorigin(e, self.origin);
+ setmodel (e, "models/ebomb.mdl");
+ e.movetype = MOVETYPE_NONE;
+ e.solid = SOLID_NOT;
+ e.think = SUB_Null;
+ e.nextthink = -1;
+ e.scale = 16;
+}
+
+//============================================================================
+
+void() walkmonster_start_go =
+{
+ self.origin_z = self.origin_z + 1; // raise off floor a bit
+
+ tracebox(self.origin, self.mins, self.maxs, self.origin, TRUE, self);
+ if (trace_startsolid)
+ {
+ dprint("walkmonster in wall at: ");
+ dprint(vtos(self.origin));
+ dprint("\n");
+ monsterinwall();
+ droptofloor();
+ }
+ else
+ {
+ droptofloor();
+ if (!walkmove(0,0))
+ {
+ dprint("walkmonster in wall at: ");
+ dprint(vtos(self.origin));
+ dprint("\n");
+ monsterinwall();
+ }
+ }
+
+ //self.cantrigger = TRUE;
+
+ self.takedamage = DAMAGE_AIM;
+
+ self.ideal_yaw = self.angles * '0 1 0';
+ if (!self.yaw_speed)
+ self.yaw_speed = 20;
+ self.view_ofs = '0 0 25';
+ self.use = monster_use;
+
+ self.flags = self.flags | FL_MONSTER;
+
+ if (monsterwander)
+ self.spawnflags = self.spawnflags | MONSTER_WANDER;
+
+ if (self.target)
+ {
+ self.goalentity = self.movetarget = find(world, targetname, self.target);
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ if (!self.movetarget)
+ {
+ dprint("Monster can't find target at ");
+ dprint(vtos(self.origin));
+ dprint("\n");
+ }
+ // this used to be an objerror
+ if (self.movetarget.classname == "path_corner")
+ self.th_walk ();
+ else
+ {
+ if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+ {
+ monster_spawnwanderpath();
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ self.th_walk ();
+ }
+ else
+ {
+ self.pausetime = 99999999;
+ self.th_stand ();
+ }
+ }
+ }
+ else
+ {
+ if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+ {
+ monster_spawnwanderpath();
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ self.th_walk ();
+ }
+ else
+ {
+ self.pausetime = 99999999;
+ self.th_stand ();
+ }
+ }
+
+// spread think times so they don't all happen at same time
+ self.nextthink = self.nextthink + random()*0.5 + 0.1;
+ self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
+
+ force_retouch = 2; // mainly to detect teleports
+
+ monster_appearsetup();
+}
+
+
+void() walkmonster_start =
+{
+ self.candrown = 1; // this is turned off by some monsters like zombies
+ // delay drop to floor to make sure all doors have been spawned
+ // spread think times so they don't all happen at same time
+ self.nextthink = time + random()*0.5 + 0.3;
+ self.think = walkmonster_start_go;
+ total_monsters = total_monsters + 1;
+ self.bot_attack = TRUE;
+ self.frags = 2; // actually just used to get havocbots to attack it...
+ self.bleedfunc = genericbleedfunc;
+ self.ismonster = TRUE;
+
+ monster_setalpha (0);
+}
+
+
+
+void() flymonster_start_go =
+{
+ self.takedamage = DAMAGE_AIM;
+
+ self.ideal_yaw = self.angles * '0 1 0';
+ if (!self.yaw_speed)
+ self.yaw_speed = 10;
+ self.view_ofs = '0 0 25';
+ self.use = monster_use;
+
+ self.flags = self.flags | FL_FLY;
+ self.flags = self.flags | FL_MONSTER;
+
+ if (!walkmove(0,0))
+ {
+ dprint("flymonster in wall at: ");
+ dprint(vtos(self.origin));
+ dprint("\n");
+ monsterinwall();
+ }
+
+ //self.cantrigger = TRUE;
+
+ if (monsterwander)
+ self.spawnflags = self.spawnflags | MONSTER_WANDER;
+
+ if (self.target)
+ {
+ self.goalentity = self.movetarget = find(world, targetname, self.target);
+ if (!self.movetarget)
+ {
+ dprint("Monster can't find target at ");
+ dprint(vtos(self.origin));
+ dprint("\n");
+ }
+ // this used to be an objerror
+ if (self.movetarget.classname == "path_corner")
+ self.th_walk ();
+ else
+ {
+ if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+ {
+ monster_spawnwanderpath();
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ self.th_walk ();
+ }
+ else
+ {
+ self.pausetime = 99999999;
+ self.th_stand ();
+ }
+ }
+ }
+ else
+ {
+ if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+ {
+ monster_spawnwanderpath();
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ self.th_walk ();
+ }
+ else
+ {
+ self.pausetime = 99999999;
+ self.th_stand ();
+ }
+ }
+ self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
+
+ force_retouch = 2; // mainly to detect teleports
+
+ monster_appearsetup();
+}
+
+void() flymonster_start =
+{
+ self.candrown = 1;
+ // spread think times so they don't all happen at same time
+ self.nextthink = time + random()*0.5 + 0.1;
+ self.think = flymonster_start_go;
+ total_monsters = total_monsters + 1;
+ self.bot_attack = TRUE;
+ self.frags = 2; // actually just used to get havocbots to attack it...
+ self.bleedfunc = genericbleedfunc;
+ self.ismonster = TRUE;
+
+ monster_setalpha (0);
+}
+
+
+void() swimmonster_start_go =
+{
+ if (deathmatch)
+ {
+ remove(self);
+ return;
+ }
+
+ //self.cantrigger = TRUE;
+
+ self.takedamage = DAMAGE_AIM;
+
+ self.ideal_yaw = self.angles * '0 1 0';
+ if (!self.yaw_speed)
+ self.yaw_speed = 10;
+ self.view_ofs = '0 0 10';
+ self.use = monster_use;
+
+ self.flags = self.flags | FL_SWIM;
+ self.flags = self.flags | FL_MONSTER;
+
+ if (monsterwander)
+ self.spawnflags = self.spawnflags | MONSTER_WANDER;
+
+ if (self.target)
+ {
+ self.goalentity = self.movetarget = find(world, targetname, self.target);
+ if (!self.movetarget)
+ {
+ dprint("Monster can't find target at ");
+ dprint(vtos(self.origin));
+ dprint("\n");
+ }
+ // this used to be an objerror
+ if (self.movetarget.classname == "path_corner")
+ self.th_walk ();
+ else
+ {
+ if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+ {
+ monster_spawnwanderpath();
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ self.th_walk ();
+ }
+ else
+ {
+ self.pausetime = 99999999;
+ self.th_stand ();
+ }
+ }
+ }
+ else
+ {
+ if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+ {
+ monster_spawnwanderpath();
+ self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+ self.th_walk ();
+ }
+ else
+ {
+ self.pausetime = 99999999;
+ self.th_stand ();
+ }
+ }
+ self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
+
+ force_retouch = 2; // mainly to detect teleports
+
+ monster_appearsetup();
+}
+
+void() swimmonster_start =
+{
+ // spread think times so they don't all happen at same time
+ self.candrown = 0;
+ self.nextthink = time + random()*0.5 + 0.1;
+ self.think = swimmonster_start_go;
+ total_monsters = total_monsters + 1;
+ self.bot_attack = TRUE;
+ self.frags = 2; // actually just used to get havocbots to attack it...
+ self.bleedfunc = genericbleedfunc;
+ self.ismonster = TRUE;
+
+ monster_setalpha(0);
+}
+
+void(vector org, float bodydamage, float armordamage, vector force, float damgtype) genericbleedfunc =
+{
+ vector v;
+ v = '0 0 0' - force * 0.05;
+ if (armordamage > 0)
+ te_spark(org, v, armordamage * 3);
+ if (bodydamage > 0)
+ te_blood(org, v, bodydamage);
+}
--- /dev/null
+//#define MONSTES_ENABLED
+#ifdef MONSTES_ENABLED
+
+float autocvar_g_monster_zombie_attack_run_damage;
+float autocvar_g_monster_zombie_attack_run_delay;
+float autocvar_g_monster_zombie_attack_run_force;
+float autocvar_g_monster_zombie_attack_run_hitrange;
+float autocvar_g_monster_zombie_attack_run_range;
+float autocvar_g_monster_zombie_attack_stand_damage;
+float autocvar_g_monster_zombie_attack_stand_delay;
+float autocvar_g_monster_zombie_attack_stand_force;
+float autocvar_g_monster_zombie_attack_stand_range;
+float autocvar_g_monster_zombie_health;
+float autocvar_g_monster_zombie_idle_timer_max;
+float autocvar_g_monster_zombie_idle_timer_min;
+float autocvar_g_monster_zombie_movespeed;
+float autocvar_g_monster_zombie_respawntime;
+float autocvar_g_monster_zombie_stopspeed;
+float autocvar_g_monster_zombie_targetrange;
+float autocvar_g_monster_zombie_turnspeed;
+float autocvar_g_monsters;
+
+
+#define zombie_anim_attackleap 0
+#define zombie_anim_attackrun1 1
+#define zombie_anim_attackrun2 2
+#define zombie_anim_attackrun3 3
+#define zombie_anim_attackstanding1 4
+#define zombie_anim_attackstanding2 5
+#define zombie_anim_attackstanding3 6
+#define zombie_anim_blockend 7
+#define zombie_anim_blockstart 8
+#define zombie_anim_deathback1 9
+#define zombie_anim_deathback2 10
+#define zombie_anim_deathback3 11
+#define zombie_anim_deathfront1 12
+#define zombie_anim_deathfront2 13
+#define zombie_anim_deathfront3 14
+#define zombie_anim_deathleft1 15
+#define zombie_anim_deathleft2 16
+#define zombie_anim_deathright1 17
+#define zombie_anim_deathright2 18
+#define zombie_anim_idle 19
+#define zombie_anim_painback1 20
+#define zombie_anim_painback2 21
+#define zombie_anim_painfront1 22
+#define zombie_anim_painfront2 23
+#define zombie_anim_runbackwards 24
+#define zombie_anim_runbackwardsleft 25
+#define zombie_anim_runbackwardsright 26
+#define zombie_anim_runforward 27
+#define zombie_anim_runforwardleft 28
+#define zombie_anim_runforwardright 29
+#define zombie_anim_spawn 30
+
+#define ZOMBIE_MIN '-18 -18 -25'
+#define ZOMBIE_MAX '18 18 47'
+
+#define ZV_IDLE 10
+
+#define ZV_PATH 100
+#define ZV_HUNT 200
+
+#define ZV_ATTACK_FIND 10
+#define ZV_ATTACK_RUN 20
+#define ZV_ATTACK_STAND 30
+
+#define ZV_PATH2 10000
+
+//.entity verbs_idle;
+//.entity verbs_attack;
+//.entity verbs_move;
+
+//.float state_timeout;
+//.void() monster_state;
+#define MONSTERFLAG_NORESPAWN 2
+
+void zombie_spawn();
+
+float zombie_scoretarget(entity trg)
+{
+ float tmp;
+ vector ang1;
+
+ if (trg.takedamage == DAMAGE_AIM)
+ if not (trg.flags & FL_NOTARGET)
+ if (trg.deadflag == DEAD_NO)
+ if (trg.team != self.team)
+ {
+ if((self.origin_z - trg.origin_z) < 128)
+ {
+ ang1 = normalize(self.origin - trg.origin);
+ tmp = vlen(ang1 - v_forward);
+ if(tmp > 1.5)
+ {
+ traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);
+ if(trace_ent != trg)
+ return 0;
+
+ return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
+ }
+ else if(self.enemy == trg)
+ return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
+ }
+ }
+
+ return 0;
+}
+
+void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ //dprint("zombie_corpse_damage\n");
+ Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+ self.health -= damage;
+
+ if(self.health < 0)
+ {
+ Violence_GibSplash(self, 1, 1, attacker);
+ remove(self);
+ }
+}
+
+void zombie_die(vector dir)
+{
+ vector v;
+ float f;
+
+ entity dummy;
+
+ dummy = spawn();
+ setmodel(dummy,"models/monsters/zombie.dpm");
+ setorigin(dummy, self.origin);
+ dummy.velocity = self.velocity;
+ dummy.movetype = MOVETYPE_BOUNCE;
+ dummy.think = SUB_Remove;
+ dummy.nextthink = time + 3;
+ dummy.health = 50;
+ dummy.takedamage = DAMAGE_YES;
+ dummy.event_damage = zombie_corpse_damage;
+ dummy.solid = SOLID_CORPSE;
+ setsize(dummy,self.mins,self.maxs);
+
+ SUB_SetFade(dummy,time + 5,2);
+
+
+ v = normalize(self.origin - dir);
+ f = vlen(v_forward - v) - 1;
+ if(f > 0.5)
+ dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);
+ else if(f < 0.5)
+ dummy.frame = zombie_anim_deathback1 + rint(random() * 2);
+ else
+ {
+ f = vlen(v_right - v) - 1;
+ if(f > 0.5)
+ dummy.frame = zombie_anim_deathright1 + rint(random() * 2);
+ else if(f < 0.5)
+ dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);
+ }
+
+
+ if(self.spawnflags & MONSTERFLAG_NORESPAWN)
+ {
+ self.think = SUB_Remove;
+ self.nextthink = time;
+ return;
+ }
+
+ setmodel(self,"");
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ self.event_damage = SUB_Null;
+ self.enemy = world;
+ self.think = zombie_spawn;
+ self.nextthink = time + autocvar_g_monster_zombie_respawntime;
+ self.pain_finished = self.nextthink;
+}
+
+void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+
+ vector v;
+ float f;
+
+ v = normalize(self.origin - hitloc);
+ f = vlen(v_forward - v) - 1;
+
+
+ self.health -= damage;
+ self.velocity = self.velocity + force;
+ if(self.health <= 0)
+ {
+ zombie_die(hitloc);
+ return;
+ }
+
+ Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+ if (damage > 50)
+ Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
+ if (damage > 100)
+ Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
+
+ if (time > self.pain_finished)
+ {
+ if(f < 0.5)
+ {
+ if(random() < 0.5)
+ self.frame = zombie_anim_painback1;
+ else
+ self.frame = zombie_anim_painback2;
+ }
+ else
+ {
+ if(random() < 0.5)
+ self.frame = zombie_anim_painfront1;
+ else
+ self.frame = zombie_anim_painfront2;
+ }
+
+ self.pain_finished = time + 0.36;
+ }
+}
+
+.vector bvec;
+.float bvec_time;
+
+void zombie_move()
+{
+ vector real_angle;
+ float vz, tdiff, tspeed;
+
+ tdiff = time - self.zoomstate;
+ tspeed = tdiff * autocvar_g_monster_zombie_turnspeed;
+ vz = self.velocity_z;
+ self.zoomstate = time;
+
+ if(self.bvec_time < time)
+ {
+ self.bvec_time = time + 0.2;
+ self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
+ }
+
+ if(self.enemy)
+ self.moveto = self.enemy.origin;
+ else
+ self.moveto = self.origin + v_forward;
+
+ self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);
+
+ self.angles_y = safeangle(self.angles_y);
+ real_angle = vectoangles(self.steerto) - self.angles;
+ self.angles_y += bound(-10, real_angle_y, 10);
+
+ if(vlen(self.origin - self.moveto) > 64)
+ {
+ movelib_move_simple(v_forward ,autocvar_g_monster_zombie_movespeed,0.6);
+ if(time > self.pain_finished)
+ if(self.attack_finished_single < time)
+ self.frame = zombie_anim_runforward;
+ }
+ else
+ {
+ movelib_beak_simple(autocvar_g_monster_zombie_stopspeed);
+ if(time > self.pain_finished)
+ if(self.attack_finished_single < time)
+ self.frame = zombie_anim_idle;
+ }
+
+ self.velocity_z = vz;
+ self.steerto = self.origin;
+}
+
+float zombie_verb_idle_roam(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ self.moveto = v_forward * 128;
+ self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle_stand(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ self.moveto = self.origin;
+ self.frame = zombie_anim_idle;
+ self.velocity = '0 0 0';
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ float t;
+
+ t = autocvar_g_monster_zombie_idle_timer_max - autocvar_g_monster_zombie_idle_timer_min;
+ t = autocvar_g_monster_zombie_idle_timer_min + (random() * t);
+
+ if(random() < 0.5)
+ verbstack_push(self.verbs_idle, zombie_verb_idle_roam, ZV_IDLE + 1, t, self);
+ else
+ verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_attack_findtarget(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ entity trg, best_trg;
+ float trg_score, best_trg_score;
+
+ trg = findradius(self.origin,autocvar_g_monster_zombie_targetrange);
+ while(trg)
+ {
+ trg_score = zombie_scoretarget(trg);
+ if(trg_score > best_trg_score)
+ {
+ best_trg = trg;
+ best_trg_score = trg_score;
+ }
+
+ trg = trg.chain;
+ }
+
+ if(best_trg)
+ {
+ self.enemy = best_trg;
+ dprint("Selected: ",best_trg.netname, " as target.\n");
+ }
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void zombie_runattack_damage()
+{
+ entity oldself;
+ oldself = self;
+ self = self.owner;
+
+ if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_hitrange)
+ return;
+
+ if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+ return;
+
+ Damage(self.enemy, self, self, autocvar_g_monster_zombie_attack_run_damage, DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin) * autocvar_g_monster_zombie_attack_run_force);
+
+ self = oldself;
+ self.think = SUB_Remove;
+ self.nextthink = time;
+}
+
+float zombie_verb_attack_run(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if not (self.enemy)
+ return VS_CALL_NO;
+
+ if(self.attack_finished_single > time)
+ return VS_CALL_NO;
+
+ if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_range)
+ return VS_CALL_NO;
+
+ if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ entity pain;
+ pain = spawn();
+ pain.owner = self;
+ pain.think = zombie_runattack_damage;
+ pain.nextthink = time + autocvar_g_monster_zombie_attack_run_delay;
+
+ self.attack_finished_single = time + 0.7;
+ self.frame = zombie_anim_attackrun1 + rint(random() * 2);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void zombie_standattack_damage()
+{
+ //entity oldself;
+ //oldself = self;
+ //self = self.owner;
+
+ setorigin(self,self.owner.origin + v_forward * 32);
+ RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world);
+ //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+
+
+ //self = oldself;
+ self.think = SUB_Remove;
+ self.nextthink = time;
+}
+
+float zombie_verb_attack_stand(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if not (self.enemy)
+ return VS_CALL_NO;
+
+ if(self.attack_finished_single > time)
+ return VS_CALL_NO;
+
+ if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_stand_range)
+ return VS_CALL_NO;
+
+ if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ entity pain;
+ pain = spawn();
+ pain.owner = self;
+ pain.think = zombie_runattack_damage;
+ pain.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
+
+ self.attack_finished_single = time + 0.7;
+ self.frame = zombie_anim_attackstanding1 + rint(random() * 1);
+ dprint("frame:",ftos(self.frame),"\n");
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void zombie_think()
+{
+ self.angles_x *= -1;
+ makevectors(self.angles);
+ self.angles_x *= -1;
+
+ if (zombie_scoretarget(self.enemy) == 0)
+ self.enemy = world;
+
+ verbstack_pop(self.verbs_attack);
+ //verbstack_pop(self.verbs_move);
+
+ if not (self.enemy)
+ verbstack_pop(self.verbs_idle);
+
+ zombie_move();
+
+ if(self.enemy)
+ self.nextthink = time;
+ else
+ self.nextthink = time + 0.2;
+}
+
+void zombie_spawn()
+{
+ setmodel(self,"models/monsters/zombie.dpm");
+
+ self.solid = SOLID_BBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.event_damage = zombie_damage;
+ self.enemy = world;
+ self.frame = zombie_anim_spawn;
+ self.think = zombie_think;
+ self.nextthink = time + 2.1;
+ self.pain_finished = self.nextthink;
+ self.movetype = MOVETYPE_WALK;
+ self.health = autocvar_g_monster_zombie_health;
+ self.velocity = '0 0 0';
+ self.angles = self.pos2;
+ self.moveto = self.origin;
+ self.flags = FL_MONSTER;
+
+ setorigin(self,self.pos1);
+ setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);
+}
+
+
+void spawnfunc_monster_zombie()
+{
+ if not(autocvar_g_monsters)
+ {
+ remove(self);
+ return;
+ }
+
+ precache_model("models/monsters/zombie.dpm");
+
+
+ self.verbs_idle = spawn();
+ self.verbs_attack = spawn();
+
+ self.verbs_idle.owner = self;
+ self.verbs_attack.owner = self;
+
+ self.think = zombie_spawn;
+ self.nextthink = time + 2;
+
+ traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);
+
+ self.pos1 = trace_endpos;
+ self.pos2 = self.angles;
+ self.team = MAX_SHOT_DISTANCE -1;
+
+ verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);
+
+ verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);
+ verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);
+ verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);
+
+}
+
+#endif // MONSTES_ENABLED
--- /dev/null
+#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_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_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;
+
+#define BUMB_MIN '-120 -120 -40'
+#define BUMB_MAX '120 120 40'
+
+.entity gunner1;
+//.entity gunner2;
+.vector lastaim;
+float bumb_gunner_frame()
+{
+ entity vehic, gun, gunner;
+ float ftmp, ftmp2;
+ vector vtmp;
+
+ vehic = self.vehicle;
+ gun = self.vehicle.gun1;
+ gunner = self;
+
+ self = vehic;
+ vehic.solid = SOLID_NOT;
+ crosshair_trace(gunner);
+
+ //vtmp = gettaginfo(vehic, gettagindexvehic, "tag_hardpoint01"));
+ vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
+ vtmp = vectoangles(normalize(trace_endpos - vtmp)); // Find the direction & angle
+ vtmp = shortangle_vxy(vtmp - (vehic.angles + gun.angles), vehic.angles + gun.angles); // Find aim offset
+
+ // Bind to aimspeed
+ ftmp2 = autocvar_g_vehicle_bumblebee_cannon_turnspeed * frametime; ftmp = -ftmp2;
+ vtmp_x = bound(ftmp, vtmp_x, ftmp2);
+ vtmp_y = bound(ftmp, vtmp_y, ftmp2);
+ // Bind to limts
+ gun.angles_x = bound(-autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down, vtmp_x + gun.angles_x, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up);
+ gun.angles_y = bound(-autocvar_g_vehicle_bumblebee_cannon_turnlimit_in, vtmp_y + gun.angles_y, autocvar_g_vehicle_bumblebee_cannon_turnlimit_out);
+
+ if(gunner.BUTTON_ATCK && gun.cnt <= time)
+ {
+ vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
+ v_forward = normalize(v_forward);
+ vtmp += v_forward * 50;
+
+ fireBullet (vtmp, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
+ autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
+
+ gun.cnt = time + 0.1;
+ }
+
+ setorigin(gunner, vehic.origin);
+ gunner.velocity = vehic.velocity;
+
+ vehic.solid = SOLID_BBOX;
+ gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
+ self = gunner;
+ return 1;
+}
+
+void bumb_gunner_enter()
+{
+ if(self.gunner1 != world)
+ return;
+
+ self.gunner1 = other;
+ self.gunner1.vehicle = self;
+
+ msg_entity = other;
+ WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+ WriteEntity(MSG_ONE, self.gun1);
+ WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+ if(self.tur_head)
+ {
+ WriteAngle(MSG_ONE, self.gun1.angles_x + self.angles_x); // tilt
+ WriteAngle(MSG_ONE, self.gun1.angles_y + self.angles_y); // yaw
+ WriteAngle(MSG_ONE, 0); // roll
+ }
+ other.PlayerPhysplug = bumb_gunner_frame;
+}
+
+float bumb_pilot_frame()
+{
+ entity pilot, gunner, vehic;
+ vector newvel;
+
+ pilot = self;
+ vehic = self.vehicle;
+ self = vehic;
+
+ if(pilot.BUTTON_USE && vehic.deadflag == DEAD_NO)
+ {
+ self = vehic;
+ vehicles_exit(VHEF_NORMAL);
+ self = pilot;
+ return 0;
+ }
+
+ if(vehic.deadflag != DEAD_NO)
+ {
+ self = pilot;
+ pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
+ return 1;
+ }
+
+ 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 = 5;
+ else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = -20;
+
+ 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;
+ setorigin(pilot,vehic.origin + '0 0 32');
+
+
+ if(vehic.vehicle_flags & VHF_SHIELDREGEN)
+ vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime);
+
+ if(vehic.vehicle_flags & VHF_HEALTHREGEN)
+ vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime);
+
+ if(vehic.vehicle_flags & VHF_ENERGYREGEN)
+ vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime);
+
+ VEHICLE_UPDATE_PLAYER(health, bumblebee);
+ VEHICLE_UPDATE_PLAYER(energy, bumblebee);
+ if(vehic.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(shield, bumblebee);
+
+ pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
+ self = pilot;
+
+ return 1;
+}
+
+void bumb_think()
+{
+ self.velocity = self.velocity * 0.99;
+ self.nextthink = time + 0.1;
+}
+
+void bumb_enter()
+{
+ self.touch = bumb_gunner_enter;
+}
+
+void bumb_exit(float eject)
+{
+ self.owner = world;
+ self.touch = vehicles_touch;
+}
+
+void bumb_spawn()
+{
+ self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+ self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+ self.movetype = MOVETYPE_TOSS;
+ self.solid = SOLID_BBOX;
+ //self.vehicle_energy = 1;
+ self.movetype = MOVETYPE_FLY;
+ setorigin(self, self.origin + '0 0 25');
+}
+
+void bumb_die()
+{
+ self.health = 0;
+ self.event_damage = SUB_Null;
+ self.solid = SOLID_CORPSE;
+ self.takedamage = DAMAGE_NO;
+ self.deadflag = DEAD_DYING;
+ self.movetype = MOVETYPE_BOUNCE;
+
+ pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
+}
+
+void bumb_dinit()
+{
+ 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))
+ {
+ remove(self);
+ return;
+ }
+ self.gun1 = spawn();
+ setmodel(self.gun1, "models/vehicles/bumblebee_ray.dpm");
+ setattachment(self.gun1, self, "tag_hardpoint03");
+
+ self.gun1 = spawn();
+ self.gun2 = spawn();
+
+ self.gun1.owner = self;
+ self.gun2.owner = self;
+
+ setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
+ setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
+
+ setattachment(self.gun1, self, "tag_hardpoint01");
+ setattachment(self.gun2, self, "tag_hardpoint02");
+
+ vector ofs;
+ ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint01"));
+ ofs -= self.origin;
+ setattachment(self.gun1, self, "");
+ setorigin(self.gun1, ofs);
+
+ ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint02"));
+ ofs -= self.origin;
+ setattachment(self.gun2, self, "");
+ setorigin(self.gun2, ofs);
+
+
+}
+
+void spawnfunc_vehicle_bumblebee()
+{
+
+ 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");
+
+ //vehicles_configcheck("vehicle_bumblebee.cfg", autocvar_g_vehicle_bumblebee_health);
+
+ 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;
+
+ self.think = bumb_dinit;
+ self.nextthink = time + 1;
+}
+#endif // SVQC
+
+#ifdef CSQC
+void bumblebee_draw()
+{
+
+}
+
+void bumblebee_draw2d()
+{
+
+}
+
+void bumblebee_read_extra()
+{
+
+}
+
+void vehicle_bumblebee_assemble()
+{
+
+}
+#endif //CSQC
--- /dev/null
+vector collision_force;
+vector collision_angle;
+
+vector bb1[9];
+vector bb2[9];
+
+float collision_run()
+{
+ vector vtmp, vmin, vmax, vrot, vforce, vtmp2, vtmp3;
+ float i, fvel, bcol;
+
+
+ // Extract the 8 bbox corners from mins/maxs for self
+ vmax = self.maxs;
+ vmin = self.mins;
+ bb1[0] = vmax;
+ vtmp = vmax; vtmp_x = vmin_x; bb1[1] = vtmp;
+ vtmp = vmax; vtmp_y = vmin_y; bb1[2] = vtmp;
+ vtmp = vmin; vtmp_z = vmax_z; bb1[3] = vtmp;
+ bb1[4] = vmin;
+ vtmp = vmin; vtmp_x = vmax_x; bb1[5] = vtmp;
+ vtmp = vmin; vtmp_y = vmax_y; bb1[6] = vtmp;
+ vtmp = vmax; vtmp_z = vmin_z; bb1[7] = vtmp;
+
+ makevectors(self.angles + '-2 0 0' * self.angles_x);
+ bcol = 0;
+
+ // Pass1: Transform by rotation, ajust points by impact/s
+ for(i = 8; i >= 0; --i)
+ {
+ vtmp = bb1[i];
+ vtmp = self.origin + vtmp_x * v_forward - vtmp_y * v_right + vtmp_z * v_up;
+ traceline(self.origin, vtmp, MOVE_WORLDONLY, self);
+ te_lightning1(world,self.origin,vtmp);
+ if(trace_fraction != 1.0)
+ {
+ vforce += (trace_endpos - vtmp);
+ vtmp3 = self.origin + self.velocity * frametime;
+ vtmp2 = vectoangles(normalize(vtmp - vtmp3));
+ vrot += (vectoangles(normalize(trace_endpos - vtmp3)) - vtmp2);
+ bcol += 1;
+ }
+ }
+
+ if(bcol)
+ {
+
+ vtmp = self.origin + self.velocity * frametime;
+ self.angles += vrot * frametime;
+ self.velocity += vforce * frametime;
+
+ }
+
+}
+
--- /dev/null
+#ifdef VEHICLES_CSQC
+// SendFlags
+float VSF_SETUP = 1; /// Send vehicle type etc
+float VSF_ORIGIN = 2; /// Send location
+float VSF_MOVEMENT = 4; /// Send movement update (and angles)
+float VSF_AVEL = 8; /// Send Angular velocity
+float VSF_STATS = 16; /// Send ammo, health etc
+float VSF_EXTRA = 32; /// Send additional data (turret rotations etc). Handeld per vehicle type.
+float VSF_ANIMINFO = 64; /// Animation info
+float VSF_FULL_UPDATE = 16777215; /// Send everything
+
+float VSX_FAR = 1;
+float VSX_OWNER = 2;
+float VSX_GUN1 = 4;
+float VSX_GUN2 = 8;
+
+#ifdef SVQC
+#define VSX_FARDISTANCE 2000
+float send_vehile(entity to, float sf)
+{
+ float dist, xf;
+
+ var void WriteFunc(float, float);
+
+ dist = vlen(self.origin - to.origin);
+ if(to == self.owner)
+ xf |= VSX_OWNER;
+ else if(dist > VSX_FARDISTANCE)
+ xf |= VSX_FAR;
+
+ // Always send a movement and origin to owner
+ if(to == self.owner)
+ sf |= VSF_ORIGIN | VSF_MOVEMENT;
+
+ WriteByte(MSG_ENTITY, ENT_CLIENT_VEHICLE);
+
+ // We need to know client-side what was sent
+ WriteByte(MSG_ENTITY, sf);
+ WriteByte(MSG_ENTITY, xf);
+
+ if(sf & VSF_SETUP)
+ {
+ WriteByte(MSG_ENTITY, self.hud); //vehicle type = hud
+ WriteByte(MSG_ENTITY, self.team);
+ WriteShort(MSG_ENTITY, self.colormap);
+ WriteShort(MSG_ENTITY, self.vehicle_flags);
+ }
+
+ if(sf & VSF_ORIGIN)
+ {
+ WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
+ WriteFunc(MSG_ENTITY, self.origin_x);
+ WriteFunc(MSG_ENTITY, self.origin_y);
+ WriteFunc(MSG_ENTITY, self.origin_z);
+ }
+
+ if(sf & VSF_MOVEMENT)
+ {
+ WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
+ WriteFunc(MSG_ENTITY, self.velocity_x);
+ WriteFunc(MSG_ENTITY, self.velocity_y);
+ WriteFunc(MSG_ENTITY, self.velocity_z);
+
+ WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteAngle);
+ WriteFunc(MSG_ENTITY, self.angles_x);
+ WriteFunc(MSG_ENTITY, self.angles_y);
+ WriteFunc(MSG_ENTITY, self.angles_z);
+ }
+
+ if(sf & VSF_AVEL)
+ {
+ WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
+ WriteFunc(MSG_ENTITY, self.avelocity_x);
+ WriteFunc(MSG_ENTITY, self.avelocity_y);
+ WriteFunc(MSG_ENTITY, self.avelocity_z);
+ }
+
+ if(sf & VSF_STATS)
+ {
+ WriteByte(MSG_ENTITY, self.vehicle_health);
+ if(xf & VSX_OWNER)
+ {
+ WriteByte(MSG_ENTITY, self.vehicle_shield);
+ WriteByte(MSG_ENTITY, self.vehicle_energy);
+
+ WriteByte(MSG_ENTITY, self.vehicle_ammo1);
+ WriteByte(MSG_ENTITY, self.vehicle_reload1);
+
+ WriteByte(MSG_ENTITY, self.vehicle_ammo2);
+ WriteByte(MSG_ENTITY, self.vehicle_reload2);
+
+ }
+ }
+
+ if(sf & VSF_EXTRA)
+ self.vehile_send_exta(to, sf);
+
+ return TRUE;
+}
+
+void net_link_vehile()
+{
+ self.SendFlags = 0xFFFFFF;
+ Net_LinkEntity(self, FALSE, 0, send_vehile);
+}
+#endif // SVQC
+
+#ifdef CSQC
+void vehicle_spiderbot_assemble()
+{
+
+}
+
+void vehicle_raptor_assemble()
+{
+
+}
+
+void vehicle_bumblebee_assemble()
+{
+
+}
+
+.float lastupdate;
+void read_vehicle(float bIsNew)
+{
+ float sf, xf;
+ var float ReadFunc();
+
+ sf = ReadByte();
+ xf = ReadByte();
+
+ if(xf & VSX_OWNER)
+ vehicle = self;
+
+ if(sf & VSF_SETUP)
+ {
+ self.vehicle_hud = ReadByte();
+ self.team = ReadByte();
+ self.colormap = ReadShort();
+ self.vehicle_flags = ReadShort();
+
+ switch(self.vehicle_hud)
+ {
+ case HUD_WAKIZASHI:
+ vehicle_racer_assemble();
+ break;
+ case HUD_SPIDERBOT:
+ vehicle_spiderbot_assemble();
+ break;
+ case HUD_RAPTOR:
+ vehicle_raptor_assemble();
+ break;
+ case HUD_BUMBLEBEE:
+ vehicle_bumblebee_assemble();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(self.vehicle_hud == HUD_WAKIZASHI && xf & VSX_OWNER)
+ {
+
+ vehicle_hudmodel.owner = self;
+ }
+
+ //if(xf & VSX_FAR)
+ // dprint("Client vehicle faaar set\n");
+
+ if(sf & VSF_ORIGIN)
+ {
+ ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
+ self.origin_x = ReadFunc();
+ self.origin_y = ReadFunc();
+ self.origin_z = ReadFunc();
+
+ setorigin(self, self.origin);
+ //self.lastupdate = time;
+ }
+
+ if(sf & VSF_MOVEMENT)
+ {
+ ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
+ self.velocity_x = ReadFunc();
+ self.velocity_y = ReadFunc();
+ self.velocity_z = ReadFunc();
+
+ ReadFunc = ((sf & VSX_FAR) ? ReadShort : ReadAngle);
+ self.angles_x = ReadFunc();
+ self.angles_y = ReadFunc();
+ self.angles_z = ReadFunc();
+
+ //self.lastupdate = time;
+ // self.move_velocity = self.velocity;
+ // self.move_angles = self.angles;
+ }
+
+ if(sf & VSF_AVEL)
+ {
+ ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
+ self.avelocity_x = ReadFunc();
+ self.avelocity_y = ReadFunc();
+ self.avelocity_z = ReadFunc();
+
+ // self.move_avelocity = self.avelocity;
+ }
+
+ if(sf & VSF_STATS)
+ {
+ self.vehicle_health = ReadByte();
+ if(xf & VSX_OWNER)
+ {
+ self.vehicle_shield = ReadByte();
+ self.vehicle_energy = ReadByte();
+ self.vehicle_ammo1 = ReadByte();
+ self.vehicle_reload1 = ReadByte();
+ self.vehicle_ammo2 = ReadByte();
+ self.vehicle_reload2 = ReadByte();
+ }
+ }
+
+ if(sf & VSF_EXTRA)
+ self.vehile_read_exta(sf);
+
+}
+
+#endif // CSQC
+#else
+#ifdef CSQC
+.float lastupdate;
+void read_vehicle(float bIsNew)
+{
+
+}
+#endif
+#endif // VEHICLES_CSQC
--- /dev/null
+/// Some default stacks.
+.entity verbs_idle;
+.entity verbs_attack;
+.entity verbs_move;
+//.entity vchain;
+
+/// This global gets set to the verb in question each time the stack manager calls verb_call
+entity verb;
+//.entity current_verb;
+//.float verb_done;
+
+/// Execure this verb
+#define VCM_DO 0
+/// Return the value of this verb. Return VS_CALL_REMOVE to delete it.
+#define VCM_EVAL 1
+/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE)
+#define VCM_REMOVE 2
+
+/// Verb callback
+.float(float message) verb_call;
+
+/// Points to this verb's stack.
+.entity verbstack;
+
+/// Static value of this verb
+.float verb_static_value;
+
+/// verb_call returns this when a verb in not doable
+#define VS_CALL_NO 0
+/// verb_call(VCM_DO) returns this when a verb is executing
+#define VS_CALL_YES_DOING -1
+/// verb_call(VCM_DO) returns this when a verb did execure and is done
+#define VS_CALL_YES_DONE -2
+/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager
+#define VS_CALL_REMOVE -3
+
+/*
+void verbstack_updatechain(entity stack)
+{
+ entity vrb, v;
+ if not (stack)
+ return;
+
+ dprint("verbstack_updatechain\n");
+
+ vrb = findchainentity(verbstack, stack);
+ if not (vrb)
+ {
+ stack.vchain = world;
+ return;
+ }
+
+ stack.vchain = vrb;
+ v = vrb;
+
+ while(vrb)
+ {
+ vrb = vrb.chain;
+
+
+ }
+}
+
+void verbstack_remove(entity vverb)
+{
+ entity vstack;
+ dprint("verbstack_remove\n");
+
+ vstack = verb.verbstack;
+ remove(vverb);
+ vverb.verbstack = world;
+ verbstack_updatechain(vstack);
+
+ //vverb.think = SUB_Remove;
+ //vverb.nextthink = time;
+}
+
+void verbstack_thinkremove()
+{
+ dprint("verbstack_thinkremove\n");
+ verbstack_remove(self);
+}
+*/
+
+/**
+ Push a new verb onto the specified stack. Set vrb_life to make it time-limited.
+**/
+entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner)
+{
+ entity vrb;
+
+ if not(stack)
+ return world;
+
+ if not(vrb_call)
+ return world;
+
+ vrb = spawn();
+ vrb.owner = verb_owner;
+ vrb.verbstack = stack;
+ vrb.verb_call = vrb_call;
+ vrb.verb_static_value = val_static;
+
+ vrb.classname = "verb";
+ stack.classname = "verbstack";
+
+ if(vrb_life)
+ {
+ //vrb.think = verbstack_thinkremove;
+ vrb.think = SUB_Remove;
+ vrb.nextthink = time + vrb_life;
+ }
+
+ //verbstack_updatechain(stack);
+
+ return vrb;
+}
+
+/**
+ Find the best verb in this stack and execurte it.
+ ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO
+**/
+float verbstack_pop(entity stack)
+{
+ entity vrb, bestverb, oldself;
+ float value, bestvalue;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ //vrb = stack.vchain;
+ //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n");
+ while(vrb)
+ {
+ //dprint("vn:", vrb.classname,"\n");
+ verb = vrb;
+ vrb = vrb.chain;
+ self = verb.owner;
+ value = verb.verb_call(VCM_EVAL);
+
+ if(value < 0)
+ {
+ if(value == VS_CALL_REMOVE)
+ remove(verb);
+ }
+ else
+ {
+ if(value > bestvalue)
+ {
+ bestverb = verb;
+ bestvalue = value;
+ }
+ }
+ }
+
+ if(bestverb)
+ {
+ verb = bestverb;
+ self = verb.owner;
+ value = verb.verb_call(VCM_DO);
+
+ if(value == VS_CALL_REMOVE)
+ remove(bestverb);
+ }
+
+ self = oldself;
+
+ return value;
+}
+
+float verbstack_popfifo(entity stack)
+{
+ entity oldself;
+ float ret;
+
+ oldself = self;
+ verb = findentity(stack,verbstack,stack);
+ if not (verb)
+ ret = 0;
+ else
+ {
+ self = verb.owner;
+ ret = verb.verb_call(VCM_DO);
+
+ if(ret == VS_CALL_REMOVE)
+ remove(verb);
+ }
+
+ self = oldself;
+ return ret;
+}
+
+/**
+ Find the best verb in this stack and return it.
+ ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL.
+**/
+entity verbstack_pull(entity stack)
+{
+ entity vrb;
+ entity bestverb, oldself;
+ float value, bestvalue;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ self = vrb.owner;
+
+ verb = vrb;
+ vrb = vrb.chain;
+ value = verb.verb_call(VCM_EVAL);
+
+ if(value < 0)
+ {
+ if(value == VS_CALL_REMOVE)
+ remove(verb);
+ }
+ else
+ {
+ if(value > bestvalue)
+ {
+ bestverb = verb;
+ bestvalue = value;
+ }
+ }
+ }
+
+ self = oldself;
+
+ return bestverb;
+}
+
+entity verbstack_pullfifo(entity stack)
+{
+ return findentity(stack,verbstack,stack);
+}
+
+/**
+ Delete every verb on this stack, signaling them with VCM_REMOVE first.
+**/
+void verbstack_flush(entity stack)
+{
+ entity vrb, oldself;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ self = vrb.owner;
+
+ verb = vrb;
+ vrb = vrb.chain;
+ verb.verb_call(VCM_REMOVE);
+ remove(verb);
+ }
+
+ self = oldself;
+
+ //stack.vchain = world;
+}
+
+void verbstack_doverb(entity vrb)
+{
+ float value;
+
+ verb = vrb;
+ self = verb.owner;
+ value = verb.verb_call(VCM_DO);
+
+ if(value == VS_CALL_REMOVE)
+ remove(vrb);
+}
float autocvar_g_balance_rifle_reload_ammo;
float autocvar_g_balance_rifle_reload_time;
float autocvar_g_balance_cloaked_alpha;
+float autocvar_g_balance_contents_damagerate;
+float autocvar_g_balance_contents_drowndelay;
+float autocvar_g_balance_contents_playerdamage_drowning;
+float autocvar_g_balance_contents_playerdamage_lava;
+float autocvar_g_balance_contents_playerdamage_slime;
+float autocvar_g_balance_contents_projectiledamage;
float autocvar_g_balance_crylink_primary_ammo;
float autocvar_g_balance_crylink_primary_animtime;
float autocvar_g_balance_crylink_primary_bouncedamagefactor;
float autocvar_g_balance_electro_secondary_count;
float autocvar_g_balance_electro_secondary_damage;
float autocvar_g_balance_electro_secondary_damageforcescale;
+float autocvar_g_balance_electro_secondary_damagedbycontents;
float autocvar_g_balance_electro_secondary_edgedamage;
float autocvar_g_balance_electro_secondary_force;
float autocvar_g_balance_electro_secondary_health;
float autocvar_g_balance_grapplehook_speed_fly;
float autocvar_g_balance_grapplehook_speed_pull;
float autocvar_g_balance_grapplehook_stretch;
+float autocvar_g_balance_grapplehook_damagedbycontents;
float autocvar_g_balance_grenadelauncher_bouncefactor;
float autocvar_g_balance_grenadelauncher_bouncestop;
float autocvar_g_balance_grenadelauncher_primary_ammo;
float autocvar_g_balance_hagar_primary_damage;
float autocvar_g_balance_hagar_primary_edgedamage;
float autocvar_g_balance_hagar_primary_force;
+float autocvar_g_balance_hagar_primary_health;
+float autocvar_g_balance_hagar_primary_damageforcescale;
float autocvar_g_balance_hagar_primary_lifetime;
float autocvar_g_balance_hagar_primary_radius;
float autocvar_g_balance_hagar_primary_refire;
float autocvar_g_balance_hagar_secondary_load_hold;
float autocvar_g_balance_hagar_secondary_load_releasedeath;
float autocvar_g_balance_hagar_secondary_load_abort;
+float autocvar_g_balance_hagar_secondary_load_linkexplode;
+float autocvar_g_balance_hagar_secondary_load_animtime;
float autocvar_g_balance_hagar_secondary_ammo;
float autocvar_g_balance_hagar_secondary_damage;
float autocvar_g_balance_hagar_secondary_edgedamage;
float autocvar_g_balance_hagar_secondary_force;
+float autocvar_g_balance_hagar_secondary_health;
+float autocvar_g_balance_hagar_secondary_damageforcescale;
float autocvar_g_balance_hagar_secondary_lifetime_min;
float autocvar_g_balance_hagar_secondary_lifetime_rand;
float autocvar_g_balance_hagar_secondary_radius;
float autocvar_g_balance_hook_secondary_radius;
float autocvar_g_balance_hook_secondary_refire;
float autocvar_g_balance_hook_secondary_speed;
+float autocvar_g_balance_hook_secondary_health;
+float autocvar_g_balance_hook_secondary_damageforcescale;
float autocvar_g_balance_keyhunt_damageforcescale;
float autocvar_g_balance_keyhunt_delay_collect;
float autocvar_g_balance_keyhunt_delay_return;
float autocvar_g_balance_shotgun_secondary_force;
float autocvar_g_balance_shotgun_secondary_melee_delay;
float autocvar_g_balance_shotgun_secondary_melee_range;
-float autocvar_g_balance_shotgun_secondary_melee_swing;
+float autocvar_g_balance_shotgun_secondary_melee_swing_side;
+float autocvar_g_balance_shotgun_secondary_melee_swing_up;
float autocvar_g_balance_shotgun_secondary_melee_time;
+float autocvar_g_balance_shotgun_secondary_melee_traces;
float autocvar_g_balance_shotgun_secondary_melee_no_doubleslap;
+float autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage;
+float autocvar_g_balance_shotgun_secondary_melee_multihit;
float autocvar_g_balance_shotgun_secondary_refire;
float autocvar_g_balance_shotgun_reload_ammo;
float autocvar_g_balance_shotgun_reload_time;
float autocvar_g_minstagib_speed_highspeed;
#define autocvar_g_mirrordamage cvar("g_mirrordamage")
#define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
-float autocvar_g_monster_zombie_attack_run_damage;
-float autocvar_g_monster_zombie_attack_run_delay;
-float autocvar_g_monster_zombie_attack_run_force;
-float autocvar_g_monster_zombie_attack_run_hitrange;
-float autocvar_g_monster_zombie_attack_run_range;
-float autocvar_g_monster_zombie_attack_stand_damage;
-float autocvar_g_monster_zombie_attack_stand_delay;
-float autocvar_g_monster_zombie_attack_stand_force;
-float autocvar_g_monster_zombie_attack_stand_range;
-float autocvar_g_monster_zombie_health;
-float autocvar_g_monster_zombie_idle_timer_max;
-float autocvar_g_monster_zombie_idle_timer_min;
-float autocvar_g_monster_zombie_movespeed;
-float autocvar_g_monster_zombie_respawntime;
-float autocvar_g_monster_zombie_stopspeed;
-float autocvar_g_monster_zombie_targetrange;
-float autocvar_g_monster_zombie_turnspeed;
-float autocvar_g_monsters;
+
var float autocvar_g_movement_highspeed = 1;
float autocvar_g_multijump;
float autocvar_g_multijump_add;
float autocvar_g_powerup_shield;
float autocvar_g_powerup_strength;
float autocvar_g_powerup_superhealth;
+float autocvar_g_projectiles_damage;
float autocvar_g_projectiles_newton_style;
float autocvar_g_projectiles_newton_style_2_maxfactor;
float autocvar_g_projectiles_newton_style_2_minfactor;
float autocvar_g_use_ammunition;
float autocvar_g_waypointeditor;
float autocvar_g_waypoints_for_items;
-float autocvar_g_waypointsprite_deadlifetime;
-float autocvar_g_waypointsprite_deployed_lifetime;
-float autocvar_g_waypointsprite_limitedrange;
float autocvar_g_weapon_charge_colormod_blue_full;
float autocvar_g_weapon_charge_colormod_blue_half;
float autocvar_g_weapon_charge_colormod_green_full;
string autocvar_sv_eventlog_files_nameprefix;
string autocvar_sv_eventlog_files_namesuffix;
float autocvar_sv_eventlog_files_timestamps;
-float autocvar_sv_fragmessage_information_handicap;
-float autocvar_sv_fragmessage_information_ping;
-float autocvar_sv_fragmessage_information_stats;
-float autocvar_sv_fragmessage_information_typefrag;
+float autocvar_sv_fraginfo_handicap;
+float autocvar_sv_fraginfo_ping;
+float autocvar_sv_fraginfo_stats;
+float autocvar_sv_fraginfo_typefrag;
float autocvar_sv_friction;
float autocvar_sv_friction_on_land;
float autocvar_sv_gameplayfix_q2airaccelerate;
string autocvar_sv_player_maxs;
string autocvar_sv_player_mins;
string autocvar_sv_player_viewoffset;
+float autocvar_sv_player_jumpanim_minfall;
float autocvar_sv_precacheplayermodels;
float autocvar_sv_precacheweapons;
float autocvar_sv_q3acompat_machineshotgunswap;
-float autocvar_sv_qcweaponanimation;
float autocvar_sv_ready_restart;
float autocvar_sv_ready_restart_after_countdown;
float autocvar_sv_ready_restart_repeatable;
float autocvar_sv_warsowbunny_backtosideratio;
float autocvar_sv_warsowbunny_topspeed;
float autocvar_sv_warsowbunny_turnaccel;
+float autocvar_sv_waypointsprite_deadlifetime;
+float autocvar_sv_waypointsprite_deployed_lifetime;
+float autocvar_sv_waypointsprite_limitedrange;
string autocvar_sv_weaponstats_file;
float autocvar_sv_gibhealth;
float autocvar_sys_ticrate;
float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore)
{
- local float c, savesolid, shottime;
- local vector dir, end, v, o;
+ float c, savesolid, shottime;
+ vector dir, end, v, o;
if (shotspeed < 1)
return FALSE; // could cause division by zero if calculated
if (targ.solid < SOLID_BBOX) // SOLID_NOT and SOLID_TRIGGER
// leave a valid one even if it won't reach
findtrajectory_velocity = normalize(end - org) * shotspeed + shotspeedupward * '0 0 1';
return FALSE;
-};
+}
void lag_update()
{
if (self.lag3_time) if (time > self.lag3_time) {self.lag_func(self.lag3_time, self.lag3_float1, self.lag3_float2, self.lag3_entity1, self.lag3_vec1, self.lag3_vec2, self.lag3_vec3, self.lag3_vec4);self.lag3_time = 0;}
if (self.lag4_time) if (time > self.lag4_time) {self.lag_func(self.lag4_time, self.lag4_float1, self.lag4_float2, self.lag4_entity1, self.lag4_vec1, self.lag4_vec2, self.lag4_vec3, self.lag4_vec4);self.lag4_time = 0;}
if (self.lag5_time) if (time > self.lag5_time) {self.lag_func(self.lag5_time, self.lag5_float1, self.lag5_float2, self.lag5_entity1, self.lag5_vec1, self.lag5_vec2, self.lag5_vec3, self.lag5_vec4);self.lag5_time = 0;}
-};
+}
float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
{
if (self.lag5_time == 0) {self.lag5_time = t;self.lag5_float1 = f1;self.lag5_float2 = f2;self.lag5_entity1 = e1;self.lag5_vec1 = v1;self.lag5_vec2 = v2;self.lag5_vec3 = v3;self.lag5_vec4 = v4;return TRUE;}
// no room for it (what is the best thing to do here??)
return FALSE;
-};
+}
float bot_shouldattack(entity e)
{
if(e.flags & FL_NOTARGET)
return FALSE;
return TRUE;
-};
+}
void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
{
self.bot_canfire = (random() < 0.95);
else
self.bot_canfire = 1;
-};
+}
float bot_aimdir(vector v, float maxfiredeviation)
{
- local float dist, delta_t, blend;
- local vector desiredang, diffang;
+ float dist, delta_t, blend;
+ vector desiredang, diffang;
//dprint("aim ", self.netname, ": old:", vtos(self.v_angle));
// make sure v_angle is sane first
//diffang = diffang + randomvec() * (dist * 0.05 * (3.5 - bound(0, skill, 3)));
// turn
- local float r, fixedrate, blendrate;
+ float r, fixedrate, blendrate;
fixedrate = autocvar_bot_ai_aimskill_fixedrate / bound(1,dist,1000);
blendrate = autocvar_bot_ai_aimskill_blendrate;
r = max(fixedrate, blendrate);
//dprint(" diff:", vtos(diffang), "\n");
return self.bot_canfire && (time < self.bot_firetimer);
-};
+}
vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay)
{
// Try to add code here that predicts gravity effect here, no clue HOW to though ... well not yet atleast...
return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed);
-};
+}
float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float applygravity)
{
- local float f, r, hf, distanceratio;
- local vector v;
+ float f, r, hf, distanceratio;
+ vector v;
/*
eprint(self);
dprint("bot_aim(", ftos(shotspeed));
// return FALSE;
self.dphitcontentsmask = hf;
return TRUE;
-};
+}
entity bot_spawn()
{
- local entity oldself, bot;
+ entity oldself, bot;
bot = spawnclient();
if (bot)
{
self = oldself;
}
return bot;
-};
+}
void bot_think()
{
// now call the current bot AI (havocbot for example)
self.bot_ai();
-};
+}
void bot_setnameandstuff()
{
self.cvar_cl_accuracy_data_share = 1; // share the bots weapon accuracy data with the world
self.cvar_cl_accuracy_data_receive = 0; // don't receive any weapon accuracy data
-};
+}
void bot_custom_weapon_priority_setup()
{
- local float tokens, i, c, w;
+ float tokens, i, c, w;
bot_custom_weapon = FALSE;
bot_weapons_close[c] = -1;
bot_custom_weapon = TRUE;
-};
+}
void bot_endgame()
{
- local entity e;
+ entity e;
//dprint("bot_endgame\n");
e = bot_list;
while (e)
e = e.nextbot;
}
// if dynamic waypoints are ever implemented, save them here
-};
+}
void bot_relinkplayerlist()
{
- local entity e;
- local entity prevbot;
+ entity e;
+ entity prevbot;
player_count = 0;
currentbots = 0;
player_list = e = findchainflags(flags, FL_CLIENT);
dprint(strcat("relink: ", ftos(currentbots), " bots seen.\n"));
bot_strategytoken = bot_list;
bot_strategytoken_taken = TRUE;
-};
+}
void bot_clientdisconnect()
{
JoinBestTeam(self, FALSE, TRUE);
havocbot_setupbot();
-};
+}
void bot_removefromlargestteam()
{
- local float besttime, bestcount, thiscount;
- local entity best, head;
+ float besttime, bestcount, thiscount;
+ entity best, head;
CheckAllowedTeams(world);
GetTeamCounts(world);
head = findchainfloat(isbot, TRUE);
}
currentbots = currentbots - 1;
dropclient(best);
-};
+}
void bot_removenewest()
{
- local float besttime;
- local entity best, head;
+ float besttime;
+ entity best, head;
if(teamplay)
{
}
currentbots = currentbots - 1;
dropclient(best);
-};
+}
void autoskill(float factor)
{
// 0.75 factor is for safety to make the jumps easy
}
-void bot_serverframe()
+float bot_fixcount()
{
- float realplayers, bots, activerealplayers;
entity head;
-
- if (intermission_running)
- return;
-
- if (time < 2)
- return;
-
- bot_calculate_stepheightvec();
- bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
-
- if(time > autoskill_nextthink)
- {
- float a;
- a = autocvar_skill_auto;
- if(a)
- autoskill(a);
- autoskill_nextthink = time + 5;
- }
+ float realplayers, bots, activerealplayers;
activerealplayers = 0;
realplayers = 0;
bots = 0;
}
- bot_ignore_bots = autocvar_bot_ignore_bots;
-
// only add one bot per frame to avoid utter chaos
if(time > botframe_nextthink)
{
if (bot_spawn() == world)
{
bprint("Can not add bot, server full.\n");
- botframe_nextthink = time + 10;
- break;
+ return FALSE;
}
}
while (currentbots > bots)
bot_removenewest();
}
+ return TRUE;
+}
+
+void bot_serverframe()
+{
+ if (intermission_running)
+ return;
+
+ if (time < 2)
+ return;
+
+ bot_calculate_stepheightvec();
+ bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
+
+ if(time > autoskill_nextthink)
+ {
+ float a;
+ a = autocvar_skill_auto;
+ if(a)
+ autoskill(a);
+ autoskill_nextthink = time + 5;
+ }
+
+ if(time > botframe_nextthink)
+ {
+ if(!bot_fixcount())
+ botframe_nextthink = time + 10;
+ }
+
+ bot_ignore_bots = autocvar_bot_ignore_bots;
+
if(botframe_spawnedwaypoints)
{
if(autocvar_waypoint_benchmark)
else
{
// TODO: Make this check cleaner
- local entity wp = findchain(classname, "waypoint");
+ entity wp = findchain(classname, "waypoint");
if(time - wp.nextthink > 10)
waypoint_save_links();
}
if (botframe_nextdangertime < time)
{
- local float interval;
+ float interval;
interval = autocvar_bot_ai_dangerdetectioninterval;
if (botframe_nextdangertime < time - interval * 1.5)
botframe_nextdangertime = time;
bot_custom_weapon_priority_setup();
bot_cvar_nextthink = time + 5;
}
-};
+}
if(self.waterlevel==WATERLEVEL_SWIMMING || self.aistatus & AI_STATUS_OUT_WATER)
{
// Look for the closest waypoint out of water
- local entity newgoal, head;
- local float bestdistance, distance;
+ entity newgoal, head;
+ float bestdistance, distance;
newgoal = world;
bestdistance = 10000;
self.aistatus |= AI_STATUS_ROAMING;
self.aistatus &~= AI_STATUS_ATTACKING;
- local vector now,v,next;//,heading;
- local float aimdistance,skillblend,distanceblend,blend;
+ vector now,v,next;//,heading;
+ float aimdistance,skillblend,distanceblend,blend;
next = now = ( (self.goalcurrent.absmin + self.goalcurrent.absmax) * 0.5) - (self.origin + self.view_ofs);
aimdistance = vlen(now);
//heading = self.velocity;
}
}
}
-};
+}
void havocbot_keyboard_movement(vector destorg)
{
- local vector keyboard;
- local float blend, maxspeed;
+ vector keyboard;
+ float blend, maxspeed;
float sk;
sk = skill + self.bot_moveskill;
, time);
keyboard = self.movement * (1.0 / maxspeed);
- local float trigger, trigger1;
+ float trigger, trigger1;
blend = bound(0,sk*0.1,1);
trigger = autocvar_bot_ai_keyboard_threshold;
trigger1 = 0 - trigger;
blend = bound(0,vlen(destorg-self.origin)/autocvar_bot_ai_keyboard_distance,1); // When getting close move with 360 degree
//dprint("movement ", vtos(self.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
self.movement = self.movement + (keyboard - self.movement) * blend;
-};
+}
void havocbot_bunnyhop(vector dir)
{
- local float bunnyhopdistance;
- local vector deviation;
- local float maxspeed;
+ float bunnyhopdistance;
+ vector deviation;
+ float maxspeed;
vector gco, gno;
if(autocvar_g_midair)
// for a period of time
if(time - self.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
{
- local float checkdistance;
+ float checkdistance;
checkdistance = TRUE;
// don't run if it is too close
}
}
#endif
-};
+}
void havocbot_movetogoal()
{
- local vector destorg;
- local vector diff;
- local vector dir;
- local vector flatdir;
- local vector m1;
- local vector m2;
- local vector evadeobstacle;
- local vector evadelava;
- local float s;
- local float maxspeed;
- local vector gco;
- //local float dist;
- local vector dodge;
+ vector destorg;
+ vector diff;
+ vector dir;
+ vector flatdir;
+ vector m1;
+ vector m2;
+ vector evadeobstacle;
+ vector evadelava;
+ float s;
+ float maxspeed;
+ vector gco;
+ //float dist;
+ vector dodge;
//if (self.goalentity)
// te_lightning2(self, self.origin, (self.goalentity.absmin + self.goalentity.absmax) * 0.5);
self.movement = '0 0 0';
{
if(fabs(self.velocity_z)<50)
{
- local entity head, newgoal;
- local float distance, bestdistance;
+ entity head, newgoal;
+ float distance, bestdistance;
for (head = findchain(classname, "waypoint"); head; head = head.chain)
{
else
dir = normalize(( ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5 ) - self.origin);
- local vector xyvelocity = self.velocity; xyvelocity_z = 0;
- local float xyspeed = xyvelocity * dir;
+ vector xyvelocity = self.velocity; xyvelocity_z = 0;
+ float xyspeed = xyvelocity * dir;
if(xyspeed < (maxspeed / 2))
{
}
// avoiding dangers and obstacles
- local vector dst_ahead, dst_down;
+ vector dst_ahead, dst_down;
makevectors(self.v_angle_y * '0 1 0');
dst_ahead = self.origin + self.view_ofs + (self.velocity * 0.4) + (v_forward * 32 * 3);
dst_down = dst_ahead + '0 0 -1500';
if ((dir * v_up) >= autocvar_sv_jumpvelocity*0.5 && (self.flags & FL_ONGROUND)) self.BUTTON_JUMP=1;
if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill-self.bot_dodgeskill)*0.1,1)) self.BUTTON_JUMP=TRUE;
if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill-self.bot_dodgeskill)*0.1,1)) self.havocbot_ducktime=time+0.3/bound(0.1,skill+self.bot_dodgeskill,10);
-};
+}
void havocbot_chooseenemy()
{
- local entity head, best, head2;
- local float rating, bestrating, i, hf;
- local vector eye, v;
+ entity head, best, head2;
+ float rating, bestrating, i, hf;
+ vector eye, v;
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
{
self.enemy = world;
self.enemy = best;
self.havocbot_stickenemy = TRUE;
-};
+}
float havocbot_chooseweapon_checkreload(float new_weapon)
{
// if this weapon is scheduled for reloading, don't switch to it during combat
if (self.weapon_load[new_weapon] < 0)
{
- local float i, other_weapon_available;
+ float i, other_weapon_available;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
// if we are out of ammo for all other weapons, it's an emergency to switch to anything else
void havocbot_chooseweapon()
{
- local float i;
+ float i;
// ;)
if(g_weaponarena == WEPBIT_TUBA)
if(i < 1)
return;
- local float w;
- local float distance; distance=bound(10,vlen(self.origin-self.enemy.origin)-200,10000);
+ float w;
+ float distance; distance=bound(10,vlen(self.origin-self.enemy.origin)-200,10000);
// Should it do a weapon combo?
- local float af, ct, combo_time, combo;
+ float af, ct, combo_time, combo;
af = ATTACK_FINISHED(self);
ct = autocvar_bot_ai_weapon_combo_threshold;
}
}
}
-};
+}
void havocbot_aim()
{
- local vector selfvel, enemyvel;
+ vector selfvel, enemyvel;
// if(self.flags & FL_INWATER)
// return;
if (time < self.nextaim)
}
else
lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5, '0 0 0');
-};
+}
float havocbot_moveto_refresh_route()
{
float havocbot_moveto(vector pos)
{
- local entity wp;
+ entity wp;
if(self.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
{
debuggoalstack();
// Heading
- local vector dir = ( ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5 ) - (self.origin + self.view_ofs);
+ vector dir = ( ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5 ) - (self.origin + self.view_ofs);
dir_z = 0;
bot_aimdir(dir, -1);
// LordHavoc: disabled because this is too expensive
return '0 0 0';
#if 0
- local entity head;
- local vector dodge, v, n;
- local float danger, bestdanger, vl, d;
+ entity head;
+ vector dodge, v, n;
+ float danger, bestdanger, vl, d;
dodge = '0 0 0';
bestdanger = -20;
// check for dangerous objects near bot or approaching bot
}
return dodge;
#endif
-};
+}
void havocbot_goalrating_ast_targets(float ratingscale)
{
- entity ad, best, pl, wp, tod;
- float radius, found, bestvalue, c;
+ entity ad, best, wp, tod;
+ float radius, found, bestvalue;
vector p;
ad = findchain(classname, "func_assault_destructible");
self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
}
-};
+}
void havocbot_role_ast_defense()
{
self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
}
-};
+}
void havocbot_role_ast_setrole(entity bot, float role)
{
bot.havocbot_role_timeout = 0;
break;
}
-};
+}
void havocbot_ast_reset_role(entity bot)
{
- local entity head;
- local float c;
-
if(self.deadflag != DEAD_NO)
return;
havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_OFFENSE);
else
havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_DEFENSE);
-};
+}
void havocbot_chooserole_ast()
{
havocbot_ast_reset_role(self);
-};
+}
f = f.ctf_worldflagnext;
}
return world;
-};
+}
entity havocbot_ctf_find_enemy_flag(entity bot)
{
f = f.ctf_worldflagnext;
}
return world;
-};
+}
float havocbot_ctf_teamcount(entity bot, vector org, float radius)
{
}
return c;
-};
+}
void havocbot_goalrating_ctf_ourflag(float ratingscale)
{
- local entity head;
+ entity head;
head = ctf_worldflaglist;
while (head)
{
}
if (head)
navigation_routerating(head, ratingscale, 10000);
-};
+}
void havocbot_goalrating_ctf_ourbase(float ratingscale)
{
- local entity head;
+ entity head;
head = ctf_worldflaglist;
while (head)
{
return;
navigation_routerating(head.basewaypoint, ratingscale, 10000);
-};
+}
void havocbot_goalrating_ctf_enemyflag(float ratingscale)
{
- local entity head;
+ entity head;
head = ctf_worldflaglist;
while (head)
{
}
if (head)
navigation_routerating(head, ratingscale, 10000);
-};
+}
void havocbot_goalrating_ctf_enemybase(float ratingscale)
{
return;
}
- local entity head;
+ entity head;
head = havocbot_ctf_find_enemy_flag(self);
return;
navigation_routerating(head.basewaypoint, ratingscale, 10000);
-};
+}
void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
{
- local entity mf;
+ entity mf;
mf = havocbot_ctf_find_flag(self);
if(mf.tag_entity)
navigation_routerating(mf.tag_entity, ratingscale, 10000);
-};
+}
void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float radius)
{
- local entity head;
+ entity head;
head = ctf_worldflaglist;
while (head)
{
head = head.ctf_worldflagnext;
}
-};
+}
void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
{
- local entity head;
- local float t;
+ entity head;
+ float t;
head = findchainfloat(bot_pickup, TRUE);
while (head)
{
}
head = head.chain;
}
-};
+}
void havocbot_role_ctf_setrole(entity bot, float role)
{
break;
}
dprint("\n");
-};
+}
void havocbot_role_ctf_carrier()
{
return;
}
}
-};
+}
void havocbot_role_ctf_escort()
{
- local entity mf, ef;
+ entity mf, ef;
if(self.deadflag != DEAD_NO)
{
havocbot_goalrating_items(10000, self.origin, 10000);
navigation_goalrating_end();
}
-};
+}
void havocbot_role_ctf_offense()
{
- local entity mf, ef;
- local vector pos;
+ entity mf, ef;
+ vector pos;
if(self.deadflag != DEAD_NO)
{
havocbot_goalrating_items(1000, self.origin, 10000);
navigation_goalrating_end();
}
-};
+}
// Retriever (temporary role):
void havocbot_role_ctf_retriever()
{
- local entity mf;
+ entity mf;
if(self.deadflag != DEAD_NO)
{
if (self.bot_strategytime < time)
{
- local float radius;
+ float radius;
radius = 10000;
self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
havocbot_goalrating_items(500, self.origin, radius);
navigation_goalrating_end();
}
-};
+}
void havocbot_role_ctf_middle()
{
- local entity mf;
+ entity mf;
if(self.deadflag != DEAD_NO)
{
if (self.bot_strategytime < time)
{
- local vector org;
+ vector org;
org = havocbot_ctf_middlepoint;
org_z = self.origin_z;
havocbot_goalrating_ctf_enemybase(2500);
navigation_goalrating_end();
}
-};
+}
void havocbot_role_ctf_defense()
{
- local entity mf;
+ entity mf;
if(self.deadflag != DEAD_NO)
{
}
if (self.bot_strategytime < time)
{
- local float radius;
- local vector org;
+ float radius;
+ vector org;
org = mf.dropped_origin;
radius = havocbot_ctf_middlepoint_radius;
navigation_goalrating_start();
// if enemies are closer to our base, go there
- local entity head, closestplayer;
- local float distance, bestdistance;
+ entity head, closestplayer;
+ float distance, bestdistance;
distance = 10000;
FOR_EACH_PLAYER(head)
{
havocbot_goalrating_items(5000, self.origin, 10000);
navigation_goalrating_end();
}
-};
+}
void havocbot_calculate_middlepoint()
{
}
havocbot_ctf_middlepoint = p1 + ((p2-p1) * 0.5);
havocbot_ctf_middlepoint_radius = vlen(p2-p1) * 0.5;
-};
+}
void havocbot_ctf_reset_role(entity bot)
{
- local float cdefense, cmiddle, coffense;
- local entity mf, ef, head;
- local float c;
+ float cdefense, cmiddle, coffense;
+ entity mf, ef, head;
+ float c;
if(bot.deadflag != DEAD_NO)
return;
havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_OFFENSE);
else
havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE);
-};
+}
void havocbot_chooserole_ctf()
{
havocbot_ctf_reset_role(self);
-};
+}
void havocbot_goalrating_freeplayers(float ratingscale, vector org, float sradius)
{
- local entity head;
+ entity head;
float distance;
FOR_EACH_PLAYER(head)
}
}
}
-};
+}
void havocbot_role_ft_offense()
{
- local entity head;
+ entity head;
float unfrozen;
if(self.deadflag != DEAD_NO)
//havocbot_goalrating_waypoints(1, self.origin, 1000);
navigation_goalrating_end();
}
-};
+}
void havocbot_role_ft_freeing()
{
//havocbot_goalrating_waypoints(1, self.origin, 1000);
navigation_goalrating_end();
}
-};
+}
void havocbot_chooserole_ft()
{
self.havocbot_role = havocbot_role_ft_freeing;
else
self.havocbot_role = havocbot_role_ft_offense;
-};
+}
void havocbot_goalrating_ball(float ratingscale, vector org)
{
- local float t;
- local entity ball_owner;
+ float t;
+ entity ball_owner;
ball_owner = ka_ball.owner;
if (ball_owner == self)
// Ball has been dropped so collect.
navigation_routerating(ka_ball, ratingscale, 2000);
-};
+}
void havocbot_role_ka_carrier()
{
self.havocbot_role = havocbot_role_ka_collector;
self.bot_strategytime = 0;
}
-};
+}
void havocbot_role_ka_collector()
{
self.havocbot_role = havocbot_role_ka_carrier;
self.bot_strategytime = 0;
}
-};
+}
void havocbot_chooserole_ka()
{
self.havocbot_role = havocbot_role_ka_carrier;
else
self.havocbot_role = havocbot_role_ka_collector;
-};
+}
void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy)
{
- local entity head;
+ entity head;
for (head = kh_worldkeylist; head; head = head.kh_worldkeynext)
{
if(head.owner == self)
}
havocbot_goalrating_items(1, self.origin, 10000);
-};
+}
void havocbot_role_kh_carrier()
{
navigation_goalrating_end();
}
-};
+}
void havocbot_role_kh_offense()
{
navigation_goalrating_end();
}
-};
+}
void havocbot_role_kh_freelancer()
{
navigation_goalrating_end();
}
-};
+}
void havocbot_chooserole_kh()
{
- local float r;
+ float r;
if(self.deadflag != DEAD_NO)
return;
self.havocbot_role = havocbot_role_kh_defense;
else
self.havocbot_role = havocbot_role_kh_freelancer;
-};
+}
void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
{
- local entity head;
- local float t, i, c, needarmor, needweapons;
+ entity head;
+ float t, i, c, needarmor, needweapons;
// Needs armor/health?
if(self.health<100)
}
head = head.chain;
}
-};
+}
void havocbot_role_ons_setrole(entity bot, float role)
{
break;
}
dprint("\n");
-};
+}
float havocbot_ons_teamcount(entity bot, float role)
{
- local float c;
- local entity head;
+ float c;
+ entity head;
FOR_EACH_PLAYER(head)
if(head.team==self.team)
++c;
return c;
-};
+}
void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
{
if not(found)
navigation_routerating(cp, ratingscale, 10000);
}
-};
+}
float havocbot_goalrating_ons_generator_attack(float ratingscale)
{
- local entity g, wp, bestwp;
- local float found, best;
+ entity g, wp, bestwp;
+ float found, best;
for (g = findchain(classname, "onslaught_generator"); g; g = g.chain)
{
}
}
return FALSE;
-};
+}
void havocbot_role_ons_offense()
{
self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
}
-};
+}
void havocbot_role_ons_assistant()
{
havocbot_ons_reset_role(self);
-};
+}
void havocbot_role_ons_defense()
{
havocbot_ons_reset_role(self);
-};
+}
void havocbot_ons_reset_role(entity bot)
{
- local entity head;
- local float c;
+ entity head;
+ float c;
if(self.deadflag != DEAD_NO)
return;
}
havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
-};
+}
void havocbot_chooserole_ons()
{
havocbot_ons_reset_role(self);
-};
+}
void havocbot_goalrating_items(float ratingscale, vector org, float sradius)
{
- local entity head;
- local entity player;
- local float rating, d, discard, distance, friend_distance, enemy_distance;
+ entity head;
+ entity player;
+ float rating, d, discard, distance, friend_distance, enemy_distance;
vector o;
ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
head = findchainfloat(bot_pickup, TRUE);
navigation_routerating(head, rating * ratingscale, 2000);
head = head.chain;
}
-};
+}
void havocbot_goalrating_controlpoints(float ratingscale, vector org, float sradius)
{
- local entity head;
+ entity head;
head = findchain(classname, "dom_controlpoint");
while (head)
{
}
head = head.chain;
}
-};
+}
void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius)
{
- local entity head;
- local float t, noteam, distance;
+ entity head;
+ float t, noteam, distance;
noteam = ((self.team == 0) || !teamplay); // fteqcc sucks
if (autocvar_bot_nofire)
navigation_routerating(head, t * ratingscale, 2000);
}
}
-};
+}
// choose a role according to the situation
-void() havocbot_role_dm;
+void havocbot_role_dm();
//DOM:
//go to best items, or control points you don't own
//havocbot_goalrating_waypoints(1, self.origin, 1000);
navigation_goalrating_end();
}
-};
+}
//DM:
//go to best items
//havocbot_goalrating_waypoints(1, self.origin, 1000);
navigation_goalrating_end();
}
-};
+}
//Race:
//go to next checkpoint, and annoy enemies
navigation_goalrating_end();
}
-};
+}
void havocbot_chooserole_dm()
{
self.havocbot_role = havocbot_role_dm;
-};
+}
void havocbot_chooserole_race()
{
self.havocbot_role = havocbot_role_race;
-};
+}
void havocbot_chooserole_dom()
{
self.havocbot_role = havocbot_role_dom;
-};
+}
void havocbot_chooserole()
{
havocbot_chooserole_ast();
else // assume anything else is deathmatch
havocbot_chooserole_dm();
-};
+}
float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
{
- local vector org;
- local vector move;
- local vector dir;
- local float dist;
- local float totaldist;
- local float stepdist;
- local float yaw;
- local float ignorehazards;
- local float swimming;
+ vector org;
+ vector move;
+ vector dir;
+ float dist;
+ float totaldist;
+ float stepdist;
+ float yaw;
+ float ignorehazards;
+ float swimming;
if(autocvar_bot_debug_tracewalk)
{
traceline( org, move, movemode, e);
if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
{
- local vector nextmove;
+ vector nextmove;
move = trace_endpos;
while(trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
{
// moved successfully
if(swimming)
{
- local float c;
+ float c;
c = pointcontents(org + '0 0 1');
if not(c == CONTENT_WATER || c == CONTENT_LAVA || c == CONTENT_SLIME)
swimming = FALSE;
debugnodestatus(org, DEBUG_NODE_FAIL);
return FALSE;
-};
+}
/////////////////////////////////////////////////////////////////////////////
// goal stack
self.goalstack29 = world;
self.goalstack30 = world;
self.goalstack31 = world;
-};
+}
// add a new goal at the beginning of the stack
// (in other words: add a new prerequisite before going to the later goals)
self.goalstack02 = self.goalstack01;
self.goalstack01 = self.goalcurrent;
self.goalcurrent = e;
-};
+}
// remove first goal from stack
// (in other words: remove a prerequisite for reaching the later goals)
self.goalstack29 = self.goalstack30;
self.goalstack30 = self.goalstack31;
self.goalstack31 = world;
-};
+}
// find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
{
- local entity waylist, w, best;
- local float dist, bestdist;
- local vector v, org, pm1, pm2;
+ entity waylist, w, best;
+ float dist, bestdist;
+ vector v, org, pm1, pm2;
pm1 = ent.origin + ent.mins;
pm2 = ent.origin + ent.maxs;
waylist = findchain(classname, "waypoint");
{
if (w.wpisbox)
{
- local vector wm1, wm2;
+ vector wm1, wm2;
wm1 = w.origin + w.mins;
wm2 = w.origin + w.maxs;
v_x = bound(wm1_x, org_x, wm2_x);
// finds the waypoints near the bot initiating a navigation query
float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist)
{
- local entity head;
- local vector v, m1, m2, diff;
- local float c;
+ entity head;
+ vector v, m1, m2, diff;
+ float c;
// navigation_testtracewalk = TRUE;
c = 0;
head = waylist;
// updates a path link if a spawnfunc_waypoint link is better than the current one
void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vector p)
{
- local vector m1;
- local vector m2;
- local vector v;
+ vector m1;
+ vector m2;
+ vector v;
if (wp.wpisbox)
{
m1 = wp.absmin;
wp.wpfire = 1;
wp.wpnearestpoint = v;
}
-};
+}
// queries the entire spawnfunc_waypoint network for pathes leading away from the bot
void navigation_markroutes(entity fixed_source_waypoint)
{
- local entity w, wp, waylist;
- local float searching, cost, cost2;
- local vector p;
+ entity w, wp, waylist;
+ float searching, cost, cost2;
+ vector p;
w = waylist = findchain(classname, "waypoint");
while (w)
{
{
// try a short range search for the nearest waypoints, and expand the search repeatedly if none are found
// as this search is expensive we will use lower values if the bot is on the air
- local float i, increment, maxdistance;
+ float i, increment, maxdistance;
if(self.flags & FL_ONGROUND)
{
increment = 750;
w = w.chain;
}
}
-};
+}
// queries the entire spawnfunc_waypoint network for pathes leading to the bot
void navigation_markroutes_inverted(entity fixed_source_waypoint)
{
- local entity w, wp, waylist;
- local float searching, cost, cost2;
- local vector p;
+ entity w, wp, waylist;
+ float searching, cost, cost2;
+ vector p;
w = waylist = findchain(classname, "waypoint");
while (w)
{
w = w.chain;
}
}
-};
+}
// updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item
void navigation_routerating(entity e, float f, float rangebias)
// dprint("jetpack ai: can bridge these two points\n");
// Lower the altitude of these points as much as possible
- local float zdistance, xydistance, cost, t, fuel;
- local vector down, npa, npb;
+ float zdistance, xydistance, cost, t, fuel;
+ vector down, npa, npb;
down = '0 0 -1' * (PL_MAX_z - PL_MIN_z) * 10;
}
}
//dprint("\n");
-};
+}
// adds an item to the the goal stack with the path to a given item
float navigation_routetogoal(entity e, vector startposition)
}
return FALSE;
-};
+}
// removes any currently touching waypoints from the goal stack
// (this is how bots detect if they reached a goal)
void navigation_poptouchedgoals()
{
- local vector org, m1, m2;
+ vector org, m1, m2;
org = self.origin;
m1 = org + self.mins;
m2 = org + self.maxs;
navigation_clearroute();
navigation_bestgoal = world;
navigation_markroutes(world);
-};
+}
// ends a goal selection session (updates goal stack to the best goal)
void navigation_goalrating_end()
self.navigation_hasgoals = FALSE; // Reset this value
}
-};
+}
void botframe_updatedangerousobjects(float maxupdate)
{
- local entity head, bot_dodgelist;
- local vector m1, m2, v, o;
- local float c, d, danger;
+ entity head, bot_dodgelist;
+ vector m1, m2, v, o;
+ float c, d, danger;
c = 0;
bot_dodgelist = findchainfloat(bot_dodge, TRUE);
botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint");
break;
botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint");
}
-};
+}
void navigation_unstuck()
{
// Debug the goal stack visually
void debuggoalstack()
{
- local entity goal;
- local vector org, go;
+ entity goal;
+ vector org, go;
if(self.goalcounter==0)goal=self.goalcurrent;
else if(self.goalcounter==1)goal=self.goalstack01;
// Returns first bot with matching name
entity find_bot_by_name(string name)
{
- local entity bot;
+ entity bot;
bot = findchainflags(flags, FL_CLIENT);
while (bot)
// Returns a bot by number on list
entity find_bot_by_number(float number)
{
- local entity bot;
- local float c;
+ entity bot;
+ float c;
if(!number)
return world;
float bot_decodecommand(string cmdstring)
{
- local float cmd_parm_type, i;
+ float cmd_parm_type, i;
float sp;
string parm;
void bot_cmdhelp(string scmd)
{
- local float i, ntype;
- local string stype;
+ float i, ntype;
+ string stype;
if(!bot_cmds_initialized)
bot_commands_init();
void bot_list_commands()
{
- local float i;
- local string ptype;
+ float i;
+ string ptype;
if(!bot_cmds_initialized)
bot_commands_init();
float bot_cmd_select_weapon()
{
- local float id;
+ float id;
id = bot_cmd.bot_cmd_parm_float;
float bot_cmd_if()
{
- local string expr, val_a, val_b;
- local float cmpofs;
+ string expr, val_a, val_b;
+ float cmpofs;
if(self.bot_cmd_condition_status != CMD_CONDITION_NONE)
{
// Current direction
if(self.bot_cmd_aim_endtime)
{
- local float progress;
+ float progress;
progress = min(1 - (self.bot_cmd_aim_endtime - time) / (self.bot_cmd_aim_endtime - self.bot_cmd_aim_begintime),1);
self.v_angle = self.bot_cmd_aim_begin + ((self.bot_cmd_aim_end - self.bot_cmd_aim_begin) * progress);
}
// New aiming direction
- local string parms;
- local float tokens, step;
+ string parms;
+ float tokens, step;
parms = bot_cmd.bot_cmd_parm_string;
return bot_cmd_aim();
}
- local entity e;
- local string parms;
- local vector v;
- local float tokens, step;
+ entity e;
+ string parms;
+ vector v;
+ float tokens, step;
parms = bot_cmd.bot_cmd_parm_string;
float bot_cmd_presskey()
{
- local string key;
+ string key;
key = bot_cmd.bot_cmd_parm_string;
float bot_cmd_releasekey()
{
- local string key;
+ string key;
key = bot_cmd.bot_cmd_parm_string;
// NOTE: Of course you need to include your commands here too :)
float bot_execute_commands_once()
{
- local float status, ispressingkey;
+ float status, ispressingkey;
// Find command
bot_setcurrentcommand();
{
if(autocvar_g_debug_bot_commands)
{
- local string parms;
+ string parms;
switch(bot_cmd_parm_type[bot_cmd.bot_cmd_type])
{
// (suitable for spawnfunc_waypoint editor)
entity waypoint_spawn(vector m1, vector m2, float f)
{
- local entity w;
+ entity w;
w = find(world, classname, "waypoint");
if not(f & WAYPOINTFLAG_PERSONAL)
w.model = "";
return w;
-};
+}
// add a new link to the spawnfunc_waypoint, replacing the furthest link it already has
void waypoint_addlink(entity from, entity to)
{
- local float c;
+ float c;
if (from == to)
return;
{
// if either is a box we have to find the nearest points on them to
// calculate the distance properly
- local vector v1, v2, m1, m2;
+ vector v1, v2, m1, m2;
v1 = from.origin;
m1 = to.absmin;
m2 = to.absmax;
if (from.wp01mincost < c) {from.wp02 = to;from.wp02mincost = c;return;} from.wp02 = from.wp01;from.wp02mincost = from.wp01mincost;
if (from.wp00mincost < c) {from.wp01 = to;from.wp01mincost = c;return;} from.wp01 = from.wp00;from.wp01mincost = from.wp00mincost;
from.wp00 = to;from.wp00mincost = c;return;
-};
+}
// relink this spawnfunc_waypoint
// (precompile a list of all reachable waypoints from this spawnfunc_waypoint)
// (SLOW!)
void waypoint_think()
{
- local entity e;
- local vector sv, sm1, sm2, ev, em1, em2, dv;
+ entity e;
+ vector sv, sm1, sm2, ev, em1, em2, dv;
bot_calculate_stepheightvec();
}
navigation_testtracewalk = 0;
self.wplinked = TRUE;
-};
+}
void waypoint_clearlinks(entity wp)
{
// clear links to other waypoints
- local float f;
+ float f;
f = 10000000;
wp.wp00 = wp.wp01 = wp.wp02 = wp.wp03 = wp.wp04 = wp.wp05 = wp.wp06 = wp.wp07 = world;
wp.wp08 = wp.wp09 = wp.wp10 = wp.wp11 = wp.wp12 = wp.wp13 = wp.wp14 = wp.wp15 = world;
wp.wp24mincost = wp.wp25mincost = wp.wp26mincost = wp.wp27mincost = wp.wp28mincost = wp.wp29mincost = wp.wp30mincost = wp.wp31mincost = f;
wp.wplinked = FALSE;
-};
+}
// tell a spawnfunc_waypoint to relink
void waypoint_schedulerelink(entity wp)
// TODO: add some sort of visible box in edit mode for box waypoints
if (autocvar_g_waypointeditor)
{
- local vector m1, m2;
+ vector m1, m2;
m1 = wp.mins;
m2 = wp.maxs;
setmodel(wp, "models/runematch/rune.mdl"); wp.effects = EF_LOWPRECISION;
// schedule a relink after other waypoints have had a chance to spawn
waypoint_clearlinks(self);
//waypoint_schedulerelink(self);
-};
+}
// remove a spawnfunc_waypoint, and schedule all neighbors to relink
void waypoint_remove(entity e)
waypoint_schedulerelink(e.wp31);
// and now remove the spawnfunc_waypoint
remove(e);
-};
+}
// empties the map of waypoints
void waypoint_removeall()
{
- local entity head, next;
+ entity head, next;
head = findchain(classname, "waypoint");
while (head)
{
remove(head);
head = next;
}
-};
+}
// tell all waypoints to relink
// (is this useful at all?)
void waypoint_schedulerelinkall()
{
- local entity head;
+ entity head;
relink_total = relink_walkculled = relink_pvsculled = relink_lengthculled = 0;
head = findchain(classname, "waypoint");
while (head)
waypoint_schedulerelink(head);
head = head.chain;
}
-};
+}
// Load waypoint links from file
float waypoint_load_links()
{
- local string filename, s;
- local float file, tokens, c, found;
- local entity wp_from, wp_to;
- local vector wp_to_pos, wp_from_pos;
+ string filename, s;
+ float file, tokens, c, found;
+ entity wp_from, wp_to;
+ vector wp_to_pos, wp_from_pos;
filename = strcat("maps/", mapname);
filename = strcat(filename, ".waypoints.cache");
file = fopen(filename, FILE_READ);
botframe_cachedwaypointlinks = TRUE;
return TRUE;
-};
+}
void waypoint_load_links_hardwired()
{
- local string filename, s;
- local float file, tokens, c, found;
- local entity wp_from, wp_to;
- local vector wp_to_pos, wp_from_pos;
+ string filename, s;
+ float file, tokens, c, found;
+ entity wp_from, wp_to;
+ vector wp_to_pos, wp_from_pos;
filename = strcat("maps/", mapname);
filename = strcat(filename, ".waypoints.hardwired");
file = fopen(filename, FILE_READ);
dprint(" waypoint links from maps/");
dprint(mapname);
dprint(".waypoints.hardwired\n");
-};
+}
// Save all waypoint links to a file
void waypoint_save_links()
{
- local string filename, s;
- local float file, c, i;
- local entity w, link;
+ string filename, s;
+ float file, c, i;
+ entity w, link;
filename = strcat("maps/", mapname);
filename = strcat(filename, ".waypoints.cache");
file = fopen(filename, FILE_WRITE);
print(" waypoints links to maps/");
print(mapname);
print(".waypoints.cache\n");
-};
+}
// save waypoints to gamedir/data/maps/mapname.waypoints
void waypoint_saveall()
{
- local string filename, s;
- local float file, c;
- local entity w;
+ string filename, s;
+ float file, c;
+ entity w;
filename = strcat("maps/", mapname);
filename = strcat(filename, ".waypoints");
file = fopen(filename, FILE_WRITE);
}
waypoint_save_links();
botframe_loadedforcedlinks = FALSE;
-};
+}
// load waypoints from file
float waypoint_loadall()
{
- local string filename, s;
- local float file, cwp, cwb, fl;
- local vector m1, m2;
+ string filename, s;
+ float file, cwp, cwb, fl;
+ vector m1, m2;
cwp = 0;
cwb = 0;
filename = strcat("maps/", mapname);
dprint(" failed\n");
}
return cwp + cwb;
-};
+}
vector waypoint_fixorigin(vector position)
{
void waypoint_spawnforitem_force(entity e, vector org)
{
- local entity w;
+ entity w;
// Fix the waypoint altitude if necessary
org = waypoint_fixorigin(org);
return;
waypoint_spawnforitem_force(e, e.origin);
-};
+}
void waypoint_spawnforteleporter_boxes(entity e, vector org1, vector org2, vector destination1, vector destination2, float timetaken)
{
- local entity w;
- local entity dw;
+ entity w;
+ entity dw;
w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK);
dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED);
// one way link to the destination
// (teleporters are not goals, so this is probably useless)
e.nearestwaypoint = w;
e.nearestwaypointtimeout = time + 1000000000;
-};
+}
void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken)
{
org = waypoint_fixorigin(org);
destination = waypoint_fixorigin(destination);
waypoint_spawnforteleporter_boxes(e, org, org, destination, destination, timetaken);
-};
+}
void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
{
destination = waypoint_fixorigin(destination);
waypoint_spawnforteleporter_boxes(e, e.absmin, e.absmax, destination, destination, timetaken);
-};
+}
entity waypoint_spawnpersonal(vector position)
{
waypoint_schedulerelink(w);
return w;
-};
+}
void botframe_showwaypointlinks()
{
- local entity player, head, w;
+ entity player, head, w;
if (time < botframe_waypointeditorlightningtime)
return;
botframe_waypointeditorlightningtime = time + 0.5;
}
player = find(player, classname, "player");
}
-};
+}
entity head;
float won;
float lost;
- local string savevar;
+ string savevar;
won = 0;
self.team = activator.team;
some_spawn_has_been_used = 1;
}
-};
+}
// Returns:
// _x: prio (-1 if unusable)
// filter out spots for assault
if(spot.target != "") {
- local entity ent;
+ entity ent;
float good, found;
ent = find(world, targetname, spot.target);
float spawn_allgood;
entity Spawn_FilterOutBadSpots(entity firstspot, entity playerlist, float mindist, float teamcheck, float anypoint)
{
- local entity spot, spotlist, spotlistend;
+ entity spot, spotlist, spotlistend;
spawn_allgood = TRUE;
spawn_allbad = TRUE;
{
// weight of a point: bound(lower, mindisttoplayer, upper)^exponent
// multiplied by spot.cnt (useful if you distribute many spawnpoints in a small area)
- local entity spot;
+ entity spot;
RandomSelection_Init();
for(spot = firstspot; spot; spot = spot.chain)
*/
entity SelectSpawnPoint (float anypoint)
{
- local float teamcheck;
- local entity firstspot_new;
- local entity spot, firstspot, playerlist;
+ float teamcheck;
+ entity firstspot_new;
+ entity spot, firstspot, playerlist;
spot = find (world, classname, "testplayerstart");
if (spot)
self.classname = "observer";
self.iscreature = FALSE;
+ self.damagedbycontents = FALSE;
self.health = -666;
self.takedamage = DAMAGE_NO;
self.solid = SOLID_NOT;
void FixPlayermodel()
{
- local string defaultmodel;
- local float defaultskin, chmdl, oldskin;
- local vector m1, m2;
+ string defaultmodel;
+ float defaultskin, chmdl, oldskin;
+ vector m1, m2;
defaultmodel = "";
WriteByte(MSG_ONE, SVC_SETVIEW);
WriteEntity(MSG_ONE, self);
}
+
+ // reset player keys
+ self.itemkeys = 0;
// player is dead and becomes observer
// FIXME fix LMS scoring for new system
self.classname = "player";
self.wasplayer = TRUE;
self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
self.movetype = MOVETYPE_WALK;
self.solid = SOLID_SLIDEBOX;
self.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
self.prevorigin = self.origin;
self.lastrocket = world; // stop rocket guiding, no revenge from the grave!
self.lastteleporttime = time; // prevent insane speeds due to changing origin
-
+ self.hud = HUD_NORMAL;
+
if(g_arena)
{
Spawnqueue_Remove(self);
Portal_ClearAll(self);
+ RemoveGrapplingHook(self);
if(self.flagcarried)
DropFlag(self.flagcarried, world, world);
if(self.ballcarried && g_nexball)
self.model = self.mdl;
else
self.model = "";
-};
+}
void UpdateChatBubble()
{
// added to the model skins
/*void UpdateColorModHack()
{
- local float c;
+ float c;
c = self.clientcolors & 15;
// LordHavoc: only bothering to support white, green, red, yellow, blue
if (!teamplay) self.colormod = '0 0 0';
else if (c == 12) self.colormod = '1.22 1.22 0.10';
else if (c == 13) self.colormod = '0.10 0.10 1.73';
else self.colormod = '1 1 1';
-};*/
+}*/
.float oldcolormap;
void respawn(void)
return FALSE; // forced spectators can never join
// TODO simplify this
- local entity e;
+ entity e;
- local float totalClients;
+ float totalClients;
FOR_EACH_CLIENT(e)
totalClients += 1;
if (!autocvar_g_maxplayers)
return maxclients - totalClients + includeMe;
- local float currentlyPlaying;
+ float currentlyPlaying;
FOR_EACH_REALPLAYER(e)
currentlyPlaying += 1;
MUTATOR_CALLHOOK(PlayerPreThink);
- if(!self.cvar_cl_newusekeysupported)
+ if(!self.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
{
if(self.BUTTON_USE && !self.usekeypressed)
PlayerUseKey();
self.prevorigin = self.origin;
- if ((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss)
+ if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x) // prevent crouching if using melee attack
{
if (!self.crouch)
{
self.crouch = TRUE;
self.view_ofs = PL_CROUCH_VIEW_OFS;
setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
- setanim(self, self.anim_duck, FALSE, TRUE, TRUE);
+ // setanim(self, self.anim_duck, FALSE, TRUE, TRUE); // this anim is BROKEN anyway
}
}
else
void ImpulseCommands (void)
{
- local float imp;
+ float imp;
vector org;
float i;
float m;
if (self.crouch)
setanim(self, self.anim_duckjump, FALSE, TRUE, TRUE);
- else
+ else if (self.animstate_startframe != self.anim_melee_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // jump animation shouldn't override melee until we have animation blending (or until the anim finished, 21/20 = numframes/fps)
setanim(self, self.anim_jump, FALSE, TRUE, TRUE);
if(g_jump_grunt)
}
void CheckWaterJump()
{
- local vector start, end;
+ vector start, end;
// check for a jump-out-of-water
makevectors (self.angles);
return;
}
}
-};
+}
void CheckPlayerJump()
{
if(self.flags & FL_ONGROUND)
float speedaward_lastsent;
void SV_PlayerPhysics()
{
- local vector wishvel, wishdir, v;
- local float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons;
+ vector wishvel, wishdir, v;
+ float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons;
string temps;
float buttons_prev;
float not_allowed_to_move;
maxspd_mod *= autocvar_g_movement_highspeed;
// fix physics stats for g_movement_highspeed
+ // TODO maybe rather use maxairspeed? needs testing
self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod);
if(autocvar_sv_airstrafeaccel_qw)
self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod);
self.lastflags = self.flags;
self.lastclassname = self.classname;
-};
+}
switch(status)
{
case URL_READY_CANWRITE:
- // url_fopen returned, we can write
+ // we can write
prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t");
url_fputs(fh, "#begin statsfile\n");
url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
}
}
url_fputs(fh, "#end\n\n");
- url_fclose(fh, WeaponStats_ready, world);
- buf_del(weaponstats_buffer);
- weaponstats_buffer = -1;
+ url_fclose(fh);
break;
case URL_READY_CANREAD:
// url_fclose is processing, we got a response for writing the data
while((s = url_fgets(fh)))
print(" ", s, "\n");
print("End of response.\n");
- url_fclose(fh, WeaponStats_ready, world);
+ url_fclose(fh);
break;
case URL_READY_CLOSED:
// url_fclose has finished
print("Weapon stats written\n");
+ buf_del(weaponstats_buffer);
+ weaponstats_buffer = -1;
break;
case URL_READY_ERROR:
default:
print("Weapon stats writing failed: ", ftos(status), "\n");
+ buf_del(weaponstats_buffer);
+ weaponstats_buffer = -1;
break;
}
}
return;
if(autocvar_sv_weaponstats_file != "")
{
- url_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world);
+ url_multi_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world);
}
else
{
void CopyBody(float keepvelocity)
{
- local entity oldself;
+ entity oldself;
if (self.effects & EF_NODRAW)
return;
oldself = self;
self.colormap = oldself.colormap;
self.glowmod = oldself.glowmod;
self.iscreature = oldself.iscreature;
+ self.damagedbycontents = oldself.damagedbycontents;
self.angles = oldself.angles;
self.avelocity = oldself.avelocity;
self.classname = "body";
void player_setupanimsformodel()
{
- local string animfilename;
- local float animfile;
// defaults for legacy .zym models without animinfo files
- self.anim_die1 = '0 1 0.5'; // 2 seconds
- self.anim_die2 = '1 1 0.5'; // 2 seconds
- self.anim_draw = '2 1 3'; // TODO: analyze models and set framerate
- self.anim_duck = '3 1 100'; // this anim seems bogus in most models, so make it play VERY briefly!
- self.anim_duckwalk = '4 1 1';
- self.anim_duckjump = '5 1 100'; // zym anims keep playing until changed, so this only has to start the anim, landing will end it
- self.anim_duckidle = '6 1 1';
- self.anim_idle = '7 1 1';
- self.anim_jump = '8 1 100'; // zym anims keep playing until changed, so this only has to start the anim, landing will end it
- self.anim_pain1 = '9 1 2'; // 0.5 seconds
- self.anim_pain2 = '10 1 2'; // 0.5 seconds
- self.anim_shoot = '11 1 5'; // TODO: analyze models and set framerate
- self.anim_taunt = '12 1 0.33'; // FIXME? there is no code using this anim
- self.anim_run = '13 1 1';
- self.anim_runbackwards = '14 1 1';
- self.anim_strafeleft = '15 1 1';
- self.anim_straferight = '16 1 1';
- self.anim_dead1 = '17 1 1';
- self.anim_dead2 = '18 1 1';
- self.anim_forwardright = '19 1 1';
- self.anim_forwardleft = '20 1 1';
- self.anim_backright = '21 1 1';
- self.anim_backleft = '22 1 1';
- self.anim_melee = '23 1 1';
- animparseerror = FALSE;
- animfilename = strcat(self.model, ".animinfo");
- animfile = fopen(animfilename, FILE_READ);
- if (animfile >= 0)
- {
- self.anim_die1 = animparseline(animfile);
- self.anim_die2 = animparseline(animfile);
- self.anim_draw = animparseline(animfile);
- self.anim_duck = animparseline(animfile);
- self.anim_duckwalk = animparseline(animfile);
- self.anim_duckjump = animparseline(animfile);
- self.anim_duckidle = animparseline(animfile);
- self.anim_idle = animparseline(animfile);
- self.anim_jump = animparseline(animfile);
- self.anim_pain1 = animparseline(animfile);
- self.anim_pain2 = animparseline(animfile);
- self.anim_shoot = animparseline(animfile);
- self.anim_taunt = animparseline(animfile);
- self.anim_run = animparseline(animfile);
- self.anim_runbackwards = animparseline(animfile);
- self.anim_strafeleft = animparseline(animfile);
- self.anim_straferight = animparseline(animfile);
- self.anim_forwardright = animparseline(animfile);
- self.anim_forwardleft = animparseline(animfile);
- self.anim_backright = animparseline(animfile);
- self.anim_backleft = animparseline(animfile);
- self.anim_melee = animparseline(animfile);
- fclose(animfile);
-
- // derived anims
- self.anim_dead1 = '0 1 1' + '1 0 0' * (self.anim_die1_x + self.anim_die1_y - 1);
- self.anim_dead2 = '0 1 1' + '1 0 0' * (self.anim_die2_x + self.anim_die2_y - 1);
-
- if (animparseerror)
- print("Parse error in ", animfilename, ", some player animations are broken\n");
- }
- else
- dprint("File ", animfilename, " not found, assuming legacy .zym model animation timings\n");
+ self.anim_die1 = animfixfps(self, '0 1 0.5'); // 2 seconds
+ self.anim_die2 = animfixfps(self, '1 1 0.5'); // 2 seconds
+ self.anim_draw = animfixfps(self, '2 1 3');
+ // self.anim_duck = '3 1 100'; // This anim is broken, use slot 3 as a new free slot in the future ;)
+ self.anim_duckwalk = animfixfps(self, '4 1 1');
+ self.anim_duckjump = '5 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
+ self.anim_duckidle = animfixfps(self, '6 1 1');
+ self.anim_idle = animfixfps(self, '7 1 1');
+ self.anim_jump = '8 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
+ self.anim_pain1 = animfixfps(self, '9 1 2'); // 0.5 seconds
+ self.anim_pain2 = animfixfps(self, '10 1 2'); // 0.5 seconds
+ self.anim_shoot = animfixfps(self, '11 1 5'); // analyze models and set framerate
+ self.anim_taunt = animfixfps(self, '12 1 0.33');
+ self.anim_run = animfixfps(self, '13 1 1');
+ self.anim_runbackwards = animfixfps(self, '14 1 1');
+ self.anim_strafeleft = animfixfps(self, '15 1 1');
+ self.anim_straferight = animfixfps(self, '16 1 1');
+ self.anim_dead1 = animfixfps(self, '17 1 1');
+ self.anim_dead2 = animfixfps(self, '18 1 1');
+ self.anim_forwardright = animfixfps(self, '19 1 1');
+ self.anim_forwardleft = animfixfps(self, '20 1 1');
+ self.anim_backright = animfixfps(self, '21 1 1');
+ self.anim_backleft = animfixfps(self, '22 1 1');
+ self.anim_melee = animfixfps(self, '23 1 1');
+ // TODO introspect models for finding right "fps" value (1/duration)
// reset animstate now
setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
-};
+}
void player_anim (void)
{
if (!self.animstate_override)
{
- if (!(self.flags & FL_ONGROUND))
+ if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
{
if (self.crouch)
- setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump);
+ {
+ if (self.animstate_startframe != self.anim_duckjump_x) // don't perform another trace if already playing the crouch jump anim
+ {
+ traceline(self.origin + '0 0 1' * PL_CROUCH_MIN_z, self.origin + '0 0 1' * (PL_CROUCH_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
+ if(!trace_startsolid && trace_fraction == 1 || !(self.animstate_startframe == self.anim_duckwalk_x || self.animstate_startframe == self.anim_duckidle_x)) // don't get stuck on non-crouch anims
+ {
+ setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump);
+ self.restart_jump = FALSE;
+ }
+ }
+ }
else
- setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump);
- self.restart_jump = FALSE;
+ {
+ if (self.animstate_startframe != self.anim_jump_x) // don't perform another trace if already playing the jump anim
+ {
+ traceline(self.origin + '0 0 1' * PL_MIN_z, self.origin + '0 0 1' * (PL_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
+ if(!trace_startsolid && trace_fraction == 1 || self.animstate_startframe == self.anim_idle_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // don't get stuck on idle animation in midair, nor melee after it finished
+ {
+ setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump);
+ self.restart_jump = FALSE;
+ }
+ }
+ }
}
else if (self.crouch)
{
void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- local float take, save;
+ float take, save;
vector v;
Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- local float take, save, waves, sdelay, dh, da, j;
+ float take, save, waves, sdelay, dh, da, j;
vector v;
float valid_damage_for_weaponstats;
float excess;
self.armorvalue = self.armorvalue - save;
self.health = self.health - take;
// pause regeneration for 5 seconds
- self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_health_regen);
+ if(take)
+ self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_health_regen);
if (time > self.pain_finished) //Don't switch pain sequences like crazy
{
if(sv_gentle < 1) {
if(self.classname != "body") // pain anim is BORKED on our ZYMs, FIXME remove this once we have good models
{
- if (random() > 0.5)
- setanim(self, self.anim_pain1, FALSE, TRUE, TRUE);
- else
- setanim(self, self.anim_pain2, FALSE, TRUE, TRUE);
+ if (!self.animstate_override)
+ {
+ if (random() > 0.5)
+ setanim(self, self.anim_pain1, FALSE, TRUE, TRUE);
+ else
+ setanim(self, self.anim_pain2, FALSE, TRUE, TRUE);
+ }
}
if(sound_allowed(MSG_BROADCAST, attacker))
}
// throw off bot aim temporarily
- local float shake;
+ float shake;
shake = damage * 5 / (bound(0,skill,100) + 1);
self.v_angle_x = self.v_angle_x + (random() * 2 - 1) * shake;
self.v_angle_y = self.v_angle_y + (random() * 2 - 1) * shake;
MUTATOR_CALLHOOK(PlayerDies);
weapon_action(self.weapon, WR_PLAYERDEATH);
+ RemoveGrapplingHook(self);
+
if(self.flagcarried)
{
if(attacker.classname != "player")
{
W_TriggerReload();
}
-};
+}
.float weaponcomplainindex;
float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
float w_getbestweapon(entity e)
{
return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE);
-};
+}
// generic weapons table
// TODO should they be macros instead?
float weapon_action(float wpn, float wrequest)
{
return (get_weaponinfo(wpn)).weapon_func(wrequest);
-};
+}
string W_Name(float weaponid)
{
// toss current weapon
void W_ThrowWeapon(vector velo, vector delta, float doreduce)
{
- local float w, wb;
+ float w, wb;
string a;
w = self.weapon;
sprint(self, strcat("You dropped the ^2", W_Name(w), "\n"));
else
sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", a, "\n"));
-};
+}
// Bringed back weapon frame
void W_WeaponFrame()
// call the think code which may fire the weapon
// and do so multiple times to resolve framerate dependency issues if the
// server framerate is very low and the weapon fire rate very high
- local float c;
+ float c;
c = 0;
while (c < W_TICSPERFRAME)
{
else
self.currentammo = 1;
#endif
-};
+}
vector w_shotdir;
vector w_shotend;
+.float prevstrengthsound;
+.float prevstrengthsoundattempt;
+void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
+{
+ if((!g_minstagib)
+ && (player.items & IT_STRENGTH)
+ && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
+ || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
+ {
+ sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM);
+ player.prevstrengthsound = time;
+ }
+ player.prevstrengthsoundattempt = time;
+}
+
// this function calculates w_shotorg and w_shotdir based on the weapon model
// offset, trueaim and antilag, and won't put w_shotorg inside a wall.
// make sure you call makevectors first (FIXME?)
-.float prevstrengthsound;
-.float prevstrengthsoundattempt;
void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range)
{
float nudge = 1; // added to traceline target and subtracted from result
- local float oldsolid;
+ float oldsolid;
vector vecs, dv;
oldsolid = ent.dphitcontentsmask;
if(ent.weapon == WEP_RIFLE)
ent.punchangle_x = recoil * -1;
if (snd != "")
- sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
-
- if(ent.items & IT_STRENGTH)
- if(!g_minstagib)
- if(
- (time > ent.prevstrengthsound + autocvar_sv_strengthsound_antispam_time)
- ||
- (time > ent.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)
- ) // prevent insane sound spam
{
- sound(ent, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM);
- ent.prevstrengthsound = time;
+ sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
+ W_PlayStrengthSound(ent);
}
- ent.prevstrengthsoundattempt = time;
// nudge w_shotend so a trace to w_shotend hits
w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge;
-};
+}
#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE)
#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage)
return TRUE;
}
-float qcweaponanimation;
-vector weapon_offset = '0 -10 0';
-vector weapon_adjust = '10 0 -15';
-.vector weapon_morph0origin;
-.vector weapon_morph0angles;
-.float weapon_morph0time;
-.vector weapon_morph1origin;
-.vector weapon_morph1angles;
-.float weapon_morph1time;
-.vector weapon_morph2origin;
-.vector weapon_morph2angles;
-.float weapon_morph2time;
-.vector weapon_morph3origin;
-.vector weapon_morph3angles;
-.float weapon_morph3time;
-.vector weapon_morph4origin;
-.vector weapon_morph4angles;
-.float weapon_morph4time;
-#define QCWEAPONANIMATION_ORIGIN(e) ((weapon_offset_x + e.view_ofs_x) * v_forward - (weapon_offset_y + e.view_ofs_y) * v_right + (weapon_offset_z + e.view_ofs_z) * v_up + weapon_adjust)
-
/*
* supported formats:
*
// remove the ent
void CL_WeaponEntity_SetModel(string name)
{
- string animfilename;
- float animfile;
float v_shot_idx;
if (name != "")
{
if(!v_shot_idx)
v_shot_idx = gettagindex(self, "tag_shot");
- if(qcweaponanimation)
+ setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below
+ // preset some defaults that work great for renamed zym files (which don't need an animinfo)
+ self.anim_fire1 = animfixfps(self, '0 1 0.01');
+ self.anim_fire2 = animfixfps(self, '1 1 0.01');
+ self.anim_idle = animfixfps(self, '2 1 0.01');
+ self.anim_reload = animfixfps(self, '3 1 0.01');
+
+ // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
+ // if we don't, this is a "real" animated model
+ if(gettagindex(self, "weapon"))
+ {
+ if (!self.weaponentity)
+ self.weaponentity = spawn();
+ setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
+ setattachment(self.weaponentity, self, "weapon");
+ }
+ else if(gettagindex(self, "tag_weapon"))
{
- self.angles = '0 0 0';
- makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1');
- self.movedir = weapon_offset_x * v_forward - weapon_offset_y * v_right + weapon_offset_z * v_up + weapon_adjust;
- self.movedir_x += 32;
- self.spawnorigin = self.movedir;
- // oldorigin - not calculated here
+ if (!self.weaponentity)
+ self.weaponentity = spawn();
+ setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
+ setattachment(self.weaponentity, self, "tag_weapon");
}
else
{
- setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below
- animfilename = strcat("models/weapons/h_", name, ".iqm.animinfo");
- animfile = fopen(animfilename, FILE_READ);
- // preset some defaults that work great for renamed zym files (which don't need an animinfo)
- self.anim_fire1 = '0 1 0.01';
- self.anim_fire2 = '1 1 0.01';
- self.anim_idle = '2 1 0.01';
- self.anim_reload = '3 1 0.01';
- if (animfile >= 0)
- {
- animparseerror = FALSE;
- self.anim_fire1 = animparseline(animfile);
- self.anim_fire2 = animparseline(animfile);
- self.anim_idle = animparseline(animfile);
- self.anim_reload = animparseline(animfile);
- fclose(animfile);
- if (animparseerror)
- print("Parse error in ", animfilename, ", some player animations are broken\n");
- }
-
- // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
- // if we don't, this is a "real" animated model
- if(gettagindex(self, "weapon"))
- {
- if (!self.weaponentity)
- self.weaponentity = spawn();
- setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
- setattachment(self.weaponentity, self, "weapon");
- }
- else if(gettagindex(self, "tag_weapon"))
- {
- if (!self.weaponentity)
- self.weaponentity = spawn();
- setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
- setattachment(self.weaponentity, self, "tag_weapon");
- }
- else
- {
- if(self.weaponentity)
- remove(self.weaponentity);
- self.weaponentity = world;
- }
+ if(self.weaponentity)
+ remove(self.weaponentity);
+ self.weaponentity = world;
+ }
- setorigin(self,'0 0 0');
- self.angles = '0 0 0';
- self.frame = 0;
- self.viewmodelforclient = world;
+ setorigin(self,'0 0 0');
+ self.angles = '0 0 0';
+ self.frame = 0;
+ self.viewmodelforclient = world;
- float idx;
+ float idx;
- if(v_shot_idx) // v_ model attached to invisible h_ model
+ if(v_shot_idx) // v_ model attached to invisible h_ model
+ {
+ self.movedir = gettaginfo(self.weaponentity, v_shot_idx);
+ }
+ else
+ {
+ idx = gettagindex(self, "shot");
+ if(!idx)
+ idx = gettagindex(self, "tag_shot");
+ if(idx)
+ self.movedir = gettaginfo(self, idx);
+ else
{
- self.movedir = gettaginfo(self.weaponentity, v_shot_idx);
+ print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
+ self.movedir = '0 0 0';
}
+ }
+
+ if(self.weaponentity) // v_ model attached to invisible h_ model
+ {
+ idx = gettagindex(self.weaponentity, "shell");
+ if(!idx)
+ idx = gettagindex(self.weaponentity, "tag_shell");
+ if(idx)
+ self.spawnorigin = gettaginfo(self.weaponentity, idx);
+ }
+ else
+ idx = 0;
+ if(!idx)
+ {
+ idx = gettagindex(self, "shell");
+ if(!idx)
+ idx = gettagindex(self, "tag_shell");
+ if(idx)
+ self.spawnorigin = gettaginfo(self, idx);
else
{
- idx = gettagindex(self, "shot");
- if(!idx)
- idx = gettagindex(self, "tag_shot");
- if(idx)
- self.movedir = gettaginfo(self, idx);
- else
- {
- print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
- self.movedir = '0 0 0';
- }
+ print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n");
+ self.spawnorigin = self.movedir;
}
+ }
- if(self.weaponentity) // v_ model attached to invisible h_ model
+ if(v_shot_idx)
+ {
+ self.oldorigin = '0 0 0'; // use regular attachment
+ }
+ else
+ {
+ if(self.weaponentity)
{
- idx = gettagindex(self.weaponentity, "shell");
+ idx = gettagindex(self, "weapon");
if(!idx)
- idx = gettagindex(self.weaponentity, "tag_shell");
- if(idx)
- self.spawnorigin = gettaginfo(self.weaponentity, idx);
+ idx = gettagindex(self, "tag_weapon");
}
else
- idx = 0;
- if(!idx)
{
- idx = gettagindex(self, "shell");
+ idx = gettagindex(self, "handle");
if(!idx)
- idx = gettagindex(self, "tag_shell");
- if(idx)
- self.spawnorigin = gettaginfo(self, idx);
- else
- {
- print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n");
- self.spawnorigin = self.movedir;
- }
+ idx = gettagindex(self, "tag_handle");
}
-
- if(v_shot_idx)
+ if(idx)
{
- self.oldorigin = '0 0 0'; // use regular attachment
+ self.oldorigin = self.movedir - gettaginfo(self, idx);
}
else
{
- if(self.weaponentity)
- {
- idx = gettagindex(self, "weapon");
- if(!idx)
- idx = gettagindex(self, "tag_weapon");
- }
- else
- {
- idx = gettagindex(self, "handle");
- if(!idx)
- idx = gettagindex(self, "tag_handle");
- }
- if(idx)
- {
- self.oldorigin = self.movedir - gettaginfo(self, idx);
- }
- else
- {
- print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
- self.oldorigin = '0 0 0'; // there is no way to recover from this
- }
+ print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
+ self.oldorigin = '0 0 0'; // there is no way to recover from this
}
-
- self.viewmodelforclient = self.owner;
}
+
+ self.viewmodelforclient = self.owner;
}
else
{
self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount
// check if an instant weapon switch occurred
- if (qcweaponanimation)
- {
- if (self.state == WS_READY)
- {
- self.angles = '0 0 0';
- makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1');
- setorigin(self, QCWEAPONANIMATION_ORIGIN(self));
- }
- }
- else
- setorigin(self, self.view_ofs);
+ setorigin(self, self.view_ofs);
// reset animstate now
self.wframe = WFRAME_IDLE;
- self.weapon_morph0time = 0;
- self.weapon_morph1time = 0;
- self.weapon_morph2time = 0;
- self.weapon_morph3time = 0;
- self.weapon_morph4time = 0;
setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
}
}
self.angles = '0 0 0';
- local float f;
+ float f;
f = 0;
if (self.state == WS_RAISE && !intermission_running)
{
f = (self.owner.weapon_nextthink - time) * g_weaponratefactor / autocvar_g_balance_weaponswitchdelay;
self.angles_x = -90 * f * f;
- if (qcweaponanimation)
- {
- makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1');
- setorigin(self, QCWEAPONANIMATION_ORIGIN(self));
- }
}
else if (self.state == WS_DROP && !intermission_running)
{
f = 1 - (self.owner.weapon_nextthink - time) * g_weaponratefactor / autocvar_g_balance_weaponswitchdelay;
self.angles_x = -90 * f * f;
- if (qcweaponanimation)
- {
- makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1');
- setorigin(self, QCWEAPONANIMATION_ORIGIN(self));
- }
}
else if (self.state == WS_CLEAR)
{
f = 1;
self.angles_x = -90 * f * f;
- if (qcweaponanimation)
- {
- makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1');
- setorigin(self, QCWEAPONANIMATION_ORIGIN(self));
- }
- }
- else if (qcweaponanimation && time < self.owner.weapon_morph1time)
- {
- f = (time - self.owner.weapon_morph0time) / (self.owner.weapon_morph1time - self.owner.weapon_morph0time);
- f = 1 - pow(1 - f, 3);
- self.angles = self.owner.weapon_morph0angles * (1 - f) + self.owner.weapon_morph1angles * f;
- setorigin(self, self.owner.weapon_morph0origin * (1 - f) + self.owner.weapon_morph1origin * f);
- }
- else if (qcweaponanimation && time < self.owner.weapon_morph2time)
- {
- f = (time - self.owner.weapon_morph1time) / (self.owner.weapon_morph2time - self.owner.weapon_morph1time);
- f = 1 - pow(1 - f, 3);
- self.angles = self.owner.weapon_morph1angles * (1 - f) + self.owner.weapon_morph2angles * f;
- setorigin(self, self.owner.weapon_morph1origin * (1 - f) + self.owner.weapon_morph2origin * f);
}
- else if (qcweaponanimation && time < self.owner.weapon_morph3time)
- {
- f = (time - self.owner.weapon_morph2time) / (self.owner.weapon_morph3time - self.owner.weapon_morph2time);
- f = 1 - pow(1 - f, 3);
- self.angles = self.owner.weapon_morph2angles * (1 - f) + self.owner.weapon_morph3angles * f;
- setorigin(self, self.owner.weapon_morph2origin * (1 - f) + self.owner.weapon_morph3origin * f);
- }
- else if (qcweaponanimation && time < self.owner.weapon_morph4time)
- {
- f = (time - self.owner.weapon_morph3time) / (self.owner.weapon_morph4time - self.owner.weapon_morph3time);
- f = 1 - pow(1 - f, 3);
- self.angles = self.owner.weapon_morph3angles * (1 - f) + self.owner.weapon_morph4angles * f;
- setorigin(self, self.owner.weapon_morph3origin * (1 - f) + self.owner.weapon_morph4origin * f);
- }
- else if (qcweaponanimation)
- {
- // begin a new idle morph
- self.owner.weapon_morph0time = time;
- self.owner.weapon_morph0angles = self.angles;
- self.owner.weapon_morph0origin = self.origin;
-
- float r;
- float t;
-
- r = random();
- if (r < 0.1)
- {
- // turn gun to the left to look at it
- t = 2;
- self.owner.weapon_morph1time = time + t * 0.2;
- self.owner.weapon_morph1angles = randomvec() * 3 + '-5 30 0';
- makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1');
- self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph2time = time + t * 0.6;
- self.owner.weapon_morph2angles = randomvec() * 3 + '-5 30 0';
- makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1');
- self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph3time = time + t;
- self.owner.weapon_morph3angles = '0 0 0';
- makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1');
- self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self);
- }
- else if (r < 0.2)
- {
- // raise the gun a bit
- t = 2;
- self.owner.weapon_morph1time = time + t * 0.2;
- self.owner.weapon_morph1angles = randomvec() * 3 + '30 -10 0';
- makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1');
- self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph2time = time + t * 0.5;
- self.owner.weapon_morph2angles = randomvec() * 3 + '30 -10 5';
- makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1');
- self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph3time = time + t;
- self.owner.weapon_morph3angles = '0 0 0';
- makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1');
- self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self);
- }
- else if (r < 0.3)
- {
- // tweak it a bit
- t = 5;
- self.owner.weapon_morph1time = time + t * 0.3;
- self.owner.weapon_morph1angles = randomvec() * 6;
- makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1');
- self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph2time = time + t * 0.7;
- self.owner.weapon_morph2angles = randomvec() * 6;
- makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1');
- self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph3time = time + t;
- self.owner.weapon_morph3angles = '0 0 0';
- makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1');
- self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self);
- }
- else
- {
- // hold it mostly steady
- t = random() * 6 + 4;
- self.owner.weapon_morph1time = time + t * 0.2;
- self.owner.weapon_morph1angles = randomvec() * 1;
- makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1');
- self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph2time = time + t * 0.5;
- self.owner.weapon_morph2angles = randomvec() * 1;
- makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1');
- self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self);
-
- self.owner.weapon_morph3time = time + t * 0.7;
- self.owner.weapon_morph3angles = randomvec() * 1;
- makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1');
- self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self);
- }
-
- self.owner.weapon_morph4time = time + t;
- self.owner.weapon_morph4angles = '0 0 0';
- makevectors(self.owner.weapon_morph4angles_x * '-1 0 0' + self.owner.weapon_morph4angles_y * '0 1 0' + self.owner.weapon_morph4angles_z * '0 0 1');
- self.owner.weapon_morph4origin = QCWEAPONANIMATION_ORIGIN(self);
-
- }
-};
+}
void CL_ExteriorWeaponentity_Think()
{
if(autocvar_g_loituma)
{
- vector moddir, modup;
vector modangles;
float t;
self.glowmod = self.owner.weaponentity_glowmod;
self.colormap = self.owner.colormap;
-};
+}
// spawning weaponentity for client
void CL_SpawnWeaponentity()
self.exteriorweaponentity.angles = '0 0 0';
self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
self.exteriorweaponentity.nextthink = time;
-};
+}
void Send_WeaponComplain (entity e, float wpn, string wpnname, float type)
{
float client_hasweapon(entity cl, float wpn, float andammo, float complain)
{
- local float weaponbit, f;
- local entity oldself;
+ float weaponbit, f;
+ entity oldself;
if(time < self.hasweapon_complain_spam)
complain = 0;
f = f + weapon_action(wpn, WR_CHECKAMMO2);
// always allow selecting the Mine Layer if we placed mines, so that we can detonate them
- local entity mine;
+ entity mine;
if(wpn == WEP_MINE_LAYER)
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
f = 1;
play2(cl, "weapons/unavailable.wav");
}
return FALSE;
-};
+}
// Weapon subs
void w_clear()
self.weaponentity.state = WS_CLEAR;
self.weaponentity.effects = 0;
}
-};
+}
void w_ready()
{
if (self.weaponentity)
self.weaponentity.state = WS_READY;
weapon_thinkf(WFRAME_IDLE, 1000000, w_ready);
-};
+}
// Setup weapon for client (after this raise frame will be launched)
void weapon_setup(float windex)
{
entity e;
- qcweaponanimation = autocvar_sv_qcweaponanimation;
e = get_weaponinfo(windex);
self.items &~= IT_AMMO;
self.items = self.items | e.items;
self.switchingweapon = windex; // to make sure
self.weaponname = e.mdl;
self.bulletcounter = 0;
-};
+}
// perform weapon to attack (weaponstate and attack_finished check is here)
void W_SwitchToOtherWeapon(entity pl)
if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
{
// always keep the Mine Layer if we placed mines, so that we can detonate them
- local entity mine;
+ entity mine;
if(self.weapon == WEP_MINE_LAYER)
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
return FALSE;
if (self.weaponentity)
{
self.weaponentity.wframe = fr;
- if (qcweaponanimation)
- {
- if (fr != WFRAME_IDLE)
- {
- self.weapon_morph0time = time;
- self.weapon_morph0angles = self.weaponentity.angles;
- self.weapon_morph0origin = self.weaponentity.origin;
-
- self.weapon_morph1angles = '0 0 0';
- self.weapon_morph1time = time + t;
- makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1');
- self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
-
- self.weapon_morph2angles = '0 0 0';
- self.weapon_morph2time = time + t;
- makevectors(self.weapon_morph2angles_x * '-1 0 0' + self.weapon_morph2angles_y * '0 1 0' + self.weapon_morph2angles_z * '0 0 1');
- self.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
-
- self.weapon_morph3angles = '0 0 0';
- self.weapon_morph3time = time + t;
- makevectors(self.weapon_morph3angles_x * '-1 0 0' + self.weapon_morph3angles_y * '0 1 0' + self.weapon_morph3angles_z * '0 0 1');
- self.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
-
- self.weapon_morph4angles = '0 0 0';
- self.weapon_morph4time = time + t;
- makevectors(self.weapon_morph4angles_x * '-1 0 0' + self.weapon_morph4angles_y * '0 1 0' + self.weapon_morph4angles_z * '0 0 1');
- self.weapon_morph4origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
-
- if (fr == WFRAME_FIRE1)
- {
- self.weapon_morph1angles = '5 0 0';
- self.weapon_morph1time = time + t * 0.1;
- makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1');
- self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
- self.weapon_morph4time = time + t + 1; // delay idle effect
- }
- else if (fr == WFRAME_FIRE2)
- {
- self.weapon_morph1angles = '10 0 0';
- self.weapon_morph1time = time + t * 0.1;
- makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1');
- self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
- self.weapon_morph4time = time + t + 1; // delay idle effect
- }
- else if (fr == WFRAME_RELOAD)
- {
- self.weapon_morph1time = time + t * 0.05;
- self.weapon_morph1angles = '-10 40 0';
- makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1');
- self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
-
- self.weapon_morph2time = time + t * 0.15;
- self.weapon_morph2angles = '-10 40 5';
- makevectors(self.weapon_morph2angles_x * '-1 0 0' + self.weapon_morph2angles_y * '0 1 0' + self.weapon_morph2angles_z * '0 0 1');
- self.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
-
- self.weapon_morph3time = time + t * 0.25;
- self.weapon_morph3angles = '-10 40 0';
- makevectors(self.weapon_morph3angles_x * '-1 0 0' + self.weapon_morph3angles_y * '0 1 0' + self.weapon_morph3angles_z * '0 0 1');
- self.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity);
- }
- }
- }
- else
- {
- if (fr == WFRAME_IDLE)
- a = self.weaponentity.anim_idle;
- else if (fr == WFRAME_FIRE1)
- a = self.weaponentity.anim_fire1;
- else if (fr == WFRAME_FIRE2)
- a = self.weaponentity.anim_fire2;
- else if (fr == WFRAME_RELOAD)
- a = self.weaponentity.anim_reload;
- a_z *= g_weaponratefactor;
- setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
- }
+ if (fr == WFRAME_IDLE)
+ a = self.weaponentity.anim_idle;
+ else if (fr == WFRAME_FIRE1)
+ a = self.weaponentity.anim_fire1;
+ else if (fr == WFRAME_FIRE2)
+ a = self.weaponentity.anim_fire2;
+ else if (fr == WFRAME_RELOAD)
+ a = self.weaponentity.anim_reload;
+ a_z *= g_weaponratefactor;
+ setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
}
v_forward = of;
anim_z = anim_y / (t + sys_frametime);
setanim(self, anim, FALSE, TRUE, TRUE);
}
+ else if (self.animstate_startframe == self.anim_idle_x) // only allow shoot anim to override idle animation until we have animation blending
+ {
+ anim = self.anim_shoot;
+ anim_z = anim_y / (t + sys_frametime);
+ setanim(self, anim, FALSE, TRUE, TRUE);
+ }
}
-};
+}
void weapon_boblayer1(float spd, vector org)
{
// VorteX: haste can be added here
-};
+}
vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute)
{
entity xflash;
flash.owner = self;
flash.angles_z = random() * 360;
- if(qcweaponanimation)
- {
- setorigin(flash, w_shotorg + w_shotdir * 50);
- flash.angles = vectoangles(w_shotdir);
- flash.angles_z = random() * 360;
- }
+
+ if(gettagindex(self.weaponentity, "shot"))
+ setattachment(flash, self.weaponentity, "shot");
else
- {
- if(gettagindex(self.weaponentity, "shot"))
- setattachment(flash, self.weaponentity, "shot");
- else
- setattachment(flash, self.weaponentity, "tag_shot");
- setorigin(flash, offset);
+ setattachment(flash, self.weaponentity, "tag_shot");
+ setorigin(flash, offset);
- xflash = spawn();
- copyentity(flash, xflash);
+ xflash = spawn();
+ copyentity(flash, xflash);
- flash.viewmodelforclient = self;
+ flash.viewmodelforclient = self;
- if(self.weaponentity.oldorigin_x > 0)
- {
- setattachment(xflash, self.exteriorweaponentity, "");
- setorigin(xflash, self.weaponentity.oldorigin + offset);
- }
+ if(self.weaponentity.oldorigin_x > 0)
+ {
+ setattachment(xflash, self.exteriorweaponentity, "");
+ setorigin(xflash, self.weaponentity.oldorigin + offset);
+ }
+ else
+ {
+ if(gettagindex(self.exteriorweaponentity, "shot"))
+ setattachment(xflash, self.exteriorweaponentity, "shot");
else
- {
- if(gettagindex(self.exteriorweaponentity, "shot"))
- setattachment(xflash, self.exteriorweaponentity, "shot");
- else
- setattachment(xflash, self.exteriorweaponentity, "tag_shot");
- setorigin(xflash, offset);
- }
+ setattachment(xflash, self.exteriorweaponentity, "tag_shot");
+ setorigin(xflash, offset);
}
}
.float checkfail;
void SV_ParseClientCommand(string s) {
- string cmd;
- float tokens;
float i;
entity e;
- tokens = tokenize_console(s);
-
- cmd = strtolower(argv(0));
- if(cmd != "reportcvar")
- if(cmd != "sentcvar")
- if(cmd != "pause")
- if(cmd != "prespawn")
- if(cmd != "spawn")
- if(cmd != "begin")
+ cmd_argc = tokenize_console(s);
+ cmd_string = s;
+ cmd_name = strtolower(argv(0));
+ if(cmd_name != "reportcvar")
+ if(cmd_name != "sentcvar")
+ if(cmd_name != "pause")
+ if(cmd_name != "prespawn")
+ if(cmd_name != "spawn")
+ if(cmd_name != "begin")
{
if(cmd_floodcheck())
return;
}
+ if(MUTATOR_CALLHOOK(SV_ParseClientCommand))
+ return; // already handled
+
if(GameCommand_Vote(s, self)) {
return;
} else if(GameCommand_MapVote(argv(0))) {
return;
- } else if(cmd == "checkfail") {
+ } else if(cmd_name == "checkfail") {
print(sprintf("CHECKFAIL: %s (%s) epically failed check %s\n", self.netname, self.netaddress, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1))));
self.checkfail = 1;
- } else if(cmd == "autoswitch") {
+ } else if(cmd_name == "autoswitch") {
// be backwards compatible with older clients (enabled)
self.autoswitch = ("0" != argv(1));
- local string autoswitchmsg;
+ string autoswitchmsg;
if (self.autoswitch) {
autoswitchmsg = "on";
} else {
autoswitchmsg = "off";
}
sprint(self, strcat("^1autoswitch turned ", autoswitchmsg, "\n"));
- } else if(cmd == "clientversion") {
+ } else if(cmd_name == "clientversion") {
if not(self.flags & FL_CLIENT)
return;
if (argv(1) == "$gameversion") {
self.classname = "observer";
stuffcmd(self,"menu_showteamselect\n");
}
- } else if(cmd == "reportcvar") { // old system
+ } else if(cmd_name == "reportcvar") { // old system
if(substring(argv(2), 0, 1) == "$") // undefined cvar: use the default value on the server then
{
s = strcat(substring(s, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\"");
- tokens = tokenize_console(s);
+ cmd_argc = tokenize_console(s);
}
GetCvars(1);
- } else if(cmd == "sentcvar") { // new system
- if(tokens == 2) // undefined cvar: use the default value on the server then
+ } else if(cmd_name == "sentcvar") { // new system
+ if(cmd_argc == 2) // undefined cvar: use the default value on the server then
{
s = strcat(substring(s, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\"");
- tokens = tokenize_console(s);
+ cmd_argc = tokenize_console(s);
}
GetCvars(1);
- } else if(cmd == "spectate") {
+ } else if(cmd_name == "spectate") {
if(cmd_floodcheck())
return;
if not(self.flags & FL_CLIENT)
sprint(self, "WARNING: you will spectate in the next round.\n");
self.caplayer = 0;
}
- } else if(cmd == "join") {
+ } else if(cmd_name == "join") {
if not(self.flags & FL_CLIENT)
return;
if(!g_arena)
centerprint(self, PREVENT_JOIN_TEXT);
}
}
- } else if( cmd == "selectteam" ) {
+ } else if( cmd_name == "selectteam" ) {
if not(self.flags & FL_CLIENT)
return;
if( !teamplay ) {
} else {
sprint( self, strcat( "selectteam none/red/blue/yellow/pink/auto - \"", argv(1), "\" not recognised\n" ) );
}
- } else if(cmd == "ready") {
+ } else if(cmd_name == "ready") {
if not(self.flags & FL_CLIENT)
return;
sprint(self, "^1Game has already been restarted\n");
}
}
- } else if(cmd == "maplist") {
+ } else if(cmd_name == "maplist") {
sprint(self, maplist_reply);
- } else if(cmd == "lsmaps") {
+ } else if(cmd_name == "lsmaps") {
sprint(self, lsmaps_reply);
- } else if(cmd == "lsnewmaps") {
+ } else if(cmd_name == "lsnewmaps") {
sprint(self, lsnewmaps_reply);
- } else if(cmd == "records") {
+ } else if(cmd_name == "records") {
for(i = 0; i < 10; ++i)
sprint(self, records_reply[i]);
- } else if(cmd == "ladder") {
+ } else if(cmd_name == "ladder") {
sprint(self, ladder_reply);
- } else if(cmd == "rankings") {
+ } else if(cmd_name == "rankings") {
sprint(self, rankings_reply);
- } else if(cmd == "voice") {
- if(tokens >= 3)
+ } else if(cmd_name == "voice") {
+ if(cmd_argc >= 3)
VoiceMessage(argv(1), substring(s, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
else
VoiceMessage(argv(1), "");
- } else if(cmd == "say") {
- if(tokens >= 2)
+ } else if(cmd_name == "say") {
+ if(cmd_argc >= 2)
Say(self, FALSE, world, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1);
//clientcommand(self, formatmessage(s));
- } else if(cmd == "say_team") {
- if(tokens >= 2)
+ } else if(cmd_name == "say_team") {
+ if(cmd_argc >= 2)
Say(self, TRUE, world, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1);
//clientcommand(self, formatmessage(s));
- } else if(cmd == "tell") {
- e = GetCommandPlayerSlotTargetFromTokenizedCommand(tokens, 1);
- if(e && tokens > ParseCommandPlayerSlotTarget_firsttoken)
+ } else if(cmd_name == "tell") {
+ e = GetCommandPlayerSlotTargetFromTokenizedCommand(cmd_argc, 1);
+ if(e && cmd_argc > ParseCommandPlayerSlotTarget_firsttoken)
{
Say(self, FALSE, e, substring(s, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken)), TRUE);
}
else
{
- if(tokens > ParseCommandPlayerSlotTarget_firsttoken)
+ if(cmd_argc > ParseCommandPlayerSlotTarget_firsttoken)
trigger_magicear_processmessage_forallears(self, -1, world, substring(s, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken)));
sprint(self, "ERROR: usage: tell # playerid text...\n");
}
//clientcommand(self, formatmessage(s));
- } else if(cmd == "info") {
- cmd = cvar_string_builtin(strcat("sv_info_", argv(1))); // This needed fixed for the cvar check
- if(cmd == "")
+ } else if(cmd_name == "info") {
+ cmd_name = cvar_string_builtin(strcat("sv_info_", argv(1))); // This needed fixed for the cvar check
+ if(cmd_name == "")
sprint(self, "ERROR: unsupported info command\n");
else
- wordwrap_sprint(cmd, 1111);
- } else if(cmd == "suggestmap") {
+ wordwrap_sprint(cmd_name, 1111);
+ } else if(cmd_name == "suggestmap") {
sprint(self, strcat(MapVote_Suggest(argv(1)), "\n"));
- } else if(cmd == "timeout") {
+ } else if(cmd_name == "timeout") {
if not(self.flags & FL_CLIENT)
return;
if(autocvar_sv_timeout) {
else
sprint(self, "^7Error: only players can call a timeout!\n");
}
- } else if(cmd == "timein") {
+ } else if(cmd_name == "timein") {
if not(self.flags & FL_CLIENT)
return;
if(autocvar_sv_timeout) {
evaluateTimein();
}
- } else if(cmd == "teamstatus") {
+ } else if(cmd_name == "teamstatus") {
Score_NicePrint(self);
- } else if(cmd == "cvar_changes") {
+ } else if(cmd_name == "cvar_changes") {
sprint(self, cvar_changes);
- } else if(cmd == "cvar_purechanges") {
+ } else if(cmd_name == "cvar_purechanges") {
sprint(self, cvar_purechanges);
- } else if(CheatCommand(tokens)) {
+ } else if(CheatCommand(cmd_argc)) {
} else {
#if 0
//if(ctf_clientcommand())
// return;
// grep for Cmd_AddCommand_WithClientCommand to find them all
- if(cmd != "status")
- //if(cmd != "say") // handled above
- //if(cmd != "say_team") // handled above
- if(cmd != "kill")
- if(cmd != "pause")
- if(cmd != "ping")
- if(cmd != "name")
- if(cmd != "color")
- if(cmd != "rate")
- if(cmd != "pmodel")
- if(cmd != "playermodel")
- if(cmd != "playerskin")
- if(cmd != "prespawn")
- if(cmd != "spawn")
- if(cmd != "begin")
- if(cmd != "pings")
- if(cmd != "sv_startdownload")
- if(cmd != "download")
+ if(cmd_name != "status")
+ //if(cmd_name != "say") // handled above
+ //if(cmd_name != "say_team") // handled above
+ if(cmd_name != "kill")
+ if(cmd_name != "pause")
+ if(cmd_name != "ping")
+ if(cmd_name != "name")
+ if(cmd_name != "color")
+ if(cmd_name != "rate")
+ if(cmd_name != "pmodel")
+ if(cmd_name != "playermodel")
+ if(cmd_name != "playerskin")
+ if(cmd_name != "prespawn")
+ if(cmd_name != "spawn")
+ if(cmd_name != "begin")
+ if(cmd_name != "pings")
+ if(cmd_name != "sv_startdownload")
+ if(cmd_name != "download")
{
print("WARNING: Invalid clientcommand by ", self.netname, ": ", s, "\n");
return;
#endif
if(self.jointime > 0 && time > self.jointime + 10 && time > self.nickspamtime) // allow any changes in the first 10 seconds since joining
- if(cmd == "name" || cmd == "playermodel") // TODO also playerskin and color?
+ if(cmd_name == "name" || cmd_name == "playermodel") // TODO also playerskin and color?
{
if(self.nickspamtime == 0 || time > self.nickspamtime + autocvar_g_nick_flood_timeout)
// good, no serious flood
void ReadyRestartForce()
{
- local entity e;
+ entity e;
bprint("^1Server is restarting...\n");
*/
void ReadyCount()
{
- local entity e;
- local float r, p;
+ entity e;
+ float r, p;
r = p = 0;
//if the map uses a timelimit make sure that timeout cannot be called right before the map ends
if (autocvar_timelimit) {
//a timelimit was used
- local float myTl;
+ float myTl;
myTl = autocvar_timelimit;
- local float lastPossibleTimeout;
+ float lastPossibleTimeout;
lastPossibleTimeout = (myTl*60) - autocvar_sv_timeout_leadtime - 1;
if (lastPossibleTimeout < time - game_starttime)
}
InitializeEntity(self, ctf_flag_spawnstuff, INITPRIO_SETLOCATION);
-};
+}
void LogCTF(string mode, float flagteam, entity actor)
{
e.cnt = FLAG_BASE;
e.owner = world;
e.flags = FL_ITEM | FL_NOTARGET; // clear FL_ONGROUND and any other junk
-};
+}
void ReturnFlag(entity e)
{
}
e.owner = world;
RegenFlag(e);
-};
+}
void DropFlag(entity e, entity penalty_receiver, entity attacker)
{
- local entity p;
+ entity p;
if(e.classname != "item_flag_team")
{
tracebox(e.origin, e.mins, e.maxs, e.origin, TRUE, e);
if(trace_startsolid)
dprint("FLAG FALLTHROUGH will happen SOON\n");
-};
+}
void FlagThink()
{
- local entity e;
+ entity e;
self.nextthink = time + 0.1;
DropFlag(self, world, world);
return;
}
-};
+}
float ctf_usekey()
{
void flag_cap_ring_spawn(vector org)
{
shockwave_spawn("models/ctf/shockwavetransring.md3", org - '0 0 15', -0.8, 0, 1);
-};
+}
void FlagTouch()
{
if(gameover) return;
- local float t;
- local entity player;
- local string s, s0, h0, h1;
+ float t;
+ entity player;
+ string s, s0, h0, h1;
if (other.classname != "player")
return;
if (other.health < 1) // ignore dead players
WaypointSprite_AttachCarrier("flagcarrier", other, RADARICON_FLAGCARRIER, '1 1 0');
}
}
-};
+}
/*QUAKED spawnfunc_info_player_team1 (1 0 0) (-16 -16 -24) (16 16 24)
CTF Starting point for a player
}
self.team = COLOR_TEAM1; // red
spawnfunc_info_player_deathmatch();
-};
-//self.team = 4;self.classname = "info_player_start";spawnfunc_info_player_start();};
+}
+//self.team = 4;self.classname = "info_player_start";spawnfunc_info_player_start();}
/*QUAKED spawnfunc_info_player_team2 (1 0 0) (-16 -16 -24) (16 16 24)
CTF Starting point for a player in
}
self.team = COLOR_TEAM2; // blue
spawnfunc_info_player_deathmatch();
-};
-//self.team = 13;self.classname = "info_player_start";spawnfunc_info_player_start();};
+}
+//self.team = 13;self.classname = "info_player_start";spawnfunc_info_player_start();}
/*QUAKED spawnfunc_info_player_team3 (1 0 0) (-16 -16 -24) (16 16 24)
CTF Starting point for a player in
}
self.team = COLOR_TEAM3; // yellow
spawnfunc_info_player_deathmatch();
-};
+}
/*QUAKED spawnfunc_info_player_team4 (1 0 0) (-16 -16 -24) (16 16 24)
}
self.team = COLOR_TEAM4; // purple
spawnfunc_info_player_deathmatch();
-};
+}
void item_flag_reset()
{
self.glow_size = 25;
self.glow_trail = 1;
}
-};
+}
/*QUAKED spawnfunc_item_flag_team1 (0 0.5 0.8) (-48 -48 -37) (48 48 37)
CTF flag for team one (Red).
precache_model("models/ctf/shockwavetransring.md3");
self.reset = item_flag_reset;
-};
+}
/*QUAKED spawnfunc_item_flag_team2 (0 0.5 0.8) (-48 -48 -24) (48 48 64)
CTF flag for team two (Blue).
precache_model("models/ctf/shockwavetransring.md3");
self.reset = item_flag_reset;
-};
+}
/*QUAKED spawnfunc_ctf_team (0 .5 .8) (-16 -16 -24) (16 16 32)
}
self.classname = "ctf_team";
self.team = self.cnt + 1;
-};
+}
// code from here on is just to support maps that don't have control point and team entities
void ctf_spawnteam (string teamname, float teamcolor)
{
- local entity oldself;
+ entity oldself;
oldself = self;
self = spawn();
self.classname = "ctf_team";
spawnfunc_ctf_team();
self = oldself;
-};
+}
// spawn some default teams if the map is not set up for ctf
void ctf_spawnteams()
ctf_spawnteam("Red", COLOR_TEAM1 - 1);
ctf_spawnteam("Blue", COLOR_TEAM2 - 1);
-};
+}
void ctf_delayedinit()
{
ctf_spawnteams();
ScoreRules_ctf();
-};
+}
void ctf_init()
{
//#NO AUTOCVARS START
g_ctf_win_mode = cvar("g_ctf_win_mode");
//#NO AUTOCVARS END
-};
+}
void ctf_setstatus2(entity flag, float shift)
{
{
// no status bits
}
-};
+}
void ctf_setstatus()
{
self.items &~= IT_BLUE_FLAG_LOST;
self.items &~= IT_CTF_SHIELDED;
- local entity flag;
+ entity flag;
float redflags, blueflags;
if(self.ctf_captureshielded)
ctf_setstatus2(flag, IT_BLUE_FLAG_TAKEN);
}
}
-};
+}
/*
-entity(float cteam) ctf_team_has_commander =
+entity ctf_team_has_commander(float cteam)
{
entity pl;
if(cteam != COLOR_TEAM1 || cteam != COLOR_TEAM2)
}
}
return world;
-};
+}
-void(entity e, float st) ctf_setstate =
+void ctf_setstate(entity e, float st)
{
e.ctf_state = st;
++e.version;
-};
+}
-void(float cteam) ctf_new_commander =
+void ctf_new_commander(float cteam)
{
entity pl, plmax;
ctf_setstate(plmax, 3);
sprint(plmax, "^3You're the commander now!\n");
centerprint(plmax, "^3You're the commander now!\n");
-};
+}
-void() ctf_clientconnect =
+void ctf_clientconnect()
{
self.iscommander = FALSE;
if(self.team != 0 && self.classname == "player" && !ctf_team_has_commander(self.team)) {
ctf_new_commander(self.team);
}
-};
+}
-void() ctf_playerchanged =
+void ctf_playerchanged()
{
if(!self.team || self.classname != "player") {
ctf_setstate(self, -1);
self.team_saved = self.team;
ctf_new_commander(self.team);
-};
+}
-void() ctf_clientdisconnect =
+void ctf_clientdisconnect()
{
if(self.iscommander)
{
ctf_new_commander(self.team);
}
-};
+}
entity GetPlayer(string);
-float() ctf_clientcommand =
+float ctf_clientcommand()
{
entity e;
if(argv(0) == "order") {
return TRUE;
}
return FALSE;
-};
+}
*/
.vector anim_die1; // player dies
.vector anim_die2; // player dies differently
.vector anim_draw; // player pulls out a weapon
-.vector anim_duck; // player crouches (from idle to duckidle)
+// .vector anim_duck; // player crouches (from idle to duckidle)
.vector anim_duckwalk; // player walking while crouching
.vector anim_duckjump; // player jumping from a crouch
.vector anim_duckidle; // player idling while crouching
.float watersound_finished;
.float iscreature;
+.float damagedbycontents;
.vector oldvelocity;
.float pauseregen_finished;
.float runes;
+// Keys player is holding
+.float itemkeys;
+// message delay for func_door locked by keys and key locks
+// this field is used on player entities
+.float key_door_messagetime;
+
.float version;
.float cvar_cl_handicap;
.float cvar_cl_playerdetailreduction;
.float cvar_cl_clippedspectating;
+.float cvar_cl_autoscreenshot;
.float cvar_cl_movement_track_canjump;
.float cvar_cl_newusekeysupported;
.float misc_bulletcounter; // replaces uzi & hlac bullet counter.
void PlayerUseKey();
+
void dompoint_captured ()
{
- local entity head;
- local float old_delay, old_team, real_team;
+ entity head;
+ float old_delay, old_team, real_team;
// now that the delay has expired, switch to the latest team to lay claim to this point
head = self.owner;
FOR_EACH_REALCLIENT(head)
set_dom_state(head);
-};
+}
void AnimateDomPoint()
{
void dompointthink()
{
- local float fragamt;
+ float fragamt;
self.nextthink = time + 0.1;
void dompointtouch()
{
- local entity head;
+ entity head;
if (other.classname != "player")
return;
if (other.health < 1)
self.enemy = other; // individual player scoring
self.enemy_playerid = other.playerid;
dompoint_captured();
-};
+}
/*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
Team declaration for Domination gameplay, this allows you to decide what team
// this would have to be changed if used in quakeworld
if(self.cnt)
self.team = self.cnt + 1; // WHY are these different anyway?
-};
+}
void dom_controlpoint_setup()
{
- local entity head;
+ entity head;
// find the spawnfunc_dom_team representing unclaimed points
head = find(world, classname, "dom_team");
while(head && head.netname != "")
waypoint_spawnforitem(self);
WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1');
-};
+}
self.effects = self.effects | EF_LOWPRECISION;
if (autocvar_g_domination_point_fullbright)
self.effects |= EF_FULLBRIGHT;
-};
+}
// code from here on is just to support maps that don't have control point and team entities
void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
{
- local entity oldself;
+ entity oldself;
oldself = self;
self = spawn();
self.classname = "dom_team";
//eprint(self);
self = oldself;
-};
+}
void dom_spawnpoint(vector org)
{
- local entity oldself;
+ entity oldself;
oldself = self;
self = spawn();
self.classname = "dom_controlpoint";
setorigin(self, org);
spawnfunc_dom_controlpoint();
self = oldself;
-};
+}
// spawn some default teams if the map is not set up for domination
void dom_spawnteams()
if(numteams > 3)
dom_spawnteam("Pink", COLOR_TEAM4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
-};
+}
void dom_delayedinit()
{
- local entity head;
+ entity head;
// if no teams are found, spawn defaults, if custom teams are set, use them
if (find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
}
ScoreRules_dom();
-};
+}
void dom_init()
{
addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
-};
+}
void entcs_init()
{
print("Initializing ClientSide information entities\n");
-};
+}
float entcs_customize()
{
if(sf & 16)
WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
return TRUE;
-};
+}
void entcs_think()
{
self.armorvalue = o.armorvalue;
self.SendFlags |= 16;
}
-};
+}
entity attach_entcs()
{
- local entity ent;
+ entity ent;
ent = spawn();
ent.classname = "entcs_sender_v2";
self.entcs = ent;
return ent;
-};
+}
void detach_entcs()
{
remove(self.entcs);
self.entcs = world;
-};
+}
//How to use:
/*
// to spawn a bot
- local entity oldself;
+ entity oldself;
oldself = self;
self = spawnclient();
if (!self)
self = oldself;
// to remove all bots
- local entity head;
+ entity head;
head = find(world, classname, "player");
while (head)
{
//it is a good idea to return FALSE early in the function if possible to reduce cpu usage, because this function may be called many thousands of times per frame if there are many customized entities on a 64+ player server.
//you are free to change anything in self, but please do not change any other entities (the results may be very inconsistent).
//example ideas for use of this extension:
-//making icons over teammates' heads which are only visible to teammates. for exasmple: float() playericon_customizeentityforclient = {return self.owner.team == other.team;};
-//making cloaked players more visible to their teammates than their enemies. for example: float() player_customizeentityforclient = {if (self.items & IT_CLOAKING) {if (self.team == other.team) self.alpha = 0.6;else self.alpha = 0.1;} return TRUE;};
-//making explosion models that face the viewer (does not work well with chase_active). for example: float() explosion_customizeentityforclient = {self.angles = vectoangles(other.origin + other.view_ofs - self.origin);self.angles_x = 0 - self.angles_x;};
+//making icons over teammates' heads which are only visible to teammates. for exasmple: float() playericon_customizeentityforclient = {return self.owner.team == other.team;}
+//making cloaked players more visible to their teammates than their enemies. for example: float() player_customizeentityforclient = {if (self.items & IT_CLOAKING) {if (self.team == other.team) self.alpha = 0.6;else self.alpha = 0.1;} return TRUE;}
+//making explosion models that face the viewer (does not work well with chase_active). for example: float() explosion_customizeentityforclient = {self.angles = vectoangles(other.origin + other.view_ofs - self.origin);self.angles_x = 0 - self.angles_x;}
//implementation notes:
//entity customization is done before per-client culling (visibility for instance) because the entity may be doing setorigin to display itself in different locations on different clients, may be altering its .modelindex, .effects and other fields important to culling, so customized entities increase cpu usage (non-customized entities can use all the early culling they want however, as they are not changing on a per client basis).
//"leftarm" (which is a child of "torso") which would return 2 instead...
float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup =
{
- local string bonename;
+ string bonename;
while (bonenum >= 0)
{
bonename = skel_get_bonename(skel, bonenum);
bonenum = skel_get_boneparent(skel, bonenum);
}
return 0;
-};
+}
// create a skeletonindex for our player using current modelindex
void() example_skel_player_setup =
{
self.skeletonindex = skel_create(self.modelindex);
-};
+}
// setup bones of skeleton based on an animation
// note: animmodelindex can be a different model than self.modelindex
void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin =
self.lerpfrac3 = 0;
self.lerpfrac4 = 0;
skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000);
-};
+}
// apply a different framegroup animation to bones with a specified parent
void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride =
{
- local float bonenum;
- local float numbones;
+ float bonenum;
+ float numbones;
self.frame = framegroup;
self.frame2 = 0;
self.frame3 = 0;
skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1);
bonenum = bonenum + 1;
}
-};
+}
// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling
void(vector eyetarget, string bonename) example_skel_player_update_eyetarget =
{
- local float bonenum;
- local vector ang;
- local vector oldforward, oldright, oldup;
- local vector relforward, relright, relup, relorg;
- local vector boneforward, boneright, boneup, boneorg;
- local vector parentforward, parentright, parentup, parentorg;
- local vector u, v;
- local vector modeleyetarget;
+ float bonenum;
+ vector ang;
+ vector oldforward, oldright, oldup;
+ vector relforward, relright, relup, relorg;
+ vector boneforward, boneright, boneup, boneorg;
+ vector parentforward, parentright, parentup, parentorg;
+ vector u, v;
+ vector modeleyetarget;
bonenum = skel_find_bone(self.skeletonindex, bonename) - 1;
if (bonenum < 0)
return;
v_forward = oldforward;
v_right = oldright;
v_up = oldup;
-};
+}
// delete skeleton when we're done with it
// note: skeleton remains valid until next frame when it is really deleted
void() example_skel_player_delete =
{
skel_delete(self.skeletonindex);
self.skeletonindex = 0;
-};
+}
//
// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
//
// func_breakable
// - basically func_assault_destructible for general gameplay use
//
-void LaunchDebris (string debrisname, vector force) =
+void LaunchDebris (string debrisname, vector force)
{
local entity dbr;
if(dbr.damageforcescale)
dbr.takedamage = DAMAGE_YES;
SUB_SetFade(dbr, time + self.debristime + crandom() * self.debristimejitter, self.debrisfadetime);
-};
+}
void func_breakable_colormod()
{
void func_breakable_look_destroyed()
{
- local float floor_z;
+ float floor_z;
if(self.solid == SOLID_BSP) // in case a misc_follow moved me, save the current origin first
self.dropped_origin = self.origin;
UpdateFrags(attacker, f);
}
+string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
+{
+ string health_output;
+ string ping_output;
+ string handicap_output;
+ string output;
+
+ // health/armor of attacker (person who killed you)
+ if(autocvar_sv_fraginfo_stats && (player.health >= 1))
+ if((autocvar_sv_fraginfo_stats == 2) || !inWarmupStage)
+ health_output = strcat("^7(Health ^1", ftos(rint(player.health)), "^7 / Armor ^2", ftos(rint(player.armorvalue)), "^7)");
+
+ // ping display
+ if(autocvar_sv_fraginfo_ping)
+ ping_output = ((clienttype(player) == CLIENTTYPE_BOT) ? "^2Bot" : strcat("Ping ", ((player.ping >= 150) ? "^1" : "^2"), ftos(player.ping), "ms"));
+
+ // handicap display
+ if(autocvar_sv_fraginfo_handicap)
+ {
+ if(autocvar_sv_fraginfo_handicap == 2)
+ handicap_output = strcat(output, strcat("Handicap ^2", ((player.cvar_cl_handicap <= 1) ? "Off" : ftos(player.cvar_cl_handicap))));
+ else if(player.cvar_cl_handicap) // with _handicap 1, only show this if there actually is a handicap enabled.
+ handicap_output = strcat("Handicap ^2", ftos(player.cvar_cl_handicap));
+ }
+
+ // format the string
+ output = strcat(health_output, (health_output ? " ^7(" : ((ping_output || handicap_output) ? "^7(" : "")),
+ ping_output, ((ping_output && handicap_output) ? "^7 / " : ""),
+ handicap_output, ((ping_output || handicap_output) ? "^7)" : ""));
+
+ // add new line to the beginning if there is a message
+ if(output) { output = strcat("\n", output); }
+
+ return output;
+}
+
string AppendItemcodes(string s, entity player)
{
float w;
}
else if (attacker.classname == "player")
{
- if(teamplay && attacker.team == targ.team)
+ if(!IsDifferentTeam(attacker, targ))
{
if(attacker.team == COLOR_TEAM1)
type = KILL_TEAM_RED;
PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
}
- if((autocvar_sv_fragmessage_information_typefrag) && (targ.BUTTON_CHAT)) {
- Send_CSQC_KillCenterprint(attacker, s, GetAdvancedDeathReports(targ), KILL_TYPEFRAG, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, a, GetAdvancedDeathReports(attacker), KILL_TYPEFRAGGED, MSG_KILL);
+ if((autocvar_sv_fraginfo_typefrag) && (targ.BUTTON_CHAT)) {
+ 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 {
- Send_CSQC_KillCenterprint(attacker, s, GetAdvancedDeathReports(targ), KILL_FRAG, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, a, GetAdvancedDeathReports(attacker), KILL_FRAGGED, MSG_KILL);
+ Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_FRAG, MSG_KILL);
+ Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_FRAGGED, MSG_KILL);
}
attacker.taunt_soundtime = time + 1;
if (gameover || targ.killcount == -666)
return;
- local entity oldself;
+ entity oldself;
oldself = self;
self = targ;
damage_targ = targ;
damage = 0;
force = '0 0 0';
}
- else if(teamplay && attacker.team == targ.team)
+ else if(!IsDifferentTeam(attacker, targ))
{
if(autocvar_teamplay_mode == 1)
damage = 0;
if(targ.takedamage == DAMAGE_AIM)
if(targ != attacker)
{
- if(targ.classname == "player")
+ if(damage_headshotbonus > 0)
{
- // HEAD SHOT:
- // find height of hit on player axis
- // if above view_ofs and below maxs, and also in the middle half of the bbox, it is head shot
- vector headmins, headmaxs, org;
- org = antilag_takebackorigin(targ, time - ANTILAG_LATENCY(attacker));
- headmins = org + GetHeadshotMins(targ);
- headmaxs = org + GetHeadshotMaxs(targ);
- if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs))
+ if(targ.classname == "player")
+ {
+ // HEAD SHOT:
+ // find height of hit on player axis
+ // if above view_ofs and below maxs, and also in the middle half of the bbox, it is head shot
+ vector headmins, headmaxs, org;
+ org = antilag_takebackorigin(targ, time - ANTILAG_LATENCY(attacker));
+ headmins = org + GetHeadshotMins(targ);
+ headmaxs = org + GetHeadshotMaxs(targ);
+ if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs))
+ {
+ deathtype |= HITTYPE_HEADSHOT;
+ }
+ }
+ else if(targ.classname == "turret_head")
{
deathtype |= HITTYPE_HEADSHOT;
}
+ if(deathtype & HITTYPE_HEADSHOT)
+ damage *= 1 + damage_headshotbonus;
}
- else if(targ.classname == "turret_head")
- {
- deathtype |= HITTYPE_HEADSHOT;
- }
- if(deathtype & HITTYPE_HEADSHOT)
- damage *= 1 + damage_headshotbonus;
entity victim;
if((targ.vehicle_flags & VHF_ISVEHICLE) && targ.owner)
finaldmg = coredamage * power + edgedamage * (1 - power);
if (finaldmg > 0)
{
- local float a;
- local float c;
- local float hits;
- local float total;
- local float hitratio;
- local vector hitloc;
- local vector myblastorigin;
+ float a;
+ float c;
+ float hits;
+ float total;
+ float hitratio;
+ vector hitloc;
+ vector myblastorigin;
myblastorigin = WarpZone_TransformOrigin(targ, blastorigin);
center = targ.origin + (targ.mins + targ.maxs) * 0.5;
// if it's a player, use the view origin as reference
{
float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch, s;
vector dir, org, end, v0, dv, v, myorg, vs;
- if(self.realowner.health <= 0 || self.realowner.hook != self) // how did that happen?
- { // well, better fix it anyway
- remove(self);
+ if(self.realowner.hook != self) // how did that happen?
+ {
+ error("Owner lost the hook!\n");
return;
}
if(LostMovetypeFollow(self))
void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- if(self.health > 0)
+ if(self.health <= 0)
+ return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_balance_projectiledamage says to halt
+
+ self.health = self.health - damage;
+
+ if (self.health <= 0)
{
- self.health = self.health - damage;
- if (self.health <= 0)
+ if(attacker != self.realowner)
{
- if(attacker != self.realowner)
- {
- self.realowner.pusher = attacker;
- self.realowner.pushltime = time + autocvar_g_maxpushtime;
- }
- RemoveGrapplingHook(self.realowner);
+ self.realowner.pusher = attacker;
+ self.realowner.pushltime = time + autocvar_g_maxpushtime;
}
+ RemoveGrapplingHook(self.realowner);
}
}
void FireGrapplingHook (void)
{
- local entity missile;
- local vector org;
+ entity missile;
+ vector org;
float s;
vector vs;
self.hook = missile;
missile.reset = GrapplingHookReset;
missile.classname = "grapplinghook";
+ missile.flags = FL_PROJECTILE;
missile.movetype = MOVETYPE_FLY;
PROJECTILE_MAKETRIGGER(missile);
missile.event_damage = GrapplingHook_Damage;
missile.takedamage = DAMAGE_AIM;
missile.damageforcescale = 0;
+ missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents);
missile.hook_start = missile.hook_end = missile.origin;
remove(self);
self.nextthink = time + 0.1;
-};
+}
void dynlight_find_aiment()
{
- local entity targ;
+ entity targ;
if (!self.target)
objerror ("dynlight: no target to follow");
self.v_angle = self.angles - targ.angles;
self.think = dynlight_think;
self.nextthink = time + 0.1;
-};
+}
void dynlight_find_path()
{
- local entity targ;
+ entity targ;
if (!self.target)
objerror ("dynlight: no target to follow");
setorigin (self, targ.origin);
self.think = train_next;
self.nextthink = time + 0.1;
-};
+}
void dynlight_find_target()
{
- local entity targ;
+ entity targ;
if (!self.target)
objerror ("dynlight: no target to follow");
self.light_lev = self.lefty;
else
self.light_lev = 0;
-};
+}
void spawnfunc_dynlight()
{
local entity targ;
InitializeEntity(self, dynlight_find_path, INITPRIO_FINDTARGET);
return;
}
-};
+}
-void SUB_Null() {};
+void SUB_Null() {}
float SUB_True() { return 1; }
float SUB_False() { return 0; }
e.animstate_override = override;
e.frame = e.animstate_startframe;
e.frame1time = servertime;
-};
+}
void updateanim(entity e)
{
}
e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
//print(ftos(time), " -> ", ftos(e.frame), "\n");
-};
-
-float animparseerror;
-vector animparseline(float animfile)
-{
- local string line;
- local float c;
- local vector anim;
- if (animfile < 0)
- return '0 1 2';
- line = fgets(animfile);
- c = tokenize_console(line);
- if (c < 3)
+}
+
+vector animfixfps(entity e, vector a)
+{
+ // multi-frame anim: keep as-is
+ if(a_y == 1)
{
- animparseerror = TRUE;
- return '0 1 2';
+ float dur;
+ dur = frameduration(e.modelindex, a_x);
+ if(dur > 0)
+ a_z = 1.0 / dur;
}
- anim_x = stof(argv(0));
- anim_y = stof(argv(1));
- anim_z = stof(argv(2));
- // don't allow completely bogus values
- if (anim_x < 0 || anim_y < 1 || anim_z < 0.001)
- anim = '0 1 2';
- return anim;
-};
+ return a;
+}
/*
==================
*/
void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz)
{
- local entity player;
- local float oldsolid;
+ entity player;
+ float oldsolid;
// check whether antilagged traces are enabled
if (lag < 0.001)
if (lag)
{
// take players back into the past
- player = player_list;
- while (player)
- {
- antilag_takeback(player, time - lag);
- player = player.nextplayer;
- }
+ FOR_EACH_PLAYER(player)
+ if(player != forent)
+ antilag_takeback(player, time - lag);
}
// do the trace
// restore players to current positions
if (lag)
{
- player = player_list;
- while (player)
- {
- antilag_restore(player);
- player = player.nextplayer;
- }
+ FOR_EACH_PLAYER(player)
+ if(player != forent)
+ antilag_restore(player);
}
// restore shooter solid type
}
self.angles = '0 0 0';
-};
+}
void InitTrigger()
{
self.movetype = MOVETYPE_NONE;
self.modelindex = 0;
self.model = "";
-};
+}
void InitSolidBSPTrigger()
{
self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0
// self.modelindex = 0;
self.model = "";
-};
+}
float InitMovingBrushTrigger()
{
return 0;
}
return 1;
-};
+}
float Tetris_Level()
{
return ((floor((self.tet_lines / 10)) + 1));
-};
+}
void tetsnd(string snd)
{
if(ln < 1 || ln > TET_LINES)
error("WTF");
bufstr_set(tet_line_buf, ln + TET_LINES * num_for_edict(self), vl);
-};
+}
string GetLine(float ln)
{
if(ln < 1 || ln > TET_LINES)
return TET_EMPTY_LINE;
return bufstr_get(tet_line_buf, ln + TET_LINES * num_for_edict(self));
-};
+}
float GetXBlock(float x, string dat)
{
if(x < 1 || x > TET_WIDTH)
error("WTF");
return stof(substring(dat, x-1, 1));
-};
+}
string SetXBlock(float x, string dat, float new)
{
ftos(new),
substring(dat, x, -1)
);
-};
+}
float GetSquare(float x, float y)
{
return GetXBlock(x, GetLine(y));
-};
+}
void SetSquare(float x, float y, float val)
{
dat = GetLine(y);
dat = SetXBlock(x, dat, val);
SetLine(y, dat);
-};
+}
float PieceColor(float pc)
{
return !!(ce_y & pow(4, x-1)); // second row
else
return 0; // illegal parms
-};
+}
vector tet_piecemins;
vector tet_piecemaxs;
void PieceMinsMaxs(float rot, float pc)
float pnum(float num, float dig)
{
- local float f, i;
+ float f, i;
if (num < 0)
{
WriteChar(MSG_ONE, 173);
}
WriteChar(MSG_ONE, 176 + num);
return dig;
-};
+}
void DrawLine(float ln)
{
self.piece_type = 0;
self.next_piece = self.tet_lines = self.tet_score = 0;
self.tet_piece_bucket = 0;
-};
+}
void Tet_GameExit()
{
self.tet_vs_id = 0;
ResetTetris();
self.movetype = MOVETYPE_WALK;
-};
+}
void PrintField()
{
self.tet_piece_bucket = b;
return p + 1;
}
-};
+}
void TetAddScore(float n)
{
self.tet_score = self.tet_score + n * Tetris_Level();
if (self.tet_score > tet_high_score)
tet_high_score = self.tet_score;
-};
+}
float CheckMetrics(float piece, float orgx, float orgy, float rot) /*FIXDECL*/
{
// check to see if the piece, if moved to the locations will overlap
tetsnd("tetline");
else
tetsnd("tetland");
-};
+}
void HandleGame(float keyss)
{
return;
}
CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);
-};
+}
/*
*********************************
Tet_GameExit();
self.impulse = 0;
}
-};
+}
float TetrisPreFrame()
else
self.tet_drawtime = time + 0.5;
return 1;
-};
+}
float frik_anglemoda(float v)
{
return v - floor(v/360) * 360;
-};
+}
float angcompa(float y1, float y2)
{
y1 = frik_anglemoda(y1);
y2 = frik_anglemoda(y2);
- local float answer;
+ float answer;
answer = y1 - y2;
if (answer > 180)
answer = answer - 360;
else if (answer < -180)
answer = answer + 360;
return answer;
-};
+}
.float tetkey_down, tetkey_rotright, tetkey_left, tetkey_right, tetkey_rotleft, tetkey_drop;
}
return 1;
-};
+}
#else
activator = self.enemy;
SUB_UseTargets ();
remove(self);
-};
+}
/*
==============================
*/
void SUB_UseTargets()
{
- local entity t, stemp, otemp, act;
+ entity t, stemp, otemp, act;
string s;
float i;
activator = act;
self = stemp;
other = otemp;
-};
+}
//=============================================================================
self.takedamage = DAMAGE_YES;
self.solid = SOLID_BBOX;
}
-};
+}
// the trigger was just touched/killed/used
// called wheil C code is looping through area links...
self.touch = SUB_Null;
}
-};
+}
void multi_use()
{
self.goalentity = other;
self.enemy = activator;
multi_trigger();
-};
+}
void multi_touch()
{
self.enemy = other;
self.goalentity = other;
multi_trigger ();
-};
+}
void multi_eventdamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
setorigin (self, self.origin); // make sure it links into the world
}
}
-};
+}
/*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
{
self.wait = -1;
spawnfunc_trigger_multiple();
-};
+}
//=============================================================================
{
self.use = SUB_UseTargets;
self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
-};
+}
void delay_use()
{
centerprint(activator, "Sequence completed!");
self.enemy = activator;
multi_trigger ();
-};
+}
void counter_reset()
{
self.use = counter_use;
self.reset = counter_reset;
-};
+}
void trigger_hurt_use()
{
}
return;
-};
+}
/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
Any object touching this will be hurt
if(trigger_hurt_last)
trigger_hurt_last.trigger_hurt_next = self;
trigger_hurt_last = self;
-};
+}
float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
{
}
}
}
-};
+}
void spawnfunc_trigger_heal()
{
if(self.noise == "")
self.noise = "misc/mediumhealth.wav";
precache_sound(self.noise);
-};
+}
//////////////////////////////////////////////////////////////
self.count -= 1;
self.nextthink = time;
}
-};
+}
void trigger_gravity_use()
{
self.state = !self.state;
-};
+}
void trigger_gravity_touch()
{
sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
UpdateCSQCProjectile(self.owner);
}
-};
+}
void spawnfunc_trigger_gravity()
{
if(self.spawnflags & 2)
self.state = FALSE;
}
-};
+}
//=============================================================================
ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
remove(self);
}
-};
+}
void spawnfunc_func_stardust() {
WriteShort(MSG_ENTITY, self.count);
WriteByte(MSG_ENTITY, self.cnt);
return 1;
-};
+}
/*QUAKED spawnfunc_func_rain (0 .5 .8) ?
This is an invisible area like a trigger, which rain falls inside of.
self.Version = 1;
Net_LinkEntity(self, FALSE, 0, rainsnow_SendEntity);
-};
+}
/*QUAKED spawnfunc_func_snow (0 .5 .8) ?
self.Version = 1;
Net_LinkEntity(self, FALSE, 0, rainsnow_SendEntity);
-};
+}
void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype);
self.state = 0;
self.use = multivibrator_toggle;
self.think = multivibrator_send;
- self.nextthink = time;
+ self.nextthink = max(1, time);
IFTARGETED
multivibrator_reset();
localcmd("endmatch\n");
else
localcmd(strcat("changelevel ", self.chmap, "\n"));
-};
+}
void spawnfunc_target_changelevel()
{
self.use = spawnfunc_target_changelevel_use;
-};
+}
* players. Also plays reminder sounds.
*/
void timeoutHandler_Think() {
- local entity plr;
+ entity plr;
if (timeoutStatus == 1) {
if (remainingLeadTime > 0) {
//centerprint the information to every player
BADPREFIX("con_");
BADPREFIX("scoreboard_");
BADPREFIX("g_campaign");
+ BADPREFIX("g_waypointsprite_");
BADPREFIX("gl_");
BADPREFIX("joy");
BADPREFIX("hud_");
// private
BADCVAR("developer");
- BADCVAR("g_banned_list");
BADCVAR("log_dest_udp");
BADCVAR("log_file");
BADCVAR("net_address");
BADCVAR("port");
BADCVAR("savedgamecfg");
BADCVAR("serverconfig");
+ BADCVAR("sv_autoscreenshot");
BADCVAR("sv_heartbeatperiod");
BADCVAR("sv_vote_master_password");
BADCVAR("sys_colortranslation");
BADCVAR("timestamps");
BADPREFIX("developer_");
BADPREFIX("g_ban_");
+ BADPREFIX("g_banned_list");
BADPREFIX("g_chat_flood_");
BADPREFIX("g_playerstats_");
BADPREFIX("g_voice_flood_");
BADPREFIX("sv_logscores_");
BADPREFIX("sv_master");
BADPREFIX("sv_weaponstats_");
+ BADPREFIX("sv_waypointsprite_");
// these can contain player IDs, so better hide
BADPREFIX("g_forced_team_");
BADPREFIX("net_");
BADPREFIX("prvm_");
BADPREFIX("skill_");
- BADPREFIX("sv_fragmessage_");
+ BADPREFIX("sv_fraginfo_");
BADPREFIX("sv_maxidle_");
BADPREFIX("sv_vote_");
BADPREFIX("timelimit_");
allowed_to_spawn = TRUE;
- local entity head;
+ entity head;
head = nextent(world);
maxclients = 0;
while(head)
float Map_Count, Map_Current;
string Map_Current_Name;
-// NOTE: this now expects the map list to be already tokenize()d and the count in Map_Count
+// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
float GetMaplistPosition()
{
float pos, idx;
{
// settings persist, except...
localcmd("\nsettemp_restore\n");
-};
+}
void Map_Goto()
{
}
return "";
-};
+}
float DoNextMapOverride()
{
return TRUE;
}
return FALSE;
-};
+}
void GotoNextMap()
{
- //local string nextmap;
- //local float n, nummaps;
- //local string s;
+ //string nextmap;
+ //float n, nummaps;
+ //string s;
if (alreadychangedlevel)
return;
alreadychangedlevel = TRUE;
}
Map_Goto();
}
-};
+}
/*
{
FixIntermissionClient(self);
- if(autocvar_sv_autoscreenshot)
- if(self.autoscreenshot > 0)
- if(time > self.autoscreenshot)
+ if( (autocvar_sv_autoscreenshot || self.cvar_cl_autoscreenshot)
+ && ((self.autoscreenshot > 0) && (time > self.autoscreenshot)) )
{
self.autoscreenshot = -1;
if(clienttype(self) == CLIENTTYPE_REAL)
return;
MapVote_Start();
-};
+}
/*
============
//objerror ("FindIntermission: no spot");
return world;
-};
+}
*/
/*
// fixme: don't check players; instead check spawnfunc_dom_team and spawnfunc_ctf_team entities
// (div0: and that in CheckRules_World please)
-};
+}
float checkrules_equality;
float checkrules_suddendeathwarning;
float WinningCondition_Onslaught()
{
entity head;
- local float t1, t2, t3, t4;
+ float t1, t2, t3, t4;
WinningConditionHelper(); // set worldstatus
void assault_new_round();
float WinningCondition_Assault()
{
- local float status;
+ float status;
WinningConditionHelper(); // set worldstatus
SetWinners(team, COLOR_TEAM1);
}
- local entity ent;
+ entity ent;
ent = find(world, classname, "target_assault_roundend");
if(ent)
{
}
else
{
- local entity oldself;
+ entity oldself;
oldself = self;
self = ent;
assault_new_round();
//print("WINNING\n");
NextLevel();
}
-};
+}
float mapvote_nextthink;
float mapvote_initialized;
}
MapVote_Tick();
-};
+}
string GotoMap(string m)
{
else
{
// close the file
- fputs(self.cnt, "};\n");
+ fputs(self.cnt, "}\n");
fclose(self.cnt);
print("Finished. Please edit data/", self.netname, " with an image editing application and place it in the TGA format in the gfx folder.\n");
RadarMap_Next();
fh = fopen("effectinfo.txt", FILE_READ);
while((s = fgets(fh)))
{
- tokenize(s); // tokenize_console would hit the loop counter :(
+ tokenize_console(s);
if(argv(0) == "effect")
{
if(db_get(d, argv(1)) != "1")
if (argv(0) == "nospectators")
{
blockSpectators = 1;
- local entity plr;
+ entity plr;
FOR_EACH_CLIENT(plr) //give every spectator <g_maxplayers_spectator_blocktime> seconds time to become a player
{
if(plr.classname == "spectator" || plr.classname == "observer")
if(argv(0) == "bot_cmd")
{
- local entity bot;
+ entity bot;
if(argv(1) == "help")
{
return;
}
+ // set bot count
+ if(argv(1) == "setbots")
+ {
+ if(argc >= 3 && argv(1) == "setbots")
+ {
+ cvar_settemp("minplayers", "0");
+ cvar_settemp("bot_number", argv(2));
+ bot_fixcount();
+ }
+ }
+
// Load cmds from file
if(argv(1) == "load" && argc == 3)
{
if(argc >= 3 && argv(0) == "sv_cmd" && argv(1) == "bot_cmd")
{
- // let's start at token 2 so we can skip sv_cmd bot_cmd
- bot = find_bot_by_number(stof(argv(2)));
- if(bot == world)
- bot = find_bot_by_name(argv(2));
- if(bot)
- bot_queuecommand(bot, strcat(argv(3), " ", argv(4)));
+ if(argv(2) == "reset")
+ {
+ bot_resetqueues();
+ }
+ else if(argv(2) == "setbots")
+ {
+ cvar_settemp("minplayers", "0");
+ cvar_settemp("bot_number", argv(3));
+ if(!bot_fixcount())
+ print("Sorry, could not set requested bot count\n");
+ }
+ else
+ {
+ // let's start at token 2 so we can skip sv_cmd bot_cmd
+ bot = find_bot_by_number(stof(argv(2)));
+ if(bot == world)
+ bot = find_bot_by_name(argv(2));
+ if(bot)
+ bot_queuecommand(bot, strcat(argv(3), " ", argv(4)));
+ }
}
else
localcmd(strcat(s, "\n"));
--- /dev/null
+/*
+TODO:
+- add an unlock sound (here to trigger_keylock and to func_door)
+- display available keys on the HUD
+- make more tests
+- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
+- should keys have a trigger?
+*/
+
+float item_keys_usekey(entity l, entity p) {
+ float valid = l.itemkeys & p.itemkeys;
+
+ if not(valid) {
+ // other has none of the needed keys
+ return FALSE;
+ } else if (l.itemkeys == valid) {
+ // ALL needed keys were given
+ l.itemkeys = 0;
+ return TRUE;
+ } else {
+ // only some of the needed keys were given
+ l.itemkeys &~= valid;
+ return TRUE;
+ }
+}
+
+string item_keys_keylist(float keylist) {
+ float base, l;
+ string n;
+
+ // no keys
+ if not(keylist)
+ return "";
+
+ // one key
+ if ((keylist & (keylist-1)) != 0)
+ return strcat("the ", item_keys_names[lowestbit(keylist)]);
+
+ while (keylist) {
+ l = lowestbit(keylist);
+ if (n)
+ n = strcat(n, ", the ", item_keys_names[base + l]);
+ else
+ n = strcat("the ", item_keys_names[base + l]);
+
+ keylist = bitshift(keylist, -(l + 1));
+ base+= l + 1;
+ }
+
+ return n;
+}
+
+
+/*
+================================
+item_key
+================================
+*/
+
+/**
+ * Key touch handler.
+ */
+void item_key_touch(void) {
+ if (other.classname != "player")
+ return;
+
+ // player already picked up this key
+ if (other.itemkeys & self.itemkeys)
+ return;
+
+ other.itemkeys |= self.itemkeys;
+ play2(other, self.noise);
+
+ centerprint(other, self.message);
+};
+
+/**
+ * Spawn a key with given model, key code and color.
+ */
+void spawn_item_key() {
+ precache_model(self.model);
+
+ if (self.spawnflags & 1) // FLOATING
+ self.noalign = 1;
+
+ if (self.noalign)
+ self.movetype = MOVETYPE_NONE;
+ else
+ self.movetype = MOVETYPE_TOSS;
+
+ precache_sound(self.noise);
+
+ self.mdl = self.model;
+ self.effects = EF_LOWPRECISION;
+ setmodel(self, self.model);
+ //setsize(self, '-16 -16 -24', '16 16 32');
+ setorigin(self, self.origin + '0 0 32');
+ setsize(self, '-16 -16 -56', '16 16 0');
+ self.modelflags |= MF_ROTATE;
+ self.solid = SOLID_TRIGGER;
+
+ if (!self.noalign)
+ {
+ // first nudge it off the floor a little bit to avoid math errors
+ setorigin(self, self.origin + '0 0 1');
+ // note droptofloor returns FALSE if stuck/or would fall too far
+ droptofloor();
+ }
+
+ self.touch = item_key_touch;
+};
+
+
+/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+A key entity.
+The itemkeys should contain one of the following key IDs:
+1 - GOLD key -
+2 - SILVER key
+4 - BRONZE key
+8 - RED keycard
+16 - BLUE keycard
+32 - GREEN keycard
+Custom keys:
+... - last key is 1<<23
+Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those.
+-----------KEYS------------
+colormod: color of the key (default: '.9 .9 .9').
+itemkeys: a key Id.
+message: message to print when player picks up this key.
+model: custom key model to use.
+netname: the display name of the key.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+This is the only correct way to put keys on the map!
+
+itemkeys MUST always have exactly one bit set.
+*/
+void spawnfunc_item_key() {
+ local string _model, _netname;
+ local vector _colormod;
+
+ // reject this entity if more than one key was set!
+ if (self.itemkeys>0 && (self.itemkeys & (self.itemkeys-1)) != 0) {
+ objerror("item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
+ remove(self);
+ return;
+ }
+
+ // find default netname and colormod
+ switch(self.itemkeys) {
+ case 1:
+ _netname = "GOLD key";
+ _colormod = '1 .9 0';
+ break;
+
+ case 2:
+ _netname = "SILVER key";
+ _colormod = '.9 .9 .9';
+ break;
+
+ case 4:
+ _netname = "BRONZE key";
+ _colormod = '.6 .25 0';
+ break;
+
+ case 8:
+ _netname = "RED keycard";
+ _colormod = '.9 0 0';
+ break;
+
+ case 16:
+ _netname = "BLUE keycard";
+ _colormod = '0 0 .9';
+ break;
+
+ case 32:
+ _netname = "GREEN keycard";
+ _colormod = '0 .9 0';
+ break;
+
+ default:
+ if (!self.netname) {
+ objerror("item_key doesn't have a default name for this key and a custom one was not specified!");
+ remove(self);
+ return;
+ } else if (!self.colormod) {
+ _colormod = '1 1 1';
+ }
+ break;
+
+ }
+
+ // find default model
+ if (self.itemkeys <= ITEM_KEY_BIT(2)) {
+ _model = "models/keys/key.md3";
+ } else if (self.itemkeys >= ITEM_KEY_BIT(3) && self.itemkeys <= ITEM_KEY_BIT(5)) {
+ _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
+ } else if (!self.model) {
+ objerror("item_key doesn't have a default model for this key and a custom one was not specified!");
+ remove(self);
+ return;
+ }
+
+ // set defailt netname
+ if (!self.netname)
+ self.netname = _netname;
+
+ // set default colormod
+ if (!self.colormod)
+ self.colormod = _colormod;
+
+ // set default model
+ if (!self.model)
+ self.model = _model;
+
+ // set default pickup message
+ if (!self.message)
+ self.message = strzone(strcat("You've picked up the ", self.netname, "!"));
+
+ if (!self.noise)
+ self.noise = "misc/itempickup.wav";
+
+ // save the name for later
+ item_keys_names[lowestbit(self.itemkeys)] = self.netname;
+
+ // put the key on the map
+ spawn_item_key();
+}
+
+/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+SILVER key.
+-----------KEYS------------
+colormod: color of the key (default: '.9 .9 .9').
+message: message to print when player picks up this key.
+model: custom model to use.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+Don't use this entity on new maps! Use item_key instead.
+*/
+void spawnfunc_item_key1(void) {
+ self.classname = "item_key";
+ self.itemkeys = ITEM_KEY_BIT(1);
+ spawnfunc_item_key();
+};
+
+/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+GOLD key.
+-----------KEYS------------
+colormod: color of the key (default: '1 .9 0').
+message: message to print when player picks up this key.
+model: custom model to use.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+Don't use this entity on new maps! Use item_key instead.
+*/
+void spawnfunc_item_key2(void) {
+ self.classname = "item_key";
+ self.itemkeys = ITEM_KEY_BIT(0);
+ spawnfunc_item_key();
+};
+
+
+/*
+================================
+trigger_keylock
+================================
+*/
+
+/**
+ * trigger givent targets
+ */
+void trigger_keylock_trigger(string s) {
+ local entity t, stemp, otemp, atemp;
+
+ stemp = self;
+ otemp = other;
+ atemp = activator;
+
+
+ for(t = world; (t = find(t, targetname, s)); )
+ if (t.use) {
+ self = t;
+ other = stemp;
+ activator = atemp;
+ self.use();
+ }
+
+ self = stemp;
+ other = otemp;
+ activator = atemp;
+};
+
+/**
+ * kill killtarget of trigger keylock.
+ */
+void trigger_keylock_kill(string s) {
+ local entity t;
+ for(t = world; (t = find(t, targetname, s)); )
+ remove(t);
+};
+
+void trigger_keylock_touch(void) {
+ local float key_used, started_delay;
+
+ key_used = FALSE;
+ started_delay = FALSE;
+
+ // only player may trigger the lock
+ if (other.classname != "player")
+ return;
+
+
+ // check silver key
+ if (self.itemkeys)
+ key_used = item_keys_usekey(self, other);
+
+ activator = other;
+
+ if (self.itemkeys) {
+ // at least one of the keys is missing
+ if (key_used) {
+ // one or more keys were given, but others are still missing!
+ play2(other, self.noise1);
+ centerprint(other, strcat("You also need ", item_keys_keylist(self.itemkeys), "!"));
+ other.key_door_messagetime = time + 2;
+ } else if (other.key_door_messagetime <= time) {
+ // no keys were given
+ play2(other, self.noise2);
+ centerprint(other, strcat("You need ", item_keys_keylist(self.itemkeys), "!"));
+ other.key_door_messagetime = time + 2;
+ }
+
+ // trigger target2
+ if (self.delay <= time || started_delay == TRUE)
+ if (self.target2) {
+ trigger_keylock_trigger(self.target2);
+ started_delay = TRUE;
+ self.delay = time + self.wait;
+ }
+ } else {
+ // all keys were given!
+ play2(other, self.noise);
+ centerprint(other, self.message);
+
+ if (self.target)
+ trigger_keylock_trigger(self.target);
+
+ if (self.killtarget)
+ trigger_keylock_kill(self.killtarget);
+
+ remove(self);
+ }
+
+};
+
+/*QUAKED trigger_keylock (.0 .5 .8) ?
+Keylock trigger. Must target other entities.
+This trigger will trigger target entities when all required keys are provided.
+-------- KEYS --------
+itemkeys: A bit field with key IDs that are needed to open this lock.
+sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default)
+target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
+target2: trigger all entities with this targetname when triggered without giving it all the required keys.
+killtarget: remove all entities with this targetname when triggered with all the needed keys.
+message: print this message to the player who activated the trigger when all needed keys have been given.
+message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
+noise: sound to play when lock gets unlocked (default: see sounds)
+noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav)
+noise2: sound to play when a key is missing (default: misc/talk.wav)
+wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
+---------NOTES----------
+If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
+message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
+*/
+void spawnfunc_trigger_keylock(void) {
+ if (!self.itemkeys) {
+ remove(self);
+ return;
+ }
+
+ // set unlocked message
+ if (!self.message)
+ self.message = "Unlocked!";
+
+ // set default unlock noise
+ if (!self.noise) {
+ if (self.sounds == 1)
+ self.noise = "misc/secret.wav";
+ else if (self.sounds == 2)
+ self.noise = "misc/talk.wav";
+ else //if (self.sounds == 3) {
+ self.noise = "misc/trigger1.wav";
+ }
+
+ // set default use key sound
+ if (!self.noise1)
+ self.noise1 = "misc/decreasevalue.wav";
+
+ // set closed sourd
+ if (!self.noise2)
+ self.noise2 = "misc/talk.wav";
+
+ // delay between triggering message2 and trigger2
+ if (!self.wait)
+ self.wait = 5;
+
+ // precache sounds
+ precache_sound(self.noise);
+ precache_sound(self.noise1);
+ precache_sound(self.noise2);
+
+ EXACTTRIGGER_INIT;
+
+ self.touch = trigger_keylock_touch;
+};
+
+
--- /dev/null
+/**
+ * Returns the bit ID of a key
+ */
+#define ITEM_KEY_BIT(n) ( bitshift(1, n) )
+
+#define ITEM_KEY_MAX 24
+
+/**
+ * list of key names.
+ */
+string item_keys_names[ITEM_KEY_MAX];
+
+/**
+ * Use keys from p on l.
+ * Returns TRUE if any new keys were given, FALSE otherwise.
+ */
+float item_keys_usekey(entity l, entity p);
+
+/**
+ * Returns a string with a comma separated list of key names, as specified in keylist.
+ */
+string item_keys_keylist(float keylist);
+
float logfile_open;
float logfile;
-string GetAdvancedDeathReports(entity enPlayer) // Extra fragmessage information
-{
- float nPlayerHealth = rint(enPlayer.health);
- float nPlayerArmor = rint(enPlayer.armorvalue);
- float nPlayerHandicap = enPlayer.cvar_cl_handicap;
- float nPlayerPing = rint(enPlayer.ping);
- string strPlayerPingColor;
- string strMessage;
-
- if(nPlayerPing >= 150)
- strPlayerPingColor = "^1";
- else
- strPlayerPingColor = "^2";
-
- if((autocvar_sv_fragmessage_information_stats) && (enPlayer.health >= 1))
- strMessage = strcat(strMessage, "^7(Health ^1", ftos(nPlayerHealth), "^7 / Armor ^2", ftos(nPlayerArmor), "^7)");
-
- if(autocvar_sv_fragmessage_information_ping) {
- if(clienttype(enPlayer) == CLIENTTYPE_BOT) // Bots have no ping
- strMessage = strcat(strMessage, " ^7(^2Bot");
- else
- strMessage = strcat(strMessage, " ^7(Ping ", strPlayerPingColor, ftos(nPlayerPing), "ms");
- if(autocvar_sv_fragmessage_information_handicap)
- if(autocvar_sv_fragmessage_information_handicap == 2)
- if(nPlayerHandicap <= 1)
- strMessage = strcat(strMessage, "^7 / Handicap ^2Off^7)");
- else
- strMessage = strcat(strMessage, "^7 / Handicap ^2", ftos(nPlayerHandicap), "^7)");
- else if not(nPlayerHandicap <= 1)
- strMessage = strcat(strMessage, "^7 / Handicap ^2", ftos(nPlayerHandicap), "^7)");
- else
- strMessage = strcat(strMessage, "^7)");
- } else if(autocvar_sv_fragmessage_information_handicap) {
- if(autocvar_sv_fragmessage_information_handicap == 2)
- if(nPlayerHandicap <= 1)
- strMessage = strcat(strMessage, "^7(Handicap ^2Off^7)");
- else
- strMessage = strcat(strMessage, "^7(Handicap ^2", ftos(nPlayerHandicap), "^7)");
- else if(nPlayerHandicap > 1)
- strMessage = strcat(strMessage, "^7(Handicap ^2", ftos(nPlayerHandicap), "^7)");
- }
-
- if(strMessage) // add new line to the beginning if there is a message
- strMessage = strcat("\n", strMessage);
-
- return strMessage;
-}
void bcenterprint(string s)
{
// TODO replace by MSG_ALL (would show it to spectators too, though)?
self.classname = "target_location";
// location name in netname
// eventually support: count, teamgame selectors, line of sight?
-};
+}
void spawnfunc_info_location()
{
self.classname = "target_location";
self.message = self.netname;
-};
+}
string NearestLocation(vector p)
{
get_cvars_s = s;
MUTATOR_CALLHOOK(GetCvars);
GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
+ GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
GetCvars_handleFloat(s, f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction");
GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap");
vector randompos(vector m1, vector m2)
{
- local vector v;
+ vector v;
m2 = m2 - m1;
v_x = m2_x * random() + m1_x;
v_y = m2_y * random() + m1_y;
v_z = m2_z * random() + m1_z;
return v;
-};
+}
//#NO AUTOCVARS START
void readlevelcvars(void)
{
// first load all the mutators
+ if(cvar("g_invincible_projectiles"))
+ MUTATOR_ADD(mutator_invincibleprojectiles);
if(cvar("g_nix"))
MUTATOR_ADD(mutator_nix);
if(cvar("g_dodging"))
{
if (e.classname == "body")
e = e.enemy;
- if (e.owner && e.owner != e)
+ else if (e.realowner && e.realowner != e)
+ e = e.realowner;
+ else if (e.owner && e.owner != e)
e = e.owner;
else
break;
void play2team(float t, string filename)
{
- local entity head;
+ entity head;
if (autocvar_bot_sound_monopoly)
return;
if(autocvar_sv_precacheweapons)
{
//precache weapon models/sounds
- local float wep;
+ float wep;
wep = WEP_FIRST;
while (wep <= WEP_LAST)
{
float URI_GET_DISCARD = 0;
float URI_GET_IPBAN = 1;
float URI_GET_IPBAN_END = 16;
-float URI_GET_PLAYERSTATS_SENT = 17;
void URI_Get_Callback(float id, float status, string data)
{
// online ban list
OnlineBanList_URI_Get_Callback(id, status, data);
}
- else if (id == URI_GET_PLAYERSTATS_SENT)
- {
- PlayerStats_Sent_URI_Get_Callback(id, status, data);
- }
else
{
print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
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)
{
- local entity gib;
+ entity gib;
gib = spawn();
}
else
SUB_SetFade(gib, gib.giblifetime, 2);
-};
+}
void onslaught_updatelinks()
{
- local entity l, links;
- local float stop, t1, t2, t3, t4;
+ entity l, links;
+ float stop, t1, t2, t3, t4;
// first check if the game has ended
dprint("--- updatelinks ---\n");
links = findchain(classname, "onslaught_link");
dprint("--- game over ---\n");
else
dprint("--- done updating links ---\n");
-};
+}
float onslaught_controlpoint_can_be_linked(entity cp, float t)
{
float overtime_msg_time;
void onslaught_generator_think()
{
- local float d;
- local entity e;
+ float d;
+ entity e;
self.nextthink = ceil(time + 1);
if (!gameover)
{
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.scale += 0.2;
self.count +=1;
-};
+}
void onslaught_generator_ray_spawn(vector org)
{
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()
{
}
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)
{
setorigin(e, gd_owner.origin);
e.think = onslaught_generator_damage_think;
e.nextthink = time+1;
-};
+}
void onslaught_generator_deaththink()
{
- local vector org;
- local float i;
+ vector org;
+ float i;
if not (self.count)
self.count = 40;
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)
{
- local float i;
+ float i;
if (damage <= 0)
return;
if(inWarmupStage)
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()
// now begin normal thinking
self.think = onslaught_generator_think;
self.nextthink = time;
-};
+}
string onslaught_generator_waypointsprite_for_team(entity e, float t)
{
return;
}
- local entity e;
+ entity e;
precache_model("models/onslaught/generator.md3");
precache_model("models/onslaught/generator_shield.md3");
precache_model("models/onslaught/generator_dmg1.md3");
onslaught_updatelinks();
self.reset = onslaught_generator_reset;
-};
+}
.float waslinked;
.float cp_bob_spd;
remove(self);
}
-};
+}
void onslaught_controlpoint_icon_think()
{
else if (random() > 0.5)
sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTN_NORM);
}
-};
+}
void onslaught_controlpoint_icon_buildthink()
{
- local entity oself;
+ entity oself;
float a;
self.nextthink = time + sys_frametime;
if(random() < 0.9 - self.health / self.max_health)
pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
-};
+}
void onslaught_controlpoint_touch()
{
- local entity e;
+ entity e;
float a;
if (other.classname != "player")
return;
self.colormap = e.colormap;
WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime));
onslaught_updatelinks();
-};
+}
void onslaught_controlpoint_reset()
{
*/
void spawnfunc_onslaught_controlpoint()
{
- local entity e;
+ entity e;
if (!g_onslaught)
{
remove(self);
onslaught_updatelinks();
self.reset = onslaught_controlpoint_reset;
-};
+}
float onslaught_link_send(entity to, float sendflags)
{
objerror("target and target2 must be set\n");
InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET);
Net_LinkEntity(self, FALSE, 0, onslaught_link_send);
-};
+}
+++ /dev/null
-void() movetarget_f;
-void() t_movetarget;
-void() FoundTarget;
-
-float MONSTER_WANDER = 64; // disable wandering around
-float MONSTER_APPEAR = 128; // spawn invisible, and appear when triggered
-
-.float ismonster;
-.float monsterawaitingteleport; // avoid awaking monsters in teleport rooms
-
-// when a monster becomes angry at a player, that monster will be used
-// as the sight target the next frame so that monsters near that one
-// will wake up even if they wouldn't have noticed the player
-//
-entity sight_entity;
-float sight_entity_time;
-
-/*
-
-.enemy
-Will be world if not currently angry at anyone.
-
-.movetarget
-The next path spot to walk toward. If .enemy, ignore .movetarget.
-When an enemy is killed, the monster will try to return to it's path.
-
-.huntt_ime
-Set to time + something when the player is in sight, but movement straight for
-him is blocked. This causes the monster to use wall following code for
-movement direction instead of sighting on the player.
-
-.ideal_yaw
-A yaw angle of the intended direction, which will be turned towards at up
-to 45 deg / state. If the enemy is in view and hunt_time is not active,
-this will be the exact line towards the enemy.
-
-.pausetime
-A monster will leave it's stand state and head towards it's .movetarget when
-time > .pausetime.
-
-walkmove(angle, speed) primitive is all or nothing
-*/
-
-
-//
-// globals
-//
-//float current_yaw;
-
-float(float v) anglemod =
-{
- v = v - 360 * floor(v / 360);
- return v;
-};
-
-/*
-==============================================================================
-
-MOVETARGET CODE
-
-The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways heads to the next target.
-
-targetname
-must be present. The name of this movetarget.
-
-target
-the next spot to move to. If not present, stop here for good.
-
-pausetime
-The number of seconds to spend standing or bowing for path_stand or path_bow
-
-==============================================================================
-*/
-
-
-void() movetarget_f =
-{
- if (!self.targetname)
- objerror ("monster_movetarget: no targetname");
-
- self.solid = SOLID_TRIGGER;
- self.touch = t_movetarget;
- setsize (self, '-8 -8 -8', '8 8 8');
-};
-
-/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8)
-Monsters will continue walking towards the next target corner.
-*/
-void() path_corner =
-{
- movetarget_f ();
-};
-
-/*
-=============
-t_movetarget
-
-Something has bumped into a movetarget. If it is a monster
-moving towards it, change the next destination and continue.
-==============
-*/
-void() t_movetarget =
-{
- local entity temp;
-
- if (other.health < 1)
- return;
- if (other.movetarget != self)
- return;
-
- if (other.enemy)
- return; // fighting, not following a path
-
- temp = self;
- self = other;
- other = temp;
-
- /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
- if (self.classname == "monster_ogre")
- sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
- */
-
-//dprint ("t_movetarget\n");
- self.goalentity = self.movetarget = find (world, targetname, other.target);
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- if (!self.movetarget)
- {
- self.pausetime = time + 999999;
- self.th_stand ();
- return;
- }
-};
-
-void() monster_wanderpaththink =
-{
- local vector v, v1;
- local float b, c;
- self.nextthink = time + random() * 10 + 1;
- if (self.owner.health < 1) // dead, also handled in death code
- {
- self.owner.movetarget = world;
- remove(self);
- return;
- }
- b = -1;
- c = 10;
- while (c > 0)
- {
- c = c - 1;
- v = randomvec();
- traceline(self.owner.origin, v * 1024 + self.owner.origin, FALSE, self);
- v = trace_endpos - (normalize(v) * 16) - self.owner.origin;
- if (vlen(v) > b)
- {
- b = vlen(v);
- v1 = v;
- }
- }
- setorigin(self, v1 + self.owner.origin);
- self.owner.ideal_yaw = vectoyaw(self.origin - self.owner.origin);
-};
-
-void() monster_wanderpathtouch =
-{
- if (other.health < 1)
- return;
- if (other.movetarget != self)
- return;
-
- if (other.enemy)
- return; // fighting, not following a path
-
- /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
- if (other.classname == "monster_ogre")
- sound (other, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
- */
- monster_wanderpaththink();
-};
-
-void() monster_spawnwanderpath =
-{
- newmis = spawn();
- newmis.classname = "monster_wanderpath";
- newmis.solid = SOLID_TRIGGER;
- newmis.touch = monster_wanderpathtouch;
- setsize (newmis, '-8 -8 -8', '8 8 8');
- newmis.think = monster_wanderpaththink;
- newmis.nextthink = time + random() * 10 + 1;
- newmis.owner = self;
- self.goalentity = self.movetarget = newmis;
-};
-
-void() monster_checkbossflag =
-{
-//#NO AUTOCVARS START
-#if 0
- local float healthboost;
- local float r;
-
- // monsterbosses cvar or spawnflag 64 causes a monster to be a miniboss
- if ((self.spawnflags & 64) || (random() * 100 < cvar("monsterbosspercent")))
- {
- self.radsuit_finished = time + 1000000000;
- r = random() * 4;
- if (r < 2)
- {
- self.super_damage_finished = time + 1000000000;
- healthboost = 30 + self.health * 0.5;
- self.effects = self.effects | (EF_FULLBRIGHT | EF_BLUE);
- }
- if (r >= 1)
- {
- healthboost = 30 + self.health * bound(0.5, skill * 0.5, 1.5);
- self.effects = self.effects | (EF_FULLBRIGHT | EF_RED);
- self.healthregen = max(self.healthregen, min(skill * 10, 30));
- }
- self.health = self.health + healthboost;
- self.max_health = self.health;
- self.bodyhealth = self.bodyhealth * 2 + healthboost;
- do
- {
- self.colormod_x = random();
- self.colormod_y = random();
- self.colormod_z = random();
- self.colormod = normalize(self.colormod);
- }
- while (self.colormod_x > 0.6 && self.colormod_y > 0.6 && self.colormod_z > 0.6);
- }
-#endif
-//#NO AUTOCVARS END
-};
-
-
-//============================================================================
-
-/*
-=============
-range
-
-returns the range catagorization of an entity reletive to self
-0 melee range, will become hostile even if back is turned
-1 visibility and infront, or visibility and show hostile
-2 infront and show hostile
-3 only triggered by damage
-=============
-*/
-float(entity targ) range =
-{
- local float r;
- r = vlen ((self.origin + self.view_ofs) - (targ.origin + targ.view_ofs));
- if (r < 120)
- return RANGE_MELEE;
- if (r < 500)
- return RANGE_NEAR;
- if (r < 2000) // increased from 1000 for DP
- return RANGE_MID;
- return RANGE_FAR;
-};
-
-/*
-=============
-visible
-
-returns 1 if the entity is visible to self, even if not infront ()
-=============
-*/
-float (entity targ) visible =
-{
- if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
- return FALSE;
-
- traceline ((self.origin + self.view_ofs), (targ.origin + targ.view_ofs), TRUE, self); // see through other monsters
-
- if (trace_inopen && trace_inwater)
- return FALSE; // sight line crossed contents
-
- if (trace_fraction == 1)
- return TRUE;
- return FALSE;
-};
-
-
-/*
-=============
-infront
-
-returns 1 if the entity is in front (in sight) of self
-=============
-*/
-float(entity targ) infront =
-{
- local float dot;
-
- makevectors (self.angles);
- dot = normalize (targ.origin - self.origin) * v_forward;
-
- return (dot > 0.3);
-};
-// returns 0 if not infront, or the dotproduct if infront
-float(vector dir, entity targ) infront2 =
-{
- local float dot;
-
- dir = normalize(dir);
- dot = normalize (targ.origin - self.origin) * dir;
-
- if (dot >= 0.3) return dot; // infront
- return 0;
-};
-
-
-//============================================================================
-
-/*
-===========
-ChangeYaw
-
-Turns towards self.ideal_yaw at self.yaw_speed
-Sets the global variable current_yaw
-Called every 0.1 sec by monsters
-============
-*/
-/*
-
-void() ChangeYaw =
-{
- local float ideal, move;
-
-//current_yaw = self.ideal_yaw;
-// mod down the current angle
- current_yaw = anglemod( self.angles_y );
- ideal = self.ideal_yaw;
-
- if (current_yaw == ideal)
- return;
-
- move = ideal - current_yaw;
- if (ideal > current_yaw)
- {
- if (move > 180)
- move = move - 360;
- }
- else
- {
- if (move < -180)
- move = move + 360;
- }
-
- if (move > 0)
- {
- if (move > self.yaw_speed)
- move = self.yaw_speed;
- }
- else
- {
- if (move < 0-self.yaw_speed )
- move = 0-self.yaw_speed;
- }
-
- current_yaw = anglemod (current_yaw + move);
-
- self.angles_y = current_yaw;
-};
-
-*/
-
-
-//============================================================================
-
-void() HuntTarget =
-{
- self.goalentity = self.enemy;
- self.think = self.th_run;
- self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
- self.nextthink = time + 0.1;
- SUB_AttackFinished (1); // wait a while before first attack
-};
-
-.void() th_sightsound;
-
-void() SightSound =
-{
- if (self.health < 1)
- return;
- // skill 5 does not play sight sounds, instead you only hear the appear sound as they are about to attack
- if (skill >= 5)
- if (self.classname != "monster_hellfish")
- return;
-
- if (self.th_sightsound)
- self.th_sightsound();
-};
-
-void() FoundTarget =
-{
- if (self.health < 1 || !self.th_run)
- return;
- if (self.enemy.health < 1 || !self.enemy.takedamage)
- return;
- if (self.enemy.classname == "player")
- {
- // let other monsters see this monster for a while
- sight_entity = self;
- sight_entity_time = time + 0.1;
- }
-
- self.show_hostile = time + 1; // wake up other monsters
-
- SightSound ();
- HuntTarget ();
-};
-
-/*
-//float checkplayertime;
-entity lastcheckplayer;
-entity havocbot_list;
-
-
-entity() checkplayer =
-{
- local entity check;
- local float worldcount;
- // we can just fallback on checkclient if there are no bots
- if (!havocbot_list)
- return checkclient();
-*/
- /*
- if (time < checkplayertime)
- {
- traceline(self.origin + self.view_ofs, lastcheckplayer.origin + lastcheckplayer.view_ofs, TRUE, self);
- if (trace_fraction == 1)
- return lastcheckplayer;
- if (trace_ent == lastcheckplayer)
- return lastcheckplayer;
- }
- checkplayertime = time + 0.1;
- */
-/*
- check = lastcheckplayer;
- worldcount = 0;
- c = 0;
- do
- {
- c = c + 1;
- check = findfloat(check, havocattack, TRUE);
- if (check.classname == "player" || check.classname == "turretbase")
- {
- traceline(self.origin + self.view_ofs, check.origin + check.view_ofs, TRUE, self);
- if (trace_fraction == 1)
- return lastcheckplayer = check;
- if (trace_ent == check)
- return lastcheckplayer = check;
- }
- else if (check == world)
- {
- worldcount = worldcount + 1;
- if (worldcount >= 2)
- return lastcheckplayer = check;
- }
- }
- while(check != lastcheckplayer && c < 100);
- return world;
-};
-*/
-
-/*
-===========
-FindTarget
-
-Self is currently not attacking anything, so try to find a target
-
-Returns TRUE if an enemy was sighted
-
-When a player fires a missile, the point of impact becomes a fakeplayer so
-that monsters that see the impact will respond as if they had seen the
-player.
-
-To avoid spending too much time, only a single client (or fakeclient) is
-checked each frame. This means multi player games will have slightly
-slower noticing monsters.
-============
-*/
-.float findtarget;
-float() FindTarget =
-{
- local entity client;
- local float r;
-
- if (self.health < 1)
- return FALSE;
-
- // if the first or second spawnflag bit is set, the monster will only
- // wake up on really seeing the player, not another monster getting angry
-
- if (self.spawnflags & 3)
- {
- // don't wake up on seeing another monster getting angry
- client = checkclient ();
- if (!client)
- return FALSE; // current check entity isn't in PVS
- }
- else
- {
- if (sight_entity_time >= time)
- {
- client = sight_entity;
- if (client.enemy == self.enemy)
- return TRUE;
- }
- else
- {
- client = checkclient ();
- if (!client)
- return FALSE; // current check entity isn't in PVS
- }
- }
-
- if (client == self.enemy)
- return FALSE;
-
- if (client.flags & FL_NOTARGET)
- return FALSE;
-
-#if 0
- if (client.items & IT_INVISIBILITY)
- return FALSE;
-#endif
-
- // on skill 5 the monsters usually ignore the player and remain ghostlike
- if (skill >= 5)
- if (self.classname != "monster_hellfish")
- if (random() < 0.99)
- return FALSE;
-
- r = range(client);
- if (r == RANGE_FAR)
- return FALSE;
-
- if (!visible (client))
- return FALSE;
-
- if (r == RANGE_NEAR)
- {
- if (client.show_hostile < time && !infront (client))
- return FALSE;
- }
- else if (r == RANGE_MID)
- {
- // LordHavoc: was if ( /* client.show_hostile < time || */ !infront (client))
- if (client.show_hostile < time && !infront (client))
- return FALSE;
- }
-
- //
- // got one
- //
-
- if (client.model == "")
- return FALSE;
- self.enemy = client;
- if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
- {
- self.enemy = self.enemy.enemy;
- if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
- {
- self.enemy = world;
- return FALSE;
- }
- }
-
- FoundTarget ();
-
- return TRUE;
-};
-
-
-//=============================================================================
-
-void(float dist) ai_forward =
-{
- walkmove (self.angles_y, dist);
-};
-
-void(float dist) ai_back =
-{
- walkmove ( (self.angles_y+180), dist);
-};
-
-
-void(float a) monster_setalpha;
-
-/*
-=============
-ai_pain
-
-stagger back a bit
-=============
-*/
-void(float dist) ai_pain =
-{
- if (self.health < 1)
- return;
- ai_back (dist);
-};
-
-/*
-=============
-ai_painforward
-
-stagger back a bit
-=============
-*/
-void(float dist) ai_painforward =
-{
- if (self.health < 1)
- return;
- walkmove (self.ideal_yaw, dist);
-};
-
-/*
-=============
-ai_walk
-
-The monster is walking it's beat
-=============
-*/
-void(float dist) ai_walk =
-{
- if (self.health < 1)
- return;
-
- movedist = dist;
-
- // check for noticing a player
- if (self.oldenemy.takedamage)
- if (self.oldenemy.health >= 1)
- {
- self.enemy = self.oldenemy;
- self.oldenemy = world;
- FoundTarget();
- monster_setalpha(0);
- return;
- }
- if (self.enemy)
- {
- if (self.enemy.takedamage)
- {
- if (self.enemy.health >= 1)
- {
- FoundTarget();
- monster_setalpha(0);
- return;
- }
- else
- self.enemy = world;
- }
- else
- self.enemy = world;
- }
-
- self.findtarget = TRUE;
-
- movetogoal (dist);
- monster_setalpha(0);
-};
-
-
-/*
-=============
-ai_stand
-
-The monster is staying in one place for a while, with slight angle turns
-=============
-*/
-void() ai_stand =
-{
- if (self.health < 1)
- return;
- if (self.enemy)
- {
- if (self.enemy.takedamage)
- {
- if (self.enemy.health >= 1)
- {
- FoundTarget();
- monster_setalpha(0);
- return;
- }
- else
- self.enemy = world;
- }
- else
- self.enemy = world;
- }
- self.findtarget = TRUE;
-
- if (time > self.pausetime)
- {
- self.th_walk ();
- monster_setalpha(0);
- return;
- }
-
-// change angle slightly
-
- monster_setalpha(0);
-};
-
-/*
-=============
-ai_turn
-
-don't move, but turn towards ideal_yaw
-=============
-*/
-void() ai_turn =
-{
- if (self.enemy)
- {
- if (self.enemy.takedamage)
- {
- if (self.enemy.health >= 1)
- {
- FoundTarget();
- monster_setalpha(0);
- return;
- }
- else
- self.enemy = world;
- }
- else
- self.enemy = world;
- }
- self.findtarget = TRUE;
-
- ChangeYaw ();
- monster_setalpha(0);
-};
-
-//=============================================================================
-
-/*
-=============
-ChooseTurn
-=============
-*/
-void(vector pDestvec) ChooseTurn =
-{
- local vector dir, newdir;
-
- dir = self.origin - pDestvec;
-
- newdir_x = trace_plane_normal_y;
- newdir_y = 0 - trace_plane_normal_x;
- newdir_z = 0;
-
- if (dir * newdir > 0)
- {
- dir_x = 0 - trace_plane_normal_y;
- dir_y = trace_plane_normal_x;
- }
- else
- {
- dir_x = trace_plane_normal_y;
- dir_y = 0 - trace_plane_normal_x;
- }
-
- dir_z = 0;
- self.ideal_yaw = vectoyaw(dir);
-};
-
-/*
-============
-FacingIdeal
-
-============
-*/
-float() FacingIdeal =
-{
- local float delta;
-
- delta = anglemod(self.angles_y - self.ideal_yaw);
- if (delta > 45 && delta < 315)
- return FALSE;
- return TRUE;
-};
-
-
-//=============================================================================
-
-.float() th_checkattack;
-
-
-
-/*
-=============
-ai_run
-
-The monster has an enemy it is trying to kill
-=============
-*/
-void(float dist) ai_run =
-{
- local float ofs;
- if (self.health < 1)
- return;
- movedist = dist;
- // see if the enemy is dead
- if (self.enemy.health < 1 || self.enemy.takedamage == DAMAGE_NO)
- {
- self.enemy = world;
- // FIXME: look all around for other targets
- if (self.oldenemy.health >= 1 && self.oldenemy.takedamage)
- {
- self.enemy = self.oldenemy;
- self.oldenemy = world;
- HuntTarget ();
- }
- else
- {
- if (self.movetarget)
- self.th_walk ();
- else
- self.th_stand ();
- return;
- }
- }
-
- // wake up other monsters
- self.show_hostile = time + 1;
-
- // check knowledge of enemy
- enemy_range = range(self.enemy);
-
- self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
- ChangeYaw ();
-
- if (self.attack_state == AS_MELEE)
- {
- //dprint ("ai_run_melee\n");
- //Turn and close until within an angle to launch a melee attack
- if (FacingIdeal())
- {
- self.th_melee ();
- self.attack_state = AS_STRAIGHT;
- }
- return;
- }
- else if (self.attack_state == AS_MISSILE)
- {
- //dprint ("ai_run_missile\n");
- //Turn in place until within an angle to launch a missile attack
- if (FacingIdeal())
- if (self.th_missile ())
- self.attack_state = AS_STRAIGHT;
- return;
- }
-
- if (self.th_checkattack())
- return; // beginning an attack
-
- if (visible(self.enemy))
- self.search_time = time + 5;
- else if (coop)
- {
- // look for other coop players
- if (self.search_time < time)
- self.findtarget = TRUE;
- }
-
- if (self.attack_state == AS_SLIDING)
- {
- //dprint ("ai_run_slide\n");
- //Strafe sideways, but stay at aproximately the same range
- if (self.lefty)
- ofs = 90;
- else
- ofs = -90;
-
- if (walkmove (self.ideal_yaw + ofs, movedist))
- return;
-
- self.lefty = !self.lefty;
-
- walkmove (self.ideal_yaw - ofs, movedist);
- }
-
- // head straight in
- movetogoal (dist); // done in C code...
-};
-
+++ /dev/null
-.entity movetarget;
-.float pausetime;
-
-.void() th_stand;
-.void() th_walk;
-.void() th_run;
-.float() th_missile; // LordHavoc: changed from void() to float(), returns true if attacking
-.void() th_melee;
-//.void(entity attacker, float damage, float damgtype, string dethtype) th_pain; // TODO Xonotic uses event_damage
-//.void() th_die; // TODO never called directly by Xonotic
-.entity oldenemy; // mad at this player before taking damage
-entity newmis; // launch_spike sets this after spawning it
-
-// range values
-float RANGE_MELEE = 0;
-float RANGE_NEAR = 1;
-float RANGE_MID = 2;
-float RANGE_FAR = 3;
-
-float DMG_KNIGHT_MELEE_BASE = 0;
-float DMG_KNIGHT_MELEE_RANDOM1 = 3;
-float DMG_KNIGHT_MELEE_RANDOM2 = 3;
-float DMG_KNIGHT_MELEE_RANDOM3 = 3;
-
-.float show_hostile;
- // set to time+0.2 whenever a client fires a
- // weapon or takes damage. Used to alert
- // monsters that otherwise would let the player go
-
-float movedist;
-.float lefty;
-.float search_time;
-.float attack_state;
-
-float AS_STRAIGHT = 1;
-float AS_SLIDING = 2;
-float AS_MELEE = 3;
-float AS_MISSILE = 4;
-
-float SKILL4_MINALPHA = 0.4;
-
-float monsterwander;
-//#NO AUTOCVARS START
-/*
- monsterwander = cvar("monsterwander");
- // monsterwander is always on in skill 5
- if (skill >= 5)
- monsterwander = TRUE;
-*/
-//#NO AUTOCVARS END
-
-.float candrown;
-
-.void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc;
-void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc;
+++ /dev/null
-
-/*
-
-A monster is in fight mode if it thinks it can effectively attack its
-enemy.
-
-When it decides it can't attack, it goes into hunt mode.
-
-*/
-
-void SUB_AttackFinished (float normal)
-{
- self.cnt = 0; // refire count for nightmare
- if (skill < 3)
- ATTACK_FINISHED(self) = time + normal;
-}
-
-float CanDamage(entity targ, entity inflictor)
-{
- if (targ.movetype == MOVETYPE_PUSH)
- {
- traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
- if (trace_fraction == 1)
- return TRUE;
- if (trace_ent == targ)
- return TRUE;
- return FALSE;
- }
-
- traceline(inflictor.origin, targ.origin, TRUE, self);
- if (trace_fraction == 1)
- return TRUE;
- traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
- if (trace_fraction == 1)
- return TRUE;
- traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
- if (trace_fraction == 1)
- return TRUE;
- traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
- if (trace_fraction == 1)
- return TRUE;
- traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
- if (trace_fraction == 1)
- return TRUE;
-
- return FALSE;
-}
-
-float(float v) anglemod;
-
-void(vector dest) ChooseTurn;
-
-void() ai_face;
-
-
-float enemy_range;
-
-
-//=============================================================================
-
-/*
-===========
-GenericCheckAttack
-
-The player is in view, so decide to move or launch an attack
-Returns FALSE if movement should continue
-============
-*/
-float() GenericCheckAttack =
-{
- local vector spot1, spot2;
- local entity targ;
- local float chance;
-
- if (self.health < 1)
- return FALSE;
- targ = self.enemy;
-
- if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
- return FALSE;
-
-// see if any entities are in the way of the shot
- spot1 = self.origin + self.view_ofs;
- spot2 = targ.origin + targ.view_ofs;
-
- traceline (spot1, spot2, FALSE, self);
-
- if (trace_ent != targ)
- return FALSE; // don't have a clear shot
-
- if (trace_inopen && trace_inwater)
- return FALSE; // sight line crossed contents
-
- if (enemy_range == RANGE_MELEE)
- { // melee attack
- if (self.th_melee)
- {
- self.th_melee ();
- return TRUE;
- }
- }
-
-// missile attack
- if (time < ATTACK_FINISHED(self))
- return FALSE;
-
- if (!self.th_missile)
- return FALSE;
-
- if (enemy_range == RANGE_FAR)
- return FALSE;
-
- if (enemy_range == RANGE_MELEE)
- {
- chance = 0.9;
- ATTACK_FINISHED(self) = 0;
- }
- else if (enemy_range == RANGE_NEAR)
- {
- if (self.th_melee)
- chance = 0.2;
- else
- chance = 0.4;
- }
- else if (enemy_range == RANGE_MID)
- {
- if (self.th_melee)
- chance = 0.05;
- else
- chance = 0.1;
- }
- else
- chance = 0;
-
- if (random () < chance)
- if (self.th_missile ())
- {
- SUB_AttackFinished (2*random());
- return TRUE;
- }
-
- return FALSE;
-};
-
-
-/*
-=============
-ai_face
-
-Stay facing the enemy
-=============
-*/
-void() ai_face =
-{
- self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
- ChangeYaw ();
-};
-
-/*
-=============
-ai_charge
-
-The monster is in a melee attack, so get as close as possible to .enemy
-=============
-*/
-float (entity targ) visible;
-float(entity targ) infront;
-float(entity targ) range;
-
-void(float d) ai_charge =
-{
- if (self.health < 1)
- return;
- ai_face ();
- movetogoal (d); // done in C code...
-};
-
-void() ai_charge_side =
-{
- if (self.health < 1)
- return;
- local vector dtemp;
- local float heading;
-
-// aim to the left of the enemy for a flyby
-
- self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
- ChangeYaw ();
-
- makevectors (self.angles);
- dtemp = self.enemy.origin - 30*v_right;
- heading = vectoyaw(dtemp - self.origin);
-
- walkmove(heading, 20);
-};
-
-
-/*
-=============
-ai_melee
-
-=============
-*/
-void() ai_melee =
-{
- local vector delta;
- local float ldmg;
-
- if (self.health < 1)
- return;
- if (!self.enemy)
- return; // removed before stroke
-
- delta = self.enemy.origin - self.origin;
-
- if (vlen(delta) > 60)
- return;
-
- ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
- ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
- ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
- traceline(self.origin, self.enemy.origin, FALSE, self);
-
- Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); // TODO add force to monster melee attacks?
-};
-
-
-void() ai_melee_side =
-{
- local vector delta;
- local float ldmg;
-
- if (self.health < 1)
- return;
- if (!self.enemy)
- return; // removed before stroke
-
- ai_charge_side();
-
- delta = self.enemy.origin - self.origin;
-
- if (vlen(delta) > 60)
- return;
- if (!CanDamage (self.enemy, self))
- return;
- ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
- ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
- ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
- traceline(self.origin, self.enemy.origin, FALSE, self);
- Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0');
-};
-
+++ /dev/null
-/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
-
-// name =[framenum, nexttime, nextthink] {code}
-// expands to:
-// name ()
-// {
-// self.frame=framenum;
-// self.nextthink = time + nexttime;
-// self.think = nextthink
-// <code>
-// };
-
-.float ismonster;
-
-.float modelindex2;
-
-/*
-================
-monster_use
-
-Using a monster makes it angry at the current activator
-LordHavoc: using a monster with the spawnflag 'Appear' makes it appear
-================
-*/
-void() monster_use =
-{
- if (self.enemy)
- return;
- if (self.health < 1)
- return;
- if (self.mdl)
- if (self.spawnflags & MONSTER_APPEAR)
- {
- self.nextthink = time + 0.1;
- self.spawnflags = self.spawnflags - MONSTER_APPEAR;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- //self.movetype = MOVETYPE_STEP;
- self.model = self.mdl;
- self.mdl = "";
- self.modelindex = self.modelindex2;
- self.modelindex2 = 0;
- //setorigin(self, self.origin + '0 0 1');
- spawn_tdeath(self.origin, self, self.origin);
- return;
- }
-
-#if 0
- if (activator.items & IT_INVISIBILITY)
- return;
-#endif
- if (activator.flags & FL_NOTARGET)
- return;
- if (activator.classname != "player")
- return;
-
- // delay reaction so if the monster is teleported, its sound is still heard
- self.enemy = activator;
- self.nextthink = time + 0.1;
- self.think = FoundTarget;
-};
-
-void() monster_appearsetup =
-{
- if ((self.spawnflags & MONSTER_APPEAR) == 0)
- return;
- self.mdl = self.model;
- self.modelindex2 = self.modelindex;
- self.modelindex = 0;
- self.solid = SOLID_NOT;
- self.takedamage = DAMAGE_NO;
- //self.movetype = MOVETYPE_NONE;
- self.nextthink = -1;
- self.model = "";
-};
-
-/*
-================
-monster_setalpha
-
-Sets relative alpha of monster in skill 4 mode.
-================
-*/
-void(float a) monster_setalpha =
-{
- if (skill < 4 || self.classname == "monster_hellfish")
- {
- self.alpha = 1.0;
- return;
- }
-
- if (skill >= 5)
- {
- // randomly forget enemy, this makes monsters randomly return to their normal ghostlike state
- if (a == 0)
- if (self.enemy)
- if (random() < 0.1)
- self.enemy = world;
- // randomly blink (playing the same alarming sound as if attacking)
- if (self.enemy == world)
- {
- a = 0;
- if (time >= 0.3) // don't blink during the init process because it might become permanent
- if (random() < 0.005)
- {
- // blink for an instant, this causes the appear sound, alarming the player as if under attack
- /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
- sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
- */
- a = 1;
- }
- }
- // if ghosted, become non-solid and immune to damage
- if (a <= 0 || self.enemy == world)
- {
- self.solid = SOLID_NOT;
- self.takedamage = DAMAGE_NO;
- }
- else
- {
- // if unghosting, make sure we have an enemy, otherwise stay ghosted (even if blinking) so we can't be shot while blinking
- /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
- if (self.solid != SOLID_SLIDEBOX)
- sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
- */
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- }
- }
- self.alpha = SKILL4_MINALPHA + (1 - SKILL4_MINALPHA) * bound(0, a, 1);
-};
-
-/*
-================
-monster_death_use
-
-When a mosnter dies, it fires all of its targets with the current
-enemy as activator.
-================
-*/
-void() monster_death_use =
-{
-// fall to ground
- if (self.flags & FL_FLY)
- self.flags = self.flags - FL_FLY;
- if (self.flags & FL_SWIM)
- self.flags = self.flags - FL_SWIM;
-
- if (!self.target)
- return;
-
- activator = self.enemy;
- SUB_UseTargets ();
-};
-
-
-void() monsterinwall =
-{
- local entity e;
- if (!autocvar_developer)
- return;
- // this is handy for level designers,
- // puts a spikey ball where the error is...
- e = spawn();
- setorigin(e, self.origin);
- setmodel (e, "models/ebomb.mdl");
- e.movetype = MOVETYPE_NONE;
- e.solid = SOLID_NOT;
- e.think = SUB_Null;
- e.nextthink = -1;
- e.scale = 16;
-};
-
-//============================================================================
-
-void() walkmonster_start_go =
-{
- self.origin_z = self.origin_z + 1; // raise off floor a bit
-
- tracebox(self.origin, self.mins, self.maxs, self.origin, TRUE, self);
- if (trace_startsolid)
- {
- dprint("walkmonster in wall at: ");
- dprint(vtos(self.origin));
- dprint("\n");
- monsterinwall();
- droptofloor();
- }
- else
- {
- droptofloor();
- if (!walkmove(0,0))
- {
- dprint("walkmonster in wall at: ");
- dprint(vtos(self.origin));
- dprint("\n");
- monsterinwall();
- }
- }
-
- //self.cantrigger = TRUE;
-
- self.takedamage = DAMAGE_AIM;
-
- self.ideal_yaw = self.angles * '0 1 0';
- if (!self.yaw_speed)
- self.yaw_speed = 20;
- self.view_ofs = '0 0 25';
- self.use = monster_use;
-
- self.flags = self.flags | FL_MONSTER;
-
- if (monsterwander)
- self.spawnflags = self.spawnflags | MONSTER_WANDER;
-
- if (self.target)
- {
- self.goalentity = self.movetarget = find(world, targetname, self.target);
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- if (!self.movetarget)
- {
- dprint("Monster can't find target at ");
- dprint(vtos(self.origin));
- dprint("\n");
- }
- // this used to be an objerror
- if (self.movetarget.classname == "path_corner")
- self.th_walk ();
- else
- {
- if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
- {
- monster_spawnwanderpath();
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- }
- else
- {
- if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
- {
- monster_spawnwanderpath();
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
-
-// spread think times so they don't all happen at same time
- self.nextthink = self.nextthink + random()*0.5 + 0.1;
- self.iscreature = TRUE;
-
- force_retouch = 2; // mainly to detect teleports
-
- monster_appearsetup();
-};
-
-
-void() walkmonster_start =
-{
- self.candrown = 1; // this is turned off by some monsters like zombies
- // delay drop to floor to make sure all doors have been spawned
- // spread think times so they don't all happen at same time
- self.nextthink = time + random()*0.5 + 0.3;
- self.think = walkmonster_start_go;
- total_monsters = total_monsters + 1;
- self.bot_attack = TRUE;
- self.frags = 2; // actually just used to get havocbots to attack it...
- self.bleedfunc = genericbleedfunc;
- self.ismonster = TRUE;
-
- monster_setalpha (0);
-};
-
-
-
-void() flymonster_start_go =
-{
- self.takedamage = DAMAGE_AIM;
-
- self.ideal_yaw = self.angles * '0 1 0';
- if (!self.yaw_speed)
- self.yaw_speed = 10;
- self.view_ofs = '0 0 25';
- self.use = monster_use;
-
- self.flags = self.flags | FL_FLY;
- self.flags = self.flags | FL_MONSTER;
-
- if (!walkmove(0,0))
- {
- dprint("flymonster in wall at: ");
- dprint(vtos(self.origin));
- dprint("\n");
- monsterinwall();
- }
-
- //self.cantrigger = TRUE;
-
- if (monsterwander)
- self.spawnflags = self.spawnflags | MONSTER_WANDER;
-
- if (self.target)
- {
- self.goalentity = self.movetarget = find(world, targetname, self.target);
- if (!self.movetarget)
- {
- dprint("Monster can't find target at ");
- dprint(vtos(self.origin));
- dprint("\n");
- }
- // this used to be an objerror
- if (self.movetarget.classname == "path_corner")
- self.th_walk ();
- else
- {
- if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
- {
- monster_spawnwanderpath();
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- }
- else
- {
- if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
- {
- monster_spawnwanderpath();
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- self.iscreature = TRUE;
-
- force_retouch = 2; // mainly to detect teleports
-
- monster_appearsetup();
-};
-
-void() flymonster_start =
-{
- self.candrown = 1;
- // spread think times so they don't all happen at same time
- self.nextthink = time + random()*0.5 + 0.1;
- self.think = flymonster_start_go;
- total_monsters = total_monsters + 1;
- self.bot_attack = TRUE;
- self.frags = 2; // actually just used to get havocbots to attack it...
- self.bleedfunc = genericbleedfunc;
- self.ismonster = TRUE;
-
- monster_setalpha (0);
-};
-
-
-void() swimmonster_start_go =
-{
- if (deathmatch)
- {
- remove(self);
- return;
- }
-
- //self.cantrigger = TRUE;
-
- self.takedamage = DAMAGE_AIM;
-
- self.ideal_yaw = self.angles * '0 1 0';
- if (!self.yaw_speed)
- self.yaw_speed = 10;
- self.view_ofs = '0 0 10';
- self.use = monster_use;
-
- self.flags = self.flags | FL_SWIM;
- self.flags = self.flags | FL_MONSTER;
-
- if (monsterwander)
- self.spawnflags = self.spawnflags | MONSTER_WANDER;
-
- if (self.target)
- {
- self.goalentity = self.movetarget = find(world, targetname, self.target);
- if (!self.movetarget)
- {
- dprint("Monster can't find target at ");
- dprint(vtos(self.origin));
- dprint("\n");
- }
- // this used to be an objerror
- if (self.movetarget.classname == "path_corner")
- self.th_walk ();
- else
- {
- if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
- {
- monster_spawnwanderpath();
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- }
- else
- {
- if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
- {
- monster_spawnwanderpath();
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- self.iscreature = TRUE;
-
- force_retouch = 2; // mainly to detect teleports
-
- monster_appearsetup();
-};
-
-void() swimmonster_start =
-{
- // spread think times so they don't all happen at same time
- self.candrown = 0;
- self.nextthink = time + random()*0.5 + 0.1;
- self.think = swimmonster_start_go;
- total_monsters = total_monsters + 1;
- self.bot_attack = TRUE;
- self.frags = 2; // actually just used to get havocbots to attack it...
- self.bleedfunc = genericbleedfunc;
- self.ismonster = TRUE;
-
- monster_setalpha(0);
-};
-
-void(vector org, float bodydamage, float armordamage, vector force, float damgtype) genericbleedfunc =
-{
- local vector v;
- v = '0 0 0' - force * 0.05;
- if (armordamage > 0)
- te_spark(org, v, armordamage * 3);
- if (bodydamage > 0)
- te_blood(org, v, bodydamage);
-}
+++ /dev/null
-//#define MONSTES_ENABLED
-#ifdef MONSTES_ENABLED
-
-#define zombie_anim_attackleap 0
-#define zombie_anim_attackrun1 1
-#define zombie_anim_attackrun2 2
-#define zombie_anim_attackrun3 3
-#define zombie_anim_attackstanding1 4
-#define zombie_anim_attackstanding2 5
-#define zombie_anim_attackstanding3 6
-#define zombie_anim_blockend 7
-#define zombie_anim_blockstart 8
-#define zombie_anim_deathback1 9
-#define zombie_anim_deathback2 10
-#define zombie_anim_deathback3 11
-#define zombie_anim_deathfront1 12
-#define zombie_anim_deathfront2 13
-#define zombie_anim_deathfront3 14
-#define zombie_anim_deathleft1 15
-#define zombie_anim_deathleft2 16
-#define zombie_anim_deathright1 17
-#define zombie_anim_deathright2 18
-#define zombie_anim_idle 19
-#define zombie_anim_painback1 20
-#define zombie_anim_painback2 21
-#define zombie_anim_painfront1 22
-#define zombie_anim_painfront2 23
-#define zombie_anim_runbackwards 24
-#define zombie_anim_runbackwardsleft 25
-#define zombie_anim_runbackwardsright 26
-#define zombie_anim_runforward 27
-#define zombie_anim_runforwardleft 28
-#define zombie_anim_runforwardright 29
-#define zombie_anim_spawn 30
-
-#define ZOMBIE_MIN '-18 -18 -25'
-#define ZOMBIE_MAX '18 18 47'
-
-#define ZV_IDLE 10
-
-#define ZV_PATH 100
-#define ZV_HUNT 200
-
-#define ZV_ATTACK_FIND 10
-#define ZV_ATTACK_RUN 20
-#define ZV_ATTACK_STAND 30
-
-#define ZV_PATH2 10000
-
-//.entity verbs_idle;
-//.entity verbs_attack;
-//.entity verbs_move;
-
-//.float state_timeout;
-//.void() monster_state;
-#define MONSTERFLAG_NORESPAWN 2
-
-void zombie_spawn();
-
-float zombie_scoretarget(entity trg)
-{
- float tmp;
- vector ang1;
-
- if (trg.takedamage == DAMAGE_AIM)
- if not (trg.flags & FL_NOTARGET)
- if (trg.deadflag == DEAD_NO)
- if (trg.team != self.team)
- {
- if((self.origin_z - trg.origin_z) < 128)
- {
- ang1 = normalize(self.origin - trg.origin);
- tmp = vlen(ang1 - v_forward);
- if(tmp > 1.5)
- {
- traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);
- if(trace_ent != trg)
- return 0;
-
- return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
- }
- else if(self.enemy == trg)
- return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
- }
- }
-
- return 0;
-}
-
-void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
- //dprint("zombie_corpse_damage\n");
- Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
-
- self.health -= damage;
-
- if(self.health < 0)
- {
- Violence_GibSplash(self, 1, 1, attacker);
- remove(self);
- }
-}
-
-void zombie_die(vector dir)
-{
- vector v;
- float f;
-
- entity dummy;
-
- dummy = spawn();
- setmodel(dummy,"models/monsters/zombie.dpm");
- setorigin(dummy, self.origin);
- dummy.velocity = self.velocity;
- dummy.movetype = MOVETYPE_BOUNCE;
- dummy.think = SUB_Remove;
- dummy.nextthink = time + 3;
- dummy.health = 50;
- dummy.takedamage = DAMAGE_YES;
- dummy.event_damage = zombie_corpse_damage;
- dummy.solid = SOLID_CORPSE;
- setsize(dummy,self.mins,self.maxs);
-
- SUB_SetFade(dummy,time + 5,2);
-
-
- v = normalize(self.origin - dir);
- f = vlen(v_forward - v) - 1;
- if(f > 0.5)
- dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);
- else if(f < 0.5)
- dummy.frame = zombie_anim_deathback1 + rint(random() * 2);
- else
- {
- f = vlen(v_right - v) - 1;
- if(f > 0.5)
- dummy.frame = zombie_anim_deathright1 + rint(random() * 2);
- else if(f < 0.5)
- dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);
- }
-
-
- if(self.spawnflags & MONSTERFLAG_NORESPAWN)
- {
- self.think = SUB_Remove;
- self.nextthink = time;
- return;
- }
-
- setmodel(self,"");
- self.solid = SOLID_NOT;
- self.takedamage = DAMAGE_NO;
- self.event_damage = SUB_Null;
- self.enemy = world;
- self.think = zombie_spawn;
- self.nextthink = time + autocvar_g_monster_zombie_respawntime;
- self.pain_finished = self.nextthink;
-}
-
-void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-
- vector v;
- float f;
-
- v = normalize(self.origin - hitloc);
- f = vlen(v_forward - v) - 1;
-
-
- self.health -= damage;
- self.velocity = self.velocity + force;
- if(self.health <= 0)
- {
- zombie_die(hitloc);
- return;
- }
-
- Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
-
- if (damage > 50)
- Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
- if (damage > 100)
- Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
-
- if (time > self.pain_finished)
- {
- if(f < 0.5)
- {
- if(random() < 0.5)
- self.frame = zombie_anim_painback1;
- else
- self.frame = zombie_anim_painback2;
- }
- else
- {
- if(random() < 0.5)
- self.frame = zombie_anim_painfront1;
- else
- self.frame = zombie_anim_painfront2;
- }
-
- self.pain_finished = time + 0.36;
- }
-}
-
-.vector bvec;
-.float bvec_time;
-
-void zombie_move()
-{
- vector real_angle;
- float vz, tdiff, tspeed;
-
- tdiff = time - self.zoomstate;
- tspeed = tdiff * autocvar_g_monster_zombie_turnspeed;
- vz = self.velocity_z;
- self.zoomstate = time;
-
- if(self.bvec_time < time)
- {
- self.bvec_time = time + 0.2;
- self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
- }
-
- if(self.enemy)
- self.moveto = self.enemy.origin;
- else
- self.moveto = self.origin + v_forward;
-
- self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);
-
- self.angles_y = safeangle(self.angles_y);
- real_angle = vectoangles(self.steerto) - self.angles;
- self.angles_y += bound(-10, real_angle_y, 10);
-
- if(vlen(self.origin - self.moveto) > 64)
- {
- movelib_move_simple(v_forward ,autocvar_g_monster_zombie_movespeed,0.6);
- if(time > self.pain_finished)
- if(self.attack_finished_single < time)
- self.frame = zombie_anim_runforward;
- }
- else
- {
- movelib_beak_simple(autocvar_g_monster_zombie_stopspeed);
- if(time > self.pain_finished)
- if(self.attack_finished_single < time)
- self.frame = zombie_anim_idle;
- }
-
- self.velocity_z = vz;
- self.steerto = self.origin;
-}
-
-float zombie_verb_idle_roam(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if(self.enemy)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
-
- self.moveto = v_forward * 128;
- self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float zombie_verb_idle_stand(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if(self.enemy)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
-
- self.moveto = self.origin;
- self.frame = zombie_anim_idle;
- self.velocity = '0 0 0';
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float zombie_verb_idle(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if(self.enemy)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
- float t;
-
- t = autocvar_g_monster_zombie_idle_timer_max - autocvar_g_monster_zombie_idle_timer_min;
- t = autocvar_g_monster_zombie_idle_timer_min + (random() * t);
-
- if(random() < 0.5)
- verbstack_push(self.verbs_idle, zombie_verb_idle_roam, ZV_IDLE + 1, t, self);
- else
- verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float zombie_verb_attack_findtarget(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if(self.enemy)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
-
- entity trg, best_trg;
- float trg_score, best_trg_score;
-
- trg = findradius(self.origin,autocvar_g_monster_zombie_targetrange);
- while(trg)
- {
- trg_score = zombie_scoretarget(trg);
- if(trg_score > best_trg_score)
- {
- best_trg = trg;
- best_trg_score = trg_score;
- }
-
- trg = trg.chain;
- }
-
- if(best_trg)
- {
- self.enemy = best_trg;
- dprint("Selected: ",best_trg.netname, " as target.\n");
- }
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-void zombie_runattack_damage()
-{
- entity oldself;
- oldself = self;
- self = self.owner;
-
- if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_hitrange)
- return;
-
- if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
- return;
-
- Damage(self.enemy, self, self, autocvar_g_monster_zombie_attack_run_damage, DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin) * autocvar_g_monster_zombie_attack_run_force);
-
- self = oldself;
- self.think = SUB_Remove;
- self.nextthink = time;
-}
-
-float zombie_verb_attack_run(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if not (self.enemy)
- return VS_CALL_NO;
-
- if(self.attack_finished_single > time)
- return VS_CALL_NO;
-
- if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_range)
- return VS_CALL_NO;
-
- if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
- entity pain;
- pain = spawn();
- pain.owner = self;
- pain.think = zombie_runattack_damage;
- pain.nextthink = time + autocvar_g_monster_zombie_attack_run_delay;
-
- self.attack_finished_single = time + 0.7;
- self.frame = zombie_anim_attackrun1 + rint(random() * 2);
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-void zombie_standattack_damage()
-{
- //entity oldself;
- //oldself = self;
- //self = self.owner;
-
- setorigin(self,self.owner.origin + v_forward * 32);
- RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world);
- //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
-
-
- //self = oldself;
- self.think = SUB_Remove;
- self.nextthink = time;
-}
-
-float zombie_verb_attack_stand(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if not (self.enemy)
- return VS_CALL_NO;
-
- if(self.attack_finished_single > time)
- return VS_CALL_NO;
-
- if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_stand_range)
- return VS_CALL_NO;
-
- if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
- entity pain;
- pain = spawn();
- pain.owner = self;
- pain.think = zombie_runattack_damage;
- pain.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
-
- self.attack_finished_single = time + 0.7;
- self.frame = zombie_anim_attackstanding1 + rint(random() * 1);
- dprint("frame:",ftos(self.frame),"\n");
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-void zombie_think()
-{
- self.angles_x *= -1;
- makevectors(self.angles);
- self.angles_x *= -1;
-
- if (zombie_scoretarget(self.enemy) == 0)
- self.enemy = world;
-
- verbstack_pop(self.verbs_attack);
- //verbstack_pop(self.verbs_move);
-
- if not (self.enemy)
- verbstack_pop(self.verbs_idle);
-
- zombie_move();
-
- if(self.enemy)
- self.nextthink = time;
- else
- self.nextthink = time + 0.2;
-}
-
-void zombie_spawn()
-{
- setmodel(self,"models/monsters/zombie.dpm");
-
- self.solid = SOLID_BBOX;
- self.takedamage = DAMAGE_AIM;
- self.event_damage = zombie_damage;
- self.enemy = world;
- self.frame = zombie_anim_spawn;
- self.think = zombie_think;
- self.nextthink = time + 2.1;
- self.pain_finished = self.nextthink;
- self.movetype = MOVETYPE_WALK;
- self.health = autocvar_g_monster_zombie_health;
- self.velocity = '0 0 0';
- self.angles = self.pos2;
- self.moveto = self.origin;
- self.flags = FL_MONSTER;
-
- setorigin(self,self.pos1);
- setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);
-}
-
-
-void spawnfunc_monster_zombie()
-{
- if not(autocvar_g_monsters)
- {
- remove(self);
- return;
- }
-
- precache_model("models/monsters/zombie.dpm");
-
-
- self.verbs_idle = spawn();
- self.verbs_attack = spawn();
-
- self.verbs_idle.owner = self;
- self.verbs_attack.owner = self;
-
- self.think = zombie_spawn;
- self.nextthink = time + 2;
-
- traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);
-
- self.pos1 = trace_endpos;
- self.pos2 = self.angles;
- self.team = MAX_SHOT_DISTANCE -1;
-
- verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);
-
- verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);
- verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);
- verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);
-
-}
-
-#endif // MONSTES_ENABLED
// called when the use key is pressed
// if MUTATOR_RETURNVALUE is 1, don't do anything
// return 1 if the use key actually did something
+
+MUTATOR_HOOKABLE(SV_ParseClientCommand);
+ // called when a client command is parsed
+ // NOTE: hooks MUST start with if(MUTATOR_RETURNVALUE) return 0;
+ // NOTE: return 1 if you handled the command, return 0 to continue handling
+ // NOTE: THESE HOOKS MUST NEVER EVER CALL tokenize()
+ // INPUT
+ string cmd_name; // command name
+ float cmd_argc; // also, argv() can be used
+ string cmd_string; // whole command, use only if you really have to
+ /*
+ // example:
+ MUTATOR_HOOKFUNCTION(foo_SV_ParseClientCommand)
+ {
+ if(MUTATOR_RETURNVALUE) // command was already handled?
+ return 0;
+ if(cmd_name == "echocvar" && cmd_argc >= 2)
+ {
+ print(cvar_string(argv(1)), "\n");
+ return 1;
+ }
+ if(cmd_name == "echostring" && cmd_argc >= 2)
+ {
+ print(substring(cmd_string, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), "\n");
+ return 1;
+ }
+ return 0;
+ }
+ */
void ka_RespawnBall(void);
void ka_DropEvent(entity);
void ka_TimeScoring(void);
+void ka_EventLog(string, entity);
entity ka_ball;
other.effects |= autocvar_g_keepaway_ballcarrier_effects;
// messages and sounds
+ ka_EventLog("pickup", other);
Send_KillNotification(other.netname, "", "", KA_PICKUPBALL, MSG_KA);
WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
WriteString(MSG_BROADCAST, strcat(other.netname, "^7 has picked up the ball!"));
plyr.effects &~= autocvar_g_keepaway_ballcarrier_effects;
// messages and sounds
+ ka_EventLog("dropped", plyr);
Send_KillNotification(plyr.netname, "", "", KA_DROPBALL, MSG_KA);
WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
WriteString(MSG_BROADCAST, strcat(plyr.netname, "^7 has dropped the ball!"));
}
}
+void ka_EventLog(string mode, entity actor) // use an alias for easy changing and quick editing later
+{
+ if(autocvar_sv_eventlog)
+ GameLogEcho(strcat(":ka:", mode, ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
+}
+
MUTATOR_HOOKFUNCTION(ka_Scoring)
{
if((frag_attacker != frag_target) && (frag_attacker.classname == "player"))
--- /dev/null
+MUTATOR_HOOKFUNCTION(invincibleprojectiles_EditProjectile)
+{
+ if(other.health)
+ {
+ // disable health which in effect disables damage calculations
+ other.health = 0;
+ }
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(invincibleprojectiles_BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":InvincibleProjectiles");
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(invincibleprojectiles_BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", Invincible Projectiles");
+ return 0;
+}
+
+MUTATOR_DEFINITION(mutator_invincibleprojectiles)
+{
+ MUTATOR_HOOK(EditProjectile, invincibleprojectiles_EditProjectile, CBC_ORDER_ANY);
+ MUTATOR_HOOK(BuildMutatorsString, invincibleprojectiles_BuildMutatorsString, CBC_ORDER_ANY);
+ MUTATOR_HOOK(BuildMutatorsPrettyString, invincibleprojectiles_BuildMutatorsPrettyString, CBC_ORDER_ANY);
+
+ return 0;
+}
MUTATOR_DECLARATION(gamemode_freezetag);
MUTATOR_DECLARATION(gamemode_keepaway);
+MUTATOR_DECLARATION(mutator_invincibleprojectiles);
MUTATOR_DECLARATION(mutator_nix);
MUTATOR_DECLARATION(mutator_dodging);
MUTATOR_DECLARATION(mutator_rocketflying);
void nexball_setstatus (void)
{
- local entity oldself;
+ entity oldself;
self.items &~= IT_KEY1;
if (self.ballcarried)
{
void DropOwner (void)
{
- local entity ownr;
+ entity ownr;
ownr = self.owner;
DropBall(self, ownr.origin, ownr.velocity);
makevectors(ownr.v_angle_y * '0 1 0');
void GiveBall (entity plyr, entity ball)
{
- local entity ownr;
+ entity ownr;
if ((ownr = ball.owner))
{
void nb_spawnteam (string teamname, float teamcolor)
{
dprint("^2spawned team ", teamname, "\n");
- local entity e;
+ entity e;
e = spawn();
e.classname = "nexball_team";
e.netname = teamname;
e.cnt = teamcolor;
e.team = e.cnt + 1;
nb_teams += 1;
-};
+}
void nb_spawnteams (void)
{
void W_Nexball_Touch (void)
{
- local entity ball, attacker;
+ entity ball, attacker;
attacker = self.owner;
PROJECTILE_TOUCH;
void W_Nexball_Attack (float t)
{
- local entity ball;
- local float mul, mi, ma;
+ entity ball;
+ float mul, mi, ma;
if (!(ball = self.ballcarried))
return;
void W_Nexball_Attack2 (void)
{
- local entity missile;
+ entity missile;
if (!(balls & BALL_BASKET))
return;
W_SetupShot (self, FALSE, 2, "nexball/shoot2.wav", CH_WEAPON_A, 0);
string playerstats_last;
string events_last;
.float playerstats_addedglobalinfo;
-float playerstats_requested;
.string playerstats_id;
void PlayerStats_Init()
playerstats_db = db_create();
if(playerstats_db >= 0)
playerstats_waitforme = FALSE; // must wait for it at match end
-
+
+ serverflags |= SERVERFLAG_PLAYERSTATS;
+
PlayerStats_AddEvent(PLAYERSTATS_ALIVETIME);
PlayerStats_AddEvent(PLAYERSTATS_WINS);
PlayerStats_AddEvent(PLAYERSTATS_MATCHES);
db_put(playerstats_db, key, ftos(val));
}
-void PlayerStats_Sent_URI_Get_Callback(float id, float status, string data)
-{
- if(playerstats_requested)
- playerstats_waitforme = TRUE;
-}
-
/*
format spec:
M: map name
S: "hostname" of the server
C: number of "unpure" cvar changes
- W: winning team ID
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
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
- 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
+ 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
*/
void PlayerStats_ready(entity fh, entity pass, float status)
}
}
url_fputs(fh, "\n");
- db_close(playerstats_db);
- playerstats_db = -1;
- url_fclose(fh, PlayerStats_ready, world);
+ url_fclose(fh);
break;
case URL_READY_CANREAD:
// url_fclose is processing, we got a response for writing the data
while((s = url_fgets(fh)))
print(" ", s, "\n");
print("End of response.\n");
- url_fclose(fh, PlayerStats_ready, world);
+ url_fclose(fh);
break;
case URL_READY_CLOSED:
// url_fclose has finished
print("Player stats written\n");
playerstats_waitforme = TRUE;
+ db_close(playerstats_db);
+ playerstats_db = -1;
break;
case URL_READY_ERROR:
default:
uri = autocvar_g_playerstats_uri;
if(uri != "")
{
- url_fopen(uri, FILE_APPEND, PlayerStats_ready, world);
playerstats_waitforme = FALSE;
+ url_multi_fopen(uri, FILE_APPEND, PlayerStats_ready, world);
}
else
{
}
//#NO AUTOCVARS END
+void PlayerStats_Accuracy(entity p)
+{
+ entity a, w;
+ a = p.accuracy;
+ float i;
+
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ w = get_weaponinfo(i);
+
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-hit"), a.(accuracy_hit[i-1]));
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-fired"), a.(accuracy_fired[i-1]));
+
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-hit"), a.(accuracy_cnt_hit[i-1]));
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-fired"), a.(accuracy_cnt_fired[i-1]));
+
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-frags"), a.(accuracy_frags[i-1]));
+ }
+}
+
void PlayerStats_AddGlobalInfo(entity p)
{
if(playerstats_db < 0)
if(stof(db_get(playerstats_db, sprintf("%d:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0)
PlayerStats_Event(p, PLAYERSTATS_JOINS, 1);
+ PlayerStats_Accuracy(p);
+
strunzone(p.playerstats_id);
p.playerstats_id = string_null;
}
-void PlayerStats_Accuracy(entity p)
-{
- entity a, w;
- a = p.accuracy;
- float i;
-
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- w = get_weaponinfo(i);
-
- PlayerStats_Event(p, strcat("acc-", w.netname, "-hit"), a.(accuracy_hit[i-1]));
- PlayerStats_Event(p, strcat("acc-", w.netname, "-fired"), a.(accuracy_fired[i-1]));
-
- PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-hit"), a.(accuracy_cnt_hit[i-1]));
- PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-fired"), a.(accuracy_cnt_fired[i-1]));
-
- PlayerStats_Event(p, strcat("acc-", w.netname, "-frags"), a.(accuracy_frags[i-1]));
- }
-}
-
void PlayerStats_EndMatch(float finished)
{
entity p, winner;
- winner = PlayerScore_Sort(score_dummyfield);
- FOR_EACH_PLAYER(p) // spectators intentionally not included
+ winner = PlayerScore_Sort(score_dummyfield);
+ FOR_EACH_CLIENT(p) // spectators intentionally not included
{
- PlayerScore_PlayerStats(p);
PlayerStats_Accuracy(p);
+ if(g_arena || g_lms || g_ca)
+ {
+ if(p.alivetime <= 0)
+ continue;
+ }
+ else
+ {
+ if(p.classname != "player")
+ continue;
+ }
+ PlayerScore_PlayerStats(p);
PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_VALID, 1);
if(finished)
{
// call at game over
void PlayerStats_Shutdown(); // send stats to the server
-// URI GET callback
-void PlayerStats_Sent_URI_Get_Callback(float id, float status, string data);
-
// call this whenever a player leaves
void PlayerStats_AddGlobalInfo(entity p);
playerdemo.qh
+// singleplayer stuff
+item_key.qh
secret.qh
scores_rules.qc
sv_main.qc
g_triggers.qc
-secret.qc
g_models.qc
+// singleplayer stuff
+item_key.qc
+secret.qc
+
cl_weaponsystem.qc
w_common.qc
../common/items.qc
-monsters/defs.qc
-monsters/fight.qc
-monsters/ai.qc
-monsters/m_monsters.qc
-monsters/monster_zombie.qc
+
accuracy.qc
csqcprojectile.qc
mutators/gamemode_keyhunt.qc
mutators/gamemode_freezetag.qc
mutators/gamemode_keepaway.qc
+mutators/mutator_invincibleproj.qc
mutators/mutator_nix.qc
mutators/mutator_dodging.qc
mutators/mutator_rocketflying.qc
-
void CreatureFrame (void)
{
- local entity oldself;
- local float dm;
+ entity oldself;
+ float dm;
+
oldself = self;
- for(self = world; (self = findfloat(self, iscreature, TRUE)); )
+ for(self = world; (self = findfloat(self, damagedbycontents, TRUE)); )
{
- if (self.movetype == MOVETYPE_NOCLIP)
- continue;
+ if (self.movetype == MOVETYPE_NOCLIP) { continue; }
+
float vehic = (self.vehicle_flags & VHF_ISVEHICLE);
- if (self.waterlevel)
+ float projectile = (self.flags & FL_PROJECTILE);
+
+ if (self.watertype <= CONTENT_WATER && self.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
{
if (!(self.flags & FL_INWATER))
{
self.flags |= FL_INWATER;
self.dmgtime = 0;
}
- if(!vehic) // vehicles don't drown
+
+ if(!vehic && !projectile) // vehicles and projectiles don't drown
{
if (self.waterlevel != WATERLEVEL_SUBMERGED)
{
- if(self.air_finished < time + 9)
+ if(self.air_finished < time)
PlayerSound(playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- self.air_finished = time + 12;
+ self.air_finished = time + autocvar_g_balance_contents_drowndelay;
self.dmg = 2;
}
else if (self.air_finished < time)
if (!self.deadflag)
if (self.pain_finished < time)
{
- Damage (self, world, world, 5, DEATH_DROWN, self.origin, '0 0 0');
+ Damage (self, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN, self.origin, '0 0 0');
self.pain_finished = time + 0.5;
}
}
}
+
if (self.dmgtime < time)
{
- self.dmgtime = time + 0.2;
- if (self.watertype == CONTENT_LAVA)
+ self.dmgtime = time + autocvar_g_balance_contents_damagerate;
+
+ if (!projectile)
{
- if (self.watersound_finished < time)
+ if (self.watertype == CONTENT_LAVA)
{
- self.watersound_finished = time + 0.5;
- sound (self, CH_PLAYER, "player/lava.wav", VOL_BASE, ATTN_NORM);
+ if (self.watersound_finished < time)
+ {
+ self.watersound_finished = time + 0.5;
+ sound (self, CH_PLAYER, "player/lava.wav", VOL_BASE, ATTN_NORM);
+ }
+ Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
}
- Damage (self, world, world, 6 * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
- }
- else if (self.watertype == CONTENT_SLIME)
- {
- if (self.watersound_finished < time)
+ else if (self.watertype == CONTENT_SLIME)
{
- self.watersound_finished = time + 0.5;
- sound (self, CH_PLAYER, "player/slime.wav", VOL_BASE, ATTN_NORM);
+ if (self.watersound_finished < time)
+ {
+ self.watersound_finished = time + 0.5;
+ sound (self, CH_PLAYER, "player/slime.wav", VOL_BASE, ATTN_NORM);
+ }
+ Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
}
- Damage (self, world, world, 2 * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
+ }
+ else if ((self.watertype == CONTENT_LAVA) || (self.watertype == CONTENT_SLIME))
+ {
+ Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
}
}
}
self.dmg = 2;
}
- if(!vehic) // vehicles don't get falling damage
+ if(!vehic && !projectile) // vehicles don't get falling damage
{
// check for falling damage
float velocity_len = vlen(self.velocity);
s = substring(s, 1, -1);
}
- n = tokenize(s);
+ n = tokenize_console(s);
for(i = 0; i < n; ++i)
{
s = argv(i);
.float rendermode;
.vector rendercolor;
-void spawnfunc_weapon_crossbow() {};
-void spawnfunc_weapon_handgrenade() {};
-void spawnfunc_ammo_crossbow() {};
-void spawnfunc_ammo_9mmclip() {};
-void spawnfunc_ammo_gaussclip() {};
-void spawnfunc_weapon_rpg() {};
-void spawnfunc_weapon_357() {};
-void ammo_ARgrenades() {};
-void spawnfunc_item_battery() {};
-void spawnfunc_ammo_rpgclip() {};
-void weapon_9mmAR() {};
-void spawnfunc_weapon_tripmine() {};
-void spawnfunc_weapon_snark() {};
-void spawnfunc_ammo_buckshot() {};
-void ammo_9mmAR() {};
-void spawnfunc_ammo_357() {};
-void spawnfunc_weapon_gauss() {};
-void spawnfunc_weapon_hornetgun() {};
-//void spawnfunc_weapon_shotgun() {};
-void spawnfunc_item_healthkit() {};
-void spawnfunc_item_longjump() {};
-void spawnfunc_item_antidote() {};
-void spawnfunc_func_recharge() {};
-void spawnfunc_info_node() {};
-void spawnfunc_env_sound() {};
-void spawnfunc_light_spot() {};
-void spawnfunc_func_healthcharger() {};
+void spawnfunc_weapon_crossbow() {}
+void spawnfunc_weapon_handgrenade() {}
+void spawnfunc_ammo_crossbow() {}
+void spawnfunc_ammo_9mmclip() {}
+void spawnfunc_ammo_gaussclip() {}
+void spawnfunc_weapon_rpg() {}
+void spawnfunc_weapon_357() {}
+void ammo_ARgrenades() {}
+void spawnfunc_item_battery() {}
+void spawnfunc_ammo_rpgclip() {}
+void weapon_9mmAR() {}
+void spawnfunc_weapon_tripmine() {}
+void spawnfunc_weapon_snark() {}
+void spawnfunc_ammo_buckshot() {}
+void ammo_9mmAR() {}
+void spawnfunc_ammo_357() {}
+void spawnfunc_weapon_gauss() {}
+void spawnfunc_weapon_hornetgun() {}
+//void spawnfunc_weapon_shotgun() {}
+void spawnfunc_item_healthkit() {}
+void spawnfunc_item_longjump() {}
+void spawnfunc_item_antidote() {}
+void spawnfunc_func_recharge() {}
+void spawnfunc_info_node() {}
+void spawnfunc_env_sound() {}
+void spawnfunc_light_spot() {}
+void spawnfunc_func_healthcharger() {}
void func_ladder_touch()
other.ladder_time = time + 0.1;
other.ladder_entity = self;
-};
+}
void spawnfunc_func_ladder()
{
EXACTTRIGGER_INIT;
self.touch = func_ladder_touch;
-};
+}
void spawnfunc_func_water()
{
EXACTTRIGGER_INIT;
self.touch = func_ladder_touch;
-};
+}
// pickup evaluation functions
// these functions decide how desirable an item is to the bots
-float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;};
+float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;}
float weapon_pickupevalfunc(entity player, entity item)
{
}
return item.bot_pickupbasevalue * c;
-};
+}
float commodity_pickupevalfunc(entity player, entity item)
{
c = c + max(0, 1 - player.health / item.max_health);
return item.bot_pickupbasevalue * c;
-};
+}
.float is_item;
*/
void minstagib_items (float itemid)
{
- local float rnd;
+ float rnd;
self.classname = "minstagib";
// replace rocket launchers and nex guns with ammo cells
vector trigger_push_calculatevelocity(vector org, entity tgt, float ht)
{
- local float grav, sdist, zdist, vs, vz, jumpheight;
- local vector sdir, torg;
+ float grav, sdist, zdist, vs, vz, jumpheight;
+ vector sdir, torg;
torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
void trigger_push_touch()
{
- vector move;
-
if (self.active == ACTIVE_NOT)
return;
sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
self.pushltime = time + 0.2;
}
- local float ct;
+ float ct;
ct = clienttype(other);
if( ct == CLIENTTYPE_REAL || ct == CLIENTTYPE_BOT)
{
- local float i;
- local float found;
+ float i;
+ float found;
found = FALSE;
for(i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i)
if(other.(jumppadsused[i]) == self)
}
else
other.lastteleporttime = time;
+
+ if (!other.animstate_override)
+ {
+ if (other.crouch)
+ setanim(other, other.anim_duckjump, FALSE, TRUE, TRUE);
+ else
+ setanim(other, other.anim_jump, FALSE, TRUE, TRUE);
+ }
}
else
other.jumppadcount = TRUE;
self.think = SUB_Remove;
self.nextthink = time;
}
-};
+}
.vector dest;
void trigger_push_findtarget()
{
- local entity e, t;
- local vector org;
- local float flighttime;
+ entity e, t;
+ vector org;
// first calculate a typical start point for the jump
org = (self.absmin + self.absmax) * 0.5;
waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
remove(e);
}
-};
+}
/*
* ENTITY PARAMETERS:
// this must be called to spawn the teleport waypoints for bots
InitializeEntity(self, trigger_push_findtarget, INITPRIO_FINDTARGET);
-};
+}
-void spawnfunc_target_push() {};
-void spawnfunc_info_notnull() {};
-void spawnfunc_target_position() {};
+void spawnfunc_target_push() {}
+void spawnfunc_info_notnull() {}
+void spawnfunc_target_position() {}
void plat_spawn_inside_trigger()
{
- local entity trigger;
- local vector tmin, tmax;
+ entity trigger;
+ vector tmin, tmax;
trigger = spawn();
trigger.touch = plat_center_touch;
}
setsize (trigger, tmin, tmax);
-};
+}
void plat_hit_top()
{
self.state = 1;
self.think = plat_go_down;
self.nextthink = self.ltime + 3;
-};
+}
void plat_hit_bottom()
{
sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
self.state = 2;
-};
+}
void plat_go_down()
{
sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM);
self.state = 3;
SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
-};
+}
void plat_go_up()
{
sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM);
self.state = 4;
SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
-};
+}
void plat_center_touch()
{
plat_go_up ();
else if (self.state == 1)
self.nextthink = self.ltime + 1; // delay going down
-};
+}
void plat_outside_touch()
{
self = self.enemy;
if (self.state == 1)
plat_go_down ();
-};
+}
void plat_trigger_use()
{
if (self.think)
return; // already activated
plat_go_down();
-};
+}
void plat_crush()
// plat state already had changed
// this isn't a bug per se!
}
-};
+}
void plat_use()
{
if (self.state != 4)
objerror ("plat_use: not in up state");
plat_go_down();
-};
+}
.string sound1, sound2;
}
}
-void spawnfunc_path_corner() { };
+void spawnfunc_path_corner() { }
void spawnfunc_func_plat()
{
if (!self.t_length)
self.reset = plat_reset;
plat_reset();
-};
+}
void() train_next;
SUB_UseTargets();
self = oldself;
self.enemy = world;
-};
+}
void train_next()
{
- local entity targ;
+ entity targ;
targ = find(world, targetname, self.target);
self.enemy = targ;
self.target = targ.target;
if(self.noise != "")
sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
-};
+}
void func_train_find()
{
- local entity targ;
+ entity targ;
targ = find(world, targetname, self.target);
self.target = targ.target;
if (!self.target)
setorigin(self, targ.origin - self.mins);
self.nextthink = self.ltime + 1;
self.think = train_next;
-};
+}
/*QUAKED spawnfunc_func_train (0 .5 .8) ?
Ridable platform, targets spawnfunc_path_corner path to follow.
self.dmgtime2 = time;
// TODO make a reset function for this one
-};
+}
void func_rotating_setactive(float astate)
{
self.think = SUB_Null;
// TODO make a reset function for this one
-};
+}
.float height;
void func_bobbing_controller_think()
{
- local vector v;
+ vector v;
self.nextthink = time + 0.1;
if not (self.owner.active == ACTIVE_ACTIVE)
if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed
// * 10 so it will arrive in 0.1 sec
self.owner.velocity = (v - self.owner.origin) * 10;
-};
+}
/*QUAKED spawnfunc_func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS
Brush model that moves back and forth on one axis (default Z).
*/
void spawnfunc_func_bobbing()
{
- local entity controller;
+ entity controller;
if (self.noise != "")
{
precache_sound(self.noise);
self.effects |= EF_LOWPRECISION;
// TODO make a reset function for this one
-};
+}
.float freq;
void func_pendulum_controller_think()
{
- local float v;
+ float v;
self.nextthink = time + 0.1;
if not (self.owner.active == ACTIVE_ACTIVE)
// * 10 so it will arrive in 0.1 sec
self.owner.avelocity_z = (remainder(v - self.owner.angles_z, 360)) * 10;
}
-};
+}
void spawnfunc_func_pendulum()
{
- local entity controller;
+ entity controller;
if (self.noise != "")
{
precache_sound(self.noise);
//self.effects |= EF_LOWPRECISION;
// TODO make a reset function for this one
-};
+}
// button and multiple button
activator = self.enemy;
SUB_UseTargets();
self.frame = 1; // use alternate textures
-};
+}
void button_done()
{
self.state = STATE_BOTTOM;
-};
+}
void button_return()
{
self.frame = 0; // use normal textures
if (self.health)
self.takedamage = DAMAGE_YES; // can be shot again
-};
+}
void button_blocked()
{
// do nothing, just don't come all the way back out
-};
+}
void button_fire()
self.state = STATE_UP;
SUB_CalcMove (self.pos2, self.speed, button_wait);
-};
+}
void button_reset()
{
self.enemy = activator;
button_fire ();
-};
+}
void button_touch()
{
if (other.owner)
self.enemy = other.owner;
button_fire ();
-};
+}
void button_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
self.enemy = damage_attacker;
button_fire ();
}
-};
+}
/*QUAKED spawnfunc_func_button (0 .5 .8) ?
self.flags |= FL_NOTARGET;
button_reset();
-};
+}
float DOOR_START_OPEN = 1;
door_go_down ();
}
*/
-};
+}
void door_hit_top()
self.think = door_rotating_go_down;
}
self.nextthink = self.ltime + self.wait;
-};
+}
void door_hit_bottom()
{
if (self.noise1 != "")
sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
self.state = STATE_BOTTOM;
-};
+}
void door_go_down()
{
self.state = STATE_DOWN;
SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
-};
+}
void door_go_up()
{
self.message = "";
SUB_UseTargets();
self.message = oldmessage;
-};
+}
+
/*
=============================================================================
*/
+float door_check_keys(void) {
+ local entity door;
+
+
+ if (self.owner)
+ door = self.owner;
+ else
+ door = self;
+
+ // no key needed
+ if not(door.itemkeys)
+ return TRUE;
+
+ // this door require a key
+ // only a player can have a key
+ if (other.classname != "player")
+ return FALSE;
+
+ if (item_keys_usekey(door, other)) {
+ // some keys were used
+ if (other.key_door_messagetime <= time) {
+ play2(other, "misc/talk.wav");
+ centerprint(other, strcat("You also need ", item_keys_keylist(door.itemkeys), "!"));
+ other.key_door_messagetime = time + 2;
+ }
+ } else {
+ // no keys were used
+ if (other.key_door_messagetime <= time) {
+ play2(other, "misc/talk.wav");
+ centerprint(other, strcat("You need ", item_keys_keylist(door.itemkeys), "!"));
+ other.key_door_messagetime = time + 2;
+ }
+ }
+
+ if (door.itemkeys) {
+ // door is now unlocked
+ play2(other, "misc/talk.wav");
+ centerprint(other, "Door unlocked!");
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
void door_fire()
{
- local entity oself;
- local entity starte;
+ entity oself;
+ entity starte;
if (self.owner != self)
objerror ("door_fire: self.owner != self");
self = self.enemy;
} while ( (self != starte) && (self != world) );
self = oself;
-};
+}
void door_use()
{
- local entity oself;
+ entity oself;
//dprint("door_use (model: ");dprint(self.model);dprint(")\n");
+
if (self.owner)
{
oself = self;
door_fire ();
self = oself;
}
-};
+}
void door_trigger_touch()
{
if (other.health < 1)
- if not(other.iscreature && other.deadflag == DEAD_NO)
- return;
+ if not(other.iscreature && other.deadflag == DEAD_NO)
+ return;
if (time < self.attack_finished_single)
return;
+
+ // check if door is locked
+ if (!door_check_keys())
+ return;
+
self.attack_finished_single = time + 1;
activator = other;
self = self.owner;
door_use ();
-};
+}
void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- local entity oself;
+ entity oself;
if(self.spawnflags & DOOR_NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
self.health = self.health - damage;
+
+ if (self.itemkeys) {
+ // don't allow opening doors through damage if keys are required
+ return;
+ }
+
if (self.health <= 0)
{
oself = self;
door_use ();
self = oself;
}
-};
+}
/*
centerprint (other, self.owner.message);
play2(other, "misc/talk.wav");
}
-};
+}
void door_generic_plat_blocked()
door_rotating_go_down ();
}
*/
-};
+}
void door_rotating_hit_top()
return; // don't come down automatically
self.think = door_rotating_go_down;
self.nextthink = self.ltime + self.wait;
-};
+}
void door_rotating_hit_bottom()
{
self.lip = 0;
}
self.state = STATE_BOTTOM;
-};
+}
void door_rotating_go_down()
{
self.state = STATE_DOWN;
SUB_CalcAngleMove (self.pos1, self.speed, door_rotating_hit_bottom);
-};
+}
void door_rotating_go_up()
{
self.message = "";
SUB_UseTargets();
self.message = oldmessage;
-};
+}
entity spawn_field(vector fmins, vector fmaxs)
{
- local entity trigger;
- local vector t1, t2;
+ entity trigger;
+ vector t1, t2;
trigger = spawn();
trigger.classname = "doortriggerfield";
t2 = fmaxs;
setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
return (trigger);
-};
+}
float EntitiesTouching(entity e1, entity e2)
if (e1.absmax_z < e2.absmin_z)
return FALSE;
return TRUE;
-};
+}
/*
*/
void LinkDoors()
{
- local entity t, starte;
- local vector cmins, cmaxs;
+ entity t, starte;
+ vector cmins, cmaxs;
if (self.enemy)
return; // already linked by another door
}
} while (1 );
-};
+}
-/*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK x x TOGGLE
+/*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE
if two doors touch, they are assumed to be connected and operate as a unit.
TOGGLE causes the door to wait in both the start and end states for a trigger event.
START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
+GOLD_KEY causes the door to open only if the activator holds a gold key.
+
+SILVER_KEY causes the door to open only if the activator holds a silver key.
+
"message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
"angle" determines the opening direction
"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
self.think = SUB_Null;
}
+// spawnflags require key (for now only func_door)
+#define SPAWNFLAGS_GOLD_KEY 8
+#define SPAWNFLAGS_SILVER_KEY 16
void spawnfunc_func_door()
{
+ // Quake 1 keys compatibility
+ if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
+ self.itemkeys |= ITEM_KEY_BIT(0);
+ if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
+ self.itemkeys |= ITEM_KEY_BIT(1);
+
//if (!self.deathtype) // map makers can override this
// self.deathtype = " got in the way";
SetMovedir ();
self.blocked = door_blocked;
self.use = door_use;
- if(self.spawnflags & 8)
- self.dmg = 10000;
+ // FIXME: undocumented flag 8, originally (Q1) GOLD_KEY
+ // if(self.spawnflags & 8)
+ // self.dmg = 10000;
if(self.dmg && (!self.message))
self.message = "was squished";
InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
self.reset = door_reset;
-};
+}
/*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS
if two doors touch, they are assumed to be connected and operate as a unit.
InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
self.reset = door_rotating_reset;
-};
+}
/*
=============================================================================
void fd_secret_use()
{
- local float temp;
+ float temp;
string message_save;
self.health = 10000;
SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
if (self.noise2 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
-};
+}
// Wait after first movement...
void fd_secret_move1()
self.think = fd_secret_move2;
if (self.noise3 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
-};
+}
// Start moving sideways w/sound...
void fd_secret_move2()
if (self.noise2 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
-};
+}
// Wait here until time to go back...
void fd_secret_move3()
self.nextthink = self.ltime + self.wait;
self.think = fd_secret_move4;
}
-};
+}
// Move backward...
void fd_secret_move4()
if (self.noise2 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);
-};
+}
// Wait 1 second...
void fd_secret_move5()
self.think = fd_secret_move6;
if (self.noise3 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
-};
+}
void fd_secret_move6()
{
if (self.noise2 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
-};
+}
void fd_secret_done()
{
}
if (self.noise3 != "")
sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
-};
+}
void secret_blocked()
{
return;
self.attack_finished_single = time + 0.5;
//T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
-};
+}
/*
==============
centerprint (other, self.message);
play2(other, "misc/talk.wav");
}
-};
+}
void secret_reset()
{
self.reset = secret_reset;
secret_reset();
-};
+}
/*QUAKED spawnfunc_func_fourier (0 .5 .8) ?
Brush model that moves in a pattern of added up sine waves, can be used e.g. for circular motions.
void func_fourier_controller_think()
{
- local vector v;
+ vector v;
float n, i, t;
self.nextthink = time + 0.1;
if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed
// * 10 so it will arrive in 0.1 sec
self.owner.velocity = (v - self.owner.origin) * 10;
-};
+}
void spawnfunc_func_fourier()
{
- local entity controller;
+ entity controller;
if (self.noise != "")
{
precache_sound(self.noise);
self.effects |= EF_LOWPRECISION;
// TODO make a reset function for this one
-};
+}
// reusing some fields havocbots declared
.entity wp00, wp01, wp02, wp03;
self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0);
- local entity controller;
+ entity controller;
controller = spawn();
controller.classname = "func_vectormamamam_controller";
controller.owner = self;
if(self.gametype)
{
string gametypename;
- // static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "teamtournament"};
+ // static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "teamtournament"}
gametypename = "ffa";
if(teamplay)
gametypename = "team";
self.swamp_interval = 1;
if(self.swamp_slowdown <= 0)
self.swamp_slowdown = 0.5;
-};
+}
}
}
-void Simple_TeleportPlayer(entity teleporter, entity player)
+entity Simple_TeleportPlayer(entity teleporter, entity player)
{
vector locout;
entity e;
float p;
// Find the output teleporter
- if(!teleporter.enemy)
+ if(teleporter.enemy)
+ {
+ e = teleporter.enemy;
+ }
+ else
{
RandomSelection_Init();
for(e = world; (e = find(e, targetname, teleporter.target)); )
}
RandomSelection_Add(e, 0, string_null, (e.cnt ? e.cnt : 1), p);
}
- teleporter.enemy = RandomSelection_chosen_ent;
+ e = RandomSelection_chosen_ent;
}
- if(!teleporter.enemy) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
+ if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
- makevectors(teleporter.enemy.mangle);
+ makevectors(e.mangle);
- if(teleporter.enemy.speed)
- if(vlen(player.velocity) > teleporter.enemy.speed)
- player.velocity = normalize(player.velocity) * max(0, teleporter.enemy.speed);
+ if(e.speed)
+ if(vlen(player.velocity) > e.speed)
+ player.velocity = normalize(player.velocity) * max(0, e.speed);
if(autocvar_g_teleport_maxspeed)
if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
- locout = teleporter.enemy.origin + '0 0 1' * (1 - player.mins_z - 24);
- TeleportPlayer(teleporter, player, locout, teleporter.enemy.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+ locout = e.origin + '0 0 1' * (1 - player.mins_z - 24);
+ TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+
+ return e;
}
void Teleport_Touch (void)
return;
if not(other.iscreature)
- if (other.deadflag != DEAD_NO)
return;
// for gameplay: vehicles can't teleport
if(other.classname == "player")
RemoveGrapplingHook(other);
- Simple_TeleportPlayer(self, other);
+ entity e;
+ e = Simple_TeleportPlayer(self, other);
activator = other;
s = self.target; self.target = string_null;
if not(self.target) self.target = s;
oldself = self;
- self = self.enemy;
+ self = e;
SUB_UseTargets();
self = oldself;
}
{
UpdateCSQCProjectileAfterTeleport(pl);
// "disown" projectiles after teleport
+ if(pl.owner)
if(pl.owner == pl.realowner)
+ {
+ if(!(pl.flags & FL_PROJECTILE))
+ print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
pl.owner = world;
+ }
if(pl.classname == "player")
{
// reset tracking of oldvelocity for impact damage (sudden velocity changes)
void spawnfunc_trigger_relay_if()
{
self.use = trigger_relay_if_use;
-};
+}
}
string GetClientVersionMessage() {
- local string versionmsg;
+ string versionmsg;
if (self.version_mismatch) {
if(self.version < autocvar_gameversion) {
versionmsg = "^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8";
modifications = strcat(modifications, ", Jet pack");
modifications = substring(modifications, 2, strlen(modifications) - 2);
- local string versionmessage;
+ string versionmessage;
versionmessage = GetClientVersionMessage();
s = strcat("This is Xonotic ", autocvar_g_xonoticversion, "\n", versionmessage);
// code from here on is just to support maps that don't have team entities
void tdm_spawnteam (string teamname, float teamcolor)
{
- local entity e;
+ entity e;
e = spawn();
e.classname = "tdm_team";
e.netname = teamname;
e.cnt = teamcolor;
e.team = e.cnt + 1;
-};
+}
// spawn some default teams if the map is not set up for tdm
void tdm_spawnteams()
tdm_spawnteam("Yellow", COLOR_TEAM3-1);
if(numteams >= 4)
tdm_spawnteam("Pink", COLOR_TEAM4-1);
-};
+}
void tdm_delayedinit()
{
// if no teams are found, spawn defaults
if (find(world, classname, "tdm_team") == world)
tdm_spawnteams();
-};
+}
void tdm_init()
{
InitializeEntity(world, tdm_delayedinit, INITPRIO_GAMETYPE);
-};
+}
.float aim_flags;
/// Dont aim.
#define TFL_AIM_NO 1
-/// Go for ground, not direct hit
-//#define TFL_AIM_GROUND 2
/// Go for ground, not direct hit, but only if target is on ground.
-#define TFL_AIM_GROUND2 4
-/// Use balistic aim. FIXME: not implemented
-#define TFL_AIM_BALISTIC 8
+#define TFL_AIM_GROUNDGROUND 2
/// Try to predict target movement (does not account for gravity)
-#define TFL_AIM_LEAD 16
+#define TFL_AIM_LEAD 4
/// Compensate for shot traveltime when lead
-#define TFL_AIM_SHOTTIMECOMPENSATE 32
-/// Aim slightly in front of target
-#define TFL_AIM_INFRONT 64
-/// Aim slightly behind target
-#define TFL_AIM_BEHIND 128
-/// blend real and predicted z positions. (fake bounce prediction)
-// #define TFL_AIM_ZEASE 256
+#define TFL_AIM_SHOTTIMECOMPENSATE 8
/// Try to do real prediction of targets z pos at impact.
-#define TFL_AIM_ZPREDICT 512
+#define TFL_AIM_ZPREDICT 16
/// Simply aim at target's current location
-#define TFL_AIM_SIMPLE 1024
+#define TFL_AIM_SIMPLE 32
/// track (turn and pitch head) flags
.float track_flags;
#define TFL_TRACKTYPE_STEPMOTOR 1
/// Smoth absolute movement. Looks ok, fair accuracy.
#define TFL_TRACKTYPE_FLUIDPRECISE 2
-/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the feilds below are set
+/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the fields below are set
#define TFL_TRACKTYPE_FLUIDINERTIA 3
/// TFL_TRACKTYPE_FLUIDINERTIA: pitch multiplier
.float track_accel_pitch;
/// How prefire check is preformed
.float firecheck_flags;
-/// Dont kill the world
-#define TFL_FIRECHECK_WORLD 2
/// Dont kill the dead
#define TFL_FIRECHECK_DEAD 4
/// Range limits apply
/// Check own .attack_finished_single vs time
#define TFL_FIRECHECK_REFIRE 4096
/// Move the acctual target to aimspot before tracing impact (and back after)
-#define TFL_FIRECHECK_VERIFIED 8192
+//#define TFL_FIRECHECK_VERIFIED 8192
/// Dont do any chekcs
#define TFL_FIRECHECK_NO 16384
#define TFL_TURRCAPS_ISTURRET 65536
/// Ammo types needed and/or provided
-.float ammo_flags;
+//.float ammo_flags;
+#define ammo_flags currentammo
/// Has and needs no ammo
#define TFL_AMMO_NONE 64
/// Uses power
#define TFL_DMG_HEADSHAKE 128
/// Die and stay dead.
#define TFL_DMG_DEATH_NORESPAWN 256
-/// Supress std turret gibs on death
-#define TFL_DMG_DEATH_NOGIBS 512
// Spawnflags
/// Spawn in teambased modes
/// Defend this entity (or ratehr this entitys position)
.entity tur_defend;
-/// on/off toggle.
-.float tur_active;
-
/// and shoot from here. (can be non constant, think MLRS)
.vector tur_shotorg;
supports:
TFL_AIM_NO
-TFL_AIM_GROUND2
+TFL_AIM_GROUNDGROUND
TFL_AIM_LEAD
TFL_AIM_SHOTTIMECOMPENSATE
-TFL_AIM_INFRONT
-TFL_AIM_BEHIND
-
-not supported:
-TFL_AIM_BALISTIC
-
-removed
-TFL_AIM_ZEASE
-TFL_AIM_GROUND
*/
vector turret_stdproc_aim_generic()
{
// Baseline
pre_pos = real_origin(self.enemy);
- if (self.aim_flags & TFL_AIM_INFRONT) // Aim a bit in front of the target
- pre_pos = pre_pos + (normalize(self.enemy.velocity) * 64);
-
- if (self.aim_flags & TFL_AIM_BEHIND) // Aim a bit behind the target
- pre_pos = pre_pos - (normalize(self.enemy.velocity) * 32);
-
// Lead?
if (self.aim_flags & TFL_AIM_LEAD)
{
pre_pos = pre_pos + self.enemy.velocity * mintime;
}
- if(self.aim_flags & TFL_AIM_GROUND2)
+ if(self.aim_flags & TFL_AIM_GROUNDGROUND)
{
//tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
traceline(pre_pos + '0 0 32',pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
return;
// Inactive turrets take no damage. (hm..)
- if not (self.tur_active)
+ if not (self.active)
return;
if (teamplay)
self.tur_head.angles_y = self.tur_head.angles_y + (-0.5 + random()) * damage;
self.SendFlags |= TNSF_ANG;
-
}
if (self.turrcaps_flags & TFL_TURRCAPS_MOVE)
ent.turret_respawnhook();
}
+void turret_projectile_explode()
+{
+
+ self.takedamage = DAMAGE_NO;
+ self.event_damage = SUB_Null;
+#ifdef TURRET_DEBUG
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
+void turret_projectile_touch()
+{
+ PROJECTILE_TOUCH;
+ turret_projectile_explode();
+}
+
+void turret_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{
+ self.velocity += vforce;
+ self.health -= damage;
+ //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
+ if(self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, turret_projectile_explode);
+}
+
+entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
+{
+ entity proj;
+
+ sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTN_NORM);
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
+ proj.owner = self;
+ proj.realowner = self;
+ proj.bot_dodge = TRUE;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.think = turret_projectile_explode;
+ proj.touch = turret_projectile_touch;
+ proj.nextthink = time + 9;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ proj.flags = FL_PROJECTILE;
+ proj.enemy = self.enemy;
+ proj.totalfrags = _death;
+ PROJECTILE_MAKETRIGGER(proj);
+ if(_health)
+ {
+ proj.health = _health;
+ proj.takedamage = DAMAGE_YES;
+ proj.event_damage = turret_projectile_damage;
+ }
+ else
+ proj.flags |= FL_NOTARGET;
+
+ CSQCProjectile(proj, _cli_anim, _proj_type, _cull);
+
+ return proj;
+}
+
/**
** updates enemy distances, predicted impact point/time
** and updated aim<->predict impact distance.
self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos);
self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos);
- if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy))
+ /*if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy))
{
oldpos = self.enemy.origin;
- setorigin(self.enemy,self.tur_aimpos);
- tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1',self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
- setorigin(self.enemy,oldpos);
+ setorigin(self.enemy, self.tur_aimpos);
+ tracebox(self.tur_shotorg, '-1 -1 -1', '1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
+ setorigin(self.enemy, oldpos);
if(trace_ent == self.enemy)
self.tur_dist_impact_to_aimpos = 0;
else
self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);
}
- else
- tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
+ else*/
+ tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5);
self.tur_impactent = trace_ent;
if (self.track_flags == TFL_TRACK_NO)
return;
- if not (self.tur_active)
+ if not (self.active)
target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch);
else if (self.enemy == world)
{
float turret_stdproc_firecheck()
{
// This one just dont care =)
- if (self.firecheck_flags & TFL_FIRECHECK_NO) return 1;
+ if (self.firecheck_flags & TFL_FIRECHECK_NO)
+ return 1;
+
+ if (self.enemy == world)
+ return 0;
// Ready?
if (self.firecheck_flags & TFL_FIRECHECK_REFIRE)
if (self.enemy.deadflag != DEAD_NO)
return 0;
- // Plz stop killing the world!
- if (self.firecheck_flags & TFL_FIRECHECK_WORLD)
- if (self.enemy == world)
- return 0;
-
// Own ammo?
if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO)
if (self.ammo < self.shot_dmg)
if (self.ammo < (self.shot_dmg * self.shot_volly))
return 0;
- if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
+ /*if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
if(self.tur_impactent != self.enemy)
- return 0;
+ return 0;*/
return 1;
}
// ONS uses somewhat backwards linking.
if (teamplay)
{
- if not (g_onslaught)
+ if (g_onslaught)
if (self.target)
{
e = find(world, targetname,self.target);
// Inactive turrets needs to run the think loop,
// So they can handle animation and wake up if need be.
- if not (self.tur_active)
+ if not (self.active)
{
turret_stdproc_track();
return;
self.team = activator.team;
if(self.team == 0)
- self.tur_active = 0;
+ self.active = ACTIVE_NOT;
else
- self.tur_active = 1;
+ self.active = ACTIVE_ACTIVE;
}
if not (e)
{
e = spawn();
-
- /*
- setorigin(e,'0 0 0');
- setmodel(e,"models/turrets/plasma.md3");
- vector v;
- v = gettaginfo(e,gettagindex(e,"tag_fire"));
- if(v == '0 0 0')
- {
- //objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway.");
- //crash();
- }
- setmodel(e,"");
- */
-
e.classname = "turret_manager";
e.think = turrets_manager_think;
e.nextthink = time + 2;
}
-
- /*
- if(csqc_shared)
- {
- dprint("WARNING: turret requested csqc_shared but this is not implemented. Expect strange things to happen.\n");
- csqc_shared = 0;
- }
- */
if not (self.spawnflags & TSF_SUSPENDED)
droptofloor_builtin();
* if it hits a glitch in my logic :P so try to set as mutch
* as possible beforehand.
*/
- if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
- self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
- else
- self.ticrate = 0.1; // 10 fps for normal turrets
-
+ if not(self.ticrate)
+ {
+ if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
+ self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
+ else
+ self.ticrate = 0.1; // 10 fps for normal turrets
+ }
+
self.ticrate = bound(sys_frametime, self.ticrate, 60); // keep it sane
// General stuff
self.shot_volly_refire = bound(self.shot_refire, self.shot_volly_refire, 60);
if not (self.firecheck_flags)
- self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES |
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES |
TFL_FIRECHECK_LOS | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCECK |
- TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_WORLD;
+ TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE;
// Range stuff.
if not (self.target_range)
{
self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
if(self.turrcaps_flags & TFL_TURRCAPS_RADIUSDMG)
- self.aim_flags |= TFL_AIM_GROUND2;
+ self.aim_flags |= TFL_AIM_GROUNDGROUND;
}
if not (self.track_type)
self.classname = "turret_main";
- self.tur_active = 1;
+ self.active = ACTIVE_ACTIVE;
// In ONS mode, and linked to a ONS ent. need to call the use to set team.
if (g_onslaught && ee)
}
turret_link();
- turret_stdproc_respawn();
-
- if (!turret_tag_fire_update())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+ turret_stdproc_respawn();
+ turret_tag_fire_update();
return 1;
}
* Update self.tur_shotorg by getting up2date bone info
* NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
*/
-float turret_tag_fire_update()
+#define turret_tag_fire_update() self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));v_forward = normalize(v_forward)
+float turret_tag_fire_update_s()
{
if(!self.tur_head)
{
float bforce, float f_dmg, float f_velfactor, float deathtype)
{
- local vector hitloc, force, endpoint, dir;
- local entity ent;
+ vector hitloc, force, endpoint, dir;
+ entity ent;
dir = normalize(end - start);
force = dir * bforce;
if(_turret.target_range < vlen(_turret.tur_shotorg - real_origin(_target)))
{
- dprint("Wtf?\n");
+ //dprint("Wtf?\n");
score *= 0.001;
}
#define ewheel_amin_bck_slow 3
#define ewheel_amin_bck_fast 4
-void turret_ewheel_projectile_explode()
-{
-#ifdef TURRET_DEBUG
- float d;
-
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_EWHEEL, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_EWHEEL, world);
-#endif
-
- remove (self);
-}
-
-
void ewheel_attack()
{
- entity proj;
float i;
for (i = 0; i < 1; ++i)
{
turret_do_updates(self);
- sound (self, CH_WEAPON_A, "weapons/lasergun_fire.wav", VOL_BASE, ATTN_NORM);
+ turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE);
pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- proj.classname = "ewheel bolt";
- proj.owner = self;
- proj.bot_dodge = FALSE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_ewheel_projectile_explode;
- proj.nextthink = time + 9;
- //proj.solid = SOLID_TRIGGER;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.touch = turret_ewheel_projectile_explode;
- proj.enemy = self.enemy;
- proj.flags = FL_PROJECTILE | FL_NOTARGET;
- PROJECTILE_MAKETRIGGER(proj);
-
- CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE);
-
self.tur_head.frame += 2;
if (self.tur_head.frame > 3)
movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop);
}
- if(self.frame != newframe)
+ turrets_setframe(newframe , FALSE);
+
+ /*if(self.frame != newframe)
{
self.frame = newframe;
self.SendFlags |= TNSF_ANIM;
self.anim_start_time = time;
- }
+ }*/
}
remove(self);
return;
}
-
+
+ self.frame = 1;
self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-
- self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
-
self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
self.movetype = MOVETYPE_WALK;
self.solid = SOLID_SLIDEBOX;
self.takedamage = DAMAGE_AIM;
+ self.idle_aim = '0 0 0';
+ self.pos1 = self.origin;
setsize(self, '-32 -32 0', '32 32 48');
- self.idle_aim = '0 0 0';
-
- self.pos1 = self.origin;
// Our fire routine
self.turret_firefunc = ewheel_attack;
void spawnfunc_turret_flac();
void turret_flac_dinit();
void turret_flac_attack();
-void turret_flac_projectile_explode();
-void turret_flac_attack()
+void turret_flac_projectile_think_explode()
{
- local entity proj;
-
- turret_tag_fire_update();
-
- sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- setsize(proj, '0 0 0', '0 0 0');
- proj.classname = "flac_projectile";
- proj.owner = self;
- proj.bot_dodge = TRUE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.flags = FL_PROJECTILE;
- proj.takedamage = DAMAGE_NO;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.angles = vectoangles(proj.velocity);
- proj.touch = turret_flac_projectile_explode;
- proj.think = turret_flac_projectile_explode;
- proj.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 3) / self.shot_speed);
- proj.enemy = self.enemy;
- proj.cnt = time + 5;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_HAGAR, TRUE);
-
- self.tur_head.frame = self.tur_head.frame + 1;
- if (self.tur_head.frame >= 4) self.tur_head.frame = 0;
-
-}
-
-void turret_flac_projectile_explode()
-{
- if( (self.enemy != world) &&
- (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3) )
- {
- // OMG HAXX!
+ if(self.enemy != world)
+ if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
- }
- self.event_damage = SUB_Null;
-
+
#ifdef TURRET_DEBUG
- float ftmp;
- ftmp = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_FLAC, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + ftmp; //self.owner.shot_dmg;
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_FLAC, world);
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
#endif
-
- remove (self);
+ remove(self);
}
+void turret_flac_attack()
+{
+ entity proj;
+
+ turret_tag_fire_update();
+
+ proj = turret_projectile("weapons/hagar_fire.wav", 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
+ 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);
+
+ self.tur_head.frame = self.tur_head.frame + 1;
+ if (self.tur_head.frame >= 4)
+ self.tur_head.frame = 0;
+
+}
void turret_flac_dinit()
{
- if (self.netname == "") self.netname = "FLAC Cannon";
+ if (self.netname == "")
+ self.netname = "FLAC Cannon";
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_MISSILEKILL;
self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
+
if (turret_stdproc_init("flac_std", "models/turrets/base.md3", "models/turrets/flac.md3", TID_FLAC) == 0)
{
remove(self);
self.damage_flags |= TFL_DMG_HEADSHAKE;
self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
-
-
+
// Our fire routine
self.turret_firefunc = turret_flac_attack;
self.turrcaps_flags = TFL_TURRCAPS_SUPPORT | TFL_TURRCAPS_AMMOSOURCE;
self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMTS;
- self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_WORLD;
+ self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
self.shoot_flags = TFL_SHOOT_HITALLVALID;
self.aim_flags = TFL_AIM_NO;
self.track_flags = TFL_TRACK_NO;
-.float shot_speed_max;
-.float shot_speed_gain;
-
void spawnfunc_turret_hellion();
void turret_hellion_dinit();
void turret_hellion_attack();
-void turret_hellion_missile_explode();
-void turret_hellion_missile_think();
-void turret_hellion_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-
-void turret_hellion_postthink()
-{
- if (autocvar_g_turrets_reloadcvars)
- {
- if (!self.shot_speed_max) self.shot_speed_max = autocvar_g_turrets_unit_hellion_std_shot_speed_max;
- if (!self.shot_speed_gain) self.shot_speed_gain = autocvar_g_turrets_unit_hellion_std_shot_speed_gain;
- }
-
- if (self.tur_head.frame != 0)
- self.tur_head.frame += 1;
-
- if (self.tur_head.frame >= 7)
- self.tur_head.frame = 0;
-}
-
-void turret_hellion_attack()
-{
- entity missile;
-
- if(self.tur_head.frame != 0)
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
- else
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
-
- sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
-
- missile = spawn ();
- setorigin(missile, self.tur_shotorg);
- setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
- missile.classname = "hellion_missile";
- missile.owner = self;
- missile.bot_dodge = TRUE;
- missile.bot_dodgerating = self.shot_dmg;
- missile.takedamage = DAMAGE_YES;
- missile.event_damage = turret_hellion_missile_damage;
- missile.damageforcescale = 2;
- missile.health = 10;
- missile.enemy = self.enemy;
- missile.think = turret_hellion_missile_think;
- missile.nextthink = time;// + 0.2;
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLY;
- missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- missile.angles = vectoangles(missile.velocity);
- missile.touch = turret_hellion_missile_explode;
- missile.flags = FL_PROJECTILE;
- missile.solid = SOLID_BBOX;
- missile.tur_health = time + 9;
- missile.tur_aimpos = randomvec() * 128;
- te_explosion (missile.origin);
- CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
-
- self.tur_head.frame += 1;
-}
-
-void turret_hellion_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-{
- self.health = self.health - damage;
- self.velocity = self.velocity + vforce;
- if (self.health <= 0) turret_hellion_missile_explode();
-}
void turret_hellion_missile_think()
{
olddir = normalize(self.velocity);
if(self.tur_health < time)
- turret_hellion_missile_explode();
+ turret_projectile_explode();
// Enemy dead? just keep on the current heading then.
if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
self.angles = vectoangles(self.velocity);
if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
- turret_hellion_missile_explode();
+ turret_projectile_explode();
// Accelerate
- self.velocity = olddir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max);
+ self.velocity = olddir * min(vlen(self.velocity) * autocvar_g_turrets_unit_hellion_std_shot_speed_gain, autocvar_g_turrets_unit_hellion_std_shot_speed_max);
UpdateCSQCProjectile(self);
// Enemy in range?
if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
- turret_hellion_missile_explode();
+ turret_projectile_explode();
// Predict enemy position
itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
self.angles = vectoangles(self.velocity);
// Accelerate
- self.velocity = newdir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max);
+ self.velocity = newdir * min(vlen(self.velocity) * autocvar_g_turrets_unit_hellion_std_shot_speed_gain, autocvar_g_turrets_unit_hellion_std_shot_speed_max);
if (itime < 0.05)
- self.think = turret_hellion_missile_explode;
+ self.think = turret_projectile_explode;
UpdateCSQCProjectile(self);
}
-
-void turret_hellion_missile_explode()
+void turret_hellion_attack()
{
- float d;
-
- if(self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = turret_hellion_missile_explode;
- self.nextthink = time;
- return;
- }
-
- self.event_damage = SUB_Null;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_HELLION, world);
-
-#ifdef TURRET_DEBUG
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#endif
+ entity missile;
+
+ if(self.tur_head.frame != 0)
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
+ else
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
+
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+ missile.think = turret_hellion_missile_think;
+ missile.nextthink = time;
+ missile.flags = FL_PROJECTILE;
+ missile.tur_health = time + 9;
+ missile.tur_aimpos = randomvec() * 128;
+ self.tur_head.frame += 1;
+}
- // Target dead, get another is still targeting the same.
- if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
- self.owner.enemy = world;
+void turret_hellion_postthink()
+{
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame += 1;
- remove (self);
+ if (self.tur_head.frame >= 7)
+ self.tur_head.frame = 0;
}
void turret_hellion_dinit()
{
if (self.netname == "") self.netname = "Hellion Missile Turret";
- if not (self.shot_speed_max)
- self.shot_speed_max = autocvar_g_turrets_unit_hellion_std_shot_speed_max;
-
- if not (self.shot_speed_gain)
- self.shot_speed_gain = autocvar_g_turrets_unit_hellion_std_shot_speed_gain;
-
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
self.aim_flags = TFL_AIM_SIMPLE;
self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK ;
- self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO;
self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
if (turret_stdproc_init("hellion_std", "models/turrets/base.md3", "models/turrets/hellion.md3", TID_HELLION) == 0)
void spawnfunc_turret_hk();
void turret_hk_dinit();
void turret_hk_attack();
-void turret_hk_missile_explode();
-void turret_hk_missile_think();
-void turret_hk_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
-float turret_hk_addtarget(entity e_target,entity e_sender);
-//void turret_hk_missile_touch();
-
-float hk_maxspeed;
-float hk_minspeed;
-float hk_accel;
-float hk_accel2;
-float hk_decel;
-float turret_hk_addtarget(entity e_target,entity e_sender)
-{
- if (e_target)
- {
- if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
- {
- self.enemy = e_target;
- return 1;
- }
- }
-
- return 0;
-}
float hk_is_valid_target(entity e_target)
{
return 1;
}
-
-void turret_hk_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
- if (attacker.team == self.team)
- damage *= 0.5;
-
- self.velocity += force;
-
- self.health -= damage;
-
- if (self.health <= 0)
- turret_hk_missile_explode();
-}
-
-void turret_hk_attack()
-{
- local entity missile;
- //local entity flash2;
-
- sound (self, CH_WEAPON_A, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
-
- missile = spawn ();
- missile.solid = SOLID_BBOX;
- setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
- setorigin(missile, self.tur_shotorg);
-
- missile.scale = 1;
- missile.classname = "hk_missile";
- missile.owner = self;
- missile.bot_dodge = TRUE;
- missile.bot_dodgerating = self.shot_dmg;
- missile.takedamage = DAMAGE_YES;
- missile.damageforcescale = 4;
- missile.health = 10;
- missile.think = turret_hk_missile_think;
- missile.event_damage = turret_hk_missile_damage;
- missile.nextthink = time + 0.25;
- missile.movetype = MOVETYPE_BOUNCEMISSILE;
- missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
- missile.angles = vectoangles(missile.velocity);
- missile.touch = turret_hk_missile_explode; //turret_hk_missile_touch;
- missile.flags = FL_PROJECTILE;
- missile.enemy = self.enemy;
- missile.team = self.team;
- missile.cnt = time + 30;
- missile.ticrate = max(autocvar_sys_ticrate,0.05);
-
- CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, fly sound
-
- te_explosion (missile.origin);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
-}
-
void turret_hk_missile_think()
{
vector vu, vd, vf, vl, vr, ve; // Vector (direction)
// Close enougth to do decent damage?
if ( edist <= (self.owner.shot_radius * 0.25) )
{
- turret_hk_missile_explode();
+ turret_projectile_explode();
return;
}
ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
// To close to something, Slow down!
- if ( ((ff < 0.7) || (ad > 4)) && (myspeed > hk_minspeed) )
- myspeed = max(myspeed * hk_decel,hk_minspeed);
+ if ( ((ff < 0.7) || (ad > 4)) && (myspeed > autocvar_g_turrets_unit_hk_std_shot_speed) )
+ myspeed = max(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_decel, autocvar_g_turrets_unit_hk_std_shot_speed);
// Failry clear, accelerate.
- if ( (ff > 0.7) && (myspeed < hk_maxspeed) )
- myspeed = min(myspeed * hk_accel,hk_maxspeed);
+ if ( (ff > 0.7) && (myspeed < autocvar_g_turrets_unit_hk_std_shot_speed_max) )
+ myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel, autocvar_g_turrets_unit_hk_std_shot_speed_max);
// Setup trace pitch
pt_seek = 1 - ff;
{
// Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
myspeed = vlen(self.velocity);
- if (myspeed < hk_maxspeed)
- myspeed = min(myspeed * hk_accel2,hk_maxspeed);
+ if (myspeed < autocvar_g_turrets_unit_hk_std_shot_speed_max)
+ myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel2,autocvar_g_turrets_unit_hk_std_shot_speed_max);
wishdir = ve;
}
- if ((myspeed > hk_minspeed) && (self.cnt > time))
- myspeed = min(myspeed * hk_accel2,hk_maxspeed);
+ if ((myspeed > autocvar_g_turrets_unit_hk_std_shot_speed) && (self.cnt > time))
+ myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel2,autocvar_g_turrets_unit_hk_std_shot_speed_max);
// Ranoutagazfish?
if (self.cnt < time)
UpdateCSQCProjectile(self);
}
-void turret_hk_missile_explode()
+void turret_hk_attack()
{
- float d;
-
- if(self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = turret_hk_missile_explode;
- self.nextthink = time;
- return;
- }
-
- if ((other == self.owner)||(other == self.owner.tur_head))
- return;
+ entity missile;
- self.event_damage = SUB_Null;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_HK, world);
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
-#ifdef TURRET_DEBUG
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#endif
+ missile.think = turret_hk_missile_think;
+ missile.nextthink = time + 0.25;
+ missile.movetype = MOVETYPE_BOUNCEMISSILE;
+ missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
+ missile.angles = vectoangles(missile.velocity);
+ missile.cnt = time + 30;
+ missile.ticrate = max(autocvar_sys_ticrate, 0.05);
- // Target dead, get another is still targeting the same.
- if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
- self.owner.enemy = world;
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
- remove (self);
}
void turret_hk_postthink()
{
- if (autocvar_g_turrets_reloadcvars)
- {
- hk_maxspeed = autocvar_g_turrets_unit_hk_std_shot_speed_max;
- hk_minspeed = autocvar_g_turrets_unit_hk_std_shot_speed;
- hk_accel = autocvar_g_turrets_unit_hk_std_shot_speed_accel;
- hk_accel2 = autocvar_g_turrets_unit_hk_std_shot_speed_accel2;
- hk_decel = autocvar_g_turrets_unit_hk_std_shot_speed_decel;
- }
-
if (self.tur_head.frame != 0)
self.tur_head.frame = self.tur_head.frame + 1;
if (self.tur_head.frame > 5)
self.tur_head.frame = 0;
+}
+float turret_hk_addtarget(entity e_target,entity e_sender)
+{
+ if (e_target)
+ {
+ if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
+ {
+ self.enemy = e_target;
+ return 1;
+ }
+ }
+
+ return 0;
}
void turret_hk_dinit()
{
- if (self.netname == "") self.netname = "Hunter-killer turret";
-
- hk_maxspeed = autocvar_g_turrets_unit_hk_std_shot_speed_max;
- hk_minspeed = autocvar_g_turrets_unit_hk_std_shot_speed;
- hk_accel = autocvar_g_turrets_unit_hk_std_shot_speed_accel;
- hk_accel2 = autocvar_g_turrets_unit_hk_std_shot_speed_accel2;
- hk_decel = autocvar_g_turrets_unit_hk_std_shot_speed_decel;
+ if (self.netname == "")
+ self.netname = "Hunter-killer turret";
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_RECIVETARGETS;
-
self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-
self.aim_flags = TFL_AIM_SIMPLE;
-
self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
-
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
self.shoot_flags = TFL_SHOOT_CLEARTARGET;
if (turret_stdproc_init("hk_std", "models/turrets/base.md3", "models/turrets/hk.md3", TID_HK) == 0)
void spawnfunc_turret_mlrs();
void turret_mlrs_dinit();
void turret_mlrs_attack();
-void turret_mlrs_rocket_explode();
-void turret_mlrs_rocket_touch();
void turret_mlrs_postthink()
{
dprint("ammo:",ftos(self.ammo),"\n");
dprint("shot_dmg:",ftos(self.shot_dmg),"\n");
}
-
}
void turret_mlrs_attack()
{
entity missile;
-
- turret_tag_fire_update();
-
- sound (self, CH_WEAPON_A, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
-
- missile = spawn ();
- setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
- setorigin(missile, self.tur_shotorg);
- missile.classname = "mlrs_missile";
- missile.owner = self;
- missile.bot_dodge = TRUE;
- missile.bot_dodgerating = self.shot_dmg;
- missile.takedamage = DAMAGE_NO;
- missile.damageforcescale = 4;
- missile.think = turret_mlrs_rocket_explode;
- missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- missile.angles = vectoangles(missile.velocity);
- missile.touch = turret_mlrs_rocket_touch;
- missile.flags = FL_PROJECTILE;
- missile.solid = SOLID_BBOX;
- missile.enemy = self.enemy;
-
- CSQCProjectile(missile, TRUE, PROJECTILE_ROCKET, FALSE); // no cull, fly sound
-
- te_explosion (missile.origin);
-}
-
-void turret_mlrs_rocket_touch()
-{
- if( (other == self.owner) || (other == self.owner.tur_head) )
- return;
-
- PROJECTILE_TOUCH;
-
- turret_mlrs_rocket_explode();
-}
-
-void turret_mlrs_rocket_explode()
-{
-
- if(self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = turret_mlrs_rocket_explode;
- self.nextthink = time;
- return;
- }
-
-#ifdef TURRET_DEBUG
- float d;
-
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_MLRS, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_MLRS, world);
-#endif
-
- // Target dead, Tell turret.
- if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
- self.owner.enemy = world;
-
- remove (self);
+
+ 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);
+ te_explosion (missile.origin);
}
void turret_mlrs_dinit()
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;// | TFL_AIM_GROUND2;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
if (turret_stdproc_init("mlrs_std", "models/turrets/base.md3", "models/turrets/mlrs.md3", TID_MLRS) == 0)
{
void turret_plasma_dual_init();
void turret_plasma_attack();
-void turret_plasma_projectile_explode();
+
void turret_plasma_postthink()
{
}
void turret_plasma_attack()
-{
- entity proj;
-
- sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
+{
+ turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- setsize(proj, '-1 -1 -1', '1 1 1');
- proj.classname = "plasmabomb";
- proj.owner = self;
- proj.bot_dodge = TRUE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_plasma_projectile_explode;
- proj.nextthink = time + 9;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.touch = turret_plasma_projectile_explode;
- proj.flags = FL_PROJECTILE;
- proj.enemy = self.enemy;
- proj.flags = FL_PROJECTILE | FL_NOTARGET;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
-
if (self.tur_head.frame == 0)
self.tur_head.frame = 1;
}
void turret_plasma_dual_attack()
{
- entity proj;
-
- sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- setsize(proj, '0 0 0', '0 0 0');
- proj.classname = "plasmabomb";
- proj.owner = self;
- proj.bot_dodge = TRUE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_plasma_projectile_explode;
- proj.nextthink = time + 9;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.touch = turret_plasma_projectile_explode;
- proj.flags = FL_PROJECTILE;
- proj.enemy = self.enemy;
- proj.flags = FL_PROJECTILE | FL_NOTARGET;
-
+ turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
self.tur_head.frame += 1;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
-}
-
-void turret_plasma_projectile_explode()
-{
- self.event_damage = SUB_Null;
- //w_deathtypestring = "ate to much plasma";
-#ifdef TURRET_DEBUG
- float d;
-
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_PLASMA, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET_PLASMA, world);
-#endif
-
- remove (self);
}
void turret_plasma_std_init()
self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
// How to aim
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2;
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUNDGROUND;
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
if (turret_stdproc_init("plasma_std", "models/turrets/base.md3", "models/turrets/plasma.md3", TID_PLASMA) == 0)
{
self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
// How to aim at targets
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2 ;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUNDGROUND ;
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
if (turret_stdproc_init("plasma_dual", "models/turrets/base.md3", "models/turrets/plasmad.md3", TID_PLASMA_DUAL) == 0)
float turret_tesla_firecheck()
{
- if not (turret_stdproc_firecheck())
- return 0;
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan;
+
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ do_target_scan = 1;
+
+ // Old target (if any) invalid?
+ if(self.target_validate_time < time)
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ self.target_validate_time = time + 0.5;
+ do_target_scan = 1;
+ }
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
- self.enemy = turret_select_target();
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
+ if not (turret_stdproc_firecheck())
+ return 0;
if(self.enemy)
return 1;
return 0;
-
}
+
void turret_tesla_fire()
{
- entity e,t;
- float d,r,i;
+ entity e, t;
+ float d, r, i;
//w_deathtypestring = "discoverd how a tesla coil works";
void turret_tesla_postthink()
{
- if not (self.tur_active)
+ if not (self.active)
{
self.tur_head.avelocity = '0 0 0';
return;
e = findradius(where,32);
while (e)
{
- if (turret_validate_target(self,e,self.target_validate_flags))
+ if (turret_validate_target(self, e, self.target_validate_flags))
if (e != self && e.owner != self)
- Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg ,DEATH_TURRET_WALKER_MEELE,'0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force);
+ Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg, DEATH_TURRET_WALKER_MEELE, '0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force);
e = e.chain;
}
}
void walker_rocket_explode()
{
- if (self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = walker_rocket_explode;
- self.nextthink = time;
- return;
- }
-
- RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, world,autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALKER_ROCKET, world);
-
+ RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALKER_ROCKET, world);
remove (self);
}
{
self.health = self.health - damage;
self.velocity = self.velocity + vforce;
+
if (self.health <= 0)
- walker_rocket_explode();
+ W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
}
#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, autocvar_g_turrets_unit_walker_std_rocket_speed, autocvar_g_turrets_unit_walker_std_rocket_turnrate); UpdateCSQCProjectile(self)
self.cnt = time + 0.5;
}
- if (edist < 256)
+ if (edist < 128)
self.tur_shotorg = '0 0 0';
if (self.tur_health < time)
}
.float idletime;
-
-
-
void walker_postthink()
{
fixedmakevectors(self.angles);
self.oldorigin = self.origin;
turrets_setframe(self.animflag, FALSE);
-
}
void walker_attack()
entity e;
// Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
- if(self.movetype != MOVETYPE_WALK)
+ if(self.movetype != MOVETYPE_WALK)
return;
setorigin(self, self.pos1);
if (self.target != "")
{
- e = find(world,targetname,self.target);
+ e = find(world, targetname, self.target);
if (!e)
{
dprint("Warning! initital waypoint for Walker does NOT exsist!\n");
dprint("Warning: not a turrret path\n");
else
{
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ #ifdef WALKER_FANCYPATHING
+ self.pathcurrent = WALKER_PATH(self.origin, e.origin);
self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
}
}
}
void walker_diehook()
{
-#ifdef self.pathcurrent
+#ifdef WALKER_FANCYPATHING
if (self.pathcurrent)
pathlib_deletepath(self.pathcurrent.owner);
#endif
-
self.pathcurrent = world;
}
void turret_walker_dinit()
{
-
entity e;
if (self.netname == "") self.netname = "Walker Turret";
remove(self);
return;
}
-
- self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
+ setsize(self, WALKER_MIN, WALKER_MAX);
self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-
self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
self.movetype = MOVETYPE_WALK;
self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
-
-
- setsize(self, WALKER_MIN, WALKER_MAX);
-
+ self.takedamage = DAMAGE_AIM;
setorigin(self, self.origin);
- tracebox(self.origin + '0 0 128', self.mins,self.maxs,self.origin - '0 0 10000', MOVE_NORMAL, self);
+ tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
setorigin(self, trace_endpos + '0 0 4');
self.pos1 = self.origin;
self.pos2 = self.angles;
-
self.idle_aim = '0 0 0';
self.turret_firecheckfunc = walker_firecheck;
self.turret_firefunc = walker_attack;
+++ /dev/null
-#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_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_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;
-
-#define BUMB_MIN '-120 -120 -40'
-#define BUMB_MAX '120 120 40'
-
-.entity gunner1;
-//.entity gunner2;
-.vector lastaim;
-float bumb_gunner_frame()
-{
- entity vehic, gun, gunner;
- float ftmp, ftmp2;
- vector vtmp;
-
- vehic = self.vehicle;
- gun = self.vehicle.gun1;
- gunner = self;
-
- self = vehic;
- vehic.solid = SOLID_NOT;
- crosshair_trace(gunner);
-
- //vtmp = gettaginfo(vehic, gettagindexvehic, "tag_hardpoint01"));
- vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
- vtmp = vectoangles(normalize(trace_endpos - vtmp)); // Find the direction & angle
- vtmp = shortangle_vxy(vtmp - (vehic.angles + gun.angles), vehic.angles + gun.angles); // Find aim offset
-
- // Bind to aimspeed
- ftmp2 = autocvar_g_vehicle_bumblebee_cannon_turnspeed * frametime; ftmp = -ftmp2;
- vtmp_x = bound(ftmp, vtmp_x, ftmp2);
- vtmp_y = bound(ftmp, vtmp_y, ftmp2);
- // Bind to limts
- gun.angles_x = bound(-autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down, vtmp_x + gun.angles_x, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up);
- gun.angles_y = bound(-autocvar_g_vehicle_bumblebee_cannon_turnlimit_in, vtmp_y + gun.angles_y, autocvar_g_vehicle_bumblebee_cannon_turnlimit_out);
-
- if(gunner.BUTTON_ATCK && gun.cnt <= time)
- {
- vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
- v_forward = normalize(v_forward);
- vtmp += v_forward * 50;
-
- fireBullet (vtmp, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
- autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
-
- gun.cnt = time + 0.1;
- }
-
- setorigin(gunner, vehic.origin);
- gunner.velocity = vehic.velocity;
-
- vehic.solid = SOLID_BBOX;
- gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
- self = gunner;
- return 1;
-}
-
-void bumb_gunner_enter()
-{
- if(self.gunner1 != world)
- return;
-
- self.gunner1 = other;
- self.gunner1.vehicle = self;
-
- msg_entity = other;
- WriteByte (MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, self.gun1);
- WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
- if(self.tur_head)
- {
- WriteAngle(MSG_ONE, self.gun1.angles_x + self.angles_x); // tilt
- WriteAngle(MSG_ONE, self.gun1.angles_y + self.angles_y); // yaw
- WriteAngle(MSG_ONE, 0); // roll
- }
- other.PlayerPhysplug = bumb_gunner_frame;
-}
-
-float bumb_pilot_frame()
-{
- entity pilot, gunner, vehic;
- vector newvel;
-
- pilot = self;
- vehic = self.vehicle;
- self = vehic;
-
- if(pilot.BUTTON_USE && vehic.deadflag == DEAD_NO)
- {
- self = vehic;
- vehicles_exit(VHEF_NORMAL);
- self = pilot;
- return 0;
- }
-
- if(vehic.deadflag != DEAD_NO)
- {
- self = pilot;
- pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
- return 1;
- }
-
- 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 = 5;
- else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = -20;
-
- 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;
- setorigin(pilot,vehic.origin + '0 0 32');
-
-
- if(vehic.vehicle_flags & VHF_SHIELDREGEN)
- vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime);
-
- if(vehic.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime);
-
- if(vehic.vehicle_flags & VHF_ENERGYREGEN)
- vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime);
-
- VEHICLE_UPDATE_PLAYER(health, bumblebee);
- VEHICLE_UPDATE_PLAYER(energy, bumblebee);
- if(vehic.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(shield, bumblebee);
-
- pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
- self = pilot;
-
- return 1;
-}
-
-void bumb_think()
-{
- self.velocity = self.velocity * 0.99;
- self.nextthink = time + 0.1;
-}
-
-void bumb_enter()
-{
- self.touch = bumb_gunner_enter;
-}
-
-void bumb_exit(float eject)
-{
- self.owner = world;
- self.touch = vehicles_touch;
-}
-
-void bumb_spawn()
-{
- self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
- self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
- self.movetype = MOVETYPE_TOSS;
- self.solid = SOLID_BBOX;
- //self.vehicle_energy = 1;
- self.movetype = MOVETYPE_FLY;
- setorigin(self, self.origin + '0 0 25');
-}
-
-void bumb_die()
-{
- self.health = 0;
- self.event_damage = SUB_Null;
- self.solid = SOLID_CORPSE;
- self.takedamage = DAMAGE_NO;
- self.deadflag = DEAD_DYING;
- self.movetype = MOVETYPE_BOUNCE;
-
- pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
-}
-
-void bumb_dinit()
-{
- 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))
- {
- remove(self);
- return;
- }
- self.gun1 = spawn();
- setmodel(self.gun1, "models/vehicles/bumblebee_ray.dpm");
- setattachment(self.gun1, self, "tag_hardpoint03");
-
- self.gun1 = spawn();
- self.gun2 = spawn();
-
- self.gun1.owner = self;
- self.gun2.owner = self;
-
- setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
- setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
-
- setattachment(self.gun1, self, "tag_hardpoint01");
- setattachment(self.gun2, self, "tag_hardpoint02");
-
- vector ofs;
- ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint01"));
- ofs -= self.origin;
- setattachment(self.gun1, self, "");
- setorigin(self.gun1, ofs);
-
- ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint02"));
- ofs -= self.origin;
- setattachment(self.gun2, self, "");
- setorigin(self.gun2, ofs);
-
-
-}
-
-void spawnfunc_vehicle_bumblebee()
-{
-
- 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");
-
- //vehicles_configcheck("vehicle_bumblebee.cfg", autocvar_g_vehicle_bumblebee_health);
-
- 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;
-
- self.think = bumb_dinit;
- self.nextthink = time + 1;
-}
-#endif // SVQC
-
-#ifdef CSQC
-void bumblebee_draw()
-{
-
-}
-
-void bumblebee_draw2d()
-{
-
-}
-
-void bumblebee_read_extra()
-{
-
-}
-
-void vehicle_bumblebee_assemble()
-{
-
-}
-#endif //CSQC
+++ /dev/null
-vector collision_force;
-vector collision_angle;
-
-vector bb1[9];
-vector bb2[9];
-
-float collision_run()
-{
- vector vtmp, vmin, vmax, vrot, vforce, vtmp2, vtmp3;
- float i, fvel, bcol;
-
-
- // Extract the 8 bbox corners from mins/maxs for self
- vmax = self.maxs;
- vmin = self.mins;
- bb1[0] = vmax;
- vtmp = vmax; vtmp_x = vmin_x; bb1[1] = vtmp;
- vtmp = vmax; vtmp_y = vmin_y; bb1[2] = vtmp;
- vtmp = vmin; vtmp_z = vmax_z; bb1[3] = vtmp;
- bb1[4] = vmin;
- vtmp = vmin; vtmp_x = vmax_x; bb1[5] = vtmp;
- vtmp = vmin; vtmp_y = vmax_y; bb1[6] = vtmp;
- vtmp = vmax; vtmp_z = vmin_z; bb1[7] = vtmp;
-
- makevectors(self.angles + '-2 0 0' * self.angles_x);
- bcol = 0;
-
- // Pass1: Transform by rotation, ajust points by impact/s
- for(i = 8; i >= 0; --i)
- {
- vtmp = bb1[i];
- vtmp = self.origin + vtmp_x * v_forward - vtmp_y * v_right + vtmp_z * v_up;
- traceline(self.origin, vtmp, MOVE_WORLDONLY, self);
- te_lightning1(world,self.origin,vtmp);
- if(trace_fraction != 1.0)
- {
- vforce += (trace_endpos - vtmp);
- vtmp3 = self.origin + self.velocity * frametime;
- vtmp2 = vectoangles(normalize(vtmp - vtmp3));
- vrot += (vectoangles(normalize(trace_endpos - vtmp3)) - vtmp2);
- bcol += 1;
- }
- }
-
- if(bcol)
- {
-
- vtmp = self.origin + self.velocity * frametime;
- self.angles += vrot * frametime;
- self.velocity += vforce * frametime;
-
- }
-
-}
-
+++ /dev/null
-#ifdef VEHICLES_CSQC
-// SendFlags
-float VSF_SETUP = 1; /// Send vehicle type etc
-float VSF_ORIGIN = 2; /// Send location
-float VSF_MOVEMENT = 4; /// Send movement update (and angles)
-float VSF_AVEL = 8; /// Send Angular velocity
-float VSF_STATS = 16; /// Send ammo, health etc
-float VSF_EXTRA = 32; /// Send additional data (turret rotations etc). Handeld per vehicle type.
-float VSF_ANIMINFO = 64; /// Animation info
-float VSF_FULL_UPDATE = 16777215; /// Send everything
-
-float VSX_FAR = 1;
-float VSX_OWNER = 2;
-float VSX_GUN1 = 4;
-float VSX_GUN2 = 8;
-
-#ifdef SVQC
-#define VSX_FARDISTANCE 2000
-float send_vehile(entity to, float sf)
-{
- float dist, xf;
-
- var void WriteFunc(float, float);
-
- dist = vlen(self.origin - to.origin);
- if(to == self.owner)
- xf |= VSX_OWNER;
- else if(dist > VSX_FARDISTANCE)
- xf |= VSX_FAR;
-
- // Always send a movement and origin to owner
- if(to == self.owner)
- sf |= VSF_ORIGIN | VSF_MOVEMENT;
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_VEHICLE);
-
- // We need to know client-side what was sent
- WriteByte(MSG_ENTITY, sf);
- WriteByte(MSG_ENTITY, xf);
-
- if(sf & VSF_SETUP)
- {
- WriteByte(MSG_ENTITY, self.hud); //vehicle type = hud
- WriteByte(MSG_ENTITY, self.team);
- WriteShort(MSG_ENTITY, self.colormap);
- WriteShort(MSG_ENTITY, self.vehicle_flags);
- }
-
- if(sf & VSF_ORIGIN)
- {
- WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
- WriteFunc(MSG_ENTITY, self.origin_x);
- WriteFunc(MSG_ENTITY, self.origin_y);
- WriteFunc(MSG_ENTITY, self.origin_z);
- }
-
- if(sf & VSF_MOVEMENT)
- {
- WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
- WriteFunc(MSG_ENTITY, self.velocity_x);
- WriteFunc(MSG_ENTITY, self.velocity_y);
- WriteFunc(MSG_ENTITY, self.velocity_z);
-
- WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteAngle);
- WriteFunc(MSG_ENTITY, self.angles_x);
- WriteFunc(MSG_ENTITY, self.angles_y);
- WriteFunc(MSG_ENTITY, self.angles_z);
- }
-
- if(sf & VSF_AVEL)
- {
- WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
- WriteFunc(MSG_ENTITY, self.avelocity_x);
- WriteFunc(MSG_ENTITY, self.avelocity_y);
- WriteFunc(MSG_ENTITY, self.avelocity_z);
- }
-
- if(sf & VSF_STATS)
- {
- WriteByte(MSG_ENTITY, self.vehicle_health);
- if(xf & VSX_OWNER)
- {
- WriteByte(MSG_ENTITY, self.vehicle_shield);
- WriteByte(MSG_ENTITY, self.vehicle_energy);
-
- WriteByte(MSG_ENTITY, self.vehicle_ammo1);
- WriteByte(MSG_ENTITY, self.vehicle_reload1);
-
- WriteByte(MSG_ENTITY, self.vehicle_ammo2);
- WriteByte(MSG_ENTITY, self.vehicle_reload2);
-
- }
- }
-
- if(sf & VSF_EXTRA)
- self.vehile_send_exta(to, sf);
-
- return TRUE;
-}
-
-void net_link_vehile()
-{
- self.SendFlags = 0xFFFFFF;
- Net_LinkEntity(self, FALSE, 0, send_vehile);
-}
-#endif // SVQC
-
-#ifdef CSQC
-void vehicle_spiderbot_assemble()
-{
-
-}
-
-void vehicle_raptor_assemble()
-{
-
-}
-
-void vehicle_bumblebee_assemble()
-{
-
-}
-
-.float lastupdate;
-void read_vehicle(float bIsNew)
-{
- float sf, xf;
- var float ReadFunc();
-
- sf = ReadByte();
- xf = ReadByte();
-
- if(xf & VSX_OWNER)
- vehicle = self;
-
- if(sf & VSF_SETUP)
- {
- self.vehicle_hud = ReadByte();
- self.team = ReadByte();
- self.colormap = ReadShort();
- self.vehicle_flags = ReadShort();
-
- switch(self.vehicle_hud)
- {
- case HUD_WAKIZASHI:
- vehicle_racer_assemble();
- break;
- case HUD_SPIDERBOT:
- vehicle_spiderbot_assemble();
- break;
- case HUD_RAPTOR:
- vehicle_raptor_assemble();
- break;
- case HUD_BUMBLEBEE:
- vehicle_bumblebee_assemble();
- break;
- default:
- break;
- }
- }
-
- if(self.vehicle_hud == HUD_WAKIZASHI && xf & VSX_OWNER)
- {
-
- vehicle_hudmodel.owner = self;
- }
-
- //if(xf & VSX_FAR)
- // dprint("Client vehicle faaar set\n");
-
- if(sf & VSF_ORIGIN)
- {
- ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
- self.origin_x = ReadFunc();
- self.origin_y = ReadFunc();
- self.origin_z = ReadFunc();
-
- setorigin(self, self.origin);
- //self.lastupdate = time;
- }
-
- if(sf & VSF_MOVEMENT)
- {
- ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
- self.velocity_x = ReadFunc();
- self.velocity_y = ReadFunc();
- self.velocity_z = ReadFunc();
-
- ReadFunc = ((sf & VSX_FAR) ? ReadShort : ReadAngle);
- self.angles_x = ReadFunc();
- self.angles_y = ReadFunc();
- self.angles_z = ReadFunc();
-
- //self.lastupdate = time;
- // self.move_velocity = self.velocity;
- // self.move_angles = self.angles;
- }
-
- if(sf & VSF_AVEL)
- {
- ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
- self.avelocity_x = ReadFunc();
- self.avelocity_y = ReadFunc();
- self.avelocity_z = ReadFunc();
-
- // self.move_avelocity = self.avelocity;
- }
-
- if(sf & VSF_STATS)
- {
- self.vehicle_health = ReadByte();
- if(xf & VSX_OWNER)
- {
- self.vehicle_shield = ReadByte();
- self.vehicle_energy = ReadByte();
- self.vehicle_ammo1 = ReadByte();
- self.vehicle_reload1 = ReadByte();
- self.vehicle_ammo2 = ReadByte();
- self.vehicle_reload2 = ReadByte();
- }
- }
-
- if(sf & VSF_EXTRA)
- self.vehile_read_exta(sf);
-
-}
-
-#endif // CSQC
-#else
-#ifdef CSQC
-.float lastupdate;
-void read_vehicle(float bIsNew)
-{
-
-}
-#endif
-#endif // VEHICLES_CSQC
float autocvar_g_vehicle_racer_blowup_edgedamage;
float autocvar_g_vehicle_racer_blowup_forceintensity;
+float autocvar_g_vehicle_racer_bouncefactor;
+float autocvar_g_vehicle_racer_bouncestop;
+vector autocvar_g_vehicle_racer_bouncepain;
+
var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
void racer_align4point()
self.owner = world;
}
+void racer_worldimpact()
+{
+ if(self.play_time < time)
+ if(autocvar_g_vehicle_racer_bouncepain_x)
+ vehilces_worldimpact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
+
+}
void racer_spawn()
{
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_worldimpact = racer_worldimpact;
+ //self.destvec = autocvar_g_vehicle_racer_bouncepain;
}
float autocvar_g_vehicle_raptor_shield_regen;
float autocvar_g_vehicle_raptor_shield_regen_pause;
+float autocvar_g_vehicle_raptor_bouncefactor;
+float autocvar_g_vehicle_raptor_bouncestop;
+vector autocvar_g_vehicle_raptor_bouncepain;
+
void raptor_spawn();
float raptor_frame();
float raptor_takeoff();
float raptor_altitude(float amax)
{
- tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), TRUE, self);
+ tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self);
return vlen(self.origin - trace_endpos);
}
}
void raptor_land()
-{
-
+{
float hgt;
-
- hgt = raptor_altitude(512);
+
+ hgt = raptor_altitude(512);
self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
self.angles_x *= 0.95;
self.angles_z *= 0.95;
if(hgt < 128)
- if(self.frame != 0)
- self.frame = max(self.frame - 0.25, 0);
+ if(hgt > 0)
+ self.frame = (hgt / 128) * 25;
self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000);
self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
if(hgt < 16)
{
- self.movetype = MOVETYPE_TOSS;
- self.think = raptor_think;
+ self.movetype = MOVETYPE_TOSS;
+ self.think = raptor_think;
+ self.frame = 0;
}
self.nextthink = time;
self.touch = raptor_blowup;
}
+void raptor_worldimpact()
+{
+ if(self.play_time < time)
+ if(autocvar_g_vehicle_raptor_bouncepain_x)
+ vehilces_worldimpact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
+}
+
void raptor_spawn()
{
self.frame = 0;
setsize(self, RAPTOR_MIN, RAPTOR_MAX );
self.delay = time;
+
+ self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
+ self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
+ self.vehicle_worldimpact = raptor_worldimpact;
}
// If we dont do this ever now and then, the raptors rotors
float autocvar_g_vehicle_spiderbot_rocket_turnrate;
float autocvar_g_vehicle_spiderbot_rocket_lifetime;
+float autocvar_g_vehicle_spiderbot_bouncefactor;
+float autocvar_g_vehicle_spiderbot_bouncestop;
+vector autocvar_g_vehicle_spiderbot_bouncepain;
+
+
void spiderbot_exit(float eject);
void spiderbot_enter();
void spiderbot_spawn();
self.owner = world;
}
-
+void spider_worldimpact()
+{
+ if(self.play_time < time)
+ if(autocvar_g_vehicle_spiderbot_bouncepain_x)
+ vehilces_worldimpact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
+}
void spiderbot_spawn()
{
self.frame = 5;
setorigin(self, self.pos1 + '0 0 128');
self.angles = self.pos2;
+ self.vehicle_worldimpact = spider_worldimpact;
}
void spiderbot_headfade()
self.touch = vehicles_touch;
self.event_damage = vehicles_damage;
self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
self.movetype = MOVETYPE_WALK;
self.solid = SOLID_SLIDEBOX;
self.takedamage = DAMAGE_AIM;
return FALSE;
}
+void vehilces_worldimpact(float _minspeed, float _speedfac, float _maxpain)
+{
+ if(self.play_time < time)
+ {
+ float wc, take;
+ wc = vlen(self.velocity - self.oldvelocity);
+ if(_minspeed < wc)
+ {
+ take = min(_speedfac * wc, _maxpain);
+ Damage (self, world, world, take, DEATH_FALL, self.origin, '0 0 0');
+ self.play_time = time + 0.25;
+
+ dprint("oldvel: ", vtos(self.oldvelocity), "\n");
+ dprint("vel: ", vtos(self.velocity), "\n");
+ dprint("wc: ", ftos(wc), "\n");
+ dprint("take: ", ftos(take), "\n");
+
+ }
+ }
+}
+
+.void() vehicle_worldimpact;
void vehicles_touch()
{
// Vehicle currently in use
// Colided with world?
if(other == world)
{
+ if(self.vehicle_worldimpact)
+ self.vehicle_worldimpact();
}
else
{
self.takedamage = DAMAGE_AIM;
self.bot_attack = TRUE;
self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
self.hud = vhud;
self.vehicle_die = dieproc;
+++ /dev/null
-/// Some default stacks.
-.entity verbs_idle;
-.entity verbs_attack;
-.entity verbs_move;
-//.entity vchain;
-
-/// This global gets set to the verb in question each time the stack manager calls verb_call
-entity verb;
-//.entity current_verb;
-//.float verb_done;
-
-/// Execure this verb
-#define VCM_DO 0
-/// Return the value of this verb. Return VS_CALL_REMOVE to delete it.
-#define VCM_EVAL 1
-/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE)
-#define VCM_REMOVE 2
-
-/// Verb callback
-.float(float message) verb_call;
-
-/// Points to this verb's stack.
-.entity verbstack;
-
-/// Static value of this verb
-.float verb_static_value;
-
-/// verb_call returns this when a verb in not doable
-#define VS_CALL_NO 0
-/// verb_call(VCM_DO) returns this when a verb is executing
-#define VS_CALL_YES_DOING -1
-/// verb_call(VCM_DO) returns this when a verb did execure and is done
-#define VS_CALL_YES_DONE -2
-/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager
-#define VS_CALL_REMOVE -3
-
-/*
-void verbstack_updatechain(entity stack)
-{
- entity vrb, v;
- if not (stack)
- return;
-
- dprint("verbstack_updatechain\n");
-
- vrb = findchainentity(verbstack, stack);
- if not (vrb)
- {
- stack.vchain = world;
- return;
- }
-
- stack.vchain = vrb;
- v = vrb;
-
- while(vrb)
- {
- vrb = vrb.chain;
-
-
- }
-}
-
-void verbstack_remove(entity vverb)
-{
- entity vstack;
- dprint("verbstack_remove\n");
-
- vstack = verb.verbstack;
- remove(vverb);
- vverb.verbstack = world;
- verbstack_updatechain(vstack);
-
- //vverb.think = SUB_Remove;
- //vverb.nextthink = time;
-}
-
-void verbstack_thinkremove()
-{
- dprint("verbstack_thinkremove\n");
- verbstack_remove(self);
-}
-*/
-
-/**
- Push a new verb onto the specified stack. Set vrb_life to make it time-limited.
-**/
-entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner)
-{
- entity vrb;
-
- if not(stack)
- return world;
-
- if not(vrb_call)
- return world;
-
- vrb = spawn();
- vrb.owner = verb_owner;
- vrb.verbstack = stack;
- vrb.verb_call = vrb_call;
- vrb.verb_static_value = val_static;
-
- vrb.classname = "verb";
- stack.classname = "verbstack";
-
- if(vrb_life)
- {
- //vrb.think = verbstack_thinkremove;
- vrb.think = SUB_Remove;
- vrb.nextthink = time + vrb_life;
- }
-
- //verbstack_updatechain(stack);
-
- return vrb;
-}
-
-/**
- Find the best verb in this stack and execurte it.
- ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO
-**/
-float verbstack_pop(entity stack)
-{
- entity vrb, bestverb, oldself;
- float value, bestvalue;
-
- oldself = self;
-
- vrb = findchainentity(verbstack,stack);
- //vrb = stack.vchain;
- //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n");
- while(vrb)
- {
- //dprint("vn:", vrb.classname,"\n");
- verb = vrb;
- vrb = vrb.chain;
- self = verb.owner;
- value = verb.verb_call(VCM_EVAL);
-
- if(value < 0)
- {
- if(value == VS_CALL_REMOVE)
- remove(verb);
- }
- else
- {
- if(value > bestvalue)
- {
- bestverb = verb;
- bestvalue = value;
- }
- }
- }
-
- if(bestverb)
- {
- verb = bestverb;
- self = verb.owner;
- value = verb.verb_call(VCM_DO);
-
- if(value == VS_CALL_REMOVE)
- remove(bestverb);
- }
-
- self = oldself;
-
- return value;
-}
-
-float verbstack_popfifo(entity stack)
-{
- entity oldself;
- float ret;
-
- oldself = self;
- verb = findentity(stack,verbstack,stack);
- if not (verb)
- ret = 0;
- else
- {
- self = verb.owner;
- ret = verb.verb_call(VCM_DO);
-
- if(ret == VS_CALL_REMOVE)
- remove(verb);
- }
-
- self = oldself;
- return ret;
-}
-
-/**
- Find the best verb in this stack and return it.
- ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL.
-**/
-entity verbstack_pull(entity stack)
-{
- entity vrb;
- entity bestverb, oldself;
- float value, bestvalue;
-
- oldself = self;
-
- vrb = findchainentity(verbstack,stack);
- while(vrb)
- {
- self = vrb.owner;
-
- verb = vrb;
- vrb = vrb.chain;
- value = verb.verb_call(VCM_EVAL);
-
- if(value < 0)
- {
- if(value == VS_CALL_REMOVE)
- remove(verb);
- }
- else
- {
- if(value > bestvalue)
- {
- bestverb = verb;
- bestvalue = value;
- }
- }
- }
-
- self = oldself;
-
- return bestverb;
-}
-
-entity verbstack_pullfifo(entity stack)
-{
- return findentity(stack,verbstack,stack);
-}
-
-/**
- Delete every verb on this stack, signaling them with VCM_REMOVE first.
-**/
-void verbstack_flush(entity stack)
-{
- entity vrb, oldself;
-
- oldself = self;
-
- vrb = findchainentity(verbstack,stack);
- while(vrb)
- {
- self = vrb.owner;
-
- verb = vrb;
- vrb = vrb.chain;
- verb.verb_call(VCM_REMOVE);
- remove(verb);
- }
-
- self = oldself;
-
- //stack.vchain = world;
-}
-
-void verbstack_doverb(entity vrb)
-{
- float value;
-
- verb = vrb;
- self = verb.owner;
- value = verb.verb_call(VCM_DO);
-
- if(value == VS_CALL_REMOVE)
- remove(vrb);
-}
}
float GameCommand_Vote(string s, entity e) {
- local float playercount;
+ float playercount;
float argc;
argc = tokenize_console(s);
if(argv(0) == "help") {
else if(votecalled) {
print_to(e, "^1There is already a vote called.");
} else {
- local string vote;
+ string vote;
vote = VoteParse(s, argc);
if(vote == "") {
print_to(e, "^1Your vote is empty. See 'vhelp' for more info.");
VoteCount(); // needed if you are the only one
msg_entity = e;
- local entity player;
+ entity player;
FOR_EACH_REALCLIENT(player)
{
++playercount;
}
} else if(argv(1) == "do") {
if(!e || e.vote_master) {
- local string dovote;
+ string dovote;
dovote = VoteParse(s, argc);
if(dovote == "") {
print_to(e, "^1Your command was empty. See 'vhelp' for more info.");
print_to(e, "^1You are NOT a master. You might need to login or vote to become master first. See 'vhelp' for more info.");
}
} else if(argv(1) == "login") {
- local string masterpwd;
+ string masterpwd;
masterpwd = autocvar_sv_vote_master_password;
if(masterpwd != "") {
- local float granted;
+ float granted;
granted = (masterpwd == argv(2));
if (e)
e.vote_master = granted;
}
void VoteHelp(entity e) {
- local string vmasterdis;
+ string vmasterdis;
if(!autocvar_sv_vote_master) {
vmasterdis = " ^1(disabled)";
}
- local string vlogindis;
+ string vlogindis;
if("" == autocvar_sv_vote_master_password) {
vlogindis = " ^1(disabled)";
}
- local string vcalldis;
+ string vcalldis;
if(!autocvar_sv_vote_call) {
vcalldis = " ^1(disabled)";
}
}
void VoteReset() {
- local entity player;
+ entity player;
FOR_EACH_CLIENT(player)
{
}
void VoteCount() {
- local float playercount;
+ float playercount;
playercount = 0;
vote_yescount = 0;
vote_nocount = 0;
vote_abstaincount = 0;
- local entity player;
+ entity player;
//same for real players
- local float realplayercount;
- local float realplayeryescount;
- local float realplayernocount;
- local float realplayerabstaincount;
+ float realplayercount;
+ float realplayeryescount;
+ float realplayernocount;
+ float realplayerabstaincount;
realplayercount = realplayernocount = realplayerabstaincount = realplayeryescount = 0;
Nagger_VoteCountChanged();
.vector railgunforce;
void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype)
{
- local vector hitloc, force, endpoint, dir;
- local entity ent, endent;
- local float endq3surfaceflags;
+ vector hitloc, force, endpoint, dir;
+ entity ent, endent;
+ float endq3surfaceflags;
float totaldmg;
entity o;
{
if(vlen(trace_endpos - fireBallisticBullet_trace_callback_ent.origin) > 16)
zcurveparticles_from_tracetoss(fireBallisticBullet_trace_callback_eff, fireBallisticBullet_trace_callback_ent.origin, trace_endpos, fireBallisticBullet_trace_callback_ent.velocity);
+ WarpZone_trace_forent = world;
+ self.owner = world;
}
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)
if(lag)
FOR_EACH_PLAYER(pl)
- antilag_takeback(pl, time - lag);
+ if(pl != self)
+ antilag_takeback(pl, time - lag);
oldself = self;
self = proj;
trace_fraction = 0;
fireBallisticBullet_trace_callback_ent = self;
fireBallisticBullet_trace_callback_eff = eff;
- // FIXME can we somehow do this with just ONE trace?
- WarpZone_TraceToss(self, self.owner);
- if(self.owner && WarpZone_trace_firstzone)
- {
- self.owner = world;
- self.velocity = v0;
- self.gravity = g0;
- continue;
- }
WarpZone_TraceToss_ThroughZone(self, self.owner, world, fireBallisticBullet_trace_callback);
self.velocity = v0;
self.gravity = g0;
if(lag)
FOR_EACH_PLAYER(pl)
- antilag_restore(pl);
+ if(pl != self)
+ antilag_restore(pl);
remove(proj);
trace_endpos = end;
}
+float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception)
+{
+ float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA);
+ float is_from_owner = (inflictor == projowner);
+ float is_from_exception = (exception != -1);
+
+ //print(strcat("from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n")));
+
+ if(autocvar_g_projectiles_damage <= -2)
+ {
+ return FALSE; // no damage to projectiles at all, not even with the exceptions
+ }
+ else if(autocvar_g_projectiles_damage == -1)
+ {
+ if(is_from_exception)
+ return (exception); // if exception is detected, allow it to override
+ else
+ return FALSE; // otherwise, no other damage is allowed
+ }
+ else if(autocvar_g_projectiles_damage == 0)
+ {
+ if(is_from_exception)
+ return (exception); // if exception is detected, allow it to override
+ else if not(is_from_contents)
+ return FALSE; // otherwise, only allow damage from contents
+ }
+ else if(autocvar_g_projectiles_damage == 1)
+ {
+ if(is_from_exception)
+ return (exception); // if exception is detected, allow it to override
+ else if not(is_from_contents || is_from_owner)
+ return FALSE; // otherwise, only allow self damage and damage from contents
+ }
+ else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions
+ {
+ if(is_from_exception)
+ return (exception); // if exception is detected, allow it to override
+ }
+
+ return TRUE; // if none of these return, then allow damage anyway.
+}
+
void W_PrepareExplosionByDamage(entity attacker, void() explode)
{
self.takedamage = DAMAGE_NO;
void W_Crylink_Attack (void)
{
- local float counter, shots;
- local entity proj, prevproj, firstproj;
- local vector s;
+ float counter, shots;
+ entity proj, prevproj, firstproj;
+ vector s;
vector forward, right, up;
float maxdmg;
void W_Crylink_Attack2 (void)
{
- local float counter, shots;
- local entity proj, prevproj, firstproj;
+ float counter, shots;
+ entity proj, prevproj, firstproj;
float maxdmg;
W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo);
W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_crylink(float req)
void W_Plasma_TriggerCombo(vector org, float rad, entity own)
{
- local entity e;
+ entity e;
e = WarpZone_FindRadius(org, rad, TRUE);
while (e)
{
{
if(self.health <= 0)
return;
+
// note: combos are usually triggered by W_Plasma_TriggerCombo, not damage
+ float is_combo = (inflictor.classname == "plasma_chain" || inflictor.classname == "plasma_prim");
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_combo ? 1 : -1)))
+ return; // g_projectiles_damage says to halt
+
self.health = self.health - damage;
if (self.health <= 0)
{
self.takedamage = DAMAGE_NO;
self.nextthink = time;
- if (inflictor.classname == "plasma_chain" || inflictor.classname == "plasma_prim")
+ if (is_combo)
{
// change owner to whoever caused the combo explosion
self.realowner = inflictor.realowner;
void W_Electro_Attack()
{
- local entity proj;
+ entity proj;
W_DecreaseAmmo(ammo_cells, autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_reload_ammo);
void W_Electro_Attack2()
{
- local entity proj;
+ entity proj;
W_DecreaseAmmo(ammo_cells, autocvar_g_balance_electro_secondary_ammo, autocvar_g_balance_electro_reload_ammo);
proj.health = autocvar_g_balance_electro_secondary_health;
proj.event_damage = W_Plasma_Damage;
proj.flags = FL_PROJECTILE;
+ proj.damagedbycontents = (autocvar_g_balance_electro_secondary_damagedbycontents);
proj.bouncefactor = autocvar_g_balance_electro_secondary_bouncefactor;
proj.bouncestop = autocvar_g_balance_electro_secondary_bouncestop;
W_Reload(min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo), autocvar_g_balance_electro_reload_ammo, autocvar_g_balance_electro_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_electro(float req)
else if (req == WR_SUICIDEMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s could not remember where they put plasma");
+ w_deathtypestring = _("%s could not remember where they put their electro plasma");
else
- w_deathtypestring = _("%s played with plasma");
+ w_deathtypestring = _("%s played with electro plasma");
}
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
{
if(w_deathtype & HITTYPE_SPLASH) // unchecked: BOUNCE
- w_deathtypestring = _("%s just noticed %s's blue ball");
+ w_deathtypestring = _("%s just noticed %s's electro plasma");
else // unchecked: BOUNCE
- w_deathtypestring = _("%s got in touch with %s's blue ball");
+ w_deathtypestring = _("%s got in touch with %s's electro plasma");
}
else
{
if(w_deathtype & HITTYPE_BOUNCE) // combo
- w_deathtypestring = _("%s felt the electrifying air of %s's combo");
+ w_deathtypestring = _("%s felt the electrifying air of %s's electro combo");
else if(w_deathtype & HITTYPE_SPLASH)
- w_deathtypestring = _("%s got too close to %s's blue beam");
+ w_deathtypestring = _("%s got too close to %s's blue electro bolt");
else
- w_deathtypestring = _("%s was blasted by %s's blue beam");
+ w_deathtypestring = _("%s was blasted by %s's blue electro bolt");
}
}
return TRUE;
{
if(self.health <= 0)
return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_projectiles_damage says to halt
+
self.health = self.health - damage;
if (self.health <= 0)
{
void W_Fireball_Attack1()
{
- local entity proj;
+ entity proj;
W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, autocvar_g_balance_fireball_primary_damage + autocvar_g_balance_fireball_primary_bfgdamage);
void W_Fireball_Attack2()
{
- local entity proj;
+ entity proj;
vector f_diff;
float c;
W_Reload(min(autocvar_g_balance_fireball_primary_ammo, autocvar_g_balance_fireball_secondary_ammo), autocvar_g_balance_fireball_reload_ammo, autocvar_g_balance_fireball_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_fireball(float req)
{
if (self.health <= 0)
return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_projectiles_damage says to halt
+
self.health = self.health - damage;
+
if (self.health <= 0)
- {
- W_PrepareExplosionByDamage(attacker, self.think);
- }
+ W_PrepareExplosionByDamage(attacker, self.use);
}
void W_Grenade_Think1 (void)
void W_Grenade_Attack (void)
{
- local entity gren;
+ entity gren;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo);
gren.health = autocvar_g_balance_grenadelauncher_primary_health;
gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale;
gren.event_damage = W_Grenade_Damage;
+ gren.damagedbycontents = TRUE;
W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
gren.angles = vectoangles (gren.velocity);
void W_Grenade_Attack2 (void)
{
- local entity gren;
+ entity gren;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_secondary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo);
gren.health = autocvar_g_balance_grenadelauncher_secondary_health;
gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale;
gren.event_damage = W_Grenade_Damage;
+ gren.damagedbycontents = TRUE;
W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary);
gren.angles = vectoangles (gren.velocity);
W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_glauncher(float req)
else if (req == WR_SUICIDEMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s tried out his own grenade");
+ w_deathtypestring = _("%s didn't see their own grenade");
else
- w_deathtypestring = _("%s detonated");
+ w_deathtypestring = _("%s blew themself up with their grenadelauncher");
}
else if (req == WR_KILLMESSAGE)
{
remove (self);
}
+void W_Hagar_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if (self.health <= 0)
+ return;
+
+ float is_linkexplode = ((inflictor.realowner == self.realowner)
+ && (inflictor.projectiledeathtype & HITTYPE_SECONDARY)
+ && (self.projectiledeathtype & HITTYPE_SECONDARY));
+
+ if(is_linkexplode)
+ is_linkexplode = (is_linkexplode && autocvar_g_balance_hagar_secondary_load_linkexplode);
+ else
+ is_linkexplode = -1; // not secondary load, so continue as normal without exception.
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, is_linkexplode))
+ return; // g_projectiles_damage says to halt
+
+ self.health = self.health - damage;
+ self.angles = vectoangles(self.velocity);
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(attacker, self.think);
+}
+
void W_Hagar_Touch (void)
{
PROJECTILE_TOUCH;
void W_Hagar_Attack (void)
{
- local entity missile;
+ entity missile;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_reload_ammo);
missile.classname = "missile";
missile.bot_dodge = TRUE;
missile.bot_dodgerating = autocvar_g_balance_hagar_primary_damage;
+
+ missile.takedamage = DAMAGE_YES;
+ missile.health = autocvar_g_balance_hagar_primary_health;
+ missile.damageforcescale = autocvar_g_balance_hagar_primary_damageforcescale;
+ missile.event_damage = W_Hagar_Damage;
+ missile.damagedbycontents = TRUE;
+
missile.touch = W_Hagar_Touch;
missile.use = W_Hagar_Explode;
missile.think = adaptor_think2use_hittype_splash;
void W_Hagar_Attack2 (void)
{
- local entity missile;
+ entity missile;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo);
missile.classname = "missile";
missile.bot_dodge = TRUE;
missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage;
+
+ missile.takedamage = DAMAGE_YES;
+ missile.health = autocvar_g_balance_hagar_secondary_health;
+ missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale;
+ missile.event_damage = W_Hagar_Damage;
+ missile.damagedbycontents = TRUE;
+
missile.touch = W_Hagar_Touch2;
missile.cnt = 0;
missile.use = W_Hagar_Explode2;
other = missile; MUTATOR_CALLHOOK(EditProjectile);
}
-.float hagar_loadstep, hagar_loadblock, hagar_loadbeep;
+.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
void W_Hagar_Attack2_Load_Release (void)
{
// time to release the rockets we've loaded
- local entity missile;
- local float counter, shots, spread_pershot;
- local vector s;
+ entity missile;
+ float counter, shots, spread_pershot;
+ vector s;
vector forward, right, up;
if(!self.hagar_load)
missile.classname = "missile";
missile.bot_dodge = TRUE;
missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage;
+
+ missile.takedamage = DAMAGE_YES;
+ missile.health = autocvar_g_balance_hagar_secondary_health;
+ missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale;
+ missile.event_damage = W_Hagar_Damage;
+ missile.damagedbycontents = TRUE;
missile.touch = W_Hagar_Touch; // not bouncy
missile.use = W_Hagar_Explode2;
missile.think = adaptor_think2use_hittype_splash;
missile.nextthink = time + autocvar_g_balance_hagar_secondary_lifetime_min + random() * autocvar_g_balance_hagar_secondary_lifetime_rand;
PROJECTILE_MAKETRIGGER(missile);
- missile.projectiledeathtype = WEP_HAGAR;
+ missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
setorigin (missile, w_shotorg);
setsize(missile, '0 0 0', '0 0 0');
missile.movetype = MOVETYPE_FLY;
counter = counter + 1;
}
- weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready);
+ weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_load_animtime, w_ready);
self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_refire * W_WeaponRateFactor();
self.hagar_load = 0;
}
{
// loadable hagar secondary attack, must always run each frame
- local float loaded, enough_ammo;
+ float loaded, enough_ammo;
loaded = self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max;
// this is different than WR_CHECKAMMO when it comes to reloading
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo);
self.weaponentity.state = WS_INUSE;
self.hagar_load += 1;
- sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
- self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor();
+ if (self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max)
+ self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_hold * W_WeaponRateFactor();
+ else
+ self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor();
}
}
else if(!self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame
if(self.hagar_load)
{
- if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && !autocvar_g_balance_hagar_secondary_load_hold))
+ // play warning sound if we're about to release
+ if((loaded || !enough_ammo) && self.hagar_loadstep - 0.5 < time && autocvar_g_balance_hagar_secondary_load_hold >= 0)
+ {
+ if(!self.hagar_warning && self.hagar_load) // prevents the beep from playing each frame
+ {
+ // we're about to automatically release after holding time, play a beep sound to notify the player
+ sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM);
+ self.hagar_warning = TRUE;
+ }
+ }
+
+ // release if player let go of button or if they've held it in too long
+ if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && autocvar_g_balance_hagar_secondary_load_hold >= 0))
{
self.weaponentity.state = WS_READY;
W_Hagar_Attack2_Load_Release();
else
{
self.hagar_loadbeep = FALSE;
+ self.hagar_warning = FALSE;
}
// we aren't checking ammo during an attack, so we must do it here
}
else if (req == WR_THINK)
{
- local float loadable_secondary;
+ float loadable_secondary;
loadable_secondary = autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary;
if (loadable_secondary)
W_Reload(min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo), autocvar_g_balance_hagar_reload_ammo, autocvar_g_balance_hagar_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_hagar(float req)
precache_sound("weapons/hagexp3.wav");
}
else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s played with tiny rockets");
+ w_deathtypestring = _("%s played with tiny hagar rockets");
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_BOUNCE) // must be secondary; unchecked: SPLASH
- w_deathtypestring = _("%s hoped %s's missiles wouldn't bounce");
+ w_deathtypestring = _("%s was pummeled with a burst of hagar rockets by %s");
else // unchecked: SPLASH, SECONDARY
- w_deathtypestring = _("%s was pummeled by %s");
+ w_deathtypestring = _("%s was pummeled with hagar rockets by %s");
}
return TRUE;
}
void W_HLAC_Attack (void)
{
- local entity missile;
+ entity missile;
float spread;
W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_reload_ammo);
void W_HLAC_Attack2f (void)
{
- local entity missile;
+ entity missile;
float spread;
spread = autocvar_g_balance_hlac_secondary_spread;
{
weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_animtime, w_ready);
}
-};
+}
void spawnfunc_weapon_hlac (void)
{
W_Reload(min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo), autocvar_g_balance_hlac_reload_ammo, autocvar_g_balance_hlac_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_hlac(float req)
else if (req == WR_SUICIDEMESSAGE)
w_deathtypestring = _("%s should have used a smaller gun");
else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s was cut down by %s");
+ w_deathtypestring = _("%s was cut down with a HLAC by %s");
return TRUE;
}
#endif
self.movetype = MOVETYPE_NONE;
}
+void W_Hook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if (self.health <= 0)
+ return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_projectiles_damage says to halt
+
+ self.health = self.health - damage;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2);
+}
+
void W_Hook_Touch2 (void)
{
PROJECTILE_TOUCH;
void W_Hook_Attack2()
{
- local entity gren;
+ entity gren;
W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hook_secondary_ammo, FALSE);
W_SetupShot (self, FALSE, 4, "weapons/hookbomb_fire.wav", CH_WEAPON_A, autocvar_g_balance_hook_secondary_damage);
gren.think = adaptor_think2use_hittype_splash;
gren.use = W_Hook_Explode2;
gren.touch = W_Hook_Touch2;
+
+ gren.takedamage = DAMAGE_YES;
+ gren.health = autocvar_g_balance_hook_secondary_health;
+ gren.damageforcescale = autocvar_g_balance_hook_secondary_damageforcescale;
+ gren.event_damage = W_Hook_Damage;
+ gren.damagedbycontents = TRUE;
gren.velocity = '0 0 1' * autocvar_g_balance_hook_secondary_speed;
if(autocvar_g_projectiles_newton_style)
self.hook_refire = time;
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_hook(float req)
else if (req == WR_SUICIDEMESSAGE)
w_deathtypestring = _("%s did the impossible");
else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s has run into %s's gravity bomb");
+ w_deathtypestring = _("%s was caught in %s's hook gravity bomb");
return TRUE;
}
#endif
void W_Laser_Attack (float issecondary)
{
- local entity missile;
+ entity missile;
vector s_forward;
float a;
float nodamage;
float w_laser(float req)
{
- local float r1;
- local float r2;
+ float r1;
+ float r2;
if (req == WR_AIM)
{
if(autocvar_g_balance_laser_secondary)
W_Reload(0, autocvar_g_balance_laser_reload_ammo, autocvar_g_balance_laser_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_laser(float req)
newmine.health = self.health;
newmine.event_damage = self.event_damage;
newmine.spawnshieldtime = self.spawnshieldtime;
+ newmine.damagedbycontents = TRUE;
newmine.movetype = MOVETYPE_NONE; // lock the mine in place
newmine.projectiledeathtype = self.projectiledeathtype;
{
if (self.health <= 0)
return;
+
+ float is_from_enemy = (inflictor.realowner != self.realowner);
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_from_enemy ? 1 : -1)))
+ return; // g_projectiles_damage says to halt
+
self.health = self.health - damage;
self.angles = vectoangles(self.velocity);
+
if (self.health <= 0)
W_PrepareExplosionByDamage(attacker, W_Mine_Explode);
}
mine.damageforcescale = autocvar_g_balance_minelayer_damageforcescale;
mine.health = autocvar_g_balance_minelayer_health;
mine.event_damage = W_Mine_Damage;
+ mine.damagedbycontents = TRUE;
mine.movetype = MOVETYPE_TOSS;
PROJECTILE_MAKETRIGGER(mine);
W_Reload(autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo, autocvar_g_balance_minelayer_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_minelayer(float req)
precache_sound("weapons/mine_exp.wav");
}
else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s exploded");
+ if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
+ w_deathtypestring = _("%s blew themself up with their minelayer");
+ else
+ w_deathtypestring = _("%s forgot about their mine");
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
W_Reload(used_ammo, autocvar_g_balance_minstanex_reload_ammo, autocvar_g_balance_minstanex_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_minstanex(float req)
else if (req == WR_SUICIDEMESSAGE)
w_deathtypestring = _("%s is now thinking with portals");
else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s has been vaporized by %s");
+ w_deathtypestring = _("%s has been vaporized by %s's minstanex");
return TRUE;
}
#endif
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_nex(float req)
else if (req == WR_SUICIDEMESSAGE)
w_deathtypestring = _("%s is now thinking with portals");
else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s has been vaporized by %s");
+ w_deathtypestring = _("%s has been vaporized by %s's nex");
return TRUE;
}
#endif
void W_Porto_Attack (void)
{
- local entity gren;
+ entity gren;
if not(self.items & IT_UNLIMITED_SUPERWEAPONS)
self.weapons = self.weapons - (self.weapons & WEPBIT_PORTO);
self.porto_current = world;
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_porto(float req)
W_Reload(min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo), autocvar_g_balance_rifle_reload_ammo, autocvar_g_balance_rifle_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_rifle(float req)
}
else if (req == WR_SUICIDEMESSAGE)
{
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s shot themself automatically");
- else
- w_deathtypestring = _("%s sniped themself somehow");
+ w_deathtypestring = _("%s is now thinking with portals");
}
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
{
if(w_deathtype & HITTYPE_BOUNCE)
- w_deathtypestring = _("%s failed to hide from %s's bullet hail");
+ w_deathtypestring = _("%s failed to hide from %s's rifle bullet hail");
else
- w_deathtypestring = _("%s died in %s's bullet hail");
+ w_deathtypestring = _("%s died in %s's rifle bullet hail");
}
else
{
else
{
if(w_deathtype & HITTYPE_HEADSHOT)
- w_deathtypestring = _("%s got hit in the head by %s");
+ w_deathtypestring = _("%s got shot in the head with a rifle by %s");
else
- w_deathtypestring = _("%s was sniped by %s");
+ w_deathtypestring = _("%s was sniped with a rifle by %s");
}
}
}
{
if (self.health <= 0)
return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_projectiles_damage says to halt
+
self.health = self.health - damage;
self.angles = vectoangles(self.velocity);
+
if (self.health <= 0)
W_PrepareExplosionByDamage(attacker, W_Rocket_Explode);
}
void W_Rocket_Attack (void)
{
- local entity missile;
- local entity flash;
+ entity missile;
+ entity flash;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo);
missile.damageforcescale = autocvar_g_balance_rocketlauncher_damageforcescale;
missile.health = autocvar_g_balance_rocketlauncher_health;
missile.event_damage = W_Rocket_Damage;
+ missile.damagedbycontents = TRUE;
missile.movetype = MOVETYPE_FLY;
PROJECTILE_MAKETRIGGER(missile);
if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
{
// decide whether to detonate rockets
- local entity missile, targetlist, targ;
- local float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
- local float selfdamage, teamdamage, enemydamage;
+ entity missile, targetlist, targ;
+ float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
+ float selfdamage, teamdamage, enemydamage;
edgedamage = autocvar_g_balance_rocketlauncher_edgedamage;
coredamage = autocvar_g_balance_rocketlauncher_damage;
edgeradius = autocvar_g_balance_rocketlauncher_radius;
}
missile = find(missile, classname, "rocket");
}
- local float desirabledamage;
+ float desirabledamage;
desirabledamage = enemydamage;
if (time > self.invincible_finished && time > self.spawnshieldtime)
desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
targ = targ.chain;
}
}else{
- local float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
+ float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
//As the distance gets larger, a correct detonation gets near imposible
//Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player
if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1)
W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_rlauncher(float req)
precache_sound("weapons/rocket_impact.wav");
}
else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s exploded");
+ w_deathtypestring = _("%s blew themself up with their rocketlauncher");
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
{
if (self.health <= 0)
return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_projectiles_damage says to halt
if (self.realowner == attacker)
self.health = self.health - (damage * 0.25);
void Seeker_Fire_Missile(vector f_diff, entity m_target)
{
- local entity missile;
+ entity missile;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_reload_ammo);
missile.takedamage = DAMAGE_YES;
missile.health = autocvar_g_balance_seeker_missile_health;
missile.damageforcescale = autocvar_g_balance_seeker_missile_damageforcescale;
+ missile.damagedbycontents = TRUE;
//missile.think = Seeker_Missile_Animate; // csqc projectiles.
if (missile.enemy != world)
void Seeker_Fire_Flac()
{
- local entity missile;
+ entity missile;
vector f_diff;
float c;
void Seeker_Fire_Tag()
{
- local entity missile;
+ entity missile;
W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_tag_ammo, autocvar_g_balance_seeker_reload_ammo);
W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_missile_damage * autocvar_g_balance_seeker_missile_count);
W_Reload(min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo), autocvar_g_balance_seeker_reload_ammo, autocvar_g_balance_seeker_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_seeker(float req)
precache_sound("weapons/tag_impact.wav");
}
else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s played with tiny rockets");
+ w_deathtypestring = _("%s played with tiny seeker rockets");
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s was tagged by %s");
+ w_deathtypestring = _("%s was tagged with a seeker by %s");
else
- w_deathtypestring = _("%s was pummeled by %s");
+ w_deathtypestring = _("%s was pummeled with seeker rockets by %s");
}
return TRUE;
}
float spread;
float bulletspeed;
float bulletconstant;
- local entity flash;
+ entity flash;
ammoamount = autocvar_g_balance_shotgun_primary_ammo;
bullets = autocvar_g_balance_shotgun_primary_bullets;
W_AttachToShotorg(flash, '5 0 0');
}
-entity lgbeam_owner_ent;
+.float swing_prev;
+.entity swing_alreadyhit;
void shotgun_meleethink (void)
{
- // store time when we started swinging down inside self.cnt
- if(!self.cnt)
- self.cnt = time;
-
- makevectors(self.realowner.v_angle);
- vector angle;
- angle = v_forward;
-
- float meleetime;
- meleetime = autocvar_g_balance_shotgun_secondary_melee_time * W_WeaponRateFactor();
-
- // perform trace
- float f;
- f = (self.cnt + meleetime - time) / meleetime * 2 - 1;
+ // declarations
+ float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
vector targpos;
- targpos = self.realowner.origin + self.realowner.view_ofs + angle * autocvar_g_balance_shotgun_secondary_melee_range + v_right * f * autocvar_g_balance_shotgun_secondary_melee_swing + v_up * f * autocvar_g_balance_shotgun_secondary_melee_swing;
- if(!lgbeam_owner_ent)
+ if(!self.cnt) // set start time of melee
{
- lgbeam_owner_ent = spawn();
- lgbeam_owner_ent.classname = "lgbeam_owner_ent";
+ self.cnt = time;
+ W_PlayStrengthSound(self.realowner);
}
- WarpZone_traceline_antilag(lgbeam_owner_ent, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, lgbeam_owner_ent, ANTILAG_LATENCY(self.realowner));
- // apply the damage, also remove self
- if(trace_fraction < 1 && trace_ent.takedamage == DAMAGE_AIM && (trace_ent.classname == "player" || trace_ent.classname == "body"))
+ makevectors(self.realowner.v_angle); // update values for v_* vectors
+
+ // calculate swing percentage based on time
+ meleetime = autocvar_g_balance_shotgun_secondary_melee_time * W_WeaponRateFactor();
+ swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10);
+ f = ((1 - swing) * autocvar_g_balance_shotgun_secondary_melee_traces);
+
+ // check to see if we can still continue, otherwise give up now
+ if((self.realowner.deadflag != DEAD_NO) && autocvar_g_balance_shotgun_secondary_melee_no_doubleslap)
{
- vector force;
- force = angle * autocvar_g_balance_shotgun_secondary_force;
- if(accuracy_isgooddamage(self.realowner, trace_ent))
- accuracy_add(self.realowner, WEP_SHOTGUN, 0, autocvar_g_balance_shotgun_secondary_damage * min(1, f + 1));
- Damage (trace_ent, self.realowner, self.realowner, autocvar_g_balance_shotgun_secondary_damage * min(1, f + 1), WEP_SHOTGUN | HITTYPE_SECONDARY , self.realowner.origin + self.realowner.view_ofs, force);
remove(self);
+ return;
+ }
+
+ // if okay, perform the traces needed for this frame
+ for(i=self.swing_prev; i < f; ++i)
+ {
+ swing_factor = ((1 - (i / autocvar_g_balance_shotgun_secondary_melee_traces)) * 2 - 1);
+
+ targpos = (self.realowner.origin + self.realowner.view_ofs
+ + (v_forward * autocvar_g_balance_shotgun_secondary_melee_range)
+ + (v_up * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_up)
+ + (v_right * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_side));
+
+ WarpZone_traceline_antilag(self.realowner, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self.realowner, ANTILAG_LATENCY(self.realowner));
+
+ // draw lightning beams for debugging
+ //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5);
+ //te_customflash(targpos, 40, 2, '1 1 1');
+
+ is_player = (trace_ent.classname == "player" || trace_ent.classname == "body");
+
+ if((trace_fraction < 1) // if trace is good, apply the damage and remove self
+ && (trace_ent.takedamage == DAMAGE_AIM)
+ && (trace_ent != self.swing_alreadyhit)
+ && (is_player || autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage))
+ {
+ if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught.
+ swing_damage = (autocvar_g_balance_shotgun_secondary_damage * min(1, swing_factor + 1));
+ else
+ swing_damage = (autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage * min(1, swing_factor + 1));
+
+ Damage(trace_ent, self.realowner, self.realowner,
+ swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY,
+ self.realowner.origin + self.realowner.view_ofs,
+ v_forward * autocvar_g_balance_shotgun_secondary_force);
+
+ if(accuracy_isgooddamage(self.realowner, trace_ent))
+ accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage);
+
+ // draw large red flash for debugging
+ //te_customflash(targpos, 200, 2, '15 0 0');
+
+ if(autocvar_g_balance_shotgun_secondary_melee_multihit) // allow multiple hits with one swing, but not against the same player twice.
+ {
+ self.swing_alreadyhit = trace_ent;
+ continue; // move along to next trace
+ }
+ else
+ {
+ remove(self);
+ return;
+ }
+ }
}
- else if(time >= self.cnt + meleetime || (self.realowner.deadflag != DEAD_NO && autocvar_g_balance_shotgun_secondary_melee_no_doubleslap)) // missed or owner died, remove ent
+
+ if(time >= self.cnt + meleetime)
+ {
+ // melee is finished
remove(self);
- else // continue swinging the weapon in hope of hitting someone :)
+ return;
+ }
+ else
+ {
+ // set up next frame
+ self.swing_prev = i;
self.nextthink = time;
+ }
}
void W_Shotgun_Attack2 (void)
{
- sound (self, CH_SHOTS, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM);
+ sound (self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM);
weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_shotgun_secondary_animtime, w_ready);
entity meleetemp;
}
}
if (self.clip_load >= 0) // we are not currently reloading
+ if (!self.crouch) // we are not currently crouching; this fixes an exploit where your melee anim is not visible, and besides wouldn't make much sense
if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary)
if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire))
{
W_Reload(autocvar_g_balance_shotgun_primary_ammo, autocvar_g_balance_shotgun_reload_ammo, autocvar_g_balance_shotgun_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
.float prevric;
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun");
+ w_deathtypestring = _("%2$s slapped %1$s around a bit with a large shotgun");
else
- w_deathtypestring = _("%s was gunned by %s");
+ w_deathtypestring = _("%s was gunned down with a shotgun by %s");
}
return TRUE;
}
{
float f;
+ msg_entity = to;
+ if(!sound_allowed(MSG_ONE, self.realowner))
+ return FALSE;
+
WriteByte(MSG_ENTITY, ENT_CLIENT_TUBANOTE);
WriteByte(MSG_ENTITY, sf);
if(sf & 1)
{
vector o;
float n;
+
W_SetupShot(self, FALSE, 2, "", 0, autocvar_g_balance_tuba_damage);
n = Tuba_GetNote(self, hittype);
+ hittype = 0;
+ if(self.tuba_instrument & 1)
+ hittype |= HITTYPE_SECONDARY;
+ if(self.tuba_instrument & 2)
+ hittype |= HITTYPE_BOUNCE;
+ if(self.tuba_instrument & 4)
+ hittype |= HITTYPE_HEADSHOT;
+
if(self.tuba_note)
{
if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument)
precache_model ("models/weapons/g_tuba.md3");
precache_model ("models/weapons/v_tuba.md3");
precache_model ("models/weapons/h_tuba.iqm");
+ precache_model ("models/weapons/g_akordeon.md3");
+ precache_model ("models/weapons/v_akordeon.md3");
+ precache_model ("models/weapons/h_akordeon.iqm");
//float i;
//for(i = -18; i <= +27; ++i)
}
else if (req == WR_RELOAD)
{
- // TODO switch to alternate instruments :)
+ // switch to alternate instruments :)
if(self.weaponentity.state == WS_READY)
{
- /*
switch(self.tuba_instrument)
{
case 0:
self.tuba_instrument = 1;
- self.weaponname = "laser";
+ self.weaponname = "akordeon";
break;
case 1:
self.tuba_instrument = 0;
self.weaponname = "tuba";
break;
}
- */
W_SetupShot(self, FALSE, 0, "", 0, 0);
pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1);
self.weaponentity.state = WS_INUSE;
else if (req == WR_CHECKAMMO2)
return TRUE; // TODO use fuel?
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_tuba(float req)
}
else if (req == WR_SUICIDEMESSAGE)
{
- w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Tuba");
+ float instr;
+ instr = 0;
+ if(w_deathtype & HITTYPE_SECONDARY)
+ instr |= 1;
+ if(w_deathtype & HITTYPE_BOUNCE)
+ instr |= 2;
+ if(w_deathtype & HITTYPE_HEADSHOT)
+ instr |= 4;
+ switch(instr)
+ {
+ default:
+ case 0: // Tuba
+ w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Tuba");
+ break;
+ case 1: // Accordeon
+ w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Accordeon");
+ break;
+ }
}
else if (req == WR_KILLMESSAGE)
{
- w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Tuba");
+ float instr;
+ instr = 0;
+ if(w_deathtype & HITTYPE_SECONDARY)
+ instr |= 1;
+ if(w_deathtype & HITTYPE_BOUNCE)
+ instr |= 2;
+ if(w_deathtype & HITTYPE_HEADSHOT)
+ instr |= 4;
+ switch(instr)
+ {
+ default:
+ case 0: // Tuba
+ w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Tuba");
+ break;
+ case 1: // Accordeon
+ w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Accordeon");
+ break;
+ }
}
return TRUE;
}
W_Reload(min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo), autocvar_g_balance_uzi_reload_ammo, autocvar_g_balance_uzi_reload_time, "weapons/reload.wav");
}
return TRUE;
-};
+}
#endif
#ifdef CSQC
float w_uzi(float req)
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s was sniped by %s");
+ w_deathtypestring = _("%s was sniped by %s's machine gun");
else
- w_deathtypestring = _("%s was riddled full of holes by %s");
+ w_deathtypestring = _("%s was riddled full of holes by %s's machine gun");
}
return TRUE;
}
void WaypointSprite_Init()
{
- waypointsprite_limitedrange = autocvar_g_waypointsprite_limitedrange;
- waypointsprite_deployed_lifetime = autocvar_g_waypointsprite_deployed_lifetime;
- waypointsprite_deadlifetime = autocvar_g_waypointsprite_deadlifetime;
+ waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange;
+ waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime;
+ waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime;
}
void WaypointSprite_InitClient(entity e)
{
entity wz;
vector vf, vr, vu;
+ WarpZone_trace_forent = forent;
WarpZone_trace_firstzone = world;
WarpZone_trace_lastzone = world;
WarpZone_Trace_InitTransform();
}
else
{
- tracebox(org, mi, ma, end, nomonsters, forent);
+ tracebox(org, mi, ma, end, nomonsters, WarpZone_trace_forent);
if(cb)
cb(org, trace_endpos, end);
return;
nomonsters_adjusted = nomonsters;
break;
}
- if((contentshack = (forent.dphitcontentsmask && !(forent.dphitcontentsmask & DPCONTENTS_SOLID))))
- BITSET_ASSIGN(forent.dphitcontentsmask, DPCONTENTS_SOLID);
+ if((contentshack = (WarpZone_trace_forent.dphitcontentsmask && !(WarpZone_trace_forent.dphitcontentsmask & DPCONTENTS_SOLID))))
+ BITSET_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID);
// if starting in warpzone, first transform
wz = WarpZone_Find(org + mi, org + ma);
trace_ent = world;
break;
}
- tracebox(org, mi, ma, end, nomonsters_adjusted, forent);
+ tracebox(org, mi, ma, end, nomonsters_adjusted, WarpZone_trace_forent);
if(cb)
cb(org, trace_endpos, end);
if(sol < 0)
break;
if(trace_ent.classname != "trigger_warpzone")
{
- if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & forent.dphitcontentsmask) == DPCONTENTS_SOLID))
+ if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & WarpZone_trace_forent.dphitcontentsmask) == DPCONTENTS_SOLID))
{
// continue the trace, ignoring this hit (we only care for warpzones)
org = trace_endpos + normalize(end - org);
end = WarpZone_TransformOrigin(wz, end);
// we got warped, so let's step back a bit
- tracebox(org, mi, ma, org + normalize(org - end) * 32, nomonsters_adjusted, forent);
+ tracebox(org, mi, ma, org + normalize(org - end) * 32, nomonsters_adjusted, WarpZone_trace_forent);
org = trace_endpos;
}
WarpZone_MakeAllOther();
:fail
if(contentshack)
- BITCLR_ASSIGN(forent.dphitcontentsmask, DPCONTENTS_SOLID);
+ BITCLR_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID);
trace_startsolid = sol;
v_forward = vf;
v_right = vr;
o0 = e.origin;
v0 = e.velocity;
+ WarpZone_trace_forent = forent;
WarpZone_trace_firstzone = world;
WarpZone_trace_lastzone = world;
WarpZone_Trace_InitTransform();
WarpZone_tracetoss_time = 0;
if(!warpzone_warpzones_exist)
{
- tracetoss(e, forent);
+ tracetoss(e, WarpZone_trace_forent);
if(cb)
cb(e.origin, trace_endpos, trace_endpos);
dt = vlen(e.origin - o0) / vlen(e.velocity);
trace_ent = world;
break;
}
- tracetoss(e, forent);
+ tracetoss(e, WarpZone_trace_forent);
if(cb)
cb(e.origin, trace_endpos, trace_endpos);
dt = vlen(trace_endpos - e.origin) / vlen(e.velocity);
// we got warped, so let's step back a bit
e.velocity = -e.velocity;
- tracetoss(e, forent);
+ tracetoss(e, WarpZone_trace_forent);
dt = vlen(trace_endpos - e.origin) / vlen(e.velocity);
WarpZone_tracetoss_time -= dt;
e.origin = trace_endpos;
void WarpZone_MakeAllOther();
#define MOVE_NOTHING -1
+entity WarpZone_trace_forent; // temp, callback is allowed to change it
typedef void(vector start, vector hit, vector end) WarpZone_trace_callback_t; // called on every elementary trace
const var WarpZone_trace_callback_t WarpZone_trace_callback_t_null;
entity WarpZone_trace_transform; // transform accumulator during a trace
return 0;
print("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n");
+ print("Entity type: ", player.classname, "\n");
+ print("Origin: ", vtos(player.origin), "\n");
+ print("Velocity: ", vtos(player.velocity), "\n");
// retry previous move
setorigin(player, player.warpzone_oldorigin);
--- /dev/null
+akordeon
+{
+ dpglossexponentmod 64
+ dpreflectcube env/exomorph/exomorph
+ {
+ map models/weapons/akordeon.tga
+ rgbgen lightingDiffuse
+ }
+}
\ No newline at end of file
--- /dev/null
+meat
+{
+ surfaceparm nomarks
+ {
+ map textures/meat
+ }
+ {
+ map $lightmap
+ }
+}
+
+meat_alien
+{
+ surfaceparm nomarks
+ {
+ map textures/meat_alien
+ }
+ {
+ map $lightmap
+ }
+}
+
+meat_robot
+{
+ surfaceparm nomarks
+ {
+ map textures/meat_robot
+ }
+ {
+ map $lightmap
+ }
+}
+
+eyeblood
+{
+ surfaceparm nomarks
+ {
+ map textures/eyeblood
+ }
+ {
+ map $lightmap
+ }
+}
+
+nutsandbolts1
+{
+ surfaceparm nomarks
+ {
+ map textures/nutsandbolts1
+ }
+ {
+ map $lightmap
+ }
+}
+
+nutsandbolts3
+{
+ surfaceparm nomarks
+ {
+ map textures/nutsandbolts3
+ }
+ {
+ map $lightmap
+ }
+}
+
+nutsandbolts4
+{
+ surfaceparm nomarks
+ {
+ map textures/nutsandbolts4
+ }
+ {
+ map $lightmap
+ }
+}
+
+nutsandbolts5
+{
+ surfaceparm nomarks
+ {
+ map textures/nutsandbolts5
+ }
+ {
+ map $lightmap
+ }
+}
+
+nutsandboltssteel
+{
+ surfaceparm nomarks
+ {
+ map textures/nutsandbolts3
+ tcgen environment
+ }
+ {
+ map $lightmap
+ }
+}
+
+models/gibs/chunk.mdl_0
+{
+ surfaceparm nomarks
+ {
+ map models/gibs/chunk.mdl_0
+ tcgen environment
+ }
+ {
+ map $lightmap
+ }
+}
+++ /dev/null
-nutsandboltssteel
-{
- {
- map textures/nutsandbolts3
- tcgen environment
- }
- {
- map $lightmap
- }
-}
+evil_basewall/mtl_gray
+{
+ {
+ map textures/exx/base/base_metal01
+ rgbgen lightingDiffuse
+ }
+}
+
models/turrets/tesla_chrome
{
--- /dev/null
+r=44642
+
+base=261.6
+ls=$((7646/2))
+le=$((10378/2))
+for n in -18 -12 -6; do
+ this=`echo "440*e(l(2)/12*($n+60-69))" | bc -l`
+ f=`echo "$r * $this / $base + 0.5" | bc -l`
+ f=${f%.*}
+ echo "$r -> $f"
+ if [ "$f" -gt 48000 ]; then
+ o="-r 48000"
+ s=`echo "$ls * 48000 / $f + 0.5" | bc -l`
+ s=${s%.*}
+ e=`echo "$le * 48000 / $f + 0.5" | bc -l`
+ e=${e%.*}
+ else
+ o=
+ s=$ls
+ e=$le
+ fi
+ sox -r "$f" 023_Tango_Accordion-0.wav $o "tuba1_loopnote$n.wav"
+ oggenc -c "LOOP_START=$s" -c "LOOP_END=$e" -q8 -o "tuba1_loopnote$n.ogg" "tuba1_loopnote$n.wav"
+done
+
+base=659.191
+ls=$((6326/2))
+le=$((7140/2))
+for n in 0 6 12 18 24; do
+ this=`echo "440*e(l(2)/12*($n+60-69))" | bc -l`
+ f=`echo "$r * $this / $base + 0.5" | bc -l`
+ f=${f%.*}
+ echo "$r -> $f"
+ if [ "$f" -gt 48000 ]; then
+ o="-r 48000"
+ s=`echo "$ls * 48000 / $f + 0.5" | bc -l`
+ s=${s%.*}
+ e=`echo "$le * 48000 / $f + 0.5" | bc -l`
+ e=${e%.*}
+ else
+ o=
+ s=$ls
+ e=$le
+ fi
+ sox -r "$f" 023_Tango_Accordion-1.wav $o "tuba1_loopnote$n.wav"
+ oggenc -c "LOOP_START=$s" -c "LOOP_END=$e" -q8 -o "tuba1_loopnote$n.ogg" "tuba1_loopnote$n.wav"
+done
set g_vehicle_racer_blowup_edgedamage 15
set g_vehicle_racer_blowup_forceintensity 250
+set g_vehicle_racer_bouncefactor 0.25 // Factor of old velocity to keep after colission
+set g_vehicle_racer_bouncestop 0 // if != 0, New veloctiy after bounce = 0 if new velocity < this
+set g_vehicle_racer_bouncepain "35 2 250" // "minspeed_for_pain speedchange_to_pain_factor max_damage"
+
set g_vehicle_racer_mass 900
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_mass 2200
set g_vehicle_spiderbot_mass 5000
+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
+set g_vehicle_spiderbot_bouncepain "0 0 0" // "minspeed_for_pain speedchange_to_pain_factor max_damage"
set cl_vehicle_spiderbot_cross_alpha 0.4
set cl_vehicle_spiderbot_cross_size 1