From: Rudolf Polzer Date: Sun, 9 Oct 2011 14:18:34 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/fruitiex/animations' X-Git-Tag: xonotic-v0.6.0~40^2~76 X-Git-Url: http://de.git.xonotic.org/?a=commitdiff_plain;h=60ed95fe707decf91bb54393d4c11ee4faa2e418;hp=671f916094a738f4c8443b9c2153466444b59270;p=xonotic%2Fxonotic-data.pk3dir.git Merge remote-tracking branch 'origin/fruitiex/animations' --- diff --git a/balance25.cfg b/balance25.cfg index 81381f463..91db8f238 100644 --- a/balance25.cfg +++ b/balance25.cfg @@ -155,6 +155,13 @@ set g_balance_firetransfer_time 0.9 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) @@ -179,6 +186,13 @@ set g_balance_falldamage_minspeed 1400 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 @@ -209,6 +223,7 @@ 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_damagedbycontents 0 // }}} // {{{ weapon properties @@ -258,11 +273,15 @@ set g_balance_shotgun_primary_ammo 1 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 @@ -406,6 +425,7 @@ set g_balance_electro_secondary_animtime 0.3 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 @@ -512,7 +532,7 @@ set g_balance_nex_charge_rate 0.1 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 @@ -533,6 +553,8 @@ set g_balance_minstanex_reload_time 2 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 @@ -548,9 +570,13 @@ set g_balance_hagar_secondary_load_max 4 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 @@ -615,6 +641,8 @@ set g_balance_hook_secondary_refire 3 // don't drop too many bombs... 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 diff --git a/balanceFruit.cfg b/balanceFruit.cfg index 9e73743e9..fac3faa20 100644 --- a/balanceFruit.cfg +++ b/balanceFruit.cfg @@ -155,6 +155,13 @@ set g_balance_firetransfer_time 0.9 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) @@ -179,6 +186,13 @@ set g_balance_falldamage_minspeed 800 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 @@ -209,6 +223,7 @@ 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_damagedbycontents 0 // }}} // {{{ weapon properties @@ -258,11 +273,15 @@ set g_balance_shotgun_primary_ammo 1 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 @@ -406,6 +425,7 @@ set g_balance_electro_secondary_animtime 0.2 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 @@ -533,6 +553,8 @@ set g_balance_minstanex_reload_time 2 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 @@ -548,9 +570,13 @@ set g_balance_hagar_secondary_load_max 4 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 @@ -615,6 +641,8 @@ set g_balance_hook_secondary_refire 3 // don't drop too many bombs... 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 diff --git a/balanceLeeStricklin.cfg b/balanceLeeStricklin.cfg index b73360f20..57af50893 100644 --- a/balanceLeeStricklin.cfg +++ b/balanceLeeStricklin.cfg @@ -155,6 +155,13 @@ 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_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) @@ -179,6 +186,13 @@ set g_balance_falldamage_minspeed 1400 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 @@ -209,6 +223,7 @@ 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_damagedbycontents 0 // }}} // {{{ weapon properties @@ -258,11 +273,15 @@ set g_balance_shotgun_primary_ammo 1 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 @@ -406,6 +425,7 @@ set g_balance_electro_secondary_animtime 0.3 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 @@ -512,7 +532,7 @@ set g_balance_nex_charge_rate 0.1 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 "" @@ -533,6 +553,8 @@ set g_balance_minstanex_reload_time 2 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 @@ -548,9 +570,13 @@ set g_balance_hagar_secondary_load_max 4 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 @@ -615,6 +641,8 @@ set g_balance_hook_secondary_refire 3 // don't drop too many bombs... 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 diff --git a/balanceXonotic.cfg b/balanceXonotic.cfg index 182e66cb1..86e36f827 100644 --- a/balanceXonotic.cfg +++ b/balanceXonotic.cfg @@ -153,8 +153,15 @@ set g_weaponforcefactor 1 "weapon force multiplier" 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) @@ -179,6 +186,13 @@ set g_balance_falldamage_minspeed 900 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 @@ -208,14 +222,15 @@ set g_balance_grapplehook_force_rubber_overstretch 1000 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 @@ -225,7 +240,7 @@ set g_balance_laser_primary_lifetime 5 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 @@ -260,12 +275,16 @@ set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu 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 @@ -273,14 +292,14 @@ 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 @@ -289,12 +308,12 @@ set g_balance_uzi_first 1 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 @@ -319,7 +338,7 @@ set g_balance_grenadelauncher_primary_lifetime2 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 @@ -338,7 +357,7 @@ set g_balance_grenadelauncher_secondary_lifetime_stick 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 @@ -375,8 +394,8 @@ set g_balance_minelayer_reload_time 2 // }}} // {{{ 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 @@ -406,11 +425,12 @@ set g_balance_electro_secondary_animtime 0.2 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 @@ -512,7 +532,7 @@ set g_balance_nex_charge_rate 0.4 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 @@ -532,12 +552,14 @@ set g_balance_minstanex_reload_time 2 // {{{ 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 @@ -545,14 +567,18 @@ set g_balance_hagar_secondary_load_speed 0.5 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 @@ -573,7 +599,7 @@ set g_balance_rocketlauncher_lifetime 10 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 @@ -591,7 +617,7 @@ set g_balance_rocketlauncher_reload_time 2 // {{{ 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 @@ -607,7 +633,7 @@ set g_balance_hook_secondary_damage 25 // not much 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 @@ -615,6 +641,8 @@ set g_balance_hook_secondary_refire 3 // don't drop too many bombs... 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 diff --git a/balancetZork.cfg b/balancetZork.cfg index fd229feb9..b7fd9641d 100644 --- a/balancetZork.cfg +++ b/balancetZork.cfg @@ -155,6 +155,13 @@ set g_balance_firetransfer_time 0.9 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) @@ -179,6 +186,13 @@ set g_balance_falldamage_minspeed 800 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 @@ -209,6 +223,7 @@ 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_damagedbycontents 0 // }}} // {{{ weapon properties @@ -258,11 +273,15 @@ set g_balance_shotgun_primary_ammo 1 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 @@ -406,6 +425,7 @@ set g_balance_electro_secondary_animtime 0.15 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 @@ -511,7 +531,7 @@ set g_balance_nex_charge_rate 0.35 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 @@ -532,6 +552,8 @@ set g_balance_minstanex_reload_time 2 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 @@ -547,9 +569,13 @@ set g_balance_hagar_secondary_load_max 4 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 @@ -614,6 +640,8 @@ set g_balance_hook_secondary_refire 3 // don't drop too many bombs... 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 diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 3f1ca3f53..8ac7df977 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -53,6 +53,8 @@ alias asay_drop "say_team (%l) dropped %w ; impulse 17" 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" @@ -536,7 +538,6 @@ seta g_maplist_selectrandom 0 "if 1, a random map will be chosen as next map - D 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 @@ -552,6 +553,7 @@ alias clearmap "disconnect" 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" @@ -1039,8 +1041,7 @@ bind MWHEELDOWN weapprev bind r reload bind BACKSPACE dropweapon bind g dropweapon -// TODO change this to "use" once we can -bind f +use +bind f use // misc bind e +hook @@ -2160,11 +2161,20 @@ set g_playerstats_debug 0 "when 1, player stats are dumped to the console too" // create this cvar in case the engine did not set snd_soundradius 1200 +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" diff --git a/effectinfo.txt b/effectinfo.txt index bf631fb25..70f5fbb4c 100644 --- a/effectinfo.txt +++ b/effectinfo.txt @@ -1225,7 +1225,7 @@ trailspacing 4 type static color 0xffdf72 0x811200 tex 48 55 -size 1 2 +size 5 2 sizeincrease -15 alpha 100 144 988 airfriction 8 diff --git a/models/gibs/chunk.mdl_0.tga b/models/gibs/chunk.mdl_0.tga new file mode 100644 index 000000000..4f4dd2900 Binary files /dev/null and b/models/gibs/chunk.mdl_0.tga differ diff --git a/models/gibs/gib1.md3 b/models/gibs/gib1.md3 deleted file mode 100644 index 276982da5..000000000 Binary files a/models/gibs/gib1.md3 and /dev/null differ diff --git a/models/gibs/gib1.mdl b/models/gibs/gib1.mdl deleted file mode 100644 index 8f8501cb0..000000000 Binary files a/models/gibs/gib1.mdl and /dev/null differ diff --git a/models/gibs/gib2.md3 b/models/gibs/gib2.md3 deleted file mode 100644 index f5a2f7362..000000000 Binary files a/models/gibs/gib2.md3 and /dev/null differ diff --git a/models/gibs/gib2.mdl b/models/gibs/gib2.mdl deleted file mode 100644 index b4b7425ee..000000000 Binary files a/models/gibs/gib2.mdl and /dev/null differ diff --git a/models/gibs/gib3.md3 b/models/gibs/gib3.md3 deleted file mode 100644 index 8a38b42cb..000000000 Binary files a/models/gibs/gib3.md3 and /dev/null differ diff --git a/models/gibs/gib3.mdl b/models/gibs/gib3.mdl deleted file mode 100644 index 17279df13..000000000 Binary files a/models/gibs/gib3.mdl and /dev/null differ diff --git a/models/gibs/gib4.md3 b/models/gibs/gib4.md3 deleted file mode 100644 index dd4c5b53d..000000000 Binary files a/models/gibs/gib4.md3 and /dev/null differ diff --git a/models/gibs/gib5.md3 b/models/gibs/gib5.md3 deleted file mode 100644 index 6a51eb220..000000000 Binary files a/models/gibs/gib5.md3 and /dev/null differ diff --git a/models/gibs/gib6.md3 b/models/gibs/gib6.md3 deleted file mode 100644 index 956c9022b..000000000 Binary files a/models/gibs/gib6.md3 and /dev/null differ diff --git a/qcsrc/Makefile b/qcsrc/Makefile index de44b785c..e2be8a841 100644 --- a/qcsrc/Makefile +++ b/qcsrc/Makefile @@ -27,17 +27,17 @@ qc-recursive: ../menu.dat ../progs.dat ../csprogs.dat clean: rm -f ../progs.dat ../menu.dat ../csprogs.dat -FILES_CSPROGS = $(shell find client common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) server/w_*.qc +FILES_CSPROGS = $(shell find client common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc) ../csprogs.dat: $(FILES_CSPROGS) @echo make[1]: Entering directory \`$(PWD)/client\' cd client && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS) -FILES_PROGS = $(shell find server common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) server/w_*.qc +FILES_PROGS = $(shell find server common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc) ../progs.dat: $(FILES_PROGS) @echo make[1]: Entering directory \`$(PWD)/server\' cd server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS) -FILES_MENU = $(shell find menu common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) server/w_*.qc +FILES_MENU = $(shell find menu common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc) ../menu.dat: $(FILES_MENU) @echo make[1]: Entering directory \`$(PWD)/menu\' cd menu && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_MENU) diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 606123ad1..606bbc92b 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -595,7 +595,7 @@ void GameCommand(string msg) { 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; } @@ -610,7 +610,7 @@ void GameCommand(string msg) { 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; } diff --git a/qcsrc/client/csqc_builtins.qc b/qcsrc/client/csqc_builtins.qc index 48012e7a4..6ef34f35e 100644 --- a/qcsrc/client/csqc_builtins.qc +++ b/qcsrc/client/csqc_builtins.qc @@ -336,3 +336,15 @@ float trace_dphitcontents; float trace_networkentity; string(string search, string replace, string subject) strreplace = #484; + +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! diff --git a/qcsrc/client/csqc_constants.qc b/qcsrc/client/csqc_constants.qc index e82f4399b..f6e04e7b3 100644 --- a/qcsrc/client/csqc_constants.qc +++ b/qcsrc/client/csqc_constants.qc @@ -1,4 +1,4 @@ -const entity NULL = world; +#define NULL world // Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask) const float MASK_ENGINE = 1; diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 043b5ea98..fb47d9598 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -2471,19 +2471,20 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count) entity tm, pl; #define SCOREPANEL_MAX_ENTRIES 6 #define SCOREPANEL_ASPECTRATIO 2 - const float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES); - const vector fontsize = '1 1 0' * (mySize_y/entries); + float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES); + vector fontsize = '1 1 0' * (mySize_y/entries); vector rgb, score_color; rgb = '1 1 1'; score_color = '1 1 1'; - const float name_size = mySize_x*0.75; - const float spacing_size = mySize_x*0.04; + float name_size = mySize_x*0.75; + float spacing_size = mySize_x*0.04; const float highlight_alpha = 0.2; float i, me_printed, first_pl; string s; - i, first_pl = 0; + i = 0; + first_pl = 0; if (autocvar__hud_configure) { float players_per_team; @@ -2928,7 +2929,7 @@ float vote_change; // "time" when vote_active changed 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) @@ -2938,6 +2939,8 @@ void HUD_VoteWindow(void) print(_("^1You must answer before entering hud configure mode\n")); cvar_set("_hud_configure", "0"); } + if(vote_called_vote) + strunzone(vote_called_vote); vote_called_vote = strzone(_("^2Name ^7instead of \"^1Unregistered player^7\" in stats")); uid2name_dialog = 1; } diff --git a/qcsrc/client/hud_config.qc b/qcsrc/client/hud_config.qc index 109a9cf54..f26f65ea5 100644 --- a/qcsrc/client/hud_config.qc +++ b/qcsrc/client/hud_config.qc @@ -680,7 +680,7 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary) float k, level, start_pos_x; vector candidate_pos; const float LEVELS_NUM = 4; - const float level_height = vid_conheight / LEVELS_NUM; + float level_height = vid_conheight / LEVELS_NUM; :find_tab_panel level = floor(tab_panel_pos_y / level_height) * level_height; //starting level candidate_pos_x = (!tab_backward) ? vid_conwidth : 0; diff --git a/qcsrc/client/projectile.qc b/qcsrc/client/projectile.qc index 31fecfaee..37ad89da5 100644 --- a/qcsrc/client/projectile.qc +++ b/qcsrc/client/projectile.qc @@ -283,14 +283,14 @@ void Ent_Projectile() 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; diff --git a/qcsrc/client/tuba.qc b/qcsrc/client/tuba.qc index 7a29154d6..6e1c1f9bd 100644 --- a/qcsrc/client/tuba.qc +++ b/qcsrc/client/tuba.qc @@ -1,11 +1,13 @@ #define TUBA_MIN -18 #define TUBA_MAX 27 +#define TUBA_INSTRUMENTS 1 -#define TUBA_STARTNOTE(n) strcat("weapons/tuba_loopnote", ftos(n), ".wav") +#define TUBA_STARTNOTE(i,n) strcat("weapons/tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n), ".wav") .float note; // note .float attenuate; // if set, attenuate it .float cnt; // current volume .float count; // initial volume +.float tuba_instrument; float Tuba_PitchStep; @@ -34,23 +36,23 @@ void tubasound(entity e, float restart) if(e.note - m < TUBA_MIN) { if(restart) - snd1 = TUBA_STARTNOTE(e.note - m + Tuba_PitchStep); + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m + Tuba_PitchStep); p1 = pow(2.0, (m - Tuba_PitchStep) / 12.0); } else if(e.note - m + Tuba_PitchStep > TUBA_MAX) { if(restart) - snd1 = TUBA_STARTNOTE(e.note - m); + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m); p1 = pow(2.0, m / 12.0); } else { if(restart) - snd1 = TUBA_STARTNOTE(e.note - m); + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m); f1 = cos(M_PI_2 * m / Tuba_PitchStep); p1 = pow(2.0, m / 12.0); if(restart) - snd2 = TUBA_STARTNOTE(e.note - m + Tuba_PitchStep); + snd2 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m + Tuba_PitchStep); f2 = sin(M_PI_2 * m / Tuba_PitchStep); p2 = pow(2.0, (m - Tuba_PitchStep) / 12.0); } @@ -58,7 +60,7 @@ void tubasound(entity e, float restart) else { if(restart) - snd1 = TUBA_STARTNOTE(e.note); + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note); } sound7(e, CH_TUBA, snd1, e.cnt * f1, e.attenuate * autocvar_g_balance_tuba_attenuation, 100 * p1, 0); @@ -68,7 +70,7 @@ void tubasound(entity e, float restart) else { if(restart) - snd1 = TUBA_STARTNOTE(e.note); + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note); sound(e, CH_TUBA, snd1, e.cnt, e.attenuate * autocvar_g_balance_tuba_attenuation); } } @@ -103,6 +105,7 @@ void Ent_TubaNote_UpdateSound() self.enemy.cnt = bound(0, VOL_BASE * autocvar_g_balance_tuba_volume, 1); self.enemy.count = self.enemy.cnt; self.enemy.note = self.note; + self.enemy.tuba_instrument = self.tuba_instrument; tubasound(self.enemy, 1); } @@ -114,47 +117,63 @@ void Ent_TubaNote_StopSound() void Ent_TubaNote(float bIsNew) { - float f, n; + float f, n, i, att; f = ReadByte(); - n = floor(f / 2) - 42; - if(n != self.note || bIsNew) - if(self.enemy) - Ent_TubaNote_StopSound(); - if(!self.enemy) + + if(f & 1) { - self.enemy = spawn(); - self.enemy.classname = "tuba_note"; - if(Tuba_PitchStep) + n = ReadChar(); + i = ReadByte(); + att = (i & 1); + i = floor(i / 2); + + if(n != self.note || i != self.tuba_instrument || bIsNew) + { + if(self.enemy) + Ent_TubaNote_StopSound(); + } + + if(!self.enemy) + { + self.enemy = spawn(); + self.enemy.classname = "tuba_note"; + if(Tuba_PitchStep) + { + self.enemy.enemy = spawn(); + self.enemy.enemy.classname = "tuba_note_2"; + } + bIsNew = TRUE; + } + + self.enemy.attenuate = att; + + if(bIsNew) { - self.enemy.enemy = spawn(); - self.enemy.enemy.classname = "tuba_note_2"; + self.note = n; + self.tuba_instrument = i; + Ent_TubaNote_UpdateSound(); } - bIsNew = TRUE; } - if(f & 1) + + if(f & 2) { self.enemy.origin_x = ReadCoord(); self.enemy.origin_y = ReadCoord(); self.enemy.origin_z = ReadCoord(); setorigin(self.enemy, self.enemy.origin); - self.enemy.attenuate = ReadByte(); if(self.enemy.enemy) setorigin(self.enemy.enemy, self.enemy.origin); } + self.think = Ent_TubaNote_StopSound; self.entremove = Ent_TubaNote_StopSound; self.enemy.think = Ent_TubaNote_Think; self.enemy.nextthink = time + 10; - if(bIsNew) - { - self.note = n; - Ent_TubaNote_UpdateSound(); - } } void Tuba_Precache() { - float i; + float i, n; Tuba_PitchStep = autocvar_g_balance_tuba_pitchstep; if(Tuba_PitchStep) { @@ -164,9 +183,12 @@ void Tuba_Precache() Tuba_PitchStep = 0; } } - for(i = TUBA_MIN; i <= TUBA_MAX; ++i) + for(n = TUBA_MIN; n <= TUBA_MAX; ++n) { - if(!Tuba_PitchStep || (mod(i, Tuba_PitchStep) == 0)) - precache_sound(TUBA_STARTNOTE(i)); + if(!Tuba_PitchStep || (mod(n, Tuba_PitchStep) == 0)) + { + for(i = 0; i < TUBA_INSTRUMENTS; ++i) + precache_sound(TUBA_STARTNOTE(i, n)); + } } } diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 9c4057873..c59901b21 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -715,3 +715,4 @@ float HUD_MENU_ENABLE = 0; #define SERVERFLAG_ALLOW_FULLBRIGHT 1 #define SERVERFLAG_TEAMPLAY 2 +#define SERVERFLAG_PLAYERSTATS 4 diff --git a/qcsrc/common/gamecommand.qc b/qcsrc/common/gamecommand.qc index 518cf7497..c2b986bb8 100644 --- a/qcsrc/common/gamecommand.qc +++ b/qcsrc/common/gamecommand.qc @@ -191,6 +191,8 @@ float GameCommand_Generic(string command) print(" s localtime -----------------------> s : formats the current local time\n"); print(" s gmtime --------------------------> s : formats the current UTC time\n"); print(" time ------------------------------> f : seconds since VM start\n"); + print(" s /MD4 digest ---------------------> s : MD4 digest\n"); + print(" s /SHA256 digest ------------------> s : SHA256 digest\n"); print(" Set operations operate on 'such''strings'.\n"); print(" Unknown tokens insert their cvar value.\n"); print(" maplist add map\n"); @@ -790,6 +792,9 @@ float GameCommand_Generic(string command) rpn_set(strftime(FALSE, rpn_get())); } else if(rpncmd == "time") { rpn_pushf(time); + } else if(rpncmd == "digest") { + s = rpn_pop(); + rpn_set(digest_hex(s, rpn_get())); } else { rpn_push(cvar_string(rpncmd)); } diff --git a/qcsrc/common/urllib.qc b/qcsrc/common/urllib.qc index 0ab17f34a..2f7d0ee3a 100644 --- a/qcsrc/common/urllib.qc +++ b/qcsrc/common/urllib.qc @@ -1,5 +1,7 @@ -// files (-1 for URL) +// files .float url_fh; +#define URL_FH_CURL -1 +#define URL_FH_STDOUT -2 // URLs .string url_url; @@ -35,7 +37,7 @@ float url_URI_Get_Callback(float id, float status, string data) 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) @@ -76,7 +78,7 @@ float url_URI_Get_Callback(float id, float status, string data) } } -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; @@ -91,13 +93,13 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) // 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); @@ -105,6 +107,8 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) } e.url_wbufpos = 0; e.url_rbuf = -1; + e.url_ready = rdy; + e.url_ready_pass = pass; rdy(e, pass, URL_READY_CANWRITE); break; @@ -122,7 +126,7 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) 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; } @@ -131,7 +135,7 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) // 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; } @@ -140,9 +144,9 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) // 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; @@ -155,6 +159,25 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) 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; @@ -167,8 +190,10 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) 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 @@ -178,11 +203,11 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass) } // 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) @@ -205,7 +230,7 @@ void url_fclose(entity e, url_ready_func rdy, entity pass) 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); @@ -217,7 +242,7 @@ void url_fclose(entity e, url_ready_func rdy, entity pass) 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); @@ -229,8 +254,6 @@ void url_fclose(entity e, url_ready_func rdy, entity pass) // 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; @@ -240,17 +263,22 @@ void url_fclose(entity e, url_ready_func rdy, entity pass) 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); } } @@ -258,7 +286,7 @@ void url_fclose(entity e, url_ready_func rdy, entity pass) // 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"); @@ -268,6 +296,11 @@ string url_fgets(entity e) e.url_rbufpos += 1; return s; } + else if(e.url_fh == URL_FH_STDOUT) + { + // stdout + return string_null; + } else { // file @@ -278,7 +311,7 @@ string url_fgets(entity e) // 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"); @@ -286,9 +319,56 @@ void url_fputs(entity e, string s) 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); +} diff --git a/qcsrc/common/urllib.qh b/qcsrc/common/urllib.qh index a7735ed4f..f92178b2f 100644 --- a/qcsrc/common/urllib.qh +++ b/qcsrc/common/urllib.qh @@ -5,8 +5,8 @@ float URL_READY_CANREAD = 2; // 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); @@ -14,3 +14,5 @@ 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); diff --git a/qcsrc/menu/mbuiltin.qh b/qcsrc/menu/mbuiltin.qh index e5d366eb7..ffdc1bb91 100644 --- a/qcsrc/menu/mbuiltin.qh +++ b/qcsrc/menu/mbuiltin.qh @@ -341,3 +341,15 @@ string crypto_getidfp(string serveraddress) = #634; // retrieves the cached host string crypto_getencryptlevel(string serveraddress) = #635; // 0 if never encrypting, 1 supported, 2 requested, 3 required, appended by list of allowed methods in order of preference ("AES128"), preceded by a space each float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513; //description: + +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c index 6b14d1446..2711c57e7 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c @@ -72,6 +72,8 @@ string XonoticMutatorsDialog_toString(entity me) 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) @@ -191,7 +193,6 @@ void XonoticMutatorsDialog_fill(entity me) 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); @@ -200,6 +201,9 @@ void XonoticMutatorsDialog_fill(entity 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"))); diff --git a/qcsrc/menu/xonotic/dialog_settings_audio.c b/qcsrc/menu/xonotic/dialog_settings_audio.c index f85c2877c..bf3406142 100644 --- a/qcsrc/menu/xonotic/dialog_settings_audio.c +++ b/qcsrc/menu/xonotic/dialog_settings_audio.c @@ -127,6 +127,8 @@ void XonoticAudioSettingsTab_fill(entity me) 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")))); @@ -170,6 +172,6 @@ void XonoticAudioSettingsTab_fill(entity me) 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 diff --git a/qcsrc/menu/xonotic/serverlist.c b/qcsrc/menu/xonotic/serverlist.c index 6e9bf1790..f02d747cc 100644 --- a/qcsrc/menu/xonotic/serverlist.c +++ b/qcsrc/menu/xonotic/serverlist.c @@ -238,7 +238,7 @@ void XonoticServerList_refreshServerList(entity me, float mode) } else */ { - float m, o; + float m, o, i, n; // moin moin string s, typestr, modstr; s = me.filterString; @@ -261,15 +261,22 @@ void XonoticServerList_refreshServerList(entity me, float mode) // 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) == "!") @@ -277,6 +284,13 @@ void XonoticServerList_refreshServerList(entity me, float mode) 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 != "") { @@ -308,6 +322,13 @@ void XonoticServerList_draw(entity me) { 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); @@ -469,17 +490,17 @@ void ServerList_ShowFull_Click(entity box, entity me) me.ipAddressBox.cursorPos = 0; me.ipAddressBoxFocused = -1; } -void XonoticServerList_setSortOrder(entity me, float field, float direction) +void XonoticServerList_setSortOrder(entity me, float fld, float direction) { - if(me.currentSortField == field) + if(me.currentSortField == fld) direction = -me.currentSortOrder; me.currentSortOrder = direction; - me.currentSortField = field; - me.sortButton1.forcePressed = (field == SLIST_FIELD_PING); - me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME); - me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP); + me.currentSortField = fld; + me.sortButton1.forcePressed = (fld == SLIST_FIELD_PING); + me.sortButton2.forcePressed = (fld == SLIST_FIELD_NAME); + me.sortButton3.forcePressed = (fld == SLIST_FIELD_MAP); me.sortButton4.forcePressed = 0; - me.sortButton5.forcePressed = (field == SLIST_FIELD_NUMHUMANS); + me.sortButton5.forcePressed = (fld == SLIST_FIELD_NUMHUMANS); me.selectedItem = 0; if(me.selectedServer) strunzone(me.selectedServer); diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index 65a5d3e71..b8215d52c 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -325,6 +325,12 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data) } _Nex_ExtResponseSystem_UpdateTo = strzone(_Nex_ExtResponseSystem_UpdateTo); + + if(n >= 4) + { + _Nex_ExtResponseSystem_BannedServers = strzone(argv(3)); + _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 1; + } } } diff --git a/qcsrc/menu/xonotic/util.qh b/qcsrc/menu/xonotic/util.qh index 1720710d2..d8f66f4e9 100644 --- a/qcsrc/menu/xonotic/util.qh +++ b/qcsrc/menu/xonotic/util.qh @@ -47,3 +47,6 @@ void dialog_hudpanel_common_notoggle(entity me, string panelname); 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; diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 6ccaf71d4..777284841 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -120,6 +120,12 @@ float autocvar_g_balance_rifle_secondary_tracer; 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; @@ -215,6 +221,7 @@ float autocvar_g_balance_electro_secondary_bouncestop; 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; @@ -280,6 +287,7 @@ float autocvar_g_balance_grapplehook_length_min; 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; @@ -318,6 +326,8 @@ float autocvar_g_balance_hagar_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; @@ -331,10 +341,14 @@ float autocvar_g_balance_hagar_secondary_load_max; 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; @@ -397,6 +411,8 @@ float autocvar_g_balance_hook_secondary_power; 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; @@ -655,9 +671,13 @@ float autocvar_g_balance_shotgun_secondary_damage; 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; @@ -925,6 +945,7 @@ float autocvar_g_playerstats_debug; 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; @@ -1195,3 +1216,4 @@ float autocvar_welcome_message_time; float autocvar_sv_gameplayfix_gravityunaffectedbyticrate; float autocvar_g_trueaim_minrange; float autocvar_g_debug_defaultsounds; +float autocvar_g_loituma; diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 58d25b0e7..34a0cee02 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -662,6 +662,7 @@ void PutObserverInServer (void) self.classname = "observer"; self.iscreature = FALSE; + self.damagedbycontents = FALSE; self.health = -666; self.takedamage = DAMAGE_NO; self.solid = SOLID_NOT; @@ -899,6 +900,7 @@ void PutClientInServer (void) 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; @@ -1091,7 +1093,7 @@ void PutClientInServer (void) entity e; e = get_weaponinfo(j); if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars - self.weapon_load[j] = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); + self.(weapon_load[j]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); } oldself = self; @@ -2774,9 +2776,12 @@ void PlayerPreThink (void) MUTATOR_CALLHOOK(PlayerPreThink); - if(self.BUTTON_USE && !self.usekeypressed) - PlayerUseKey(); - self.usekeypressed = self.BUTTON_USE; + if(!self.cvar_cl_newusekeysupported) + { + if(self.BUTTON_USE && !self.usekeypressed) + PlayerUseKey(); + self.usekeypressed = self.BUTTON_USE; + } PrintWelcomeMessage(); diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 05a809dd3..15bb65262 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -21,7 +21,7 @@ void WeaponStats_ready(entity fh, entity pass, float status) 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")); @@ -46,9 +46,7 @@ void WeaponStats_ready(entity fh, entity pass, float status) } } 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 @@ -57,15 +55,19 @@ void WeaponStats_ready(entity fh, entity pass, float status) 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; } } @@ -76,7 +78,7 @@ void WeaponStats_Shutdown() 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 { @@ -134,6 +136,7 @@ void CopyBody(float keepvelocity) 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"; diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc index f0981f5e2..4a333934a 100644 --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@ -233,10 +233,10 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto s = strcat(s, " and ", ftos(thisammo), " ", Item_CounterFieldName(j)); // if our weapon is loaded, give its load back to the player - if(self.weapon_load[self.weapon] > 0) + if(self.(weapon_load[self.weapon]) > 0) { - own.ammofield += self.weapon_load[self.weapon]; - self.weapon_load[self.weapon] = -1; // schedule the weapon for reloading + own.ammofield += self.(weapon_load[self.weapon]); + self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading } } } @@ -368,7 +368,7 @@ void W_WeaponFrame() e = get_weaponinfo(self.switchweapon); if(e.spawnflags & WEP_FLAG_RELOADABLE && cvar(strcat("g_balance_", e.netname, "_reload_ammo"))) // prevent accessing undefined cvars { - self.clip_load = self.weapon_load[self.switchweapon]; + self.clip_load = self.(weapon_load[self.switchweapon]); self.clip_size = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); } else diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc index 21a9bc942..b3b0e6ea0 100644 --- a/qcsrc/server/cl_weaponsystem.qc +++ b/qcsrc/server/cl_weaponsystem.qc @@ -127,11 +127,24 @@ vector w_shotorg; 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 @@ -241,20 +254,10 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m 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; @@ -853,6 +856,27 @@ void CL_ExteriorWeaponentity_Think() ang_x = -/* don't ask */ang_x; self.angles = ang; } + + if(autocvar_g_loituma) + { + vector moddir, modup; + vector modangles; + float t; + + t = time * autocvar_g_loituma; + + modangles_x = t * 360; + modangles_y = 90; + modangles_z = 0; + + self.angles = + AnglesTransform_ToAngles( + AnglesTransform_Multiply( + AnglesTransform_FromAngles(self.angles), + AnglesTransform_FromAngles(modangles) + ) + ); + } } self.glowmod = self.owner.weaponentity_glowmod; @@ -1639,7 +1663,7 @@ void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload) if(ammo_reload) { self.clip_load -= ammo_use; - self.weapon_load[self.weapon] = self.clip_load; + self.(weapon_load[self.weapon]) = self.clip_load; } else self.(self.current_ammo) -= ammo_use; @@ -1668,7 +1692,7 @@ void W_ReloadedAndReady() self.(self.current_ammo) -= 1; } } - self.weapon_load[self.weapon] = self.clip_load; + self.(weapon_load[self.weapon]) = self.clip_load; // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, @@ -1751,5 +1775,5 @@ void W_Reload(float sent_ammo_min, float sent_ammo_amount, float sent_time, stri if(self.clip_load < 0) self.clip_load = 0; self.old_clip_load = self.clip_load; - self.clip_load = self.weapon_load[self.weapon] = -1; + self.clip_load = self.(weapon_load[self.weapon]) = -1; } diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index bc05d1b04..9c2e843d1 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -189,6 +189,7 @@ void setanim(entity e, vector anim, float looping, float override, float restart .float watersound_finished; .float iscreature; +.float damagedbycontents; .vector oldvelocity; .float pauseregen_finished; @@ -315,6 +316,7 @@ float default_weapon_alpha; .float cvar_cl_playerdetailreduction; .float cvar_cl_clippedspectating; .float cvar_cl_movement_track_canjump; +.float cvar_cl_newusekeysupported; .string cvar_g_xonoticversion; .string cvar_cl_weaponpriority; diff --git a/qcsrc/server/extensions.qh b/qcsrc/server/extensions.qh index 8422cf5df..57d943438 100644 --- a/qcsrc/server/extensions.qh +++ b/qcsrc/server/extensions.qh @@ -621,6 +621,13 @@ void(entity from, entity to) copyentity = #400; //description: //copies all data in the entity to another entity. +//DP_QC_CRC16 +//idea: divVerent +//darkplaces implementation: divVerent +//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. +//When caseinsensitive is set, the CRC is calculated of the lower cased string. +float(float caseinsensitive, string s, ...) crc16 = #494; + //DP_QC_CVAR_DEFSTRING //idea: id Software (Doom3), LordHavoc //darkplaces implementation: LordHavoc @@ -657,6 +664,24 @@ float CVAR_TYPEFLAG_ENGINE = 8; float CVAR_TYPEFLAG_HASDESCRIPTION = 16; float CVAR_TYPEFLAG_READONLY = 32; +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! + +//DP_QC_DIGEST_SHA256 +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//description: +//"SHA256" is also an allowed digest type + //DP_QC_EDICT_NUM //idea: 515 //DarkPlaces implementation: LordHavoc @@ -882,6 +907,30 @@ float GETTIME_CDTRACK = 4; //returns the playing time of the current cdtrack when passed to gettime() //see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels +//DP_QC_I18N +//idea: divVerent +//darkplaces implementation: divVerent +//description: +// +//The engine supports translating by gettext compatible .po files. +//progs.dat uses progs.dat..po +//menu.dat uses menu.dat..po +//csprogs.dat uses csprogs.dat..po +// +//To create a string that can be translated, define it as +// string dotranslate_FILENOTFOUND = "File not found"; +//Note: if the compiler does constant folding, this will only work if there is +//no other "File not found" string in the progs! +// +//Alternatively, if using the Xonotic patched fteqcc compiler, you can simplify +//this by using _("File not found") directly in the source code. +// +//The language is set by the "prvm_language" cvar: if prvm_language is set to +//"de", it will read progs.dat.de.po for translating strings in progs.dat. +// +//If prvm_language is set to to the special name "dump", progs.dat.pot which is +//a translation template to be edited by filling out the msgstr entries. + //DP_QC_LOG //darkplaces implementation: divVerent //builtin definitions: @@ -1209,12 +1258,14 @@ float(string name, string value) registercvar = #93; //DP_SND_FAKETRACKS //idea: requested + //darkplaces implementation: Elric //description: //the engine plays sound/cdtracks/track001.wav instead of cd track 1 and so on if found, this allows games and mods to have music tracks without using ambientsound. //Note: also plays .ogg with DP_SND_OGGVORBIS extension. //DP_SND_SOUND7_WIP1 +//DP_SND_SOUND7_WIP2 //idea: divVerent //darkplaces implementation: divVerent //builtin definitions: @@ -1225,8 +1276,9 @@ float SOUNDFLAG_RELIABLE = 1; //extensions to sound(): //- channel may be in the range from -128 to 127; channels -128 to 0 are "auto", // i.e. support multiple sounds at once, but cannot be stopped/restarted -//- a speed parameter has been reserved for later addition of pitch shifting. -// it MUST be set to 0 for now, meaning "no pitch change" +//- a value 0 in the speed parameter means no change; otherwise, it is a +// percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is +// half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2) //- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send // to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default); // similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE @@ -1614,6 +1666,8 @@ const float MOVETYPE_PHYSICS = 32; // need to be set before any physics_* builti const float SOLID_PHYSICS_BOX = 32; const float SOLID_PHYSICS_SPHERE = 33; const float SOLID_PHYSICS_CAPSULE = 34; +const float SOLID_PHYSICS_TRIMESH = 35; +const float SOLID_PHYSICS_CYLINDER = 36; //SOLID_BSP; //joint types: const float JOINTTYPE_POINT = 1; @@ -1636,6 +1690,8 @@ const float JOINTTYPE_FIXED = -1; // note that ODE does not support both in one anyway //field definitions: .float mass; // ODE mass, standart value is 1 +.vector massofs; // offsets a mass center out of object center, if not set a center of model bounds is used +.float friction; .float bouncefactor; .float bouncestop; .float jointtype; @@ -1646,7 +1702,6 @@ void(entity e, vector torque) physics_addtorque = #542; // add relative torque //description: provides Open Dynamics Engine support, requires extenal dll to be present or engine compiled with statical link option //be sure to checkextension for it to know if library is loaded and ready, also to enable physics set "physics_ode" cvar to 1 //note: this extension is highly experimental and may be unstable -//note: use SOLID_BSP on entities to get a trimesh collision models on them //DP_SV_PRINT //idea: id Software (QuakeWorld Server) @@ -2397,13 +2452,6 @@ string(string search, string replace, string subject) strireplace = #485; //description: //strreplace replaces all occurrences of 'search' with 'replace' in the string 'subject', and returns the result as a tempstring. //strireplace does the same but uses case-insensitive matching of the 'search' term -// -//DP_QC_CRC16 -//idea: divVerent -//darkplaces implementation: divVerent -//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. -//When caseinsensitive is set, the CRC is calculated of the lower cased string. -float(float caseinsensitive, string s, ...) crc16 = #494; //DP_SV_SHUTDOWN //idea: divVerent diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index 4f655ca57..5561c2df9 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -271,18 +271,22 @@ void GrapplingHookTouch (void) 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); } } @@ -324,6 +328,7 @@ void FireGrapplingHook (void) self.hook = missile; missile.reset = GrapplingHookReset; missile.classname = "grapplinghook"; + missile.flags = FL_PROJECTILE; missile.movetype = MOVETYPE_FLY; PROJECTILE_MAKETRIGGER(missile); @@ -349,6 +354,7 @@ void FireGrapplingHook (void) 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; diff --git a/qcsrc/server/g_triggers.qc b/qcsrc/server/g_triggers.qc index 6407cefaa..19442cd6c 100644 --- a/qcsrc/server/g_triggers.qc +++ b/qcsrc/server/g_triggers.qc @@ -1642,7 +1642,7 @@ void spawnfunc_trigger_multivibrator() self.state = 0; self.use = multivibrator_toggle; self.think = multivibrator_send; - self.nextthink = time; + self.nextthink = max(1, time); IFTARGETED multivibrator_reset(); diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 09daa245a..93157819e 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -1356,7 +1356,7 @@ void IntermissionThink() return; if(!mapvote_initialized) - if (time < intermission_exittime + 10 && !self.BUTTON_ATCK && !self.BUTTON_JUMP && !self.BUTTON_ATCK2 && !self.BUTTON_HOOK && !self.BUTTON_USE) + if (time < intermission_exittime + 10 && !(self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE)) return; MapVote_Start(); diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 9a848fa46..c80e9ca03 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -617,6 +617,7 @@ void GetCvars(float f) GetCvars_handleFloat(s, f, cvar_cl_allow_uid2name, "cl_allow_uid2name"); GetCvars_handleFloat(s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking"); GetCvars_handleFloat(s, f, cvar_cl_movement_track_canjump, "cl_movement_track_canjump"); + GetCvars_handleFloat(s, f, cvar_cl_newusekeysupported, "cl_newusekeysupported"); // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early) if (f > 0) @@ -1121,6 +1122,8 @@ string GetGametype(); // g_world.qc 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")) @@ -2042,7 +2045,6 @@ float MAX_IPBAN_URIS = 16; 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) { @@ -2063,10 +2065,6 @@ 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"); diff --git a/qcsrc/server/monsters/m_monsters.qc b/qcsrc/server/monsters/m_monsters.qc index ceb3f207c..ee77b5445 100644 --- a/qcsrc/server/monsters/m_monsters.qc +++ b/qcsrc/server/monsters/m_monsters.qc @@ -259,6 +259,7 @@ void() walkmonster_start_go = // 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 @@ -352,6 +353,7 @@ void() flymonster_start_go = } } self.iscreature = TRUE; + self.damagedbycontents = TRUE; force_retouch = 2; // mainly to detect teleports @@ -440,6 +442,7 @@ void() swimmonster_start_go = } } self.iscreature = TRUE; + self.damagedbycontents = TRUE; force_retouch = 2; // mainly to detect teleports diff --git a/qcsrc/server/mutators/mutator_invincibleproj.qc b/qcsrc/server/mutators/mutator_invincibleproj.qc new file mode 100644 index 000000000..d1ab52000 --- /dev/null +++ b/qcsrc/server/mutators/mutator_invincibleproj.qc @@ -0,0 +1,30 @@ +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; +} diff --git a/qcsrc/server/mutators/mutator_nix.qc b/qcsrc/server/mutators/mutator_nix.qc index 6e85e7aff..519d51daa 100644 --- a/qcsrc/server/mutators/mutator_nix.qc +++ b/qcsrc/server/mutators/mutator_nix.qc @@ -109,7 +109,7 @@ void NIX_GiveCurrentWeapon() entity e; e = get_weaponinfo(nix_weapon); if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars - self.weapon_load[nix_weapon] = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); + self.(weapon_load[nix_weapon]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); // nex too if(autocvar_g_balance_nex_charge) diff --git a/qcsrc/server/mutators/mutators.qh b/qcsrc/server/mutators/mutators.qh index d9fff4490..1ae28abe5 100644 --- a/qcsrc/server/mutators/mutators.qh +++ b/qcsrc/server/mutators/mutators.qh @@ -2,6 +2,7 @@ MUTATOR_DECLARATION(gamemode_keyhunt); MUTATOR_DECLARATION(gamemode_freezetag); MUTATOR_DECLARATION(gamemode_keepaway); +MUTATOR_DECLARATION(mutator_invincibleprojectiles); MUTATOR_DECLARATION(mutator_nix); MUTATOR_DECLARATION(mutator_dodging); MUTATOR_DECLARATION(mutator_rocketflying); diff --git a/qcsrc/server/playerstats.qc b/qcsrc/server/playerstats.qc index 9f40a453e..c6e7701e0 100644 --- a/qcsrc/server/playerstats.qc +++ b/qcsrc/server/playerstats.qc @@ -17,7 +17,9 @@ 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); @@ -154,12 +156,6 @@ void PlayerStats_TeamScore(float t, string event_id, float value) // TODO: doesn 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: @@ -241,9 +237,7 @@ 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 @@ -252,12 +246,14 @@ void PlayerStats_ready(entity fh, entity pass, float status) 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: @@ -283,8 +279,8 @@ void PlayerStats_Shutdown() 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 { @@ -295,6 +291,26 @@ void PlayerStats_Shutdown() } //#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) @@ -321,30 +337,12 @@ void PlayerStats_AddGlobalInfo(entity p) 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; diff --git a/qcsrc/server/playerstats.qh b/qcsrc/server/playerstats.qh index f546e5605..b99366434 100644 --- a/qcsrc/server/playerstats.qh +++ b/qcsrc/server/playerstats.qh @@ -44,9 +44,6 @@ void PlayerStats_TeamScore(float t, string event_id, float value); // 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); diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index c78b9f2fa..3ad4de20c 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -188,6 +188,7 @@ mutators/base.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 diff --git a/qcsrc/server/scores.qc b/qcsrc/server/scores.qc index 8d5fa100c..782c567ce 100644 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@ -56,7 +56,7 @@ float TeamScore_SendEntity(entity to, float sendflags) longflags = 0; for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2) - if(self.teamscores[i] > 127 || self.teamscores[i] <= -128) + if(self.(teamscores[i]) > 127 || self.(teamscores[i]) <= -128) longflags |= p; #if MAX_TEAMSCORE <= 8 @@ -70,9 +70,9 @@ float TeamScore_SendEntity(entity to, float sendflags) if(sendflags & p) { if(longflags & p) - WriteInt24_t(MSG_ENTITY, self.teamscores[i]); + WriteInt24_t(MSG_ENTITY, self.(teamscores[i])); else - WriteChar(MSG_ENTITY, self.teamscores[i]); + WriteChar(MSG_ENTITY, self.(teamscores[i])); } return TRUE; @@ -222,7 +222,7 @@ float PlayerScore_SendEntity(entity to, float sendflags) longflags = 0; for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2) - if(self.scores[i] > 127 || self.scores[i] <= -128) + if(self.(scores[i]) > 127 || self.(scores[i]) <= -128) longflags |= p; #if MAX_SCORE <= 8 @@ -236,9 +236,9 @@ float PlayerScore_SendEntity(entity to, float sendflags) if(sendflags & p) { if(longflags & p) - WriteInt24_t(MSG_ENTITY, self.scores[i]); + WriteInt24_t(MSG_ENTITY, self.(scores[i])); else - WriteChar(MSG_ENTITY, self.scores[i]); + WriteChar(MSG_ENTITY, self.(scores[i])); } return TRUE; diff --git a/qcsrc/server/sv_main.qc b/qcsrc/server/sv_main.qc index 15f43ad9e..ce5828aff 100644 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@ -1,28 +1,31 @@ - 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) @@ -30,31 +33,40 @@ void CreatureFrame (void) 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'); } } } @@ -70,7 +82,7 @@ void CreatureFrame (void) 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); diff --git a/qcsrc/server/t_teleporters.qc b/qcsrc/server/t_teleporters.qc index e069aec9f..02c15fb15 100644 --- a/qcsrc/server/t_teleporters.qc +++ b/qcsrc/server/t_teleporters.qc @@ -324,7 +324,11 @@ void WarpZone_PostTeleportPlayer_Callback(entity pl) UpdateCSQCProjectileAfterTeleport(pl); // "disown" projectiles after teleport 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 \n", pl.classname, ".\n"); pl.owner = world; + } if(pl.classname == "player") { // reset tracking of oldvelocity for impact damage (sudden velocity changes) diff --git a/qcsrc/server/tturrets/units/unit_ewheel.qc b/qcsrc/server/tturrets/units/unit_ewheel.qc index 86f5c4402..4858cafc6 100644 --- a/qcsrc/server/tturrets/units/unit_ewheel.qc +++ b/qcsrc/server/tturrets/units/unit_ewheel.qc @@ -287,6 +287,7 @@ void turret_ewheel_dinit() 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; diff --git a/qcsrc/server/tturrets/units/unit_walker.qc b/qcsrc/server/tturrets/units/unit_walker.qc index a438229cf..feb4b1f67 100644 --- a/qcsrc/server/tturrets/units/unit_walker.qc +++ b/qcsrc/server/tturrets/units/unit_walker.qc @@ -604,6 +604,7 @@ void turret_walker_dinit() 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; diff --git a/qcsrc/server/vehicles/vehicles.qc b/qcsrc/server/vehicles/vehicles.qc index 6006dcf92..c4e287538 100644 --- a/qcsrc/server/vehicles/vehicles.qc +++ b/qcsrc/server/vehicles/vehicles.qc @@ -42,7 +42,7 @@ void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id) entity axh; axh_id = bound(0, axh_id, MAX_AXH); - axh = own.AuxiliaryXhair[axh_id]; + axh = own.(AuxiliaryXhair[axh_id]); if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) { @@ -56,7 +56,7 @@ void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id) setorigin(axh, loc); axh.colormod = clr; axh.SendFlags = 0x01; - own.AuxiliaryXhair[axh_id] = axh; + own.(AuxiliaryXhair[axh_id]) = axh; } /* @@ -339,6 +339,7 @@ void vehicles_spawn() 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; @@ -974,6 +975,7 @@ float vehicle_initialize(string net_name, self.takedamage = DAMAGE_AIM; self.bot_attack = TRUE; self.iscreature = TRUE; + self.damagedbycontents = TRUE; self.hud = vhud; self.vehicle_die = dieproc; diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc index f1e33ec96..d0dd6eca6 100644 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@ -541,6 +541,48 @@ void fireBullet (vector start, vector dir, float spread, float damage, float for 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; diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc index 3866284a4..aa72d8ec1 100644 --- a/qcsrc/server/w_crylink.qc +++ b/qcsrc/server/w_crylink.qc @@ -616,7 +616,7 @@ float w_crylink(float req) return TRUE; ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo; - ammo_amount += self.weapon_load[WEP_CRYLINK] >= autocvar_g_balance_crylink_primary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) @@ -626,7 +626,7 @@ float w_crylink(float req) return TRUE; ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo; - ammo_amount += self.weapon_load[WEP_CRYLINK] >= autocvar_g_balance_crylink_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo; return ammo_amount; } else if (req == WR_RELOAD) diff --git a/qcsrc/server/w_electro.qc b/qcsrc/server/w_electro.qc index 526d4cd32..b127f5cba 100644 --- a/qcsrc/server/w_electro.qc +++ b/qcsrc/server/w_electro.qc @@ -83,13 +83,19 @@ void W_Plasma_Damage (entity inflictor, entity attacker, float damage, float dea { 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; @@ -175,6 +181,7 @@ void W_Electro_Attack2() 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; @@ -268,7 +275,7 @@ void lgbeam_think() { dt = min(dt, owner_player.clip_load / autocvar_g_balance_electro_primary_ammo); owner_player.clip_load = max(0, owner_player.clip_load - autocvar_g_balance_electro_primary_ammo * frametime); - owner_player.weapon_load[WEP_ELECTRO] = owner_player.clip_load; + owner_player.(weapon_load[WEP_ELECTRO]) = owner_player.clip_load; } else { @@ -507,19 +514,19 @@ float w_electro(float req) ammo_amount = 1; else ammo_amount = self.ammo_cells > 0; - ammo_amount += self.weapon_load[WEP_ELECTRO] > 0; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) > 0; } else { ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_primary_ammo; - ammo_amount += self.weapon_load[WEP_ELECTRO] >= autocvar_g_balance_electro_primary_ammo; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= autocvar_g_balance_electro_primary_ammo; } return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo; - ammo_amount += self.weapon_load[WEP_ELECTRO] >= autocvar_g_balance_electro_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= autocvar_g_balance_electro_secondary_ammo; return ammo_amount; } else if (req == WR_RESETPLAYER) diff --git a/qcsrc/server/w_fireball.qc b/qcsrc/server/w_fireball.qc index d916edd9f..31e5b6a02 100644 --- a/qcsrc/server/w_fireball.qc +++ b/qcsrc/server/w_fireball.qc @@ -115,6 +115,10 @@ void W_Fireball_Damage (entity inflictor, entity attacker, float damage, float d { 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) { @@ -365,13 +369,13 @@ float w_fireball(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_fuel >= autocvar_g_balance_fireball_primary_ammo; - ammo_amount += self.weapon_load[WEP_FIREBALL] >= autocvar_g_balance_fireball_primary_ammo; + ammo_amount += self.(weapon_load[WEP_FIREBALL]) >= autocvar_g_balance_fireball_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_fuel >= autocvar_g_balance_fireball_secondary_ammo; - ammo_amount += self.weapon_load[WEP_FIREBALL] >= autocvar_g_balance_fireball_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_FIREBALL]) >= autocvar_g_balance_fireball_secondary_ammo; return ammo_amount; } else if (req == WR_RESETPLAYER) diff --git a/qcsrc/server/w_grenadelauncher.qc b/qcsrc/server/w_grenadelauncher.qc index 1d2ee93b9..223d89fda 100644 --- a/qcsrc/server/w_grenadelauncher.qc +++ b/qcsrc/server/w_grenadelauncher.qc @@ -49,11 +49,14 @@ void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float de { 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) @@ -196,6 +199,7 @@ void W_Grenade_Attack (void) 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); @@ -242,6 +246,7 @@ void W_Grenade_Attack2 (void) 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); @@ -346,13 +351,13 @@ float w_glauncher(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo; - ammo_amount += self.weapon_load[WEP_GRENADE_LAUNCHER] >= autocvar_g_balance_grenadelauncher_primary_ammo; + ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo; - ammo_amount += self.weapon_load[WEP_GRENADE_LAUNCHER] >= autocvar_g_balance_grenadelauncher_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_secondary_ammo; return ammo_amount; } else if (req == WR_RELOAD) diff --git a/qcsrc/server/w_hagar.qc b/qcsrc/server/w_hagar.qc index 080eea39e..7d9db5c39 100644 --- a/qcsrc/server/w_hagar.qc +++ b/qcsrc/server/w_hagar.qc @@ -20,6 +20,30 @@ void W_Hagar_Explode2 (void) 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; @@ -56,6 +80,13 @@ void W_Hagar_Attack (void) 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; @@ -91,6 +122,13 @@ void W_Hagar_Attack2 (void) 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; @@ -112,7 +150,7 @@ void W_Hagar_Attack2 (void) 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 @@ -143,13 +181,19 @@ void W_Hagar_Attack2_Load_Release (void) 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; @@ -183,7 +227,7 @@ void W_Hagar_Attack2_Load_Release (void) 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; } @@ -197,7 +241,7 @@ void W_Hagar_Attack2_Load (void) // this is different than WR_CHECKAMMO when it comes to reloading if(autocvar_g_balance_hagar_reload_ammo) - enough_ammo = self.weapon_load[WEP_HAGAR] >= autocvar_g_balance_hagar_secondary_ammo; + enough_ammo = self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo; else enough_ammo = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; @@ -230,9 +274,12 @@ void W_Hagar_Attack2_Load (void) 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 @@ -251,7 +298,19 @@ void W_Hagar_Attack2_Load (void) 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(); @@ -260,6 +319,7 @@ void W_Hagar_Attack2_Load (void) else { self.hagar_loadbeep = FALSE; + self.hagar_warning = FALSE; } // we aren't checking ammo during an attack, so we must do it here @@ -347,13 +407,13 @@ float w_hagar(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo; - ammo_amount += self.weapon_load[WEP_HAGAR] >= autocvar_g_balance_hagar_primary_ammo; + ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; - ammo_amount += self.weapon_load[WEP_HAGAR] >= autocvar_g_balance_hagar_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo; return ammo_amount; } else if (req == WR_RESETPLAYER) diff --git a/qcsrc/server/w_hlac.qc b/qcsrc/server/w_hlac.qc index 978ac5f4a..0a163e2f9 100644 --- a/qcsrc/server/w_hlac.qc +++ b/qcsrc/server/w_hlac.qc @@ -205,13 +205,13 @@ float w_hlac(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo; - ammo_amount += self.weapon_load[WEP_HLAC] >= autocvar_g_balance_hlac_primary_ammo; + ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo; - ammo_amount += self.weapon_load[WEP_HLAC] >= autocvar_g_balance_hlac_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_secondary_ammo; return ammo_amount; } else if (req == WR_RELOAD) diff --git a/qcsrc/server/w_hook.qc b/qcsrc/server/w_hook.qc index 754ffff90..b6b90f693 100644 --- a/qcsrc/server/w_hook.qc +++ b/qcsrc/server/w_hook.qc @@ -52,6 +52,20 @@ void W_Hook_Explode2 (void) 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; @@ -80,6 +94,12 @@ void W_Hook_Attack2() 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) diff --git a/qcsrc/server/w_minelayer.qc b/qcsrc/server/w_minelayer.qc index 4e56d2d94..1012f9a81 100644 --- a/qcsrc/server/w_minelayer.qc +++ b/qcsrc/server/w_minelayer.qc @@ -38,6 +38,7 @@ void W_Mine_Stick (entity to) 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; @@ -241,8 +242,15 @@ void W_Mine_Damage (entity inflictor, entity attacker, float damage, float death { 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); } @@ -284,6 +292,7 @@ void W_Mine_Attack (void) 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); @@ -486,7 +495,7 @@ float w_minelayer(float req) if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_minelayer_ammo; - ammo_amount += self.weapon_load[WEP_MINE_LAYER] >= autocvar_g_balance_minelayer_ammo; + ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= autocvar_g_balance_minelayer_ammo; return ammo_amount; } } diff --git a/qcsrc/server/w_minstanex.qc b/qcsrc/server/w_minstanex.qc index 16cbdcded..10014a7e1 100644 --- a/qcsrc/server/w_minstanex.qc +++ b/qcsrc/server/w_minstanex.qc @@ -246,7 +246,7 @@ float w_minstanex(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_cells >= minstanex_ammo; - ammo_amount += self.weapon_load[WEP_MINSTANEX] >= minstanex_ammo; + ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= minstanex_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) @@ -254,7 +254,7 @@ float w_minstanex(float req) if(!autocvar_g_balance_minstanex_laser_ammo) return TRUE; ammo_amount = self.ammo_cells >= autocvar_g_balance_minstanex_laser_ammo; - ammo_amount += self.weapon_load[WEP_MINSTANEX] >= autocvar_g_balance_minstanex_laser_ammo; + ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= autocvar_g_balance_minstanex_laser_ammo; return ammo_amount; } else if (req == WR_RESETPLAYER) diff --git a/qcsrc/server/w_nex.qc b/qcsrc/server/w_nex.qc index f93670595..802298912 100644 --- a/qcsrc/server/w_nex.qc +++ b/qcsrc/server/w_nex.qc @@ -161,7 +161,7 @@ float w_nex(float req) { self.clip_load = max(autocvar_g_balance_nex_secondary_ammo, self.clip_load - autocvar_g_balance_nex_secondary_ammo * dt); } - self.weapon_load[WEP_NEX] = self.clip_load; + self.(weapon_load[WEP_NEX]) = self.clip_load; } else { @@ -216,14 +216,14 @@ float w_nex(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_primary_ammo; - ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.weapon_load[WEP_NEX] >= autocvar_g_balance_nex_primary_ammo); + ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_primary_ammo); return ammo_amount; } else if (req == WR_CHECKAMMO2) { // don't allow charging if we don't have enough ammo ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_secondary_ammo; - ammo_amount += self.weapon_load[WEP_NEX] >= autocvar_g_balance_nex_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_secondary_ammo; return ammo_amount; } else if (req == WR_RELOAD) diff --git a/qcsrc/server/w_rifle.qc b/qcsrc/server/w_rifle.qc index 02d859e0f..941a528a4 100644 --- a/qcsrc/server/w_rifle.qc +++ b/qcsrc/server/w_rifle.qc @@ -183,13 +183,13 @@ float w_rifle(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_primary_ammo; - ammo_amount += self.weapon_load[WEP_RIFLE] >= autocvar_g_balance_rifle_primary_ammo; + ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_secondary_ammo; - ammo_amount += self.weapon_load[WEP_RIFLE] >= autocvar_g_balance_rifle_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_secondary_ammo; return ammo_amount; } else if (req == WR_RESETPLAYER) diff --git a/qcsrc/server/w_rocketlauncher.qc b/qcsrc/server/w_rocketlauncher.qc index b4987b69f..4abfa0d50 100644 --- a/qcsrc/server/w_rocketlauncher.qc +++ b/qcsrc/server/w_rocketlauncher.qc @@ -238,8 +238,13 @@ void W_Rocket_Damage (entity inflictor, entity attacker, float damage, float dea { 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); } @@ -270,6 +275,7 @@ void W_Rocket_Attack (void) 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); @@ -461,7 +467,7 @@ float w_rlauncher(float req) { if(autocvar_g_balance_rocketlauncher_reload_ammo) { - if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.weapon_load[WEP_ROCKET_LAUNCHER] < autocvar_g_balance_rocketlauncher_ammo) + if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo) ammo_amount = TRUE; } else if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) diff --git a/qcsrc/server/w_seeker.qc b/qcsrc/server/w_seeker.qc index c108ba3cf..40c119035 100644 --- a/qcsrc/server/w_seeker.qc +++ b/qcsrc/server/w_seeker.qc @@ -124,6 +124,9 @@ void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, flo { 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); @@ -189,6 +192,7 @@ void Seeker_Fire_Missile(vector f_diff, entity m_target) 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) @@ -588,13 +592,13 @@ float w_seeker(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_missile_ammo; - ammo_amount += self.weapon_load[WEP_SEEKER] >= autocvar_g_balance_seeker_missile_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_missile_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) { ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo; - ammo_amount += self.weapon_load[WEP_SEEKER] >= autocvar_g_balance_seeker_tag_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo; return ammo_amount; } else if (req == WR_RELOAD) diff --git a/qcsrc/server/w_shotgun.qc b/qcsrc/server/w_shotgun.qc index a9d1ba056..b21a5f50a 100644 --- a/qcsrc/server/w_shotgun.qc +++ b/qcsrc/server/w_shotgun.qc @@ -46,47 +46,98 @@ void W_Shotgun_Attack (void) 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; } - 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 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; + } + } + } + + 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) @@ -171,7 +222,7 @@ float w_shotgun(float req) else if (req == WR_CHECKAMMO1) { ammo_amount = self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo; - ammo_amount += self.weapon_load[WEP_SHOTGUN] >= autocvar_g_balance_shotgun_primary_ammo; + ammo_amount += self.(weapon_load[WEP_SHOTGUN]) >= autocvar_g_balance_shotgun_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) diff --git a/qcsrc/server/w_tuba.qc b/qcsrc/server/w_tuba.qc index 79f12f55f..987e7b41e 100644 --- a/qcsrc/server/w_tuba.qc +++ b/qcsrc/server/w_tuba.qc @@ -236,6 +236,7 @@ float w_tuba(float req) { weapon_setup(WEP_TUBA); self.current_ammo = ammo_none; + self.tuba_instrument = 0; } else if (req == WR_RELOAD) { diff --git a/qcsrc/server/w_uzi.qc b/qcsrc/server/w_uzi.qc index 4a10ecdf3..71ea1f6f6 100644 --- a/qcsrc/server/w_uzi.qc +++ b/qcsrc/server/w_uzi.qc @@ -263,9 +263,9 @@ float w_uzi(float req) if(autocvar_g_balance_uzi_reload_ammo) { if(autocvar_g_balance_uzi_mode == 1) - ammo_amount += self.weapon_load[WEP_UZI] >= autocvar_g_balance_uzi_sustained_ammo; + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_sustained_ammo; else - ammo_amount += self.weapon_load[WEP_UZI] >= autocvar_g_balance_uzi_first_ammo; + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo; } return ammo_amount; } @@ -279,9 +279,9 @@ float w_uzi(float req) if(autocvar_g_balance_uzi_reload_ammo) { if(autocvar_g_balance_uzi_mode == 1) - ammo_amount += self.weapon_load[WEP_UZI] >= autocvar_g_balance_uzi_burst_ammo; + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_burst_ammo; else - ammo_amount += self.weapon_load[WEP_UZI] >= autocvar_g_balance_uzi_first_ammo; + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo; } return ammo_amount; } diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc index 63e3e712a..118b4f0f5 100644 --- a/qcsrc/warpzonelib/server.qc +++ b/qcsrc/warpzonelib/server.qc @@ -326,6 +326,9 @@ float WarpZone_CheckProjectileImpact(entity player) 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); diff --git a/scripts/gibs.shader b/scripts/gibs.shader new file mode 100644 index 000000000..c1c40e572 --- /dev/null +++ b/scripts/gibs.shader @@ -0,0 +1,111 @@ +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 + } +} diff --git a/scripts/nutsandbolts.shader b/scripts/nutsandbolts.shader deleted file mode 100644 index e0eb347fc..000000000 --- a/scripts/nutsandbolts.shader +++ /dev/null @@ -1,10 +0,0 @@ -nutsandboltssteel -{ - { - map textures/nutsandbolts3 - tcgen environment - } - { - map $lightmap - } -} diff --git a/update-cvarcount.sh b/update-cvarcount.sh index b7c87a34a..002401042 100755 --- a/update-cvarcount.sh +++ b/update-cvarcount.sh @@ -1,5 +1,6 @@ #!/bin/sh +errord=false countw=`awk '/^seta? g_/ { print $2; }' balanceXonotic.cfg | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32` for b in balance*.cfg; do countb=`awk '/^seta? g_/ { print $2; }' "$b" | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32` @@ -14,7 +15,10 @@ for b in balance*.cfg; do awk '/^seta? g_/ { print $2; }' "$b" | sort -u | tr -d '\r' > "$B" diff "$A" "$B" | grep '^[<>]' | sort rm -f "$A" "$B" - echo "Please wait for 30 seconds, so you have had enough time to read this..." - sleep 30 + errord=true fi done +if $errord; then + echo "Please wait for 30 seconds, so you have had enough time to read this..." + sleep 30 +fi