seta hud_panel_healtharmor_progressbar_gfx_damage 5 "show damage effect when damaged at least by this amount; 0 disables the effect"
seta hud_panel_healtharmor_progressbar_gfx_lowhealth 40 "health progressbar blinks when health is lower than this amount"
+seta hud_panel_timer_increment "0" "show elapsed time instead of remaining time"
+
seta hud_panel_engineinfo_framecounter_exponentialmovingaverage 1 "use an averaging method for calculating fps instead of counting frametime like engine does"
seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point"
seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster"
seta hud_panel_physics_acceleration_movingaverage 1 "use an averaging method for calculating acceleration instead of the real value"
seta hud_panel_phisics_update_interval 0.0666 "how often (in seconds) numeric values get updated on screen"
+seta hud_panel_physics_speed_unit "1" "speed unit (1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots)"
seta hud_panel_itemstime_progressbar_maxtime "30" "when left time is at least this amount, the status bar is full"
seta hud_panel_itemstime_hidespawned "1" "if 1 hide an item from the panel when all the occurrences of it are available again; if 2 hide it when at least one occurrence is available again"
seta hud_panel_timer_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
seta hud_panel_timer_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_timer_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
-seta hud_panel_timer_increment "" "show elapsed time instead of remaining time"
seta hud_panel_radar "" "enable/disable this panel, 2 = also enable in non-teambased gamemodes"
seta hud_panel_radar_pos "" "position of this base of the panel"
seta hud_panel_physics_acceleration_vertical "" "include the acceleration on the Z-axis"
seta hud_panel_physics_text "" "show text in panel (2 = only for speed; 3 = only for acceleration)"
seta hud_panel_physics_text_scale "" "scale text height by this factor"
-seta hud_panel_physics_speed_unit "" "speed unit (1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots)"
seta hud_panel_physics_speed_unit_show "" "also show speed unit"
seta hud_panel_physics_speed_max "" "speed progressbar gets filled up completely by this value (in qu/s)"
seta hud_panel_physics_speed_vertical "" "include the speed on the Z-axis"
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_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
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"
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_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
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"
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_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
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"
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_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
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"
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_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
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"
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_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
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"
if [ x"$mode" = x"txt" ]; then
{
- echo "en English \"English\""
+ item=`grep "^en " languages.txt`
+ echo "$item"
for X in common.*.po; do
[ -f "$X" ] || continue
if [ -n "$language" ]; then
if [ "$p" -lt 50 ]; then
continue
fi
- item="$l $l \"$l (0%)\""
+ item="$l $l \"$l\" 0%"
fi
- printf "%s\n" "$item" | sed -e "s/([0-9][0-9]*%)/($p%)/"
+ printf "%s\n" "$item" | sed -e "s/[0-9][0-9]*%/$p%/"
done
} | tr '"' '\t' | sort -k3 | tr '\t' '"'
fi
set g_ctf_oneflag 1 "Allow oneflag CTF mode on maps that support it"
set g_ctf_oneflag_reverse 0 "apply reverse mode to oneflag CTF (take flag to enemy bases to cap), overrides g_ctf_reverse only in oneflag, g_ctf_reverse still affects oneflag"
set g_ctf_flag_return 1 "auto return the flag to base when touched by a teammate"
+set g_ctf_flag_return_carrying 0 "(manual return mode) auto return the flag to base if touched by a flag carrier"
set g_ctf_flag_return_carried_radius 100 "allow flags to be returned by carrier if base is within this radius"
set g_ctf_flag_return_time 15
set g_ctf_flag_return_dropped 100
seta hud_dock_alpha "1"
seta hud_progressbar_alpha "0.600000"
+seta hud_progressbar_strength_color "1 0.39 0"
+seta hud_progressbar_superweapons_color "0.77 0.67 0"
+seta hud_progressbar_shield_color "0.36 1 0.07"
seta hud_progressbar_health_color "0.83 0.12 0"
seta hud_progressbar_armor_color "0.28 0.8 0"
seta hud_progressbar_fuel_color "0.77 0.67 0"
-seta hud_progressbar_strength_color "1 0.39 0"
-seta hud_progressbar_shield_color "0.36 1 0.07"
-seta hud_progressbar_superweapons_color "0.77 0.67 0"
seta hud_progressbar_nexball_color "0.2 0.65 0.93"
seta hud_progressbar_speed_color "0.77 0.67 0"
seta hud_progressbar_acceleration_color "0.2 0.65 0.93"
seta hud_configure_grid_xsize "0.005000"
seta hud_configure_grid_ysize "0.005000"
-seta hud_panel_weapons 1
+seta hud_panel_weapons "1"
seta hud_panel_weapons_pos "0.965000 0.125000"
seta hud_panel_weapons_size "0.035000 0.770000"
seta hud_panel_weapons_bg "border_default_east"
seta hud_panel_weapons_bg_padding "0"
seta hud_panel_weapons_accuracy "0"
seta hud_panel_weapons_label "1"
-seta hud_panel_weapons_label_scale "0.3"
+seta hud_panel_weapons_label_scale "0.300000"
seta hud_panel_weapons_complainbubble "1"
seta hud_panel_weapons_complainbubble_padding "0"
seta hud_panel_weapons_complainbubble_time "0"
seta hud_panel_weapons_timeout_speed_in "0.25"
seta hud_panel_weapons_timeout_speed_out "0.75"
seta hud_panel_weapons_onlyowned "1"
-seta hud_panel_weapons_noncurrent_alpha "0.8"
-seta hud_panel_weapons_noncurrent_scale "0.9"
+seta hud_panel_weapons_noncurrent_alpha "0.800000"
+seta hud_panel_weapons_noncurrent_scale "0.900000"
-seta hud_panel_ammo 1
+seta hud_panel_ammo "1"
seta hud_panel_ammo_pos "0.315000 0.865000"
seta hud_panel_ammo_size "0.370000 0.060000"
seta hud_panel_ammo_bg "border_tab_south"
seta hud_panel_ammo_bg_border ""
seta hud_panel_ammo_bg_padding "4"
seta hud_panel_ammo_onlycurrent "0"
-seta hud_panel_ammo_noncurrent_alpha "0.6"
-seta hud_panel_ammo_noncurrent_scale "0.4"
+seta hud_panel_ammo_noncurrent_alpha "0.600000"
+seta hud_panel_ammo_noncurrent_scale "0.400000"
seta hud_panel_ammo_iconalign "0"
seta hud_panel_ammo_progressbar "0"
seta hud_panel_ammo_progressbar_name "progressbar"
seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
-seta hud_panel_powerups 1
+seta hud_panel_powerups "1"
seta hud_panel_powerups_pos "0.325000 0.815000"
seta hud_panel_powerups_size "0.350000 0.055000"
seta hud_panel_powerups_bg "border_shadow_south"
seta hud_panel_powerups_progressbar "1"
seta hud_panel_powerups_text "1"
-seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor "1"
seta hud_panel_healtharmor_pos "0.300000 0.925000"
seta hud_panel_healtharmor_size "0.400000 0.070000"
seta hud_panel_healtharmor_bg "border_default_south"
seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
-seta hud_panel_notify 1
+seta hud_panel_notify "1"
seta hud_panel_notify_pos "0.730000 0.800000"
seta hud_panel_notify_size "0.265000 0.200000"
seta hud_panel_notify_bg "0"
seta hud_panel_notify_fadetime "3"
seta hud_panel_notify_icon_aspect "1"
-seta hud_panel_timer 1
+seta hud_panel_timer "1"
seta hud_panel_timer_pos "0.456000 0"
seta hud_panel_timer_size "0.088000 0.030000"
seta hud_panel_timer_bg "border_plain_north"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
-seta hud_panel_timer_increment "0"
-seta hud_panel_radar 1
+seta hud_panel_radar "1"
seta hud_panel_radar_pos "0 0"
seta hud_panel_radar_size "0.200000 0.250000"
seta hud_panel_radar_bg "border_corner_northwest"
seta hud_panel_radar_maximized_rotation "1"
seta hud_panel_radar_maximized_zoommode "3"
-seta hud_panel_score 1
+seta hud_panel_score "1"
seta hud_panel_score_pos "0.880000 0"
seta hud_panel_score_size "0.120000 0.080000"
seta hud_panel_score_bg "border_corner_northeast"
seta hud_panel_score_bg_padding "1"
seta hud_panel_score_rankings "1"
-seta hud_panel_racetimer 1
+seta hud_panel_racetimer "1"
seta hud_panel_racetimer_pos "0.360000 0.110000"
seta hud_panel_racetimer_size "0.280000 0.090000"
seta hud_panel_racetimer_bg "0"
seta hud_panel_racetimer_bg_border ""
seta hud_panel_racetimer_bg_padding ""
-seta hud_panel_vote 1
+seta hud_panel_vote "1"
seta hud_panel_vote_pos "0.740000 0.690000"
seta hud_panel_vote_size "0.190000 0.090000"
seta hud_panel_vote_bg " "
seta hud_panel_vote_bg_padding ""
seta hud_panel_vote_alreadyvoted_alpha "0.700000"
-seta hud_panel_modicons 1
+seta hud_panel_modicons "1"
seta hud_panel_modicons_pos "0.370000 0.030000"
seta hud_panel_modicons_size "0.260000 0.07000"
seta hud_panel_modicons_bg "border_fading_north"
seta hud_panel_modicons_dom_layout "1"
seta hud_panel_modicons_freezetag_layout "1"
-seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys "1"
seta hud_panel_pressedkeys_pos "0.445000 0.710000"
seta hud_panel_pressedkeys_size "0.110000 0.090000"
seta hud_panel_pressedkeys_bg " "
seta hud_panel_pressedkeys_aspect "1.600000"
seta hud_panel_pressedkeys_attack "0"
-seta hud_panel_chat 1
+seta hud_panel_chat "1"
seta hud_panel_chat_pos "0.010000 0.700000"
seta hud_panel_chat_size "0.460000 0.190000"
seta hud_panel_chat_bg "0"
seta hud_panel_chat_bg_border ""
seta hud_panel_chat_bg_padding ""
-seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo "0"
seta hud_panel_engineinfo_pos "0.930000 0.970000"
seta hud_panel_engineinfo_size "0.070000 0.030000"
seta hud_panel_engineinfo_bg "0"
seta hud_panel_engineinfo_framecounter_time "0.1"
seta hud_panel_engineinfo_framecounter_decimals "0"
-seta hud_panel_infomessages 1
+seta hud_panel_infomessages "1"
seta hud_panel_infomessages_pos "0.720000 0.100000"
seta hud_panel_infomessages_size "0.280000 0.080000"
seta hud_panel_infomessages_bg "0"
seta hud_panel_infomessages_bg_padding "0"
seta hud_panel_infomessages_flip "1"
-seta hud_panel_physics 3
+seta hud_panel_physics "3"
seta hud_panel_physics_pos "0.410000 0.625000"
seta hud_panel_physics_size "0.180000 0.080000"
seta hud_panel_physics_bg "0"
seta hud_panel_physics_bg_alpha "0.700000"
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_speed_unit "1"
seta hud_panel_physics_speed_unit_show "1"
seta hud_panel_physics_speed_max "1800"
seta hud_panel_physics_speed_vertical "0"
seta hud_panel_physics_text "1"
seta hud_panel_physics_text_scale "0.7"
-seta hud_panel_centerprint 1
+seta hud_panel_centerprint "1"
seta hud_panel_centerprint_pos "0.175000 0.220000"
seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
seta hud_panel_centerprint_fade_minfontsize "0"
-seta hud_panel_mapvote 1
-seta hud_panel_mapvote_pos "0 0"
-seta hud_panel_mapvote_size "1 1"
-seta hud_panel_mapvote_bg "border_default"
-seta hud_panel_mapvote_bg_color ""
-seta hud_panel_mapvote_bg_color_team ""
-seta hud_panel_mapvote_bg_alpha ""
-seta hud_panel_mapvote_bg_border ""
-seta hud_panel_mapvote_bg_padding ""
-
-seta hud_panel_itemstime 2
-seta hud_panel_itemstime_pos "0.030000 0.260000"
-seta hud_panel_itemstime_size "0.070000 0.230000"
-seta hud_panel_itemstime_bg "border_itemstime"
-seta hud_panel_itemstime_bg_color ""
-seta hud_panel_itemstime_bg_color_team ""
-seta hud_panel_itemstime_bg_alpha ""
-seta hud_panel_itemstime_bg_border ""
-seta hud_panel_itemstime_bg_padding ""
-seta hud_panel_itemstime_iconalign "0"
-seta hud_panel_itemstime_progressbar "0"
-seta hud_panel_itemstime_progressbar_name "progressbar"
-seta hud_panel_itemstime_progressbar_reduced "0"
-seta hud_panel_itemstime_text "1"
-seta hud_panel_itemstime_ratio "2"
-seta hud_panel_itemstime_dynamicsize "1"
-
seta hud_panel_minigameboard "1"
seta hud_panel_minigameboard_pos "0.22 0.15"
seta hud_panel_minigameboard_size "0.50 0.60"
seta hud_panel_minigamemenu_bg_border ""
seta hud_panel_minigamemenu_bg_padding ""
-seta hud_panel_quickmenu 1
+seta hud_panel_mapvote "1"
+seta hud_panel_mapvote_pos "0 0"
+seta hud_panel_mapvote_size "1 1"
+seta hud_panel_mapvote_bg "border_default"
+seta hud_panel_mapvote_bg_color ""
+seta hud_panel_mapvote_bg_color_team ""
+seta hud_panel_mapvote_bg_alpha ""
+seta hud_panel_mapvote_bg_border ""
+seta hud_panel_mapvote_bg_padding ""
+
+seta hud_panel_itemstime "2"
+seta hud_panel_itemstime_pos "0.030000 0.260000"
+seta hud_panel_itemstime_size "0.070000 0.230000"
+seta hud_panel_itemstime_bg "border_itemstime"
+seta hud_panel_itemstime_bg_color ""
+seta hud_panel_itemstime_bg_color_team ""
+seta hud_panel_itemstime_bg_alpha ""
+seta hud_panel_itemstime_bg_border ""
+seta hud_panel_itemstime_bg_padding ""
+seta hud_panel_itemstime_iconalign "0"
+seta hud_panel_itemstime_progressbar "0"
+seta hud_panel_itemstime_progressbar_name "progressbar"
+seta hud_panel_itemstime_progressbar_reduced "0"
+seta hud_panel_itemstime_text "1"
+seta hud_panel_itemstime_ratio "2"
+seta hud_panel_itemstime_dynamicsize "1"
+
+seta hud_panel_quickmenu "1"
seta hud_panel_quickmenu_pos "0.600000 0.445000"
seta hud_panel_quickmenu_size "0.220000 0.240000"
seta hud_panel_quickmenu_bg ""
seta hud_configure_grid_xsize "0.010000"
seta hud_configure_grid_ysize "0.010000"
-seta hud_panel_weapons 1
+seta hud_panel_weapons "1"
seta hud_panel_weapons_pos "0.930000 0.170000"
seta hud_panel_weapons_size "0.070000 0.650000"
seta hud_panel_weapons_bg "border_small_weapons"
seta hud_panel_weapons_bg_padding "4"
seta hud_panel_weapons_accuracy "1"
seta hud_panel_weapons_label "1"
-seta hud_panel_weapons_label_scale "0.5"
+seta hud_panel_weapons_label_scale "0.500000"
seta hud_panel_weapons_complainbubble "1"
seta hud_panel_weapons_complainbubble_padding "-1"
seta hud_panel_weapons_complainbubble_time "0"
seta hud_panel_weapons_noncurrent_alpha "1"
seta hud_panel_weapons_noncurrent_scale "1"
-seta hud_panel_ammo 1
+seta hud_panel_ammo "1"
seta hud_panel_ammo_pos "0.330000 0.960000"
seta hud_panel_ammo_size "0.350000 0.040000"
seta hud_panel_ammo_bg ""
seta hud_panel_ammo_bg_border ""
seta hud_panel_ammo_bg_padding ""
seta hud_panel_ammo_onlycurrent "0"
-seta hud_panel_ammo_noncurrent_alpha "0.7"
+seta hud_panel_ammo_noncurrent_alpha "0.700000"
seta hud_panel_ammo_noncurrent_scale "1"
seta hud_panel_ammo_iconalign "0"
seta hud_panel_ammo_progressbar "0"
seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
-seta hud_panel_powerups 1
+seta hud_panel_powerups "1"
seta hud_panel_powerups_pos "0.360000 0.850000"
seta hud_panel_powerups_size "0.290000 0.030000"
seta hud_panel_powerups_bg "border_small_powerups"
seta hud_panel_powerups_progressbar "1"
seta hud_panel_powerups_text "1"
-seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor "1"
seta hud_panel_healtharmor_pos "0.320000 0.910000"
seta hud_panel_healtharmor_size "0.370000 0.060000"
seta hud_panel_healtharmor_bg "border_small_healtharmor"
seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
-seta hud_panel_notify 1
+seta hud_panel_notify "1"
seta hud_panel_notify_pos "0.710000 0.800000"
seta hud_panel_notify_size "0.290000 0.190000"
seta hud_panel_notify_bg "0"
seta hud_panel_notify_fadetime "3"
seta hud_panel_notify_icon_aspect "2"
-seta hud_panel_timer 1
+seta hud_panel_timer "1"
seta hud_panel_timer_pos "0.800000 0.040000"
seta hud_panel_timer_size "0.070000 0.040000"
seta hud_panel_timer_bg "border_small_timer"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
-seta hud_panel_timer_increment "0"
-seta hud_panel_radar 2
+seta hud_panel_radar "2"
seta hud_panel_radar_pos "0 0"
seta hud_panel_radar_size "0.200000 0.240000"
seta hud_panel_radar_bg "border_small_radar"
seta hud_panel_radar_maximized_rotation "1"
seta hud_panel_radar_maximized_zoommode "3"
-seta hud_panel_score 1
+seta hud_panel_score "1"
seta hud_panel_score_pos "0.890000 0.030000"
seta hud_panel_score_size "0.100000 0.050000"
seta hud_panel_score_bg "border_small_score"
seta hud_panel_score_bg_padding "0"
seta hud_panel_score_rankings "1"
-seta hud_panel_racetimer 1
+seta hud_panel_racetimer "1"
seta hud_panel_racetimer_pos "0.360000 0.110000"
seta hud_panel_racetimer_size "0.280000 0.090000"
seta hud_panel_racetimer_bg "0"
seta hud_panel_racetimer_bg_border ""
seta hud_panel_racetimer_bg_padding ""
-seta hud_panel_vote 1
+seta hud_panel_vote "1"
seta hud_panel_vote_pos "0.720000 0.670000"
seta hud_panel_vote_size "0.190000 0.090000"
seta hud_panel_vote_bg "border_vote"
seta hud_panel_vote_bg_padding ""
seta hud_panel_vote_alreadyvoted_alpha "0.500000"
-seta hud_panel_modicons 1
+seta hud_panel_modicons "1"
seta hud_panel_modicons_pos "0.410000 0"
seta hud_panel_modicons_size "0.180000 0.080000"
seta hud_panel_modicons_bg "border_small_modicons"
seta hud_panel_modicons_dom_layout "1"
seta hud_panel_modicons_freezetag_layout "1"
-seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys "1"
seta hud_panel_pressedkeys_pos "0.450000 0.720000"
seta hud_panel_pressedkeys_size "0.110000 0.090000"
seta hud_panel_pressedkeys_bg "0"
seta hud_panel_pressedkeys_aspect "1.600000"
seta hud_panel_pressedkeys_attack "0"
-seta hud_panel_chat 1
+seta hud_panel_chat "1"
seta hud_panel_chat_pos "0.010000 0.700000"
seta hud_panel_chat_size "0.460000 0.190000"
seta hud_panel_chat_bg "0"
seta hud_panel_chat_bg_border ""
seta hud_panel_chat_bg_padding ""
-seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo "0"
seta hud_panel_engineinfo_pos "0.930000 0.970000"
seta hud_panel_engineinfo_size "0.070000 0.030000"
seta hud_panel_engineinfo_bg "0"
seta hud_panel_engineinfo_framecounter_time "0.1"
seta hud_panel_engineinfo_framecounter_decimals "0"
-seta hud_panel_infomessages 1
+seta hud_panel_infomessages "1"
seta hud_panel_infomessages_pos "0.720000 0.100000"
seta hud_panel_infomessages_size "0.280000 0.080000"
seta hud_panel_infomessages_bg "0"
seta hud_panel_infomessages_bg_padding "0"
seta hud_panel_infomessages_flip "1"
-seta hud_panel_physics 3
+seta hud_panel_physics "3"
seta hud_panel_physics_pos "0.420000 0.620000"
seta hud_panel_physics_size "0.170000 0.080000"
seta hud_panel_physics_bg ""
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_speed_unit "3"
seta hud_panel_physics_speed_unit_show "1"
seta hud_panel_physics_speed_max "1800"
seta hud_panel_physics_speed_vertical "0"
seta hud_panel_physics_text "1"
seta hud_panel_physics_text_scale "0.7"
-seta hud_panel_centerprint 1
+seta hud_panel_centerprint "1"
seta hud_panel_centerprint_pos "0.175000 0.220000"
seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
seta hud_panel_centerprint_fade_minfontsize "0"
-seta hud_panel_mapvote 1
-seta hud_panel_mapvote_pos "0 0"
-seta hud_panel_mapvote_size "1 1"
-seta hud_panel_mapvote_bg "0"
-seta hud_panel_mapvote_bg_color ""
-seta hud_panel_mapvote_bg_color_team ""
-seta hud_panel_mapvote_bg_alpha ""
-seta hud_panel_mapvote_bg_border ""
-seta hud_panel_mapvote_bg_padding ""
-
-seta hud_panel_itemstime 2
-seta hud_panel_itemstime_pos "0.030000 0.260000"
-seta hud_panel_itemstime_size "0.070000 0.230000"
-seta hud_panel_itemstime_bg "border_itemstime"
-seta hud_panel_itemstime_bg_color ""
-seta hud_panel_itemstime_bg_color_team ""
-seta hud_panel_itemstime_bg_alpha ""
-seta hud_panel_itemstime_bg_border ""
-seta hud_panel_itemstime_bg_padding ""
-seta hud_panel_itemstime_iconalign "0"
-seta hud_panel_itemstime_progressbar "0"
-seta hud_panel_itemstime_progressbar_name "progressbar"
-seta hud_panel_itemstime_progressbar_reduced "0"
-seta hud_panel_itemstime_text "1"
-seta hud_panel_itemstime_ratio "2"
-seta hud_panel_itemstime_dynamicsize "1"
-
seta hud_panel_minigameboard "1"
seta hud_panel_minigameboard_pos "0.22 0.15"
seta hud_panel_minigameboard_size "0.50 0.60"
seta hud_panel_minigamemenu_bg_border ""
seta hud_panel_minigamemenu_bg_padding ""
-seta hud_panel_quickmenu 1
+seta hud_panel_mapvote "1"
+seta hud_panel_mapvote_pos "0 0"
+seta hud_panel_mapvote_size "1 1"
+seta hud_panel_mapvote_bg "0"
+seta hud_panel_mapvote_bg_color ""
+seta hud_panel_mapvote_bg_color_team ""
+seta hud_panel_mapvote_bg_alpha ""
+seta hud_panel_mapvote_bg_border ""
+seta hud_panel_mapvote_bg_padding ""
+
+seta hud_panel_itemstime "2"
+seta hud_panel_itemstime_pos "0.030000 0.260000"
+seta hud_panel_itemstime_size "0.070000 0.230000"
+seta hud_panel_itemstime_bg "border_itemstime"
+seta hud_panel_itemstime_bg_color ""
+seta hud_panel_itemstime_bg_color_team ""
+seta hud_panel_itemstime_bg_alpha ""
+seta hud_panel_itemstime_bg_border ""
+seta hud_panel_itemstime_bg_padding ""
+seta hud_panel_itemstime_iconalign "0"
+seta hud_panel_itemstime_progressbar "0"
+seta hud_panel_itemstime_progressbar_name "progressbar"
+seta hud_panel_itemstime_progressbar_reduced "0"
+seta hud_panel_itemstime_text "1"
+seta hud_panel_itemstime_ratio "2"
+seta hud_panel_itemstime_dynamicsize "1"
+
+seta hud_panel_quickmenu "1"
seta hud_panel_quickmenu_pos "0.610000 0.450000"
seta hud_panel_quickmenu_size "0.200000 0.210000"
seta hud_panel_quickmenu_bg ""
seta hud_configure_grid_xsize "0.010000"
seta hud_configure_grid_ysize "0.010000"
-seta hud_panel_weapons 1
+seta hud_panel_weapons "1"
seta hud_panel_weapons_pos "0.350000 0.940000"
seta hud_panel_weapons_size "0.300000 0.060000"
seta hud_panel_weapons_bg ""
seta hud_panel_weapons_noncurrent_alpha "1"
seta hud_panel_weapons_noncurrent_scale "1"
-seta hud_panel_ammo 1
+seta hud_panel_ammo "1"
seta hud_panel_ammo_pos "0.650000 0.890000"
seta hud_panel_ammo_size "0.055000 0.110000"
seta hud_panel_ammo_bg ""
seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
-seta hud_panel_powerups 1
+seta hud_panel_powerups "1"
seta hud_panel_powerups_pos "0.290000 0.890000"
seta hud_panel_powerups_size "0.055000 0.110000"
seta hud_panel_powerups_bg "0"
seta hud_panel_powerups_progressbar "1"
seta hud_panel_powerups_text "1"
-seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor "1"
seta hud_panel_healtharmor_pos "0.350000 0.890000"
seta hud_panel_healtharmor_size "0.300000 0.050000"
seta hud_panel_healtharmor_bg ""
seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
-seta hud_panel_notify 1
+seta hud_panel_notify "1"
seta hud_panel_notify_pos "0 0"
seta hud_panel_notify_size "0.210000 0.260000"
seta hud_panel_notify_bg "0"
seta hud_panel_notify_fadetime "3"
seta hud_panel_notify_icon_aspect "2"
-seta hud_panel_timer 1
+seta hud_panel_timer "1"
seta hud_panel_timer_pos "0.435000 0"
seta hud_panel_timer_size "0.135000 0.060000"
seta hud_panel_timer_bg "0"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
-seta hud_panel_timer_increment "0"
-seta hud_panel_radar 2
+seta hud_panel_radar "2"
seta hud_panel_radar_pos "0.810000 0"
seta hud_panel_radar_size "0.190000 0.250000"
seta hud_panel_radar_bg "border_radar"
seta hud_panel_radar_maximized_rotation "1"
seta hud_panel_radar_maximized_zoommode "3"
-seta hud_panel_score 1
+seta hud_panel_score "1"
seta hud_panel_score_pos "0.465000 0.045000"
seta hud_panel_score_size "0.090000 0.060000"
seta hud_panel_score_bg ""
seta hud_panel_score_bg_padding ""
seta hud_panel_score_rankings "1"
-seta hud_panel_racetimer 1
+seta hud_panel_racetimer "1"
seta hud_panel_racetimer_pos "0.360000 0.090000"
seta hud_panel_racetimer_size "0.280000 0.090000"
seta hud_panel_racetimer_bg "0"
seta hud_panel_racetimer_bg_border ""
seta hud_panel_racetimer_bg_padding ""
-seta hud_panel_vote 1
+seta hud_panel_vote "1"
seta hud_panel_vote_pos "0 0.890000"
seta hud_panel_vote_size "0.170000 0.110000"
seta hud_panel_vote_bg ""
seta hud_panel_vote_bg_padding ""
seta hud_panel_vote_alreadyvoted_alpha "0.800000"
-seta hud_panel_modicons 1
+seta hud_panel_modicons "1"
seta hud_panel_modicons_pos "0.560000 0"
seta hud_panel_modicons_size "0.050000 0.100000"
seta hud_panel_modicons_bg ""
seta hud_panel_modicons_dom_layout "1"
seta hud_panel_modicons_freezetag_layout "1"
-seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys "1"
seta hud_panel_pressedkeys_pos "0.450000 0.650000"
seta hud_panel_pressedkeys_size "0.100000 0.110000"
seta hud_panel_pressedkeys_bg "0"
seta hud_panel_pressedkeys_aspect "1.600000"
seta hud_panel_pressedkeys_attack "0"
-seta hud_panel_chat 1
+seta hud_panel_chat "1"
seta hud_panel_chat_pos "0 0.775000"
seta hud_panel_chat_size "0.460000 0.110000"
seta hud_panel_chat_bg "0"
seta hud_panel_chat_bg_border ""
seta hud_panel_chat_bg_padding ""
-seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo "0"
seta hud_panel_engineinfo_pos "0.910000 0.970000"
seta hud_panel_engineinfo_size "0.090000 0.030000"
seta hud_panel_engineinfo_bg "0"
seta hud_panel_engineinfo_framecounter_time "0.1"
seta hud_panel_engineinfo_framecounter_decimals "0"
-seta hud_panel_infomessages 1
+seta hud_panel_infomessages "1"
seta hud_panel_infomessages_pos "0.710000 0"
seta hud_panel_infomessages_size "0.290000 0.100000"
seta hud_panel_infomessages_bg "0"
seta hud_panel_infomessages_bg_padding "0"
seta hud_panel_infomessages_flip "1"
-seta hud_panel_physics 3
+seta hud_panel_physics "3"
seta hud_panel_physics_pos "0.440000 0.590000"
seta hud_panel_physics_size "0.120000 0.050000"
seta hud_panel_physics_bg ""
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_speed_unit "3"
seta hud_panel_physics_speed_unit_show "1"
seta hud_panel_physics_speed_max "1800"
seta hud_panel_physics_speed_vertical "0"
seta hud_panel_physics_text "1"
seta hud_panel_physics_text_scale "0.7"
-seta hud_panel_centerprint 1
+seta hud_panel_centerprint "1"
seta hud_panel_centerprint_pos "0.175000 0.220000"
seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
seta hud_panel_centerprint_fade_minfontsize "0"
-seta hud_panel_mapvote 1
-seta hud_panel_mapvote_pos "0 0"
-seta hud_panel_mapvote_size "1 1"
-seta hud_panel_mapvote_bg "0"
-seta hud_panel_mapvote_bg_color ""
-seta hud_panel_mapvote_bg_color_team ""
-seta hud_panel_mapvote_bg_alpha ""
-seta hud_panel_mapvote_bg_border ""
-seta hud_panel_mapvote_bg_padding ""
-
-seta hud_panel_itemstime 2
-seta hud_panel_itemstime_pos "0.000000 0.310000"
-seta hud_panel_itemstime_size "0.070000 0.180000"
-seta hud_panel_itemstime_bg ""
-seta hud_panel_itemstime_bg_color ""
-seta hud_panel_itemstime_bg_color_team ""
-seta hud_panel_itemstime_bg_alpha ""
-seta hud_panel_itemstime_bg_border ""
-seta hud_panel_itemstime_bg_padding ""
-seta hud_panel_itemstime_iconalign "0"
-seta hud_panel_itemstime_progressbar "0"
-seta hud_panel_itemstime_progressbar_name "progressbar"
-seta hud_panel_itemstime_progressbar_reduced "0"
-seta hud_panel_itemstime_text "1"
-seta hud_panel_itemstime_ratio "2"
-seta hud_panel_itemstime_dynamicsize "1"
-
seta hud_panel_minigameboard "1"
seta hud_panel_minigameboard_pos "0.22 0.15"
seta hud_panel_minigameboard_size "0.50 0.60"
seta hud_panel_minigamemenu_bg_border ""
seta hud_panel_minigamemenu_bg_padding ""
-seta hud_panel_quickmenu 1
+seta hud_panel_mapvote "1"
+seta hud_panel_mapvote_pos "0 0"
+seta hud_panel_mapvote_size "1 1"
+seta hud_panel_mapvote_bg "0"
+seta hud_panel_mapvote_bg_color ""
+seta hud_panel_mapvote_bg_color_team ""
+seta hud_panel_mapvote_bg_alpha ""
+seta hud_panel_mapvote_bg_border ""
+seta hud_panel_mapvote_bg_padding ""
+
+seta hud_panel_itemstime "2"
+seta hud_panel_itemstime_pos "0.000000 0.310000"
+seta hud_panel_itemstime_size "0.070000 0.180000"
+seta hud_panel_itemstime_bg ""
+seta hud_panel_itemstime_bg_color ""
+seta hud_panel_itemstime_bg_color_team ""
+seta hud_panel_itemstime_bg_alpha ""
+seta hud_panel_itemstime_bg_border ""
+seta hud_panel_itemstime_bg_padding ""
+seta hud_panel_itemstime_iconalign "0"
+seta hud_panel_itemstime_progressbar "0"
+seta hud_panel_itemstime_progressbar_name "progressbar"
+seta hud_panel_itemstime_progressbar_reduced "0"
+seta hud_panel_itemstime_text "1"
+seta hud_panel_itemstime_ratio "2"
+seta hud_panel_itemstime_dynamicsize "1"
+
+seta hud_panel_quickmenu "1"
seta hud_panel_quickmenu_pos "0.600000 0.460000"
seta hud_panel_quickmenu_size "0.190000 0.190000"
seta hud_panel_quickmenu_bg ""
seta hud_configure_grid_xsize "0.010000"
seta hud_configure_grid_ysize "0.010000"
-seta hud_panel_weapons 1
+seta hud_panel_weapons "1"
seta hud_panel_weapons_pos "0.350000 0.940000"
seta hud_panel_weapons_size "0.300000 0.060000"
seta hud_panel_weapons_bg ""
seta hud_panel_weapons_noncurrent_alpha "1"
seta hud_panel_weapons_noncurrent_scale "1"
-seta hud_panel_ammo 1
+seta hud_panel_ammo "1"
seta hud_panel_ammo_pos "0.450000 0.630000"
seta hud_panel_ammo_size "0.080000 0.040000"
seta hud_panel_ammo_bg ""
seta hud_panel_ammo_progressbar_xoffset "0.32"
seta hud_panel_ammo_text "1"
-seta hud_panel_powerups 1
+seta hud_panel_powerups "1"
seta hud_panel_powerups_pos "0.270000 0.940000"
seta hud_panel_powerups_size "0.080000 0.060000"
seta hud_panel_powerups_bg "0"
seta hud_panel_powerups_progressbar "1"
seta hud_panel_powerups_text "1"
-seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor "1"
seta hud_panel_healtharmor_pos "0.350000 0.380000"
seta hud_panel_healtharmor_size "0.070000 0.240000"
seta hud_panel_healtharmor_bg "border_healtharmor"
seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "0"
-seta hud_panel_notify 1
+seta hud_panel_notify "1"
seta hud_panel_notify_pos "0 0"
seta hud_panel_notify_size "0.210000 0.260000"
seta hud_panel_notify_bg "0"
seta hud_panel_notify_fadetime "3"
seta hud_panel_notify_icon_aspect "2"
-seta hud_panel_timer 1
+seta hud_panel_timer "1"
seta hud_panel_timer_pos "0.435000 0"
seta hud_panel_timer_size "0.135000 0.060000"
seta hud_panel_timer_bg "0"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
-seta hud_panel_timer_increment "0"
-seta hud_panel_radar 2
+seta hud_panel_radar "2"
seta hud_panel_radar_pos "0.810000 0"
seta hud_panel_radar_size "0.190000 0.250000"
seta hud_panel_radar_bg "border_radar"
seta hud_panel_radar_maximized_rotation "1"
seta hud_panel_radar_maximized_zoommode "3"
-seta hud_panel_score 1
+seta hud_panel_score "1"
seta hud_panel_score_pos "0.465000 0.045000"
seta hud_panel_score_size "0.090000 0.060000"
seta hud_panel_score_bg ""
seta hud_panel_score_bg_padding ""
seta hud_panel_score_rankings "1"
-seta hud_panel_racetimer 1
+seta hud_panel_racetimer "1"
seta hud_panel_racetimer_pos "0.360000 0.090000"
seta hud_panel_racetimer_size "0.280000 0.090000"
seta hud_panel_racetimer_bg "0"
seta hud_panel_racetimer_bg_border ""
seta hud_panel_racetimer_bg_padding ""
-seta hud_panel_vote 1
+seta hud_panel_vote "1"
seta hud_panel_vote_pos "0 0.890000"
seta hud_panel_vote_size "0.170000 0.110000"
seta hud_panel_vote_bg ""
seta hud_panel_vote_bg_padding ""
seta hud_panel_vote_alreadyvoted_alpha "0.800000"
-seta hud_panel_modicons 1
+seta hud_panel_modicons "1"
seta hud_panel_modicons_pos "0.560000 0"
seta hud_panel_modicons_size "0.050000 0.100000"
seta hud_panel_modicons_bg ""
seta hud_panel_modicons_dom_layout "1"
seta hud_panel_modicons_freezetag_layout "1"
-seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys "1"
seta hud_panel_pressedkeys_pos "0.450000 0.690000"
seta hud_panel_pressedkeys_size "0.100000 0.110000"
seta hud_panel_pressedkeys_bg "0"
seta hud_panel_pressedkeys_aspect "1.600000"
seta hud_panel_pressedkeys_attack "0"
-seta hud_panel_chat 1
+seta hud_panel_chat "1"
seta hud_panel_chat_pos "0 0.775000"
seta hud_panel_chat_size "0.460000 0.110000"
seta hud_panel_chat_bg "0"
seta hud_panel_chat_bg_border ""
seta hud_panel_chat_bg_padding ""
-seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo "0"
seta hud_panel_engineinfo_pos "0.910000 0.970000"
seta hud_panel_engineinfo_size "0.090000 0.030000"
seta hud_panel_engineinfo_bg "0"
seta hud_panel_engineinfo_framecounter_time "0.1"
seta hud_panel_engineinfo_framecounter_decimals "0"
-seta hud_panel_infomessages 1
+seta hud_panel_infomessages "1"
seta hud_panel_infomessages_pos "0.710000 0"
seta hud_panel_infomessages_size "0.290000 0.100000"
seta hud_panel_infomessages_bg "0"
seta hud_panel_infomessages_bg_padding "0"
seta hud_panel_infomessages_flip "1"
-seta hud_panel_physics 3
+seta hud_panel_physics "3"
seta hud_panel_physics_pos "0.270000 0.730000"
seta hud_panel_physics_size "0.170000 0.030000"
seta hud_panel_physics_bg ""
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_speed_unit "3"
seta hud_panel_physics_speed_unit_show "1"
seta hud_panel_physics_speed_max "1800"
seta hud_panel_physics_speed_vertical "0"
seta hud_panel_physics_text "1"
seta hud_panel_physics_text_scale "0.7"
-seta hud_panel_centerprint 1
+seta hud_panel_centerprint "1"
seta hud_panel_centerprint_pos "0.175000 0.220000"
seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
seta hud_panel_centerprint_fade_minfontsize "0"
-seta hud_panel_mapvote 1
-seta hud_panel_mapvote_pos "0 0"
-seta hud_panel_mapvote_size "1 1"
-seta hud_panel_mapvote_bg "0"
-seta hud_panel_mapvote_bg_color ""
-seta hud_panel_mapvote_bg_color_team ""
-seta hud_panel_mapvote_bg_alpha ""
-seta hud_panel_mapvote_bg_border ""
-seta hud_panel_mapvote_bg_padding ""
-
-seta hud_panel_itemstime 2
-seta hud_panel_itemstime_pos "0.000000 0.310000"
-seta hud_panel_itemstime_size "0.070000 0.180000"
-seta hud_panel_itemstime_bg ""
-seta hud_panel_itemstime_bg_color ""
-seta hud_panel_itemstime_bg_color_team ""
-seta hud_panel_itemstime_bg_alpha ""
-seta hud_panel_itemstime_bg_border ""
-seta hud_panel_itemstime_bg_padding ""
-seta hud_panel_itemstime_iconalign "0"
-seta hud_panel_itemstime_progressbar "0"
-seta hud_panel_itemstime_progressbar_name "progressbar"
-seta hud_panel_itemstime_progressbar_reduced "0"
-seta hud_panel_itemstime_text "1"
-seta hud_panel_itemstime_ratio "2"
-seta hud_panel_itemstime_dynamicsize "1"
-
seta hud_panel_minigameboard "1"
seta hud_panel_minigameboard_pos "0.22 0.15"
seta hud_panel_minigameboard_size "0.50 0.60"
seta hud_panel_minigamemenu_bg_border ""
seta hud_panel_minigamemenu_bg_padding ""
-seta hud_panel_quickmenu 1
+seta hud_panel_mapvote "1"
+seta hud_panel_mapvote_pos "0 0"
+seta hud_panel_mapvote_size "1 1"
+seta hud_panel_mapvote_bg "0"
+seta hud_panel_mapvote_bg_color ""
+seta hud_panel_mapvote_bg_color_team ""
+seta hud_panel_mapvote_bg_alpha ""
+seta hud_panel_mapvote_bg_border ""
+seta hud_panel_mapvote_bg_padding ""
+
+seta hud_panel_itemstime "2"
+seta hud_panel_itemstime_pos "0.000000 0.310000"
+seta hud_panel_itemstime_size "0.070000 0.180000"
+seta hud_panel_itemstime_bg ""
+seta hud_panel_itemstime_bg_color ""
+seta hud_panel_itemstime_bg_color_team ""
+seta hud_panel_itemstime_bg_alpha ""
+seta hud_panel_itemstime_bg_border ""
+seta hud_panel_itemstime_bg_padding ""
+seta hud_panel_itemstime_iconalign "0"
+seta hud_panel_itemstime_progressbar "0"
+seta hud_panel_itemstime_progressbar_name "progressbar"
+seta hud_panel_itemstime_progressbar_reduced "0"
+seta hud_panel_itemstime_text "1"
+seta hud_panel_itemstime_ratio "2"
+seta hud_panel_itemstime_dynamicsize "1"
+
+seta hud_panel_quickmenu "1"
seta hud_panel_quickmenu_pos "0.600000 0.460000"
seta hud_panel_quickmenu_size "0.190000 0.190000"
seta hud_panel_quickmenu_bg ""
seta hud_configure_grid_xsize "0.010000"
seta hud_configure_grid_ysize "0.010000"
-seta hud_panel_weapons 1
+seta hud_panel_weapons "1"
seta hud_panel_weapons_pos "0.920000 0.090000"
seta hud_panel_weapons_size "0.060000 0.630000"
seta hud_panel_weapons_bg ""
seta hud_panel_weapons_noncurrent_alpha "1"
seta hud_panel_weapons_noncurrent_scale "1"
-seta hud_panel_ammo 1
+seta hud_panel_ammo "1"
seta hud_panel_ammo_pos "0.190000 0.920000"
seta hud_panel_ammo_size "0.120000 0.070000"
seta hud_panel_ammo_bg ""
seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
-seta hud_panel_powerups 1
+seta hud_panel_powerups "1"
seta hud_panel_powerups_pos "0.660000 0.940000"
seta hud_panel_powerups_size "0.330000 0.060000"
seta hud_panel_powerups_bg "0"
seta hud_panel_powerups_progressbar "1"
seta hud_panel_powerups_text "1"
-seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor "1"
seta hud_panel_healtharmor_pos "0.330000 0.920000"
seta hud_panel_healtharmor_size "0.310000 0.070000"
seta hud_panel_healtharmor_bg ""
seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
-seta hud_panel_notify 1
+seta hud_panel_notify "1"
seta hud_panel_notify_pos "0.660000 0.730000"
seta hud_panel_notify_size "0.320000 0.190000"
seta hud_panel_notify_bg "0"
seta hud_panel_notify_fadetime "3"
seta hud_panel_notify_icon_aspect "2"
-seta hud_panel_timer 1
+seta hud_panel_timer "1"
seta hud_panel_timer_pos "0.870000 0"
seta hud_panel_timer_size "0.130000 0.060000"
seta hud_panel_timer_bg "0"
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
-seta hud_panel_timer_increment "0"
-seta hud_panel_radar 2
+seta hud_panel_radar "2"
seta hud_panel_radar_pos "0.030000 0.020000"
seta hud_panel_radar_size "0.170000 0.220000"
seta hud_panel_radar_bg ""
seta hud_panel_radar_maximized_rotation "1"
seta hud_panel_radar_maximized_zoommode "3"
-seta hud_panel_score 1
+seta hud_panel_score "1"
seta hud_panel_score_pos "0.020000 0.920000"
seta hud_panel_score_size "0.150000 0.070000"
seta hud_panel_score_bg ""
seta hud_panel_score_bg_padding ""
seta hud_panel_score_rankings "1"
-seta hud_panel_racetimer 1
+seta hud_panel_racetimer "1"
seta hud_panel_racetimer_pos "0.360000 0.090000"
seta hud_panel_racetimer_size "0.280000 0.090000"
seta hud_panel_racetimer_bg "0"
seta hud_panel_racetimer_bg_border ""
seta hud_panel_racetimer_bg_padding ""
-seta hud_panel_vote 1
+seta hud_panel_vote "1"
seta hud_panel_vote_pos "0.020000 0.650000"
seta hud_panel_vote_size "0.230000 0.110000"
seta hud_panel_vote_bg ""
seta hud_panel_vote_bg_padding ""
seta hud_panel_vote_alreadyvoted_alpha "0.800000"
-seta hud_panel_modicons 1
+seta hud_panel_modicons "1"
seta hud_panel_modicons_pos "0.040000 0.270000"
seta hud_panel_modicons_size "0.080000 0.200000"
seta hud_panel_modicons_bg ""
seta hud_panel_modicons_dom_layout "1"
seta hud_panel_modicons_freezetag_layout "1"
-seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys "1"
seta hud_panel_pressedkeys_pos "0.410000 0.710000"
seta hud_panel_pressedkeys_size "0.180000 0.130000"
seta hud_panel_pressedkeys_bg "0"
seta hud_panel_pressedkeys_aspect "1.600000"
seta hud_panel_pressedkeys_attack "0"
-seta hud_panel_chat 1
+seta hud_panel_chat "1"
seta hud_panel_chat_pos "0.020000 0.780000"
seta hud_panel_chat_size "0.630000 0.110000"
seta hud_panel_chat_bg "0"
seta hud_panel_chat_bg_border ""
seta hud_panel_chat_bg_padding ""
-seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo "0"
seta hud_panel_engineinfo_pos "0.910000 0.970000"
seta hud_panel_engineinfo_size "0.090000 0.030000"
seta hud_panel_engineinfo_bg "0"
seta hud_panel_engineinfo_framecounter_time "0.1"
seta hud_panel_engineinfo_framecounter_decimals "0"
-seta hud_panel_infomessages 1
+seta hud_panel_infomessages "1"
seta hud_panel_infomessages_pos "0.510000 0"
seta hud_panel_infomessages_size "0.340000 0.090000"
seta hud_panel_infomessages_bg "0"
seta hud_panel_infomessages_bg_padding "0"
seta hud_panel_infomessages_flip "1"
-seta hud_panel_physics 3
+seta hud_panel_physics "3"
seta hud_panel_physics_pos "0.410000 0.590000"
seta hud_panel_physics_size "0.180000 0.100000"
seta hud_panel_physics_bg ""
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_speed_unit "3"
seta hud_panel_physics_speed_unit_show "1"
seta hud_panel_physics_speed_max "1800"
seta hud_panel_physics_speed_vertical "0"
seta hud_panel_physics_text "1"
seta hud_panel_physics_text_scale "0.7"
-seta hud_panel_centerprint 1
+seta hud_panel_centerprint "1"
seta hud_panel_centerprint_pos "0.175000 0.220000"
seta hud_panel_centerprint_size "0.650000 0.220000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
seta hud_panel_centerprint_fade_minfontsize "0"
-seta hud_panel_mapvote 1
-seta hud_panel_mapvote_pos "0 0"
-seta hud_panel_mapvote_size "1 1"
-seta hud_panel_mapvote_bg "0"
-seta hud_panel_mapvote_bg_color ""
-seta hud_panel_mapvote_bg_color_team ""
-seta hud_panel_mapvote_bg_alpha ""
-seta hud_panel_mapvote_bg_border ""
-seta hud_panel_mapvote_bg_padding ""
-
-seta hud_panel_itemstime 2
-seta hud_panel_itemstime_pos "0.020000 0.490000"
-seta hud_panel_itemstime_size "0.090000 0.140000"
-seta hud_panel_itemstime_bg "0"
-seta hud_panel_itemstime_bg_color ""
-seta hud_panel_itemstime_bg_color_team ""
-seta hud_panel_itemstime_bg_alpha ""
-seta hud_panel_itemstime_bg_border ""
-seta hud_panel_itemstime_bg_padding ""
-seta hud_panel_itemstime_iconalign "0"
-seta hud_panel_itemstime_progressbar "1"
-seta hud_panel_itemstime_progressbar_name "progressbar"
-seta hud_panel_itemstime_progressbar_reduced "1"
-seta hud_panel_itemstime_text "1"
-seta hud_panel_itemstime_ratio "3.5"
-seta hud_panel_itemstime_dynamicsize "1"
-
seta hud_panel_minigameboard "1"
seta hud_panel_minigameboard_pos "0.22 0.15"
seta hud_panel_minigameboard_size "0.50 0.60"
seta hud_panel_minigamemenu_bg_border ""
seta hud_panel_minigamemenu_bg_padding ""
-seta hud_panel_quickmenu 1
+seta hud_panel_mapvote "1"
+seta hud_panel_mapvote_pos "0 0"
+seta hud_panel_mapvote_size "1 1"
+seta hud_panel_mapvote_bg "0"
+seta hud_panel_mapvote_bg_color ""
+seta hud_panel_mapvote_bg_color_team ""
+seta hud_panel_mapvote_bg_alpha ""
+seta hud_panel_mapvote_bg_border ""
+seta hud_panel_mapvote_bg_padding ""
+
+seta hud_panel_itemstime "2"
+seta hud_panel_itemstime_pos "0.020000 0.490000"
+seta hud_panel_itemstime_size "0.090000 0.140000"
+seta hud_panel_itemstime_bg "0"
+seta hud_panel_itemstime_bg_color ""
+seta hud_panel_itemstime_bg_color_team ""
+seta hud_panel_itemstime_bg_alpha ""
+seta hud_panel_itemstime_bg_border ""
+seta hud_panel_itemstime_bg_padding ""
+seta hud_panel_itemstime_iconalign "0"
+seta hud_panel_itemstime_progressbar "1"
+seta hud_panel_itemstime_progressbar_name "progressbar"
+seta hud_panel_itemstime_progressbar_reduced "1"
+seta hud_panel_itemstime_text "1"
+seta hud_panel_itemstime_ratio "3.500000"
+seta hud_panel_itemstime_dynamicsize "1"
+
+seta hud_panel_quickmenu "1"
seta hud_panel_quickmenu_pos "0.700000 0.460000"
seta hud_panel_quickmenu_size "0.210000 0.250000"
seta hud_panel_quickmenu_bg ""
seta _hud_panelorder "17 15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 18 23 19 20 21 22 "
seta hud_configure_grid "1"
-seta hud_configure_grid_xsize "0.01"
-seta hud_configure_grid_ysize "0.01"
+seta hud_configure_grid_xsize "0.010000"
+seta hud_configure_grid_ysize "0.010000"
-seta hud_panel_weapons 1
+seta hud_panel_weapons "1"
seta hud_panel_weapons_pos "0.375000 0.870000"
seta hud_panel_weapons_size "0.300000 0.060000"
seta hud_panel_weapons_bg "0"
seta hud_panel_weapons_noncurrent_alpha "1"
seta hud_panel_weapons_noncurrent_scale "1"
-seta hud_panel_ammo 1
+seta hud_panel_ammo "1"
seta hud_panel_ammo_pos "0.160000 0.910000"
seta hud_panel_ammo_size "0.190000 0.090000"
seta hud_panel_ammo_bg "0"
seta hud_panel_ammo_progressbar_xoffset "0"
seta hud_panel_ammo_text "1"
-seta hud_panel_powerups 1
+seta hud_panel_powerups "1"
seta hud_panel_powerups_pos "0.660000 0.910000"
seta hud_panel_powerups_size "0.130000 0.090000"
seta hud_panel_powerups_bg "0"
seta hud_panel_powerups_progressbar "0"
seta hud_panel_powerups_text "1"
-seta hud_panel_healtharmor 1
+seta hud_panel_healtharmor "1"
seta hud_panel_healtharmor_pos "0.370000 0.930000"
seta hud_panel_healtharmor_size "0.300000 0.070000"
seta hud_panel_healtharmor_bg "0"
seta hud_panel_healtharmor_progressbar_gfx_smooth "2"
seta hud_panel_healtharmor_text "1"
-seta hud_panel_notify 0
+seta hud_panel_notify "0"
seta hud_panel_notify_pos "0.010000 0.650000"
seta hud_panel_notify_size "0.300000 0.070000"
seta hud_panel_notify_bg "0"
seta hud_panel_notify_fadetime "3"
seta hud_panel_notify_icon_aspect "2"
-seta hud_panel_timer 1
+seta hud_panel_timer "1"
seta hud_panel_timer_pos "0.850000 0"
seta hud_panel_timer_size "0.150000 0.060000"
seta hud_panel_timer_bg ""
seta hud_panel_timer_bg_alpha ""
seta hud_panel_timer_bg_border ""
seta hud_panel_timer_bg_padding "0"
-seta hud_panel_timer_increment "0"
-seta hud_panel_radar 2
+seta hud_panel_radar "2"
seta hud_panel_radar_pos "0 0"
seta hud_panel_radar_size "0.200000 0.260000"
seta hud_panel_radar_bg "border_radar"
seta hud_panel_radar_maximized_rotation "1"
seta hud_panel_radar_maximized_zoommode "3"
-seta hud_panel_score 1
+seta hud_panel_score "1"
seta hud_panel_score_pos "0.760000 0.910000"
seta hud_panel_score_size "0.200000 0.080000"
seta hud_panel_score_bg "0"
seta hud_panel_score_bg_padding ""
seta hud_panel_score_rankings "0"
-seta hud_panel_racetimer 1
+seta hud_panel_racetimer "1"
seta hud_panel_racetimer_pos "0.360000 0.140000"
seta hud_panel_racetimer_size "0.280000 0.090000"
seta hud_panel_racetimer_bg "0"
seta hud_panel_racetimer_bg_border ""
seta hud_panel_racetimer_bg_padding ""
-seta hud_panel_vote 1
+seta hud_panel_vote "1"
seta hud_panel_vote_pos "0.690000 0.750000"
seta hud_panel_vote_size "0.300000 0.100000"
seta hud_panel_vote_bg ""
seta hud_panel_vote_bg_padding "-3"
seta hud_panel_vote_alreadyvoted_alpha "0.750000"
-seta hud_panel_modicons 1
+seta hud_panel_modicons "1"
seta hud_panel_modicons_pos "0.010000 0.910000"
seta hud_panel_modicons_size "0.135000 0.090000"
seta hud_panel_modicons_bg "0"
seta hud_panel_modicons_dom_layout "1"
seta hud_panel_modicons_freezetag_layout "1"
-seta hud_panel_pressedkeys 1
+seta hud_panel_pressedkeys "1"
seta hud_panel_pressedkeys_pos "0.440000 0.760000"
seta hud_panel_pressedkeys_size "0.120000 0.094368"
seta hud_panel_pressedkeys_bg "0"
seta hud_panel_pressedkeys_aspect "1.600000"
seta hud_panel_pressedkeys_attack "0"
-seta hud_panel_chat 1
+seta hud_panel_chat "1"
seta hud_panel_chat_pos "0 0.760000"
seta hud_panel_chat_size "0.420000 0.130000"
seta hud_panel_chat_bg "0"
seta hud_panel_chat_bg_border ""
seta hud_panel_chat_bg_padding ""
-seta hud_panel_engineinfo 0
+seta hud_panel_engineinfo "0"
seta hud_panel_engineinfo_pos "0.887500 0.870000"
seta hud_panel_engineinfo_size "0.112500 0.030000"
seta hud_panel_engineinfo_bg "0"
seta hud_panel_engineinfo_framecounter_time "0.1"
seta hud_panel_engineinfo_framecounter_decimals "0"
-seta hud_panel_infomessages 1
+seta hud_panel_infomessages "1"
seta hud_panel_infomessages_pos "0.690000 0.620000"
seta hud_panel_infomessages_size "0.300000 0.100000"
seta hud_panel_infomessages_bg "0"
seta hud_panel_infomessages_bg_padding ""
seta hud_panel_infomessages_flip "1"
-seta hud_panel_physics 3
+seta hud_panel_physics "3"
seta hud_panel_physics_pos "0.430000 0.640000"
seta hud_panel_physics_size "0.140000 0.100000"
seta hud_panel_physics_bg "0"
seta hud_panel_physics_bg_alpha ""
seta hud_panel_physics_bg_border ""
seta hud_panel_physics_bg_padding ""
-seta hud_panel_physics_speed_unit "1"
seta hud_panel_physics_speed_unit_show "0"
seta hud_panel_physics_speed_max "1800"
seta hud_panel_physics_speed_vertical "0"
seta hud_panel_physics_text "2"
seta hud_panel_physics_text_scale "1"
-seta hud_panel_centerprint 1
+seta hud_panel_centerprint "1"
seta hud_panel_centerprint_pos "0.175000 0.260000"
seta hud_panel_centerprint_size "0.650000 0.200000"
seta hud_panel_centerprint_bg "0"
seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75"
seta hud_panel_centerprint_fade_minfontsize "0"
-seta hud_panel_mapvote 1
-seta hud_panel_mapvote_pos "0 0"
-seta hud_panel_mapvote_size "1 1"
-seta hud_panel_mapvote_bg "0"
-seta hud_panel_mapvote_bg_color ""
-seta hud_panel_mapvote_bg_color_team ""
-seta hud_panel_mapvote_bg_alpha ""
-seta hud_panel_mapvote_bg_border ""
-seta hud_panel_mapvote_bg_padding ""
-
-seta hud_panel_itemstime 2
-seta hud_panel_itemstime_pos "0.000000 0.290000"
-seta hud_panel_itemstime_size "0.150000 0.060000"
-seta hud_panel_itemstime_bg "0"
-seta hud_panel_itemstime_bg_color ""
-seta hud_panel_itemstime_bg_color_team ""
-seta hud_panel_itemstime_bg_alpha ""
-seta hud_panel_itemstime_bg_border ""
-seta hud_panel_itemstime_bg_padding ""
-seta hud_panel_itemstime_iconalign "0"
-seta hud_panel_itemstime_progressbar "0"
-seta hud_panel_itemstime_progressbar_name "progressbar"
-seta hud_panel_itemstime_progressbar_reduced "0"
-seta hud_panel_itemstime_text "1"
-seta hud_panel_itemstime_ratio "2"
-seta hud_panel_itemstime_dynamicsize "1"
-
seta hud_panel_minigameboard "1"
seta hud_panel_minigameboard_pos "0.22 0.15"
seta hud_panel_minigameboard_size "0.50 0.60"
seta hud_panel_minigamemenu_bg_border ""
seta hud_panel_minigamemenu_bg_padding ""
-seta hud_panel_quickmenu 1
+seta hud_panel_mapvote "1"
+seta hud_panel_mapvote_pos "0 0"
+seta hud_panel_mapvote_size "1 1"
+seta hud_panel_mapvote_bg "0"
+seta hud_panel_mapvote_bg_color ""
+seta hud_panel_mapvote_bg_color_team ""
+seta hud_panel_mapvote_bg_alpha ""
+seta hud_panel_mapvote_bg_border ""
+seta hud_panel_mapvote_bg_padding ""
+
+seta hud_panel_itemstime "2"
+seta hud_panel_itemstime_pos "0.000000 0.290000"
+seta hud_panel_itemstime_size "0.150000 0.060000"
+seta hud_panel_itemstime_bg "0"
+seta hud_panel_itemstime_bg_color ""
+seta hud_panel_itemstime_bg_color_team ""
+seta hud_panel_itemstime_bg_alpha ""
+seta hud_panel_itemstime_bg_border ""
+seta hud_panel_itemstime_bg_padding ""
+seta hud_panel_itemstime_iconalign "0"
+seta hud_panel_itemstime_progressbar "0"
+seta hud_panel_itemstime_progressbar_name "progressbar"
+seta hud_panel_itemstime_progressbar_reduced "0"
+seta hud_panel_itemstime_text "1"
+seta hud_panel_itemstime_ratio "2"
+seta hud_panel_itemstime_dynamicsize "1"
+
+seta hud_panel_quickmenu "1"
seta hud_panel_quickmenu_pos "0.010000 0.380000"
seta hud_panel_quickmenu_size "0.210000 0.250000"
seta hud_panel_quickmenu_bg ""
-ast Asturian "Asturianu (60%)"
-de German "Deutsch (90%)"
-de_CH German "Deutsch (Schweiz) (90%)"
-en_AU en_AU "en_AU (77%)"
-en English "English"
-es Spanish "Español (68%)"
-fr French "Français (98%)"
-it Italian "Italiano (97%)"
-hu Hungarian "Magyar (50%)"
-nl Dutch "Nederlands (45%)"
-pl Polish "Polski (60%)"
-pt Portuguese "Português (42%)"
-ro Romanian "Romana (90%)"
-fi Finnish "Suomi (35%)"
-el Greek "Ελληνική (25%)"
-be Belarusian "Беларуская (65%)"
-bg Bulgarian "Български (65%)"
-ru Russian "Русский (93%)"
-uk Ukrainian "Українська (60%)"
+ast Asturian "Asturianu" 60%
+de German "Deutsch" 90%
+de_CH German "Deutsch (Schweiz)" 90%
+en English "English"
+en_AU English "English (Australia)" 77%
+es Spanish "Español" 68%
+fr French "Français" 98%
+it Italian "Italiano" 97%
+hu Hungarian "Magyar" 50%
+nl Dutch "Nederlands" 45%
+pl Polish "Polski" 60%
+pt Portuguese "Português" 42%
+ro Romanian "Romana" 90%
+fi Finnish "Suomi" 35%
+el Greek "Ελληνική" 25%
+be Belarusian "Беларуская" 65%
+bg Bulgarian "Български" 65%
+ru Russian "Русский" 93%
+uk Ukrainian "Українська" 60%
\ No newline at end of file
--- /dev/null
+// bulldozer storage "level1" last updated 16-11-2015 03:11:33
+nextlevel = "level2"
+"k11" 1 "0 -1 0"
+"a20" 6 "0 0 0"
+"a19" 6 "0 0 0"
+"a18" 6 "0 0 0"
+"a17" 6 "0 0 0"
+"a15" 6 "0 0 0"
+"a14" 6 "0 0 0"
+"a13" 6 "0 0 0"
+"a12" 6 "0 0 0"
+"a11" 6 "0 0 0"
+"a10" 6 "0 0 0"
+"a9" 6 "0 0 0"
+"a8" 6 "0 0 0"
+"a7" 6 "0 0 0"
+"a6" 6 "0 0 0"
+"a5" 6 "0 0 0"
+"a4" 6 "0 0 0"
+"a3" 6 "0 0 0"
+"a2" 6 "0 0 0"
+"a1" 6 "0 0 0"
+"b1" 6 "0 0 0"
+"c1" 6 "0 0 0"
+"d1" 6 "0 0 0"
+"e1" 6 "0 0 0"
+"f1" 6 "0 0 0"
+"g1" 6 "0 0 0"
+"h1" 6 "0 0 0"
+"i1" 6 "0 0 0"
+"j1" 6 "0 0 0"
+"k1" 6 "0 0 0"
+"l1" 6 "0 0 0"
+"m1" 6 "0 0 0"
+"n1" 6 "0 0 0"
+"o1" 6 "0 0 0"
+"p1" 6 "0 0 0"
+"q1" 6 "0 0 0"
+"r1" 6 "0 0 0"
+"s1" 6 "0 0 0"
+"t1" 6 "0 0 0"
+"t2" 6 "0 0 0"
+"t3" 6 "0 0 0"
+"t4" 6 "0 0 0"
+"t5" 6 "0 0 0"
+"t6" 6 "0 0 0"
+"t7" 6 "0 0 0"
+"t8" 6 "0 0 0"
+"t9" 6 "0 0 0"
+"t10" 6 "0 0 0"
+"t11" 6 "0 0 0"
+"t12" 6 "0 0 0"
+"t13" 6 "0 0 0"
+"t14" 6 "0 0 0"
+"t15" 6 "0 0 0"
+"t16" 6 "0 0 0"
+"t17" 6 "0 0 0"
+"t18" 6 "0 0 0"
+"t19" 6 "0 0 0"
+"t20" 6 "0 0 0"
+"s20" 6 "0 0 0"
+"r20" 6 "0 0 0"
+"q20" 6 "0 0 0"
+"p20" 6 "0 0 0"
+"o20" 6 "0 0 0"
+"n20" 6 "0 0 0"
+"m20" 6 "0 0 0"
+"l20" 6 "0 0 0"
+"k20" 6 "0 0 0"
+"j20" 6 "0 0 0"
+"i20" 6 "0 0 0"
+"h20" 6 "0 0 0"
+"g20" 6 "0 0 0"
+"f20" 6 "0 0 0"
+"e20" 6 "0 0 0"
+"d20" 6 "0 0 0"
+"c20" 6 "0 0 0"
+"b20" 6 "0 0 0"
+"a16" 6 "0 0 0"
+"b2" 4 "0 0 0"
+"c18" 6 "0 0 0"
+"e18" 6 "0 0 0"
+"e17" 6 "0 0 0"
+"e16" 6 "0 0 0"
+"e15" 6 "0 0 0"
+"e14" 6 "0 0 0"
+"e13" 6 "0 0 0"
+"e12" 6 "0 0 0"
+"e11" 6 "0 0 0"
+"f10" 4 "0 0 0"
+"e9" 6 "0 0 0"
+"e8" 6 "0 0 0"
+"e7" 6 "0 0 0"
+"e6" 6 "0 0 0"
+"e5" 6 "0 0 0"
+"e4" 6 "0 0 0"
+"e3" 6 "0 0 0"
+"e2" 6 "0 0 0"
+"e19" 6 "0 0 0"
+"c17" 6 "0 0 0"
+"c16" 6 "0 0 0"
+"c15" 6 "0 0 0"
+"c14" 6 "0 0 0"
+"c13" 6 "0 0 0"
+"c12" 6 "0 0 0"
+"c11" 6 "0 0 0"
+"c10" 6 "0 0 0"
+"c9" 6 "0 0 0"
+"c8" 6 "0 0 0"
+"c7" 6 "0 0 0"
+"c6" 6 "0 0 0"
+"c5" 6 "0 0 0"
+"c4" 6 "0 0 0"
+"c3" 6 "0 0 0"
+"c2" 6 "0 0 0"
+"c19" 6 "0 0 0"
+"i14" 5 "0 0 0"
+"f12" 4 "0 0 0"
+"f11" 4 "0 0 0"
+"e10" 6 "0 0 0"
+"i10" 5 "0 0 0"
+"h10" 5 "0 0 0"
+"j10" 5 "0 0 0"
+"j9" 5 "0 0 0"
+"g11" 5 "0 0 0"
+"j8" 5 "0 0 0"
+"k8" 5 "0 0 0"
+"l8" 5 "0 0 0"
+"l9" 5 "0 0 0"
+"i8" 4 "0 0 0"
+"i9" 4 "0 0 0"
+"m11" 5 "0 0 0"
+"l10" 5 "0 0 0"
+"n11" 5 "0 0 0"
+"n13" 5 "0 0 0"
+"n12" 5 "0 0 0"
+"m13" 5 "0 0 0"
+"k13" 5 "0 0 0"
+"k14" 5 "0 0 0"
+"k15" 5 "0 0 0"
+"j15" 5 "0 0 0"
+"i13" 5 "0 0 0"
+"h15" 4 "0 0 0"
+"h14" 4 "0 0 0"
+"h13" 4 "0 0 0"
+"g15" 4 "0 0 0"
+"p17" 6 "0 0 0"
+"p16" 6 "0 0 0"
+"l13" 5 "0 0 0"
+"h12" 5 "0 0 0"
+"i15" 5 "0 0 0"
+"l15" 4 "0 0 0"
+"m15" 4 "0 0 0"
+"l14" 4 "0 0 0"
+"m14" 4 "0 0 0"
+"n14" 4 "0 0 0"
+"p15" 6 "0 0 0"
+"p14" 6 "0 0 0"
+"l11" 5 "0 0 0"
+"h11" 2 "0 0 0"
+"k9" 2 "0 0 0"
+"j14" 2 "0 0 0"
+"m12" 2 "0 0 0"
+"l12" 3 "0 0 0"
+"j11" 3 "0 0 0"
+"j12" 3 "0 0 0"
+"k10" 3 "0 0 0"
+"i12" 5 "0 0 0"
+"g12" 5 "0 0 0"
+"g10" 5 "0 0 0"
+"p13" 6 "0 0 0"
+"p12" 6 "0 0 0"
+"p11" 6 "0 0 0"
+"p10" 6 "0 0 0"
+"p9" 6 "0 0 0"
+"p8" 6 "0 0 0"
+"p7" 6 "0 0 0"
+"p6" 6 "0 0 0"
+"p5" 6 "0 0 0"
+"p4" 6 "0 0 0"
+"p3" 6 "0 0 0"
+"p2" 6 "0 0 0"
+"p18" 6 "0 0 0"
+"p19" 6 "0 0 0"
+"r16" 6 "0 0 0"
+"r15" 6 "0 0 0"
+"r14" 6 "0 0 0"
+"r13" 6 "0 0 0"
+"r12" 6 "0 0 0"
+"r11" 6 "0 0 0"
+"r10" 6 "0 0 0"
+"r9" 6 "0 0 0"
+"r8" 6 "0 0 0"
+"r7" 6 "0 0 0"
+"r6" 6 "0 0 0"
+"r5" 6 "0 0 0"
+"r4" 6 "0 0 0"
+"r3" 6 "0 0 0"
+"r2" 6 "0 0 0"
+"r17" 6 "0 0 0"
+"r18" 6 "0 0 0"
+"r19" 6 "0 0 0"
+"d12" 4 "0 0 0"
+"d6" 4 "0 0 0"
+"f6" 4 "0 0 0"
+"f7" 4 "0 0 0"
+"f8" 4 "0 0 0"
+"f9" 4 "0 0 0"
+"h9" 4 "0 0 0"
+"g9" 4 "0 0 0"
+"g8" 4 "0 0 0"
+"g7" 4 "0 0 0"
+"g6" 4 "0 0 0"
+"g5" 4 "0 0 0"
+"g4" 4 "0 0 0"
+"h6" 4 "0 0 0"
+"h7" 4 "0 0 0"
+"h8" 4 "0 0 0"
+"i7" 4 "0 0 0"
+"i6" 4 "0 0 0"
+"j6" 4 "0 0 0"
+"k6" 4 "0 0 0"
+"j7" 4 "0 0 0"
+"k7" 4 "0 0 0"
+"l6" 4 "0 0 0"
+"l7" 4 "0 0 0"
+"m10" 4 "0 0 0"
+"m8" 4 "0 0 0"
+"m7" 4 "0 0 0"
+"m6" 4 "0 0 0"
+"m5" 4 "0 0 0"
+"m4" 4 "0 0 0"
+"m3" 4 "0 0 0"
+"m2" 4 "0 0 0"
+"f19" 4 "0 0 0"
+"f18" 4 "0 0 0"
+"f17" 4 "0 0 0"
+"f16" 4 "0 0 0"
+"f15" 4 "0 0 0"
+"f13" 4 "0 0 0"
+"l3" 4 "0 0 0"
+"l4" 4 "0 0 0"
+"l5" 4 "0 0 0"
+"j3" 4 "0 0 0"
+"j2" 4 "0 0 0"
+"k3" 4 "0 0 0"
+"i3" 4 "0 0 0"
+"g3" 4 "0 0 0"
+"h3" 4 "0 0 0"
+"f3" 4 "0 0 0"
+"d3" 4 "0 0 0"
+"d19" 4 "0 0 0"
+"d17" 4 "0 0 0"
+"d5" 4 "0 0 0"
+"d4" 4 "0 0 0"
+"d7" 4 "0 0 0"
+"h5" 4 "0 0 0"
+"h4" 4 "0 0 0"
+"i4" 4 "0 0 0"
+"j4" 4 "0 0 0"
+"k5" 4 "0 0 0"
+"j5" 4 "0 0 0"
+"i5" 4 "0 0 0"
+"d18" 4 "0 0 0"
+"d10" 4 "0 0 0"
+"g13" 4 "0 0 0"
+"g14" 4 "0 0 0"
+"k4" 4 "0 0 0"
+"d8" 4 "0 0 0"
+"d9" 4 "0 0 0"
+"g16" 4 "0 0 0"
+"g17" 4 "0 0 0"
+"g18" 4 "0 0 0"
+"d11" 4 "0 0 0"
+"g19" 4 "0 0 0"
+"h19" 4 "0 0 0"
+"h18" 4 "0 0 0"
+"h16" 4 "0 0 0"
+"h17" 4 "0 0 0"
+"i16" 4 "0 0 0"
+"i17" 4 "0 0 0"
+"i18" 4 "0 0 0"
+"j19" 4 "0 0 0"
+"j18" 4 "0 0 0"
+"j17" 4 "0 0 0"
+"i19" 4 "0 0 0"
+"j16" 4 "0 0 0"
+"k16" 4 "0 0 0"
+"k17" 4 "0 0 0"
+"k18" 4 "0 0 0"
+"k19" 4 "0 0 0"
+"l19" 4 "0 0 0"
+"f5" 4 "0 0 0"
+"f4" 4 "0 0 0"
+"l18" 4 "0 0 0"
+"l17" 4 "0 0 0"
+"l16" 4 "0 0 0"
+"m16" 4 "0 0 0"
+"m17" 4 "0 0 0"
+"m18" 4 "0 0 0"
+"n19" 4 "0 0 0"
+"m19" 4 "0 0 0"
+"n18" 4 "0 0 0"
+"n17" 4 "0 0 0"
+"n16" 4 "0 0 0"
+"n15" 4 "0 0 0"
+"n10" 4 "0 0 0"
+"n9" 4 "0 0 0"
+"n8" 4 "0 0 0"
+"n7" 4 "0 0 0"
+"n6" 4 "0 0 0"
+"n5" 4 "0 0 0"
+"n4" 4 "0 0 0"
+"n3" 4 "0 0 0"
+"m9" 4 "0 0 0"
+"s2" 4 "0 0 0"
+"s3" 4 "0 0 0"
+"s4" 4 "0 0 0"
+"s5" 4 "0 0 0"
+"s6" 4 "0 0 0"
+"s7" 4 "0 0 0"
+"s8" 4 "0 0 0"
+"s9" 4 "0 0 0"
+"s10" 4 "0 0 0"
+"s11" 4 "0 0 0"
+"s12" 4 "0 0 0"
+"s13" 4 "0 0 0"
+"s14" 4 "0 0 0"
+"s15" 4 "0 0 0"
+"s16" 4 "0 0 0"
+"s17" 4 "0 0 0"
+"s18" 4 "0 0 0"
+"s19" 4 "0 0 0"
+"q19" 4 "0 0 0"
+"o19" 4 "0 0 0"
+"o18" 4 "0 0 0"
+"o17" 4 "0 0 0"
+"o16" 4 "0 0 0"
+"o15" 4 "0 0 0"
+"o14" 4 "0 0 0"
+"o13" 4 "0 0 0"
+"o12" 4 "0 0 0"
+"o11" 4 "0 0 0"
+"o10" 4 "0 0 0"
+"o9" 4 "0 0 0"
+"o8" 4 "0 0 0"
+"o7" 4 "0 0 0"
+"o6" 4 "0 0 0"
+"o5" 4 "0 0 0"
+"o4" 4 "0 0 0"
+"o3" 4 "0 0 0"
+"q8" 4 "0 0 0"
+"q15" 4 "0 0 0"
+"q16" 4 "0 0 0"
+"q17" 4 "0 0 0"
+"q18" 4 "0 0 0"
+"q3" 4 "0 0 0"
+"q4" 4 "0 0 0"
+"q6" 4 "0 0 0"
+"q7" 4 "0 0 0"
+"q5" 4 "0 0 0"
+"q9" 4 "0 0 0"
+"q10" 4 "0 0 0"
+"q11" 4 "0 0 0"
+"q12" 4 "0 0 0"
+"q13" 4 "0 0 0"
+"q14" 4 "0 0 0"
+"b14" 4 "0 0 0"
+"b13" 4 "0 0 0"
+"d13" 4 "0 0 0"
+"d14" 4 "0 0 0"
+"d15" 4 "0 0 0"
+"b15" 4 "0 0 0"
+"b16" 4 "0 0 0"
+"d16" 4 "0 0 0"
+"b17" 4 "0 0 0"
+"b18" 4 "0 0 0"
+"b19" 4 "0 0 0"
+"f2" 4 "0 0 0"
+"g2" 4 "0 0 0"
+"h2" 4 "0 0 0"
+"i2" 4 "0 0 0"
+"k2" 4 "0 0 0"
+"l2" 4 "0 0 0"
+"n2" 4 "0 0 0"
+"o2" 4 "0 0 0"
+"q2" 4 "0 0 0"
+"f14" 4 "0 0 0"
+"b12" 4 "0 0 0"
+"b11" 4 "0 0 0"
+"b10" 4 "0 0 0"
+"b9" 4 "0 0 0"
+"b8" 4 "0 0 0"
+"b7" 4 "0 0 0"
+"b6" 4 "0 0 0"
+"b5" 4 "0 0 0"
+"b4" 4 "0 0 0"
+"b3" 4 "0 0 0"
+"d2" 4 "0 0 0"
--- /dev/null
+// bulldozer storage "level2" last updated 16-11-2015 03:34:13
+nextlevel = "level3"
+"a20" 4 "0 0 0"
+"b20" 4 "0 0 0"
+"c20" 4 "0 0 0"
+"d20" 4 "0 0 0"
+"e20" 4 "0 0 0"
+"r13" 5 "0 0 0"
+"f20" 4 "0 0 0"
+"g20" 4 "0 0 0"
+"c12" 5 "0 0 0"
+"h20" 4 "0 0 0"
+"c13" 5 "0 0 0"
+"i20" 4 "0 0 0"
+"c14" 5 "0 0 0"
+"j20" 4 "0 0 0"
+"c15" 5 "0 0 0"
+"k20" 4 "0 0 0"
+"c16" 5 "0 0 0"
+"l20" 4 "0 0 0"
+"c17" 5 "0 0 0"
+"m20" 4 "0 0 0"
+"c18" 5 "0 0 0"
+"n20" 4 "0 0 0"
+"c19" 5 "0 0 0"
+"o20" 4 "0 0 0"
+"r18" 5 "0 0 0"
+"p20" 4 "0 0 0"
+"r17" 5 "0 0 0"
+"q20" 4 "0 0 0"
+"r12" 5 "0 0 0"
+"r20" 4 "0 0 0"
+"r15" 5 "0 0 0"
+"r14" 5 "0 0 0"
+"s20" 4 "0 0 0"
+"t20" 4 "0 0 0"
+"t19" 4 "0 0 0"
+"t18" 4 "0 0 0"
+"t17" 4 "0 0 0"
+"t16" 4 "0 0 0"
+"t15" 4 "0 0 0"
+"t14" 4 "0 0 0"
+"t13" 4 "0 0 0"
+"t9" 4 "0 0 0"
+"s9" 4 "0 0 0"
+"r9" 4 "0 0 0"
+"q9" 4 "0 0 0"
+"p9" 4 "0 0 0"
+"o9" 4 "0 0 0"
+"n9" 4 "0 0 0"
+"m9" 4 "0 0 0"
+"l9" 4 "0 0 0"
+"k9" 4 "0 0 0"
+"j9" 4 "0 0 0"
+"i9" 4 "0 0 0"
+"h9" 4 "0 0 0"
+"g9" 4 "0 0 0"
+"f9" 4 "0 0 0"
+"e9" 4 "0 0 0"
+"d9" 4 "0 0 0"
+"c9" 4 "0 0 0"
+"b9" 4 "0 0 0"
+"a9" 4 "0 0 0"
+"a10" 4 "0 0 0"
+"a11" 4 "0 0 0"
+"a12" 4 "0 0 0"
+"a13" 4 "0 0 0"
+"a14" 4 "0 0 0"
+"a15" 4 "0 0 0"
+"a16" 4 "0 0 0"
+"a17" 4 "0 0 0"
+"a18" 4 "0 0 0"
+"a19" 4 "0 0 0"
+"t12" 4 "0 0 0"
+"t11" 4 "0 0 0"
+"t10" 4 "0 0 0"
+"k4" 4 "0 0 0"
+"t3" 4 "0 0 0"
+"s4" 4 "0 0 0"
+"t2" 4 "0 0 0"
+"l5" 4 "0 0 0"
+"j6" 4 "0 0 0"
+"r11" 5 "0 0 0"
+"r6" 4 "0 0 0"
+"r10" 5 "0 0 0"
+"b7" 5 "0 0 0"
+"i6" 4 "0 0 0"
+"a7" 5 "0 0 0"
+"a2" 4 "0 0 0"
+"c4" 5 "0 0 0"
+"b8" 4 "0 0 0"
+"a6" 5 "0 0 0"
+"o6" 4 "0 0 0"
+"p6" 4 "0 0 0"
+"a5" 5 "0 0 0"
+"l7" 4 "0 0 0"
+"l6" 4 "0 0 0"
+"t6" 4 "0 0 0"
+"t5" 4 "0 0 0"
+"b19" 2 "0 0 0"
+"k5" 4 "0 0 0"
+"b18" 2 "0 0 0"
+"p5" 4 "0 0 0"
+"j4" 4 "0 0 0"
+"k15" 1 "0 -1 0"
+"g16" 3 "0 0 0"
+"g12" 3 "0 0 0"
+"l3" 4 "0 0 0"
+"b3" 5 "0 0 0"
+"i5" 4 "0 0 0"
+"c8" 4 "0 0 0"
+"c5" 5 "0 0 0"
+"c6" 5 "0 0 0"
+"a4" 5 "0 0 0"
+"a3" 5 "0 0 0"
+"a8" 4 "0 0 0"
+"c3" 4 "0 0 0"
+"c7" 4 "0 0 0"
+"k6" 5 "0 0 0"
+"d6" 4 "0 0 0"
+"e7" 5 "0 0 0"
+"e6" 5 "0 0 0"
+"s10" 2 "0 0 0"
+"d5" 4 "0 0 0"
+"s11" 2 "0 0 0"
+"d4" 4 "0 0 0"
+"o17" 3 "0 0 0"
+"o13" 3 "0 0 0"
+"l4" 4 "0 0 0"
+"h7" 4 "0 0 0"
+"o4" 4 "0 0 0"
+"p4" 4 "0 0 0"
+"t4" 4 "0 0 0"
+"h6" 4 "0 0 0"
+"h5" 4 "0 0 0"
+"h4" 4 "0 0 0"
+"h3" 4 "0 0 0"
+"f4" 4 "0 0 0"
+"f5" 4 "0 0 0"
+"f6" 4 "0 0 0"
+"n6" 4 "0 0 0"
+"d3" 4 "0 0 0"
+"o5" 4 "0 0 0"
+"n4" 4 "0 0 0"
+"e5" 5 "0 0 0"
+"b2" 4 "0 0 0"
+"c2" 4 "0 0 0"
+"d2" 4 "0 0 0"
+"e2" 4 "0 0 0"
+"f2" 4 "0 0 0"
+"g2" 4 "0 0 0"
+"h2" 4 "0 0 0"
+"i2" 4 "0 0 0"
+"j2" 4 "0 0 0"
+"k2" 4 "0 0 0"
+"l2" 4 "0 0 0"
+"m2" 4 "0 0 0"
+"n2" 4 "0 0 0"
+"o2" 4 "0 0 0"
+"p2" 4 "0 0 0"
+"q2" 4 "0 0 0"
+"r2" 4 "0 0 0"
+"s2" 4 "0 0 0"
+"t1" 4 "0 0 0"
+"s1" 4 "0 0 0"
+"r1" 4 "0 0 0"
+"q1" 4 "0 0 0"
+"p1" 4 "0 0 0"
+"o1" 4 "0 0 0"
+"n1" 4 "0 0 0"
+"m1" 4 "0 0 0"
+"l1" 4 "0 0 0"
+"k1" 4 "0 0 0"
+"j1" 4 "0 0 0"
+"i1" 4 "0 0 0"
+"h1" 4 "0 0 0"
+"g1" 4 "0 0 0"
+"f1" 4 "0 0 0"
+"e1" 4 "0 0 0"
+"d1" 4 "0 0 0"
+"c1" 4 "0 0 0"
+"b1" 4 "0 0 0"
+"a1" 4 "0 0 0"
+"t7" 4 "0 0 0"
+"p3" 4 "0 0 0"
+"p7" 4 "0 0 0"
+"d7" 4 "0 0 0"
+"r3" 4 "0 0 0"
+"e4" 5 "0 0 0"
+"e3" 5 "0 0 0"
+"f3" 5 "0 0 0"
+"d8" 4 "0 0 0"
+"e8" 4 "0 0 0"
+"f8" 4 "0 0 0"
+"g8" 4 "0 0 0"
+"h8" 4 "0 0 0"
+"i8" 4 "0 0 0"
+"j8" 4 "0 0 0"
+"k8" 4 "0 0 0"
+"l8" 4 "0 0 0"
+"m8" 4 "0 0 0"
+"n8" 4 "0 0 0"
+"o8" 4 "0 0 0"
+"p8" 4 "0 0 0"
+"q8" 4 "0 0 0"
+"r8" 4 "0 0 0"
+"s8" 4 "0 0 0"
+"t8" 4 "0 0 0"
+"g3" 5 "0 0 0"
+"g7" 5 "0 0 0"
+"g4" 5 "0 0 0"
+"g6" 5 "0 0 0"
+"g5" 5 "0 0 0"
+"f7" 5 "0 0 0"
+"j5" 5 "0 0 0"
+"i7" 5 "0 0 0"
+"j7" 5 "0 0 0"
+"k7" 5 "0 0 0"
+"i4" 5 "0 0 0"
+"i3" 5 "0 0 0"
+"j3" 5 "0 0 0"
+"k3" 5 "0 0 0"
+"m7" 5 "0 0 0"
+"m6" 5 "0 0 0"
+"m4" 5 "0 0 0"
+"m5" 5 "0 0 0"
+"m3" 5 "0 0 0"
+"n3" 5 "0 0 0"
+"o3" 5 "0 0 0"
+"n5" 5 "0 0 0"
+"n7" 5 "0 0 0"
+"o7" 5 "0 0 0"
+"q7" 5 "0 0 0"
+"q6" 5 "0 0 0"
+"q4" 5 "0 0 0"
+"q5" 5 "0 0 0"
+"q3" 5 "0 0 0"
+"r5" 5 "0 0 0"
+"r4" 5 "0 0 0"
+"s3" 5 "0 0 0"
+"s5" 5 "0 0 0"
+"s6" 5 "0 0 0"
+"s7" 5 "0 0 0"
+"r7" 5 "0 0 0"
+"b6" 4 "0 0 0"
+"b5" 4 "0 0 0"
+"b4" 4 "0 0 0"
--- /dev/null
+// bulldozer storage "level3" last updated 16-11-2015 04:06:54
+nextlevel = "level4"
+"a20" 4 "0 0 0"
+"a19" 4 "0 0 0"
+"f14" 2 "0 0 0"
+"a18" 4 "0 0 0"
+"a17" 4 "0 0 0"
+"a16" 4 "0 0 0"
+"a15" 4 "0 0 0"
+"f14" 3 "0 0 0"
+"b7" 4 "0 0 0"
+"b5" 4 "0 0 0"
+"b3" 4 "0 0 0"
+"s7" 4 "0 0 0"
+"s5" 4 "0 0 0"
+"s3" 4 "0 0 0"
+"b19" 4 "0 0 0"
+"s19" 4 "0 0 0"
+"a14" 4 "0 0 0"
+"a13" 4 "0 0 0"
+"a12" 4 "0 0 0"
+"a11" 4 "0 0 0"
+"a10" 4 "0 0 0"
+"a9" 4 "0 0 0"
+"a8" 4 "0 0 0"
+"a7" 4 "0 0 0"
+"a6" 4 "0 0 0"
+"a5" 4 "0 0 0"
+"a4" 4 "0 0 0"
+"a3" 4 "0 0 0"
+"a2" 4 "0 0 0"
+"a1" 4 "0 0 0"
+"b1" 4 "0 0 0"
+"c1" 4 "0 0 0"
+"d1" 4 "0 0 0"
+"e1" 4 "0 0 0"
+"f1" 4 "0 0 0"
+"g1" 4 "0 0 0"
+"h1" 4 "0 0 0"
+"i1" 4 "0 0 0"
+"j1" 4 "0 0 0"
+"k1" 4 "0 0 0"
+"l1" 4 "0 0 0"
+"m1" 4 "0 0 0"
+"n1" 4 "0 0 0"
+"o1" 4 "0 0 0"
+"p1" 4 "0 0 0"
+"q1" 4 "0 0 0"
+"r1" 4 "0 0 0"
+"s1" 4 "0 0 0"
+"t1" 4 "0 0 0"
+"t2" 4 "0 0 0"
+"t3" 4 "0 0 0"
+"t4" 4 "0 0 0"
+"t5" 4 "0 0 0"
+"t6" 4 "0 0 0"
+"t12" 4 "0 0 0"
+"t9" 4 "0 0 0"
+"t10" 4 "0 0 0"
+"t11" 4 "0 0 0"
+"t7" 4 "0 0 0"
+"t8" 4 "0 0 0"
+"t13" 4 "0 0 0"
+"t14" 4 "0 0 0"
+"t15" 4 "0 0 0"
+"t16" 4 "0 0 0"
+"t17" 4 "0 0 0"
+"t18" 4 "0 0 0"
+"t19" 4 "0 0 0"
+"t20" 4 "0 0 0"
+"r20" 4 "0 0 0"
+"q20" 4 "0 0 0"
+"p20" 4 "0 0 0"
+"s20" 4 "0 0 0"
+"o20" 4 "0 0 0"
+"n20" 4 "0 0 0"
+"m20" 4 "0 0 0"
+"l20" 4 "0 0 0"
+"k20" 4 "0 0 0"
+"j20" 4 "0 0 0"
+"i20" 4 "0 0 0"
+"h20" 4 "0 0 0"
+"g20" 4 "0 0 0"
+"f20" 4 "0 0 0"
+"e20" 4 "0 0 0"
+"d20" 4 "0 0 0"
+"c20" 4 "0 0 0"
+"b20" 4 "0 0 0"
+"c19" 4 "0 0 0"
+"b18" 4 "0 0 0"
+"b16" 4 "0 0 0"
+"c18" 4 "0 0 0"
+"b14" 4 "0 0 0"
+"b17" 7 "0 0 0"
+"b12" 4 "0 0 0"
+"b15" 7 "0 0 0"
+"b9" 7 "0 0 0"
+"b8" 4 "0 0 0"
+"b11" 7 "0 0 0"
+"b10" 4 "0 0 0"
+"b6" 4 "0 0 0"
+"b13" 7 "0 0 0"
+"b2" 4 "0 0 0"
+"b4" 4 "0 0 0"
+"s18" 4 "0 0 0"
+"s13" 7 "0 0 0"
+"s16" 4 "0 0 0"
+"s11" 7 "0 0 0"
+"s14" 4 "0 0 0"
+"s9" 7 "0 0 0"
+"s12" 4 "0 0 0"
+"s8" 4 "0 0 0"
+"s6" 4 "0 0 0"
+"s4" 4 "0 0 0"
+"s2" 4 "0 0 0"
+"s10" 4 "0 0 0"
+"s17" 7 "0 0 0"
+"s15" 7 "0 0 0"
+"c7" 4 "0 0 0"
+"c6" 4 "0 0 0"
+"d7" 4 "0 0 0"
+"f7" 4 "0 0 0"
+"e7" 4 "0 0 0"
+"g7" 4 "0 0 0"
+"h7" 4 "0 0 0"
+"i7" 4 "0 0 0"
+"j7" 4 "0 0 0"
+"k7" 4 "0 0 0"
+"l7" 4 "0 0 0"
+"m7" 4 "0 0 0"
+"n7" 4 "0 0 0"
+"o7" 4 "0 0 0"
+"p7" 4 "0 0 0"
+"q7" 4 "0 0 0"
+"r7" 4 "0 0 0"
+"h4" 4 "0 0 0"
+"g4" 4 "0 0 0"
+"f4" 4 "0 0 0"
+"e4" 4 "0 0 0"
+"d4" 4 "0 0 0"
+"c4" 4 "0 0 0"
+"c3" 4 "0 0 0"
+"d3" 4 "0 0 0"
+"e3" 4 "0 0 0"
+"f3" 4 "0 0 0"
+"g3" 4 "0 0 0"
+"h3" 4 "0 0 0"
+"i3" 4 "0 0 0"
+"j3" 4 "0 0 0"
+"k3" 4 "0 0 0"
+"l3" 4 "0 0 0"
+"m3" 4 "0 0 0"
+"n3" 4 "0 0 0"
+"o3" 4 "0 0 0"
+"p3" 4 "0 0 0"
+"q3" 4 "0 0 0"
+"r3" 4 "0 0 0"
+"r2" 4 "0 0 0"
+"q2" 4 "0 0 0"
+"p2" 4 "0 0 0"
+"o2" 4 "0 0 0"
+"n2" 4 "0 0 0"
+"m2" 4 "0 0 0"
+"l2" 4 "0 0 0"
+"k2" 4 "0 0 0"
+"j2" 4 "0 0 0"
+"i2" 4 "0 0 0"
+"h2" 4 "0 0 0"
+"g2" 4 "0 0 0"
+"f2" 4 "0 0 0"
+"e2" 4 "0 0 0"
+"d2" 4 "0 0 0"
+"c2" 4 "0 0 0"
+"r4" 4 "0 0 0"
+"q4" 4 "0 0 0"
+"p4" 4 "0 0 0"
+"o4" 4 "0 0 0"
+"n4" 4 "0 0 0"
+"m4" 4 "0 0 0"
+"l4" 4 "0 0 0"
+"k4" 4 "0 0 0"
+"j4" 4 "0 0 0"
+"i4" 4 "0 0 0"
+"i5" 4 "0 0 0"
+"h5" 4 "0 0 0"
+"g5" 4 "0 0 0"
+"f5" 4 "0 0 0"
+"e5" 4 "0 0 0"
+"d5" 4 "0 0 0"
+"c5" 4 "0 0 0"
+"d6" 4 "0 0 0"
+"e6" 4 "0 0 0"
+"f6" 4 "0 0 0"
+"g6" 4 "0 0 0"
+"h6" 4 "0 0 0"
+"i6" 4 "0 0 0"
+"j6" 4 "0 0 0"
+"k6" 4 "0 0 0"
+"l6" 4 "0 0 0"
+"m6" 4 "0 0 0"
+"n6" 4 "0 0 0"
+"o6" 4 "0 0 0"
+"p6" 4 "0 0 0"
+"q6" 4 "0 0 0"
+"r6" 4 "0 0 0"
+"r5" 4 "0 0 0"
+"q5" 4 "0 0 0"
+"p5" 4 "0 0 0"
+"o5" 4 "0 0 0"
+"n5" 4 "0 0 0"
+"m5" 4 "0 0 0"
+"l5" 4 "0 0 0"
+"k5" 4 "0 0 0"
+"j5" 4 "0 0 0"
+"d18" 4 "0 0 0"
+"e18" 4 "0 0 0"
+"g18" 4 "0 0 0"
+"h18" 4 "0 0 0"
+"f18" 4 "0 0 0"
+"j18" 4 "0 0 0"
+"i18" 4 "0 0 0"
+"k18" 4 "0 0 0"
+"m18" 4 "0 0 0"
+"l18" 4 "0 0 0"
+"n18" 4 "0 0 0"
+"o18" 4 "0 0 0"
+"p18" 4 "0 0 0"
+"q18" 4 "0 0 0"
+"r18" 4 "0 0 0"
+"q19" 4 "0 0 0"
+"p19" 4 "0 0 0"
+"o19" 4 "0 0 0"
+"n19" 4 "0 0 0"
+"m19" 4 "0 0 0"
+"l19" 4 "0 0 0"
+"k19" 4 "0 0 0"
+"j19" 4 "0 0 0"
+"i19" 4 "0 0 0"
+"h19" 4 "0 0 0"
+"g19" 4 "0 0 0"
+"f19" 4 "0 0 0"
+"e19" 4 "0 0 0"
+"d19" 4 "0 0 0"
+"r19" 4 "0 0 0"
+"f15" 5 "0 0 0"
+"f13" 5 "0 0 0"
+"f12" 5 "0 0 0"
+"g12" 5 "0 0 0"
+"g9" 5 "0 0 0"
+"g10" 5 "0 0 0"
+"g11" 5 "0 0 0"
+"h9" 5 "0 0 0"
+"i9" 5 "0 0 0"
+"k9" 5 "0 0 0"
+"l9" 5 "0 0 0"
+"l13" 5 "0 0 0"
+"l12" 5 "0 0 0"
+"l10" 5 "0 0 0"
+"l11" 5 "0 0 0"
+"l15" 5 "0 0 0"
+"l14" 5 "0 0 0"
+"l16" 5 "0 0 0"
+"g15" 5 "0 0 0"
+"h15" 5 "0 0 0"
+"i15" 5 "0 0 0"
+"j15" 5 "0 0 0"
+"k15" 5 "0 0 0"
+"p9" 5 "0 0 0"
+"p10" 5 "0 0 0"
+"q10" 5 "0 0 0"
+"q8" 2 "0 0 0"
+"r8" 2 "0 0 0"
+"r9" 2 "0 0 0"
+"j9" 3 "0 0 0"
+"i13" 2 "0 0 0"
+"k13" 1 "0 -1 0"
+"n13" 3 "0 0 0"
+"n14" 3 "0 0 0"
+"n12" 3 "0 0 0"
--- /dev/null
+// bulldozer storage "level4" last updated 16-11-2015 05:09:50
+nextlevel = "level5"
+"k10" 9 "0 -1 0"
+"k11" 9 "0 -1 0"
+"k13" 9 "0 -1 0"
+"j14" 9 "0 -1 0"
+"k14" 9 "0 -1 0"
+"k8" 5 "0 -1 0"
+"k9" 5 "0 -1 0"
+"k7" 5 "0 -1 0"
+"m8" 4 "0 -1 0"
+"l14" 9 "0 -1 0"
+"i14" 9 "0 -1 0"
+"m12" 1 "0 -1 0"
+"l11" 2 "0 -1 0"
+"m11" 2 "0 -1 0"
+"m10" 2 "0 -1 0"
+"l10" 2 "0 -1 0"
+"k12" 3 "0 -1 0"
+"m16" 5 "0 -1 0"
+"l16" 5 "0 -1 0"
+"k16" 5 "0 -1 0"
+"j4" 4 "0 -1 0"
+"i4" 4 "0 -1 0"
+"h4" 4 "0 -1 0"
+"g4" 4 "0 -1 0"
+"f4" 4 "0 -1 0"
+"e4" 4 "0 -1 0"
+"d4" 4 "0 -1 0"
+"c4" 4 "0 -1 0"
+"b4" 4 "0 -1 0"
+"h11" 3 "0 -1 0"
+"f20" 4 "0 -1 0"
+"f19" 4 "0 -1 0"
+"f17" 4 "0 -1 0"
+"f18" 4 "0 -1 0"
+"h16" 5 "0 -1 0"
+"f16" 4 "0 -1 0"
+"f15" 4 "0 -1 0"
+"f14" 5 "0 -1 0"
+"g14" 5 "0 -1 0"
+"e13" 4 "0 -1 0"
+"e12" 4 "0 -1 0"
+"e11" 4 "0 -1 0"
+"e10" 4 "0 -1 0"
+"e9" 4 "0 -1 0"
+"e8" 4 "0 -1 0"
+"e7" 4 "0 -1 0"
+"f9" 5 "0 -1 0"
+"f7" 5 "0 -1 0"
+"f8" 5 "0 -1 0"
+"f10" 5 "0 -1 0"
+"g7" 5 "0 -1 0"
+"h12" 3 "0 -1 0"
+"m14" 3 "0 -1 0"
+"a4" 4 "0 -1 0"
+"a3" 4 "0 -1 0"
+"b3" 4 "0 -1 0"
+"c3" 4 "0 -1 0"
+"d3" 4 "0 -1 0"
+"e3" 4 "0 -1 0"
+"f3" 4 "0 -1 0"
+"g3" 4 "0 -1 0"
+"h3" 4 "0 -1 0"
+"i3" 4 "0 -1 0"
+"j3" 4 "0 -1 0"
+"k3" 4 "0 -1 0"
+"l3" 4 "0 -1 0"
+"m3" 4 "0 -1 0"
+"n3" 4 "0 -1 0"
+"o3" 4 "0 -1 0"
+"p3" 4 "0 -1 0"
+"q3" 4 "0 -1 0"
+"r3" 4 "0 -1 0"
+"s3" 4 "0 -1 0"
+"t3" 4 "0 -1 0"
+"t2" 4 "0 -1 0"
+"s2" 4 "0 -1 0"
+"r2" 4 "0 -1 0"
+"q2" 4 "0 -1 0"
+"p2" 4 "0 -1 0"
+"o2" 4 "0 -1 0"
+"n2" 4 "0 -1 0"
+"m2" 4 "0 -1 0"
+"l2" 4 "0 -1 0"
+"k2" 4 "0 -1 0"
+"j2" 4 "0 -1 0"
+"i2" 4 "0 -1 0"
+"h2" 4 "0 -1 0"
+"g2" 4 "0 -1 0"
+"f2" 4 "0 -1 0"
+"e2" 4 "0 -1 0"
+"d2" 4 "0 -1 0"
+"c2" 4 "0 -1 0"
+"b2" 4 "0 -1 0"
+"a2" 4 "0 -1 0"
+"a1" 4 "0 -1 0"
+"b1" 4 "0 -1 0"
+"c1" 4 "0 -1 0"
+"d1" 4 "0 -1 0"
+"e1" 4 "0 -1 0"
+"f1" 4 "0 -1 0"
+"g1" 4 "0 -1 0"
+"h1" 4 "0 -1 0"
+"i1" 4 "0 -1 0"
+"j1" 4 "0 -1 0"
+"k1" 4 "0 -1 0"
+"l1" 4 "0 -1 0"
+"m1" 4 "0 -1 0"
+"n1" 4 "0 -1 0"
+"o1" 4 "0 -1 0"
+"p1" 4 "0 -1 0"
+"q1" 4 "0 -1 0"
+"r1" 4 "0 -1 0"
+"s1" 4 "0 -1 0"
+"t1" 4 "0 -1 0"
+"t4" 4 "0 -1 0"
+"s4" 4 "0 -1 0"
+"r4" 4 "0 -1 0"
+"q4" 4 "0 -1 0"
+"p4" 4 "0 -1 0"
+"o4" 4 "0 -1 0"
+"n4" 4 "0 -1 0"
+"m4" 4 "0 -1 0"
+"l4" 4 "0 -1 0"
+"k4" 4 "0 -1 0"
+"k5" 4 "0 -1 0"
+"j5" 4 "0 -1 0"
+"i5" 4 "0 -1 0"
+"h5" 4 "0 -1 0"
+"g5" 4 "0 -1 0"
+"f5" 4 "0 -1 0"
+"e5" 4 "0 -1 0"
+"d5" 4 "0 -1 0"
+"c5" 4 "0 -1 0"
+"b5" 4 "0 -1 0"
+"a5" 4 "0 -1 0"
+"a6" 4 "0 -1 0"
+"b6" 4 "0 -1 0"
+"c6" 4 "0 -1 0"
+"d6" 4 "0 -1 0"
+"e6" 4 "0 -1 0"
+"f6" 4 "0 -1 0"
+"g6" 4 "0 -1 0"
+"h6" 4 "0 -1 0"
+"i6" 4 "0 -1 0"
+"j6" 4 "0 -1 0"
+"k6" 4 "0 -1 0"
+"l6" 4 "0 -1 0"
+"m6" 4 "0 -1 0"
+"n6" 4 "0 -1 0"
+"o6" 4 "0 -1 0"
+"p6" 4 "0 -1 0"
+"q6" 4 "0 -1 0"
+"r6" 4 "0 -1 0"
+"s6" 4 "0 -1 0"
+"t6" 4 "0 -1 0"
+"t5" 4 "0 -1 0"
+"s5" 4 "0 -1 0"
+"r5" 4 "0 -1 0"
+"q5" 4 "0 -1 0"
+"p5" 4 "0 -1 0"
+"o5" 4 "0 -1 0"
+"n5" 4 "0 -1 0"
+"m5" 4 "0 -1 0"
+"l5" 4 "0 -1 0"
+"t7" 4 "0 -1 0"
+"s7" 4 "0 -1 0"
+"r7" 4 "0 -1 0"
+"s8" 8 "0 -1 0"
+"p7" 4 "0 -1 0"
+"o7" 4 "0 -1 0"
+"n7" 4 "0 -1 0"
+"m7" 4 "0 -1 0"
+"l7" 4 "0 -1 0"
+"j7" 5 "0 -1 0"
+"i7" 5 "0 -1 0"
+"l8" 4 "0 -1 0"
+"n8" 4 "0 -1 0"
+"o8" 4 "0 -1 0"
+"p8" 4 "0 -1 0"
+"q8" 4 "0 -1 0"
+"r8" 4 "0 -1 0"
+"s12" 8 "0 -1 0"
+"t8" 4 "0 -1 0"
+"t9" 4 "0 -1 0"
+"s9" 4 "0 -1 0"
+"r9" 4 "0 -1 0"
+"q7" 8 "0 -1 0"
+"p9" 4 "0 -1 0"
+"o9" 4 "0 -1 0"
+"m9" 5 "0 -1 0"
+"n9" 5 "0 -1 0"
+"o10" 4 "0 -1 0"
+"p10" 4 "0 -1 0"
+"q10" 4 "0 -1 0"
+"r10" 4 "0 -1 0"
+"s14" 8 "0 -1 0"
+"t10" 4 "0 -1 0"
+"t11" 4 "0 -1 0"
+"s11" 4 "0 -1 0"
+"r11" 4 "0 -1 0"
+"q9" 8 "0 -1 0"
+"p11" 4 "0 -1 0"
+"o11" 4 "0 -1 0"
+"n10" 5 "0 -1 0"
+"n11" 5 "0 -1 0"
+"o12" 4 "0 -1 0"
+"p12" 4 "0 -1 0"
+"q12" 4 "0 -1 0"
+"r12" 4 "0 -1 0"
+"t12" 4 "0 -1 0"
+"t13" 4 "0 -1 0"
+"s13" 4 "0 -1 0"
+"r13" 4 "0 -1 0"
+"q11" 8 "0 -1 0"
+"p13" 4 "0 -1 0"
+"o13" 4 "0 -1 0"
+"l9" 5 "0 -1 0"
+"n12" 5 "0 -1 0"
+"o14" 4 "0 -1 0"
+"p14" 4 "0 -1 0"
+"q14" 4 "0 -1 0"
+"r14" 4 "0 -1 0"
+"f12" 5 "0 -1 0"
+"t14" 4 "0 -1 0"
+"t15" 4 "0 -1 0"
+"s15" 4 "0 -1 0"
+"r15" 4 "0 -1 0"
+"q15" 8 "0 -1 0"
+"p15" 4 "0 -1 0"
+"o15" 4 "0 -1 0"
+"n13" 5 "0 -1 0"
+"n16" 5 "0 -1 0"
+"o16" 4 "0 -1 0"
+"p16" 4 "0 -1 0"
+"q16" 4 "0 -1 0"
+"r16" 4 "0 -1 0"
+"q13" 8 "0 -1 0"
+"t16" 4 "0 -1 0"
+"t17" 4 "0 -1 0"
+"s17" 4 "0 -1 0"
+"r17" 4 "0 -1 0"
+"q17" 4 "0 -1 0"
+"p17" 4 "0 -1 0"
+"o17" 4 "0 -1 0"
+"n17" 4 "0 -1 0"
+"m17" 4 "0 -1 0"
+"l17" 4 "0 -1 0"
+"k17" 4 "0 -1 0"
+"j17" 4 "0 -1 0"
+"i17" 4 "0 -1 0"
+"h17" 4 "0 -1 0"
+"g17" 4 "0 -1 0"
+"g18" 4 "0 -1 0"
+"h18" 4 "0 -1 0"
+"i18" 4 "0 -1 0"
+"j18" 4 "0 -1 0"
+"k18" 4 "0 -1 0"
+"l18" 4 "0 -1 0"
+"m18" 4 "0 -1 0"
+"n18" 4 "0 -1 0"
+"o18" 4 "0 -1 0"
+"p18" 4 "0 -1 0"
+"q18" 4 "0 -1 0"
+"r18" 4 "0 -1 0"
+"s18" 4 "0 -1 0"
+"t18" 4 "0 -1 0"
+"t19" 4 "0 -1 0"
+"s19" 4 "0 -1 0"
+"r19" 4 "0 -1 0"
+"q19" 4 "0 -1 0"
+"p19" 4 "0 -1 0"
+"o19" 4 "0 -1 0"
+"n19" 4 "0 -1 0"
+"m19" 4 "0 -1 0"
+"l19" 4 "0 -1 0"
+"k19" 4 "0 -1 0"
+"j19" 4 "0 -1 0"
+"i19" 4 "0 -1 0"
+"h19" 4 "0 -1 0"
+"g19" 4 "0 -1 0"
+"g20" 4 "0 -1 0"
+"h20" 4 "0 -1 0"
+"i20" 4 "0 -1 0"
+"j20" 4 "0 -1 0"
+"k20" 4 "0 -1 0"
+"l20" 4 "0 -1 0"
+"m20" 4 "0 -1 0"
+"n20" 4 "0 -1 0"
+"o20" 4 "0 -1 0"
+"p20" 4 "0 -1 0"
+"q20" 4 "0 -1 0"
+"r20" 4 "0 -1 0"
+"s20" 4 "0 -1 0"
+"t20" 4 "0 -1 0"
+"d7" 4 "0 -1 0"
+"c7" 4 "0 -1 0"
+"b7" 4 "0 -1 0"
+"a9" 8 "0 -1 0"
+"a8" 4 "0 -1 0"
+"b8" 4 "0 -1 0"
+"a7" 8 "0 -1 0"
+"d8" 4 "0 -1 0"
+"d9" 4 "0 -1 0"
+"c9" 4 "0 -1 0"
+"b9" 4 "0 -1 0"
+"a13" 8 "0 -1 0"
+"a10" 4 "0 -1 0"
+"b10" 4 "0 -1 0"
+"a11" 8 "0 -1 0"
+"d10" 4 "0 -1 0"
+"d11" 4 "0 -1 0"
+"c11" 4 "0 -1 0"
+"b11" 4 "0 -1 0"
+"a15" 8 "0 -1 0"
+"a12" 4 "0 -1 0"
+"b12" 4 "0 -1 0"
+"c10" 8 "0 -1 0"
+"d12" 4 "0 -1 0"
+"d13" 4 "0 -1 0"
+"c13" 4 "0 -1 0"
+"b13" 4 "0 -1 0"
+"s16" 8 "0 -1 0"
+"a14" 4 "0 -1 0"
+"b14" 4 "0 -1 0"
+"c12" 8 "0 -1 0"
+"d14" 4 "0 -1 0"
+"e14" 4 "0 -1 0"
+"e15" 4 "0 -1 0"
+"d15" 4 "0 -1 0"
+"c15" 4 "0 -1 0"
+"b15" 4 "0 -1 0"
+"s10" 8 "0 -1 0"
+"a16" 4 "0 -1 0"
+"b16" 4 "0 -1 0"
+"c16" 8 "0 -1 0"
+"d16" 4 "0 -1 0"
+"e16" 4 "0 -1 0"
+"e17" 4 "0 -1 0"
+"d17" 4 "0 -1 0"
+"c17" 4 "0 -1 0"
+"b17" 4 "0 -1 0"
+"a17" 4 "0 -1 0"
+"a18" 4 "0 -1 0"
+"b18" 4 "0 -1 0"
+"c18" 4 "0 -1 0"
+"d18" 4 "0 -1 0"
+"e18" 4 "0 -1 0"
+"e19" 4 "0 -1 0"
+"d19" 4 "0 -1 0"
+"c19" 4 "0 -1 0"
+"b19" 4 "0 -1 0"
+"a19" 4 "0 -1 0"
+"a20" 4 "0 -1 0"
+"b20" 4 "0 -1 0"
+"c20" 4 "0 -1 0"
+"d20" 4 "0 -1 0"
+"e20" 4 "0 -1 0"
+"f11" 5 "0 -1 0"
+"c14" 8 "0 -1 0"
+"c8" 8 "0 -1 0"
+"f13" 5 "0 -1 0"
+"g15" 5 "0 -1 0"
+"g16" 5 "0 -1 0"
+"i16" 5 "0 -1 0"
+"j16" 5 "0 -1 0"
+"n15" 5 "0 -1 0"
+"n14" 5 "0 -1 0"
+"h7" 5 "0 -1 0"
--- /dev/null
+// bulldozer storage "level5" last updated 17-11-2015 21:42:14
+nextlevel = "level6"
+"a7" 4 "0 -1 0"
+"c18" 6 "0 -1 0"
+"a19" 4 "0 -1 0"
+"d17" 6 "0 -1 0"
+"c19" 4 "0 -1 0"
+"d19" 4 "0 -1 0"
+"e19" 4 "0 -1 0"
+"f19" 4 "0 -1 0"
+"g19" 4 "0 -1 0"
+"h19" 4 "0 -1 0"
+"i19" 4 "0 -1 0"
+"j19" 4 "0 -1 0"
+"k19" 4 "0 -1 0"
+"l19" 4 "0 -1 0"
+"m19" 4 "0 -1 0"
+"n19" 4 "0 -1 0"
+"o19" 4 "0 -1 0"
+"p19" 4 "0 -1 0"
+"q19" 4 "0 -1 0"
+"r19" 4 "0 -1 0"
+"q17" 6 "0 -1 0"
+"t19" 4 "0 -1 0"
+"e10" 4 "0 -1 0"
+"e18" 4 "0 -1 0"
+"p8" 4 "0 -1 0"
+"e17" 4 "0 -1 0"
+"e16" 4 "0 -1 0"
+"e8" 4 "0 -1 0"
+"e9" 4 "0 -1 0"
+"e15" 4 "0 -1 0"
+"e13" 4 "0 -1 0"
+"e12" 4 "0 -1 0"
+"e11" 4 "0 -1 0"
+"e7" 4 "0 -1 0"
+"d7" 4 "0 -1 0"
+"c7" 4 "0 -1 0"
+"b7" 4 "0 -1 0"
+"e14" 4 "0 -1 0"
+"f17" 4 "0 -1 0"
+"o7" 4 "0 -1 0"
+"f6" 4 "0 -1 0"
+"i6" 4 "0 -1 0"
+"g6" 4 "0 -1 0"
+"h6" 4 "0 -1 0"
+"k6" 4 "0 -1 0"
+"j6" 4 "0 -1 0"
+"l6" 4 "0 -1 0"
+"m6" 4 "0 -1 0"
+"p7" 4 "0 -1 0"
+"p9" 4 "0 -1 0"
+"p10" 4 "0 -1 0"
+"p11" 4 "0 -1 0"
+"p12" 4 "0 -1 0"
+"p13" 4 "0 -1 0"
+"p14" 4 "0 -1 0"
+"o15" 4 "0 -1 0"
+"p16" 4 "0 -1 0"
+"p17" 4 "0 -1 0"
+"p18" 4 "0 -1 0"
+"q7" 4 "0 -1 0"
+"r7" 4 "0 -1 0"
+"s7" 4 "0 -1 0"
+"t7" 4 "0 -1 0"
+"c13" 4 "0 -1 0"
+"b13" 4 "0 -1 0"
+"a13" 4 "0 -1 0"
+"a12" 4 "0 -1 0"
+"b12" 4 "0 -1 0"
+"c12" 4 "0 -1 0"
+"d12" 4 "0 -1 0"
+"d11" 4 "0 -1 0"
+"c11" 4 "0 -1 0"
+"b11" 4 "0 -1 0"
+"a11" 4 "0 -1 0"
+"a10" 4 "0 -1 0"
+"b10" 4 "0 -1 0"
+"c10" 4 "0 -1 0"
+"d10" 4 "0 -1 0"
+"d9" 4 "0 -1 0"
+"c9" 4 "0 -1 0"
+"b9" 4 "0 -1 0"
+"a9" 4 "0 -1 0"
+"a8" 4 "0 -1 0"
+"b8" 4 "0 -1 0"
+"c8" 4 "0 -1 0"
+"d8" 4 "0 -1 0"
+"d13" 4 "0 -1 0"
+"d14" 4 "0 -1 0"
+"c14" 4 "0 -1 0"
+"b14" 4 "0 -1 0"
+"a14" 4 "0 -1 0"
+"a15" 4 "0 -1 0"
+"b15" 4 "0 -1 0"
+"c15" 4 "0 -1 0"
+"d15" 4 "0 -1 0"
+"d16" 4 "0 -1 0"
+"c16" 4 "0 -1 0"
+"b16" 4 "0 -1 0"
+"a16" 4 "0 -1 0"
+"a17" 4 "0 -1 0"
+"b17" 4 "0 -1 0"
+"c17" 4 "0 -1 0"
+"a1" 6 "0 -1 0"
+"d18" 4 "0 -1 0"
+"b2" 6 "0 -1 0"
+"b18" 4 "0 -1 0"
+"a18" 4 "0 -1 0"
+"f20" 4 "0 -1 0"
+"e20" 4 "0 -1 0"
+"d20" 4 "0 -1 0"
+"c20" 4 "0 -1 0"
+"b20" 4 "0 -1 0"
+"g20" 4 "0 -1 0"
+"h20" 4 "0 -1 0"
+"i20" 4 "0 -1 0"
+"j20" 4 "0 -1 0"
+"k20" 4 "0 -1 0"
+"l20" 4 "0 -1 0"
+"m20" 4 "0 -1 0"
+"n20" 4 "0 -1 0"
+"o20" 4 "0 -1 0"
+"p20" 4 "0 -1 0"
+"q20" 4 "0 -1 0"
+"r20" 4 "0 -1 0"
+"s20" 4 "0 -1 0"
+"r18" 6 "0 -1 0"
+"s13" 4 "0 -1 0"
+"r13" 4 "0 -1 0"
+"q13" 4 "0 -1 0"
+"q12" 4 "0 -1 0"
+"r12" 4 "0 -1 0"
+"s12" 4 "0 -1 0"
+"t12" 4 "0 -1 0"
+"t11" 4 "0 -1 0"
+"s11" 4 "0 -1 0"
+"r11" 4 "0 -1 0"
+"q11" 4 "0 -1 0"
+"q10" 4 "0 -1 0"
+"r10" 4 "0 -1 0"
+"s10" 4 "0 -1 0"
+"t10" 4 "0 -1 0"
+"t9" 4 "0 -1 0"
+"s9" 4 "0 -1 0"
+"r9" 4 "0 -1 0"
+"q9" 4 "0 -1 0"
+"q8" 4 "0 -1 0"
+"r8" 4 "0 -1 0"
+"s8" 4 "0 -1 0"
+"t8" 4 "0 -1 0"
+"t13" 4 "0 -1 0"
+"t14" 4 "0 -1 0"
+"s14" 4 "0 -1 0"
+"r14" 4 "0 -1 0"
+"q14" 4 "0 -1 0"
+"q15" 4 "0 -1 0"
+"r15" 4 "0 -1 0"
+"s15" 4 "0 -1 0"
+"t15" 4 "0 -1 0"
+"t16" 4 "0 -1 0"
+"s16" 4 "0 -1 0"
+"r16" 4 "0 -1 0"
+"q16" 4 "0 -1 0"
+"g15" 1 "0 -1 0"
+"r17" 4 "0 -1 0"
+"s17" 4 "0 -1 0"
+"t17" 4 "0 -1 0"
+"t18" 4 "0 -1 0"
+"s18" 4 "0 -1 0"
+"m13" 2 "0 -1 0"
+"q18" 4 "0 -1 0"
+"g3" 4 "0 -1 0"
+"f3" 4 "0 -1 0"
+"e3" 4 "0 -1 0"
+"d3" 4 "0 -1 0"
+"t1" 6 "0 -1 0"
+"b3" 4 "0 -1 0"
+"a3" 4 "0 -1 0"
+"a2" 4 "0 -1 0"
+"d4" 6 "0 -1 0"
+"c2" 4 "0 -1 0"
+"d2" 4 "0 -1 0"
+"e2" 4 "0 -1 0"
+"f2" 4 "0 -1 0"
+"g2" 4 "0 -1 0"
+"h2" 4 "0 -1 0"
+"i2" 4 "0 -1 0"
+"j2" 4 "0 -1 0"
+"k2" 4 "0 -1 0"
+"l2" 4 "0 -1 0"
+"m2" 4 "0 -1 0"
+"n2" 4 "0 -1 0"
+"o2" 4 "0 -1 0"
+"p2" 4 "0 -1 0"
+"q2" 4 "0 -1 0"
+"r2" 4 "0 -1 0"
+"q4" 6 "0 -1 0"
+"t2" 4 "0 -1 0"
+"r3" 6 "0 -1 0"
+"s1" 4 "0 -1 0"
+"r1" 4 "0 -1 0"
+"q1" 4 "0 -1 0"
+"p1" 4 "0 -1 0"
+"o1" 4 "0 -1 0"
+"n1" 4 "0 -1 0"
+"m1" 4 "0 -1 0"
+"l1" 4 "0 -1 0"
+"k1" 4 "0 -1 0"
+"j1" 4 "0 -1 0"
+"i1" 4 "0 -1 0"
+"h1" 4 "0 -1 0"
+"g1" 4 "0 -1 0"
+"f1" 4 "0 -1 0"
+"e1" 4 "0 -1 0"
+"d1" 4 "0 -1 0"
+"c1" 4 "0 -1 0"
+"b1" 4 "0 -1 0"
+"c3" 6 "0 -1 0"
+"t3" 4 "0 -1 0"
+"s3" 4 "0 -1 0"
+"t20" 6 "0 -1 0"
+"q3" 4 "0 -1 0"
+"p3" 4 "0 -1 0"
+"o3" 4 "0 -1 0"
+"n3" 4 "0 -1 0"
+"m3" 4 "0 -1 0"
+"l3" 4 "0 -1 0"
+"k3" 4 "0 -1 0"
+"j3" 4 "0 -1 0"
+"i3" 4 "0 -1 0"
+"h3" 4 "0 -1 0"
+"h4" 4 "0 -1 0"
+"g4" 4 "0 -1 0"
+"f4" 4 "0 -1 0"
+"e4" 4 "0 -1 0"
+"s2" 6 "0 -1 0"
+"c4" 4 "0 -1 0"
+"b4" 4 "0 -1 0"
+"a4" 4 "0 -1 0"
+"a5" 4 "0 -1 0"
+"b5" 4 "0 -1 0"
+"c5" 4 "0 -1 0"
+"d5" 4 "0 -1 0"
+"e5" 4 "0 -1 0"
+"f5" 4 "0 -1 0"
+"g5" 4 "0 -1 0"
+"h5" 4 "0 -1 0"
+"i5" 4 "0 -1 0"
+"j5" 4 "0 -1 0"
+"k5" 4 "0 -1 0"
+"l5" 4 "0 -1 0"
+"m5" 4 "0 -1 0"
+"n5" 4 "0 -1 0"
+"o5" 4 "0 -1 0"
+"p5" 4 "0 -1 0"
+"q5" 4 "0 -1 0"
+"r5" 4 "0 -1 0"
+"s5" 4 "0 -1 0"
+"t5" 4 "0 -1 0"
+"t4" 4 "0 -1 0"
+"s4" 4 "0 -1 0"
+"r4" 4 "0 -1 0"
+"s19" 6 "0 -1 0"
+"p4" 4 "0 -1 0"
+"o4" 4 "0 -1 0"
+"n4" 4 "0 -1 0"
+"m4" 4 "0 -1 0"
+"l4" 4 "0 -1 0"
+"k4" 4 "0 -1 0"
+"j4" 4 "0 -1 0"
+"i4" 4 "0 -1 0"
+"t6" 4 "0 -1 0"
+"s6" 4 "0 -1 0"
+"r6" 4 "0 -1 0"
+"q6" 4 "0 -1 0"
+"p6" 4 "0 -1 0"
+"o6" 4 "0 -1 0"
+"n6" 4 "0 -1 0"
+"n7" 4 "0 -1 0"
+"l7" 4 "0 -1 0"
+"j7" 4 "0 -1 0"
+"h7" 4 "0 -1 0"
+"f7" 4 "0 -1 0"
+"g7" 4 "0 -1 0"
+"i7" 4 "0 -1 0"
+"k7" 4 "0 -1 0"
+"e6" 4 "0 -1 0"
+"d6" 4 "0 -1 0"
+"c6" 4 "0 -1 0"
+"b6" 4 "0 -1 0"
+"a6" 4 "0 -1 0"
+"p15" 4 "0 -1 0"
+"m7" 4 "0 -1 0"
+"f16" 5 "0 -1 0"
+"f13" 5 "0 -1 0"
+"f15" 5 "0 -1 0"
+"f14" 5 "0 -1 0"
+"f12" 5 "0 -1 0"
+"g12" 5 "0 -1 0"
+"h12" 5 "0 -1 0"
+"h11" 5 "0 -1 0"
+"g9" 5 "0 -1 0"
+"g8" 5 "0 -1 0"
+"g11" 5 "0 -1 0"
+"g10" 5 "0 -1 0"
+"h8" 5 "0 -1 0"
+"i8" 5 "0 -1 0"
+"j8" 5 "0 -1 0"
+"k8" 5 "0 -1 0"
+"k9" 5 "0 -1 0"
+"k10" 5 "0 -1 0"
+"l9" 5 "0 -1 0"
+"m9" 5 "0 -1 0"
+"n9" 5 "0 -1 0"
+"n10" 5 "0 -1 0"
+"n11" 5 "0 -1 0"
+"n12" 5 "0 -1 0"
+"n13" 5 "0 -1 0"
+"n14" 5 "0 -1 0"
+"m14" 5 "0 -1 0"
+"l14" 5 "0 -1 0"
+"j17" 4 "0 -1 0"
+"j18" 4 "0 -1 0"
+"i18" 4 "0 -1 0"
+"h18" 4 "0 -1 0"
+"g18" 4 "0 -1 0"
+"f18" 4 "0 -1 0"
+"l13" 5 "0 -1 0"
+"l12" 5 "0 -1 0"
+"k12" 5 "0 -1 0"
+"j12" 5 "0 -1 0"
+"j13" 5 "0 -1 0"
+"j15" 5 "0 -1 0"
+"j14" 5 "0 -1 0"
+"j16" 5 "0 -1 0"
+"i16" 5 "0 -1 0"
+"h16" 5 "0 -1 0"
+"g16" 5 "0 -1 0"
+"f10" 4 "0 -1 0"
+"f9" 4 "0 -1 0"
+"f8" 4 "0 -1 0"
+"f11" 4 "0 -1 0"
+"o9" 4 "0 -1 0"
+"o8" 4 "0 -1 0"
+"m8" 4 "0 -1 0"
+"l8" 4 "0 -1 0"
+"n8" 4 "0 -1 0"
+"m15" 4 "0 -1 0"
+"l15" 4 "0 -1 0"
+"k15" 4 "0 -1 0"
+"o10" 4 "0 -1 0"
+"k14" 4 "0 -1 0"
+"k13" 4 "0 -1 0"
+"k16" 4 "0 -1 0"
+"o11" 4 "0 -1 0"
+"o12" 4 "0 -1 0"
+"o13" 4 "0 -1 0"
+"o14" 4 "0 -1 0"
+"l16" 4 "0 -1 0"
+"o16" 4 "0 -1 0"
+"o17" 4 "0 -1 0"
+"n17" 4 "0 -1 0"
+"m17" 4 "0 -1 0"
+"l17" 4 "0 -1 0"
+"k17" 4 "0 -1 0"
+"m16" 4 "0 -1 0"
+"n16" 4 "0 -1 0"
+"k18" 4 "0 -1 0"
+"l18" 4 "0 -1 0"
+"m18" 4 "0 -1 0"
+"n18" 4 "0 -1 0"
+"o18" 4 "0 -1 0"
+"n15" 4 "0 -1 0"
+"a20" 6 "0 -1 0"
+"b19" 6 "0 -1 0"
+"m12" 2 "0 -1 0"
+"m11" 2 "0 -1 0"
+"i14" 3 "0 -1 0"
+"h14" 3 "0 -1 0"
+"h13" 3 "0 -1 0"
+"i17" 4 "0 -1 0"
+"h17" 4 "0 -1 0"
+"g17" 4 "0 -1 0"
--- /dev/null
+// bulldozer storage "level4" last updated 16-11-2015 04:16:07
+nextlevel = "level1"
+"e15" 3 "0 0 0"
+"f14" 3 "0 0 0"
+"g13" 3 "0 0 0"
+"k13" 3 "0 0 0"
+"b14" 4 "0 0 0"
+"a14" 4 "0 0 0"
+"a13" 4 "0 0 0"
+"b13" 4 "0 0 0"
+"i13" 3 "0 0 0"
+"m13" 3 "0 0 0"
+"n14" 3 "0 0 0"
+"o15" 3 "0 0 0"
+"h17" 2 "0 0 0"
+"l17" 2 "0 0 0"
+"c12" 2 "0 0 0"
+"c13" 2 "0 0 0"
+"c14" 2 "0 0 0"
+"r14" 2 "0 0 0"
+"r13" 2 "0 0 0"
+"r12" 2 "0 0 0"
+"j15" 1 "0 -1 0"
+"s13" 4 "0 0 0"
+"t13" 4 "0 0 0"
+"t12" 4 "0 0 0"
+"s12" 4 "0 0 0"
+"b12" 4 "0 0 0"
+"a12" 4 "0 0 0"
+"a11" 4 "0 0 0"
+"b11" 4 "0 0 0"
+"c11" 4 "0 0 0"
+"d11" 4 "0 0 0"
+"e11" 4 "0 0 0"
+"f11" 4 "0 0 0"
+"g11" 4 "0 0 0"
+"h11" 4 "0 0 0"
+"i11" 4 "0 0 0"
+"j11" 4 "0 0 0"
+"k11" 4 "0 0 0"
+"l11" 4 "0 0 0"
+"m11" 4 "0 0 0"
+"n11" 4 "0 0 0"
+"o11" 4 "0 0 0"
+"p11" 4 "0 0 0"
+"q11" 4 "0 0 0"
+"r11" 4 "0 0 0"
+"s11" 4 "0 0 0"
+"t11" 4 "0 0 0"
+"t6" 6 "0 0 0"
+"s10" 4 "0 0 0"
+"r10" 4 "0 0 0"
+"q10" 4 "0 0 0"
+"b10" 6 "0 0 0"
+"o10" 4 "0 0 0"
+"c10" 6 "0 0 0"
+"d10" 6 "0 0 0"
+"e6" 4 "0 0 0"
+"b9" 6 "0 0 0"
+"b8" 6 "0 0 0"
+"c7" 4 "0 0 0"
+"b7" 6 "0 0 0"
+"b6" 6 "0 0 0"
+"c6" 6 "0 0 0"
+"d6" 6 "0 0 0"
+"f10" 6 "0 0 0"
+"g10" 6 "0 0 0"
+"h10" 6 "0 0 0"
+"a10" 4 "0 0 0"
+"a9" 4 "0 0 0"
+"h9" 4 "0 0 0"
+"c9" 4 "0 0 0"
+"d9" 4 "0 0 0"
+"h8" 4 "0 0 0"
+"h7" 4 "0 0 0"
+"i10" 6 "0 0 0"
+"i9" 6 "0 0 0"
+"j7" 4 "0 0 0"
+"j6" 4 "0 0 0"
+"j10" 4 "0 0 0"
+"i8" 6 "0 0 0"
+"m9" 4 "0 0 0"
+"i7" 6 "0 0 0"
+"o9" 4 "0 0 0"
+"i6" 6 "0 0 0"
+"q9" 4 "0 0 0"
+"r9" 4 "0 0 0"
+"s9" 4 "0 0 0"
+"h6" 6 "0 0 0"
+"g6" 6 "0 0 0"
+"s8" 4 "0 0 0"
+"r8" 4 "0 0 0"
+"q8" 4 "0 0 0"
+"f6" 6 "0 0 0"
+"o8" 4 "0 0 0"
+"f7" 6 "0 0 0"
+"m8" 4 "0 0 0"
+"f8" 6 "0 0 0"
+"f9" 6 "0 0 0"
+"k10" 6 "0 0 0"
+"e10" 4 "0 0 0"
+"d7" 4 "0 0 0"
+"e9" 4 "0 0 0"
+"e8" 4 "0 0 0"
+"e7" 4 "0 0 0"
+"l10" 6 "0 0 0"
+"c8" 4 "0 0 0"
+"m10" 6 "0 0 0"
+"a8" 4 "0 0 0"
+"a7" 4 "0 0 0"
+"g7" 4 "0 0 0"
+"g8" 4 "0 0 0"
+"g9" 4 "0 0 0"
+"n10" 6 "0 0 0"
+"n9" 6 "0 0 0"
+"n8" 6 "0 0 0"
+"d8" 4 "0 0 0"
+"n7" 6 "0 0 0"
+"n6" 6 "0 0 0"
+"m6" 6 "0 0 0"
+"l6" 6 "0 0 0"
+"m7" 4 "0 0 0"
+"k6" 6 "0 0 0"
+"o7" 4 "0 0 0"
+"k7" 6 "0 0 0"
+"q7" 4 "0 0 0"
+"r7" 4 "0 0 0"
+"s7" 4 "0 0 0"
+"k8" 6 "0 0 0"
+"k9" 6 "0 0 0"
+"s6" 4 "0 0 0"
+"p9" 6 "0 0 0"
+"p8" 6 "0 0 0"
+"p7" 6 "0 0 0"
+"o6" 4 "0 0 0"
+"p6" 6 "0 0 0"
+"q6" 6 "0 0 0"
+"r6" 6 "0 0 0"
+"p10" 6 "0 0 0"
+"j9" 4 "0 0 0"
+"j8" 4 "0 0 0"
+"t10" 6 "0 0 0"
+"t9" 6 "0 0 0"
+"t8" 6 "0 0 0"
+"l7" 4 "0 0 0"
+"l8" 4 "0 0 0"
+"l9" 4 "0 0 0"
+"t7" 4 "0 0 0"
+"a6" 4 "0 0 0"
+"a5" 4 "0 0 0"
+"b5" 4 "0 0 0"
+"c5" 4 "0 0 0"
+"d5" 4 "0 0 0"
+"e5" 4 "0 0 0"
+"f5" 4 "0 0 0"
+"g5" 4 "0 0 0"
+"h5" 4 "0 0 0"
+"i5" 4 "0 0 0"
+"j5" 4 "0 0 0"
+"k5" 4 "0 0 0"
+"l5" 4 "0 0 0"
+"m5" 4 "0 0 0"
+"n5" 4 "0 0 0"
+"o5" 4 "0 0 0"
+"p5" 4 "0 0 0"
+"q5" 4 "0 0 0"
+"r5" 4 "0 0 0"
+"s5" 4 "0 0 0"
+"t5" 4 "0 0 0"
+"t4" 4 "0 0 0"
+"s4" 4 "0 0 0"
+"r4" 4 "0 0 0"
+"q4" 4 "0 0 0"
+"p4" 4 "0 0 0"
+"o4" 4 "0 0 0"
+"n4" 4 "0 0 0"
+"m4" 4 "0 0 0"
+"l4" 4 "0 0 0"
+"k4" 4 "0 0 0"
+"j4" 4 "0 0 0"
+"i4" 4 "0 0 0"
+"h4" 4 "0 0 0"
+"g4" 4 "0 0 0"
+"f4" 4 "0 0 0"
+"e4" 4 "0 0 0"
+"d4" 4 "0 0 0"
+"c4" 4 "0 0 0"
+"b4" 4 "0 0 0"
+"a4" 4 "0 0 0"
+"a3" 4 "0 0 0"
+"b3" 4 "0 0 0"
+"c3" 4 "0 0 0"
+"d3" 4 "0 0 0"
+"e3" 4 "0 0 0"
+"f3" 4 "0 0 0"
+"g3" 4 "0 0 0"
+"h3" 4 "0 0 0"
+"i3" 4 "0 0 0"
+"j3" 4 "0 0 0"
+"k3" 4 "0 0 0"
+"l3" 4 "0 0 0"
+"m3" 4 "0 0 0"
+"n3" 4 "0 0 0"
+"o3" 4 "0 0 0"
+"p3" 4 "0 0 0"
+"q3" 4 "0 0 0"
+"r3" 4 "0 0 0"
+"s3" 4 "0 0 0"
+"t3" 4 "0 0 0"
+"t2" 4 "0 0 0"
+"s2" 4 "0 0 0"
+"r2" 4 "0 0 0"
+"q2" 4 "0 0 0"
+"p2" 4 "0 0 0"
+"o2" 4 "0 0 0"
+"n2" 4 "0 0 0"
+"m2" 4 "0 0 0"
+"l2" 4 "0 0 0"
+"k2" 4 "0 0 0"
+"j2" 4 "0 0 0"
+"i2" 4 "0 0 0"
+"h2" 4 "0 0 0"
+"g2" 4 "0 0 0"
+"f2" 4 "0 0 0"
+"e2" 4 "0 0 0"
+"d2" 4 "0 0 0"
+"c2" 4 "0 0 0"
+"b2" 4 "0 0 0"
+"a2" 4 "0 0 0"
+"a1" 4 "0 0 0"
+"b1" 4 "0 0 0"
+"c1" 4 "0 0 0"
+"d1" 4 "0 0 0"
+"e1" 4 "0 0 0"
+"f1" 4 "0 0 0"
+"g1" 4 "0 0 0"
+"h1" 4 "0 0 0"
+"i1" 4 "0 0 0"
+"j1" 4 "0 0 0"
+"k1" 4 "0 0 0"
+"l1" 4 "0 0 0"
+"m1" 4 "0 0 0"
+"n1" 4 "0 0 0"
+"o1" 4 "0 0 0"
+"p1" 4 "0 0 0"
+"q1" 4 "0 0 0"
+"r1" 4 "0 0 0"
+"s1" 4 "0 0 0"
+"t1" 4 "0 0 0"
+"t14" 4 "0 0 0"
+"s14" 4 "0 0 0"
+"b15" 4 "0 0 0"
+"a15" 4 "0 0 0"
+"a16" 4 "0 0 0"
+"b16" 4 "0 0 0"
+"s16" 4 "0 0 0"
+"t16" 4 "0 0 0"
+"t15" 4 "0 0 0"
+"s15" 4 "0 0 0"
+"t17" 4 "0 0 0"
+"s17" 4 "0 0 0"
+"b17" 4 "0 0 0"
+"a17" 4 "0 0 0"
+"a18" 4 "0 0 0"
+"b18" 4 "0 0 0"
+"s18" 4 "0 0 0"
+"t18" 4 "0 0 0"
+"t19" 4 "0 0 0"
+"s19" 4 "0 0 0"
+"r19" 4 "0 0 0"
+"q19" 4 "0 0 0"
+"p19" 4 "0 0 0"
+"o19" 4 "0 0 0"
+"n19" 4 "0 0 0"
+"m19" 4 "0 0 0"
+"l19" 4 "0 0 0"
+"k19" 4 "0 0 0"
+"j19" 4 "0 0 0"
+"i19" 4 "0 0 0"
+"h19" 4 "0 0 0"
+"g19" 4 "0 0 0"
+"f19" 4 "0 0 0"
+"e19" 4 "0 0 0"
+"d19" 4 "0 0 0"
+"c19" 4 "0 0 0"
+"b19" 4 "0 0 0"
+"a19" 4 "0 0 0"
+"a20" 4 "0 0 0"
+"b20" 4 "0 0 0"
+"c20" 4 "0 0 0"
+"d20" 4 "0 0 0"
+"e20" 4 "0 0 0"
+"f20" 4 "0 0 0"
+"g20" 4 "0 0 0"
+"h20" 4 "0 0 0"
+"i20" 4 "0 0 0"
+"j20" 4 "0 0 0"
+"k20" 4 "0 0 0"
+"l20" 4 "0 0 0"
+"m20" 4 "0 0 0"
+"n20" 4 "0 0 0"
+"o20" 4 "0 0 0"
+"p20" 4 "0 0 0"
+"q20" 4 "0 0 0"
+"r20" 4 "0 0 0"
+"s20" 4 "0 0 0"
+"t20" 4 "0 0 0"
return ret;
}
+entity announcer_countdown;
+
void Announcer_Countdown()
{
SELFPARAM();
- float starttime = getstatf(STAT_GAMESTARTTIME);
- float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
+ float starttime = STAT(GAMESTARTTIME);
+ float roundstarttime = STAT(ROUNDSTARTTIME);
if(roundstarttime == -1)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
remove(this);
+ announcer_countdown = NULL;
return;
}
if(roundstarttime >= starttime)
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
remove(this);
+ announcer_countdown = NULL;
return;
}
else // countdown is still going
float previous_game_starttime;
void Announcer_Gamestart()
{
- float startTime = getstatf(STAT_GAMESTARTTIME);
- float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
+ float startTime = STAT(GAMESTARTTIME);
+ float roundstarttime = STAT(ROUNDSTARTTIME);
if(roundstarttime > startTime)
startTime = roundstarttime;
{
if(time < startTime)
{
- static entity announcer_countdown;
if (!announcer_countdown)
{
announcer_countdown = new(announcer_countdown);
// Plays the 1 minute or 5 minutes (of maptime) remaining sound, if client wants it
void Announcer_Time()
{
- float timelimit = getstatf(STAT_TIMELIMIT);
- float timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time);
+ float timelimit = STAT(TIMELIMIT);
+ float timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
float warmup_timeleft = 0;
if(warmup_stage)
if(autocvar_g_warmup_limit > 0)
- warmup_timeleft = max(0, autocvar_g_warmup_limit + getstatf(STAT_GAMESTARTTIME) - time);
+ warmup_timeleft = max(0, autocvar_g_warmup_limit + STAT(GAMESTARTTIME) - time);
// 5 minute check
if(autocvar_cl_announcer_maptime >= 2)
case "quickmenu":
{
+ if (argv(2) == "help")
+ {
+ LOG_INFO(" quickmenu [[default | file | \"\"] submenu]\n");
+ LOG_INFO("Called without options (or with \"\") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.\n");
+ LOG_INFO("A submenu name can be given to open the quickmenu directly in a submenu; it requires to specify 'default', 'file' or '\"\"' option.\n");
+ return;
+ }
if (QuickMenu_IsOpened())
QuickMenu_Close();
else
LOG_INFO(" 'configname' is the name to save to for \"save\" action,\n");
LOG_INFO(" 'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
LOG_INFO(" and 'layout' is how to organize the scoreboard columns for the set action.\n");
- LOG_INFO(" quickmenu [[default | file | \"\"] submenu]\n");
- LOG_INFO(" Called without options (or with " ") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.\n");
- LOG_INFO(" Submenu option allows to open quickmenu directly in a submenu, it requires to specify 'default', 'file' or '\"\"' option.\n");
- LOG_INFO(" Full list of commands here: \"configure, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
+ LOG_INFO(" Full list of commands here: \"configure, quickmenu, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
return;
}
}
// only if this failed, find it out on our own
entity e = spawn();
+ precache_model(autocvar__cl_playermodel);
_setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
forceplayermodels_modelisgoodmodel = fexists(e.model);
forceplayermodels_model = e.model;
}
void CSQCPlayer_AnimDecide_PostUpdate(bool isnew)
{SELFPARAM();
- self.csqcmodel_isdead = !!(self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
+ self.csqcmodel_isdead = boolean(self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
}
int CSQCPlayer_FallbackFrame(int f)
{SELFPARAM();
self.teleport_time = 0;
}
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(this);
int s = W_GetGunAlignment(world);
case NUM_TEAM_2: tex = "particles/hook_blue"; rgb = '0.3 0.3 1'; break;
case NUM_TEAM_3: tex = "particles/hook_yellow"; rgb = '1 1 0.3'; break;
case NUM_TEAM_4: tex = "particles/hook_pink"; rgb = '1 0.3 1'; break;
- default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum); break;
+ default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum - 1); break;
}
break;
case NET_ENT_CLIENT_ARC_BEAM: // todo
self.HookSilent = (sf & 0x80);
self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
if(sf & 1)
{
self.velocity_z = ReadCoord();
}
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
if(bIsNew || !self.teleport_time)
{
#include "scoreboard.qh"
#include "teamradar.qh"
#include "t_items.qh"
-#include "../common/buffs/all.qh"
#include "../common/deathtypes/all.qh"
#include "../common/items/all.qc"
#include "../common/mapinfo.qh"
#include "../common/mutators/mutator/waypoints/all.qh"
-#include "../common/nades/all.qh"
#include "../common/stats.qh"
#include "../lib/csqcmodel/cl_player.qh"
// TODO: remove
REGISTRY(hud_panels, BITS(6))
#define hud_panels_from(i) _hud_panels_from(i, NULL)
-REGISTER_REGISTRY(Registerhud_panels)
+REGISTER_REGISTRY(hud_panels)
#define REGISTER_HUD_PANEL(id, draw_func, name, configflags, showflags) \
void draw_func(); \
- REGISTER(Registerhud_panels, HUD_PANEL, hud_panels, id, m_id, new(hud_panel)) { \
+ REGISTER(hud_panels, HUD_PANEL, id, m_id, new(hud_panel)) { \
make_pure(this); \
this.panel_id = this.m_id; \
this.panel_draw = draw_func; \
float stringwidth_colors(string s, vector theSize);
float stringwidth_nocolors(string s, vector theSize);
-float GetPlayerColorForce(int i);
-int GetPlayerColor(int i);
-string GetPlayerName(int i);
void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag);
.int panel_showflags;
#include "hud.qh"
#define HUD_Write(s) fputs(fh, s)
-// q: quoted, n: not quoted
-#define HUD_Write_Cvar_n(cvar) HUD_Write(strcat("seta ", cvar, " ", cvar_string(cvar), "\n"))
-#define HUD_Write_Cvar_q(cvar) HUD_Write(strcat("seta ", cvar, " \"", cvar_string(cvar), "\"\n"))
-#define HUD_Write_PanelCvar_n(cvar_suf) HUD_Write_Cvar_n(strcat("hud_panel_", panel.panel_name, cvar_suf))
-#define HUD_Write_PanelCvar_q(cvar_suf) HUD_Write_Cvar_q(strcat("hud_panel_", panel.panel_name, cvar_suf))
+#define HUD_Write_Cvar(cvar) HUD_Write(strcat("seta ", cvar, " \"", cvar_string(cvar), "\"\n"))
+#define HUD_Write_PanelCvar(cvar_suf) HUD_Write_Cvar(strcat("hud_panel_", panel.panel_name, cvar_suf))
// Save the config
void HUD_Panel_ExportCfg(string cfgname)
{
fh = fopen(filename, FILE_WRITE);
if(fh >= 0)
{
- HUD_Write_Cvar_q("hud_skin");
- HUD_Write_Cvar_q("hud_panel_bg");
- HUD_Write_Cvar_q("hud_panel_bg_color");
- HUD_Write_Cvar_q("hud_panel_bg_color_team");
- HUD_Write_Cvar_q("hud_panel_bg_alpha");
- HUD_Write_Cvar_q("hud_panel_bg_border");
- HUD_Write_Cvar_q("hud_panel_bg_padding");
- HUD_Write_Cvar_q("hud_panel_fg_alpha");
+ HUD_Write_Cvar("hud_skin");
+ HUD_Write_Cvar("hud_panel_bg");
+ HUD_Write_Cvar("hud_panel_bg_color");
+ HUD_Write_Cvar("hud_panel_bg_color_team");
+ HUD_Write_Cvar("hud_panel_bg_alpha");
+ HUD_Write_Cvar("hud_panel_bg_border");
+ HUD_Write_Cvar("hud_panel_bg_padding");
+ HUD_Write_Cvar("hud_panel_fg_alpha");
HUD_Write("\n");
- HUD_Write_Cvar_q("hud_dock");
- HUD_Write_Cvar_q("hud_dock_color");
- HUD_Write_Cvar_q("hud_dock_color_team");
- HUD_Write_Cvar_q("hud_dock_alpha");
+ HUD_Write_Cvar("hud_dock");
+ HUD_Write_Cvar("hud_dock_color");
+ HUD_Write_Cvar("hud_dock_color_team");
+ HUD_Write_Cvar("hud_dock_alpha");
HUD_Write("\n");
- HUD_Write_Cvar_q("hud_progressbar_alpha");
- HUD_Write_Cvar_q("hud_progressbar_strength_color");
- HUD_Write_Cvar_q("hud_progressbar_shield_color");
- HUD_Write_Cvar_q("hud_progressbar_health_color");
- HUD_Write_Cvar_q("hud_progressbar_armor_color");
- HUD_Write_Cvar_q("hud_progressbar_fuel_color");
- HUD_Write_Cvar_q("hud_progressbar_nexball_color");
- HUD_Write_Cvar_q("hud_progressbar_speed_color");
- HUD_Write_Cvar_q("hud_progressbar_acceleration_color");
- HUD_Write_Cvar_q("hud_progressbar_acceleration_neg_color");
+ HUD_Write_Cvar("hud_progressbar_alpha");
+ HUD_Write_Cvar("hud_progressbar_strength_color");
+ HUD_Write_Cvar("hud_progressbar_superweapons_color");
+ HUD_Write_Cvar("hud_progressbar_shield_color");
+ HUD_Write_Cvar("hud_progressbar_health_color");
+ HUD_Write_Cvar("hud_progressbar_armor_color");
+ HUD_Write_Cvar("hud_progressbar_fuel_color");
+ HUD_Write_Cvar("hud_progressbar_nexball_color");
+ HUD_Write_Cvar("hud_progressbar_speed_color");
+ HUD_Write_Cvar("hud_progressbar_acceleration_color");
+ HUD_Write_Cvar("hud_progressbar_acceleration_neg_color");
+ HUD_Write_Cvar("hud_progressbar_vehicles_ammo1_color");
+ HUD_Write_Cvar("hud_progressbar_vehicles_ammo2_color");
HUD_Write("\n");
- HUD_Write_Cvar_q("_hud_panelorder");
+ HUD_Write_Cvar("_hud_panelorder");
HUD_Write("\n");
- HUD_Write_Cvar_q("hud_configure_grid");
- HUD_Write_Cvar_q("hud_configure_grid_xsize");
- HUD_Write_Cvar_q("hud_configure_grid_ysize");
+ HUD_Write_Cvar("hud_configure_grid");
+ HUD_Write_Cvar("hud_configure_grid_xsize");
+ HUD_Write_Cvar("hud_configure_grid_ysize");
HUD_Write("\n");
// common cvars for all panels
{
panel = hud_panels_from(i);
- HUD_Write_PanelCvar_n("");
- HUD_Write_PanelCvar_q("_pos");
- HUD_Write_PanelCvar_q("_size");
- HUD_Write_PanelCvar_q("_bg");
- HUD_Write_PanelCvar_q("_bg_color");
- HUD_Write_PanelCvar_q("_bg_color_team");
- HUD_Write_PanelCvar_q("_bg_alpha");
- HUD_Write_PanelCvar_q("_bg_border");
- HUD_Write_PanelCvar_q("_bg_padding");
+ HUD_Write_PanelCvar("");
+ HUD_Write_PanelCvar("_pos");
+ HUD_Write_PanelCvar("_size");
+ HUD_Write_PanelCvar("_bg");
+ HUD_Write_PanelCvar("_bg_color");
+ HUD_Write_PanelCvar("_bg_color_team");
+ HUD_Write_PanelCvar("_bg_alpha");
+ HUD_Write_PanelCvar("_bg_border");
+ HUD_Write_PanelCvar("_bg_padding");
switch(panel) {
case HUD_PANEL_WEAPONS:
- HUD_Write_PanelCvar_q("_accuracy");
- HUD_Write_PanelCvar_q("_label");
- HUD_Write_PanelCvar_q("_label_scale");
- HUD_Write_PanelCvar_q("_complainbubble");
- HUD_Write_PanelCvar_q("_complainbubble_padding");
- HUD_Write_PanelCvar_q("_complainbubble_time");
- HUD_Write_PanelCvar_q("_complainbubble_fadetime");
- HUD_Write_PanelCvar_q("_complainbubble_color_outofammo");
- HUD_Write_PanelCvar_q("_complainbubble_color_donthave");
- HUD_Write_PanelCvar_q("_complainbubble_color_unavailable");
- HUD_Write_PanelCvar_q("_ammo");
- HUD_Write_PanelCvar_q("_ammo_color");
- HUD_Write_PanelCvar_q("_ammo_alpha");
- HUD_Write_PanelCvar_q("_aspect");
- HUD_Write_PanelCvar_q("_timeout");
- HUD_Write_PanelCvar_q("_timeout_effect");
- HUD_Write_PanelCvar_q("_timeout_fadebgmin");
- HUD_Write_PanelCvar_q("_timeout_fadefgmin");
- HUD_Write_PanelCvar_q("_timeout_speed_in");
- HUD_Write_PanelCvar_q("_timeout_speed_out");
- HUD_Write_PanelCvar_q("_onlyowned");
- HUD_Write_PanelCvar_q("_noncurrent_alpha");
- HUD_Write_PanelCvar_q("_noncurrent_scale");
+ HUD_Write_PanelCvar("_accuracy");
+ HUD_Write_PanelCvar("_label");
+ HUD_Write_PanelCvar("_label_scale");
+ HUD_Write_PanelCvar("_complainbubble");
+ HUD_Write_PanelCvar("_complainbubble_padding");
+ HUD_Write_PanelCvar("_complainbubble_time");
+ HUD_Write_PanelCvar("_complainbubble_fadetime");
+ HUD_Write_PanelCvar("_complainbubble_color_outofammo");
+ HUD_Write_PanelCvar("_complainbubble_color_donthave");
+ HUD_Write_PanelCvar("_complainbubble_color_unavailable");
+ HUD_Write_PanelCvar("_ammo");
+ HUD_Write_PanelCvar("_ammo_color");
+ HUD_Write_PanelCvar("_ammo_alpha");
+ HUD_Write_PanelCvar("_aspect");
+ HUD_Write_PanelCvar("_timeout");
+ HUD_Write_PanelCvar("_timeout_effect");
+ HUD_Write_PanelCvar("_timeout_fadebgmin");
+ HUD_Write_PanelCvar("_timeout_fadefgmin");
+ HUD_Write_PanelCvar("_timeout_speed_in");
+ HUD_Write_PanelCvar("_timeout_speed_out");
+ HUD_Write_PanelCvar("_onlyowned");
+ HUD_Write_PanelCvar("_noncurrent_alpha");
+ HUD_Write_PanelCvar("_noncurrent_scale");
break;
case HUD_PANEL_AMMO:
- HUD_Write_PanelCvar_q("_onlycurrent");
- HUD_Write_PanelCvar_q("_noncurrent_alpha");
- HUD_Write_PanelCvar_q("_noncurrent_scale");
- HUD_Write_PanelCvar_q("_iconalign");
- HUD_Write_PanelCvar_q("_progressbar");
- HUD_Write_PanelCvar_q("_progressbar_name");
- HUD_Write_PanelCvar_q("_progressbar_xoffset");
- HUD_Write_PanelCvar_q("_text");
+ HUD_Write_PanelCvar("_onlycurrent");
+ HUD_Write_PanelCvar("_noncurrent_alpha");
+ HUD_Write_PanelCvar("_noncurrent_scale");
+ HUD_Write_PanelCvar("_iconalign");
+ HUD_Write_PanelCvar("_progressbar");
+ HUD_Write_PanelCvar("_progressbar_name");
+ HUD_Write_PanelCvar("_progressbar_xoffset");
+ HUD_Write_PanelCvar("_text");
break;
case HUD_PANEL_POWERUPS:
- HUD_Write_PanelCvar_q("_iconalign");
- HUD_Write_PanelCvar_q("_baralign");
- HUD_Write_PanelCvar_q("_progressbar");
- HUD_Write_PanelCvar_q("_text");
+ HUD_Write_PanelCvar("_iconalign");
+ HUD_Write_PanelCvar("_baralign");
+ HUD_Write_PanelCvar("_progressbar");
+ HUD_Write_PanelCvar("_text");
break;
case HUD_PANEL_HEALTHARMOR:
- HUD_Write_PanelCvar_q("_flip");
- HUD_Write_PanelCvar_q("_iconalign");
- HUD_Write_PanelCvar_q("_baralign");
- HUD_Write_PanelCvar_q("_progressbar");
- HUD_Write_PanelCvar_q("_progressbar_health");
- HUD_Write_PanelCvar_q("_progressbar_armor");
- HUD_Write_PanelCvar_q("_progressbar_gfx");
- HUD_Write_PanelCvar_q("_progressbar_gfx_smooth");
- HUD_Write_PanelCvar_q("_text");
+ HUD_Write_PanelCvar("_flip");
+ HUD_Write_PanelCvar("_iconalign");
+ HUD_Write_PanelCvar("_baralign");
+ HUD_Write_PanelCvar("_progressbar");
+ HUD_Write_PanelCvar("_progressbar_health");
+ HUD_Write_PanelCvar("_progressbar_armor");
+ HUD_Write_PanelCvar("_progressbar_gfx");
+ HUD_Write_PanelCvar("_progressbar_gfx_smooth");
+ HUD_Write_PanelCvar("_text");
break;
case HUD_PANEL_NOTIFY:
- HUD_Write_PanelCvar_q("_flip");
- HUD_Write_PanelCvar_q("_fontsize");
- HUD_Write_PanelCvar_q("_time");
- HUD_Write_PanelCvar_q("_fadetime");
- HUD_Write_PanelCvar_q("_icon_aspect");
+ HUD_Write_PanelCvar("_flip");
+ HUD_Write_PanelCvar("_fontsize");
+ HUD_Write_PanelCvar("_time");
+ HUD_Write_PanelCvar("_fadetime");
+ HUD_Write_PanelCvar("_icon_aspect");
break;
case HUD_PANEL_TIMER:
- HUD_Write_PanelCvar_q("_increment");
break;
case HUD_PANEL_RADAR:
- HUD_Write_PanelCvar_q("_foreground_alpha");
- HUD_Write_PanelCvar_q("_rotation");
- HUD_Write_PanelCvar_q("_zoommode");
- HUD_Write_PanelCvar_q("_scale");
- HUD_Write_PanelCvar_q("_maximized_scale");
- HUD_Write_PanelCvar_q("_maximized_size");
- HUD_Write_PanelCvar_q("_maximized_rotation");
- HUD_Write_PanelCvar_q("_maximized_zoommode");
+ HUD_Write_PanelCvar("_foreground_alpha");
+ HUD_Write_PanelCvar("_rotation");
+ HUD_Write_PanelCvar("_zoommode");
+ HUD_Write_PanelCvar("_scale");
+ HUD_Write_PanelCvar("_maximized_scale");
+ HUD_Write_PanelCvar("_maximized_size");
+ HUD_Write_PanelCvar("_maximized_rotation");
+ HUD_Write_PanelCvar("_maximized_zoommode");
break;
case HUD_PANEL_SCORE:
- HUD_Write_PanelCvar_q("_rankings");
+ HUD_Write_PanelCvar("_rankings");
break;
case HUD_PANEL_VOTE:
- HUD_Write_PanelCvar_q("_alreadyvoted_alpha");
+ HUD_Write_PanelCvar("_alreadyvoted_alpha");
break;
case HUD_PANEL_MODICONS:
- HUD_Write_PanelCvar_q("_ca_layout");
- HUD_Write_PanelCvar_q("_dom_layout");
- HUD_Write_PanelCvar_q("_freezetag_layout");
+ HUD_Write_PanelCvar("_ca_layout");
+ HUD_Write_PanelCvar("_dom_layout");
+ HUD_Write_PanelCvar("_freezetag_layout");
break;
case HUD_PANEL_PRESSEDKEYS:
- HUD_Write_PanelCvar_q("_aspect");
- HUD_Write_PanelCvar_q("_attack");
+ HUD_Write_PanelCvar("_aspect");
+ HUD_Write_PanelCvar("_attack");
break;
case HUD_PANEL_ENGINEINFO:
- HUD_Write_PanelCvar_q("_framecounter_time");
- HUD_Write_PanelCvar_q("_framecounter_decimals");
+ HUD_Write_PanelCvar("_framecounter_time");
+ HUD_Write_PanelCvar("_framecounter_decimals");
break;
case HUD_PANEL_INFOMESSAGES:
- HUD_Write_PanelCvar_q("_flip");
+ HUD_Write_PanelCvar("_flip");
break;
case HUD_PANEL_PHYSICS:
- HUD_Write_PanelCvar_q("_speed_unit");
- HUD_Write_PanelCvar_q("_speed_unit_show");
- HUD_Write_PanelCvar_q("_speed_max");
- HUD_Write_PanelCvar_q("_speed_vertical");
- HUD_Write_PanelCvar_q("_topspeed");
- HUD_Write_PanelCvar_q("_topspeed_time");
- HUD_Write_PanelCvar_q("_acceleration_max");
- HUD_Write_PanelCvar_q("_acceleration_vertical");
- HUD_Write_PanelCvar_q("_flip");
- HUD_Write_PanelCvar_q("_baralign");
- HUD_Write_PanelCvar_q("_progressbar");
- HUD_Write_PanelCvar_q("_progressbar_acceleration_mode");
- HUD_Write_PanelCvar_q("_progressbar_acceleration_scale");
- HUD_Write_PanelCvar_q("_progressbar_acceleration_nonlinear");
- HUD_Write_PanelCvar_q("_text");
- HUD_Write_PanelCvar_q("_text_scale");
+ HUD_Write_PanelCvar("_speed_unit_show");
+ HUD_Write_PanelCvar("_speed_max");
+ HUD_Write_PanelCvar("_speed_vertical");
+ HUD_Write_PanelCvar("_topspeed");
+ HUD_Write_PanelCvar("_topspeed_time");
+ HUD_Write_PanelCvar("_acceleration_max");
+ HUD_Write_PanelCvar("_acceleration_vertical");
+ HUD_Write_PanelCvar("_flip");
+ HUD_Write_PanelCvar("_baralign");
+ HUD_Write_PanelCvar("_progressbar");
+ HUD_Write_PanelCvar("_acceleration_progressbar_mode");
+ HUD_Write_PanelCvar("_acceleration_progressbar_scale");
+ HUD_Write_PanelCvar("_acceleration_progressbar_nonlinear");
+ HUD_Write_PanelCvar("_text");
+ HUD_Write_PanelCvar("_text_scale");
break;
case HUD_PANEL_CENTERPRINT:
- HUD_Write_PanelCvar_q("_align");
- HUD_Write_PanelCvar_q("_flip");
- HUD_Write_PanelCvar_q("_fontscale");
- HUD_Write_PanelCvar_q("_time");
- HUD_Write_PanelCvar_q("_fade_in");
- HUD_Write_PanelCvar_q("_fade_out");
- HUD_Write_PanelCvar_q("_fade_subsequent");
- HUD_Write_PanelCvar_q("_fade_subsequent_passone");
- HUD_Write_PanelCvar_q("_fade_subsequent_passone_minalpha");
- HUD_Write_PanelCvar_q("_fade_subsequent_passtwo");
- HUD_Write_PanelCvar_q("_fade_subsequent_passtwo_minalpha");
- HUD_Write_PanelCvar_q("_fade_subsequent_minfontsize");
- HUD_Write_PanelCvar_q("_fade_minfontsize");
+ HUD_Write_PanelCvar("_align");
+ HUD_Write_PanelCvar("_flip");
+ HUD_Write_PanelCvar("_fontscale");
+ HUD_Write_PanelCvar("_time");
+ HUD_Write_PanelCvar("_fade_in");
+ HUD_Write_PanelCvar("_fade_out");
+ HUD_Write_PanelCvar("_fade_subsequent");
+ HUD_Write_PanelCvar("_fade_subsequent_passone");
+ HUD_Write_PanelCvar("_fade_subsequent_passone_minalpha");
+ HUD_Write_PanelCvar("_fade_subsequent_passtwo");
+ HUD_Write_PanelCvar("_fade_subsequent_passtwo_minalpha");
+ HUD_Write_PanelCvar("_fade_subsequent_minfontsize");
+ HUD_Write_PanelCvar("_fade_minfontsize");
break;
case HUD_PANEL_ITEMSTIME:
- HUD_Write_PanelCvar_q("_iconalign");
- HUD_Write_PanelCvar_q("_progressbar");
- HUD_Write_PanelCvar_q("_progressbar_name");
- HUD_Write_PanelCvar_q("_progressbar_reduced");
- HUD_Write_PanelCvar_q("_text");
- HUD_Write_PanelCvar_q("_ratio");
- HUD_Write_PanelCvar_q("_dynamicsize");
+ HUD_Write_PanelCvar("_iconalign");
+ HUD_Write_PanelCvar("_progressbar");
+ HUD_Write_PanelCvar("_progressbar_name");
+ HUD_Write_PanelCvar("_progressbar_reduced");
+ HUD_Write_PanelCvar("_text");
+ HUD_Write_PanelCvar("_ratio");
+ HUD_Write_PanelCvar("_dynamicsize");
+ break;
case HUD_PANEL_QUICKMENU:
- HUD_Write_PanelCvar_q("_align");
+ HUD_Write_PanelCvar("_align");
break;
}
HUD_Write("\n");
autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
}
-void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
-{
- float bonusNades = getstatf(STAT_NADE_BONUS);
- float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
- float bonusType = getstati(STAT_NADE_BONUS_TYPE);
- Nade def = Nades_from(bonusType);
- vector nadeColor = def.m_color;
- string nadeIcon = def.m_icon;
-
- vector iconPos, textPos;
-
- if(autocvar_hud_panel_ammo_iconalign)
- {
- iconPos = myPos + eX * 2 * mySize.y;
- textPos = myPos;
- }
- else
- {
- iconPos = myPos;
- textPos = myPos + eX * mySize.y;
- }
-
- if(bonusNades > 0 || bonusProgress > 0)
- {
- DrawNadeProgressBar(myPos, mySize, bonusProgress, nadeColor);
-
- if(autocvar_hud_panel_ammo_text)
- drawstring_aspect(textPos, ftos(bonusNades), eX * (2/3) * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-
- if(draw_expanding)
- drawpic_aspect_skin_expanding(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, expand_time);
-
- drawpic_aspect_skin(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- }
-}
+void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time); // TODO: mutator
void DrawAmmoItem(vector myPos, vector mySize, .int ammoType, bool isCurrent, bool isInfinite)
{
}
int rows = 0, columns, row, column;
- float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
+ float nade_cnt = STAT(NADE_BONUS), nade_score = STAT(NADE_BONUS_SCORE);
bool draw_nades = (nade_cnt > 0 || nade_score > 0);
float nade_statuschange_elapsedtime;
int total_ammo_count;
prev_health = 0;
prev_armor = 0;
}
- fuel = getstati(STAT_FUEL);
+ fuel = STAT(FUEL);
}
else
{
drawInfoMessage(s);
//show restart countdown:
- if (time < getstatf(STAT_GAMESTARTTIME)) {
+ if (time < STAT(GAMESTARTTIME)) {
float countdown;
//we need to ceil, otherwise the countdown would be off by .5 when using round()
- countdown = ceil(getstatf(STAT_GAMESTARTTIME) - time);
+ countdown = ceil(STAT(GAMESTARTTIME) - time);
s = sprintf(_("^1Game starts in ^3%d^1 seconds"), countdown);
drawcolorcodedstring(o, s, fontsize, a, DRAWFLAG_NORMAL);
o.y += fontsize.y;
switch(i)
{
case 0:
- stat = getstati(STAT_REDALIVE);
+ stat = STAT(REDALIVE);
pic = "player_red.tga";
color = '1 0 0';
break;
case 1:
- stat = getstati(STAT_BLUEALIVE);
+ stat = STAT(BLUEALIVE);
pic = "player_blue.tga";
color = '0 0 1';
break;
case 2:
- stat = getstati(STAT_YELLOWALIVE);
+ stat = STAT(YELLOWALIVE);
pic = "player_yellow.tga";
color = '1 1 0';
break;
default:
case 3:
- stat = getstati(STAT_PINKALIVE);
+ stat = STAT(PINKALIVE);
pic = "player_pink.tga";
color = '1 0 1';
break;
int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime, yellowflag_statuschange_elapsedtime, pinkflag_statuschange_elapsedtime, neutralflag_statuschange_elapsedtime; // time since the status changed
bool ctf_oneflag; // one-flag CTF mode enabled/disabled
- int stat_items = getstati(STAT_CTF_FLAGSTATUS, 0, 24);
+ int stat_items = STAT(CTF_FLAGSTATUS);
float fs, fs2, fs3, size1, size2;
vector e1, e2;
// Read current state
- int state = getstati(STAT_KH_KEYS);
+ int state = STAT(KH_KEYS);
int i, key_state;
int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
int stat_items;
stat_items = getstati(STAT_ITEMS, 0, 24);
- nb_pb_starttime = getstatf(STAT_NB_METERSTART);
+ nb_pb_starttime = STAT(NB_METERSTART);
if (stat_items & IT_KEY1)
mod_active = 1;
switch(i)
{
case 0:
- stat = getstatf(STAT_DOM_PPS_RED);
+ stat = STAT(DOM_PPS_RED);
pic = "dom_icon_red";
color = '1 0 0';
break;
case 1:
- stat = getstatf(STAT_DOM_PPS_BLUE);
+ stat = STAT(DOM_PPS_BLUE);
pic = "dom_icon_blue";
color = '0 0 1';
break;
case 2:
- stat = getstatf(STAT_DOM_PPS_YELLOW);
+ stat = STAT(DOM_PPS_YELLOW);
pic = "dom_icon_yellow";
color = '1 1 0';
break;
default:
case 3:
- stat = getstatf(STAT_DOM_PPS_PINK);
+ stat = STAT(DOM_PPS_PINK);
pic = "dom_icon_pink";
color = '1 0 1';
break;
}
- float pps_ratio = stat / getstatf(STAT_DOM_TOTAL_PPS);
+ float pps_ratio = stat / STAT(DOM_TOTAL_PPS);
if(mySize.x/mySize.y > aspect_ratio)
{
void HUD_Powerups()
{
int allItems = getstati(STAT_ITEMS, 0, 24);
- int allBuffs = getstati(STAT_BUFFS, 0, 24);
+ int allBuffs = STAT(BUFFS);
int strengthTime, shieldTime, superTime;
// Initialize items
if(getstati(STAT_HEALTH) <= 0) return;
if(!(allItems & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON)) && !allBuffs) return;
- strengthTime = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
- shieldTime = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99);
- superTime = bound(0, getstatf(STAT_SUPERWEAPONS_FINISHED) - time, 99);
+ strengthTime = bound(0, STAT(STRENGTH_FINISHED) - time, 99);
+ shieldTime = bound(0, STAT(INVINCIBLE_FINISHED) - time, 99);
+ superTime = bound(0, STAT(SUPERWEAPONS_FINISHED) - time, 99);
if(allItems & IT_UNLIMITED_SUPERWEAPONS)
superTime = 99;
if(superTime)
addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
- FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
- addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
- ));
+ MUTATOR_CALLHOOK(HUD_Powerups_add);
if(!powerupItemsCount)
return;
vector keysize;
keysize = eX * mySize.x * (1/3.0) + eY * mySize.y * (1/(3.0 - !autocvar_hud_panel_pressedkeys_attack));
- float pressedkeys;
- pressedkeys = getstatf(STAT_PRESSED_KEYS);
+ int pressedkeys = STAT(PRESSED_KEYS);
if(autocvar_hud_panel_pressedkeys_attack)
{
if((hud_panel_radar_rotation == 0 && !hud_panel_radar_maximized) || (hud_panel_radar_maximized_rotation == 0 && hud_panel_radar_maximized))
{
// max-min distance must fit the radar in any rotation
- bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen2d(mi_scale));
+ bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen(vec2(mi_scale)));
}
else
{
}
for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
{
+ if (!tm.m_entcs_private) continue;
+ if (entcs_is_self(tm)) continue;
color2 = GetPlayerColor(tm.sv_entnum);
//if(color == NUM_SPECTATOR || color == color2)
draw_teamradar_player(tm.origin, tm.angles, Team_ColorRGB(color2));
string timer;
float timelimit, elapsedTime, timeleft, minutesLeft;
- timelimit = getstatf(STAT_TIMELIMIT);
+ timelimit = STAT(TIMELIMIT);
- timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time);
+ timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
timeleft = ceil(timeleft);
minutesLeft = floor(timeleft / 60);
timer_color = '1 0 0'; //red
if (autocvar_hud_panel_timer_increment || timelimit == 0 || warmup_stage) {
- if (time < getstatf(STAT_GAMESTARTTIME)) {
+ if (time < STAT(GAMESTARTTIME)) {
//while restart is still active, show 00:00
timer = seconds_tostring(0);
} else {
- elapsedTime = floor(time - getstatf(STAT_GAMESTARTTIME)); //127
+ elapsedTime = floor(time - STAT(GAMESTARTTIME)); //127
timer = seconds_tostring(elapsedTime);
}
} else {
int nHidden = 0;
WepSet weapons_stat = WepSet_GetFromStat();
for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- WepSet weapons_wep = WepSet_FromWeapon(i);
- if (weapons_stat & weapons_wep) continue;
Weapon w = get_weaponinfo(i);
+ if (weapons_stat & w.m_wepset) continue;
if (w.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
}
vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, padded_panel_size, aspect);
prvm_language = strzone(cvar_string("prvm_language"));
#ifdef WATERMARK
- LOG_TRACEF("^4CSQC Build information: ^1%s\n", WATERMARK);
+ LOG_INFOF("^4CSQC Build information: ^1%s\n", WATERMARK);
#endif
binddb = db_create();
// --------------------------------------------------------------------------
// BEGIN OPTIONAL CSQC FUNCTIONS
-void Ent_RemoveEntCS()
-{
- SELFPARAM();
- entcs_receiver[this.sv_entnum] = NULL;
-}
-
-NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
-{
- make_pure(this);
- this.classname = "entcs_receiver";
- InterpolateOrigin_Undo();
- int sf = ReadByte();
-
- if(sf & BIT(0))
- this.sv_entnum = ReadByte();
- if (sf & BIT(1))
- {
- this.origin_x = ReadShort();
- this.origin_y = ReadShort();
- this.origin_z = ReadShort();
- setorigin(this, this.origin);
- }
- if (sf & BIT(2))
- {
- this.angles_y = ReadByte() * 360.0 / 256;
- this.angles_x = this.angles_z = 0;
- }
- if (sf & BIT(3))
- this.healthvalue = ReadByte() * 10;
- if (sf & BIT(4))
- this.armorvalue = ReadByte() * 10;
-
- return = true;
-
- entcs_receiver[this.sv_entnum] = this;
- this.entremove = Ent_RemoveEntCS;
- this.iflags |= IFLAG_ORIGIN;
-
- InterpolateOrigin_Note();
-}
-
void Ent_Remove();
void Ent_RemovePlayerScore()
// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
// The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
-void CSQC_Ent_Update(float bIsNewEntity)
+void CSQC_Ent_Update(bool isnew)
{
SELFPARAM();
this.sourceLocLine = __LINE__;
else
{
serverprevtime = time;
- serverdeltatime = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ serverdeltatime = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
time = serverprevtime + serverdeltatime;
}
#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
- if(this.enttype)
+ if (this.enttype)
{
- if(t != this.enttype || bIsNewEntity)
+ if (t != this.enttype || isnew)
{
LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(this), this.entnum, this.enttype, t);
Ent_Remove();
clearentity(this);
- bIsNewEntity = 1;
+ isnew = true;
}
}
else
{
- if(!bIsNewEntity)
+ if (!isnew)
{
LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(this), this.entnum, t);
- bIsNewEntity = 1;
+ isnew = true;
}
}
#endif
this.enttype = t;
bool done = false;
FOREACH(LinkedEntities, it.m_id == t, LAMBDA(
- this.classname = it.netname;
+ if (isnew) this.classname = it.netname;
if (autocvar_developer_csqcentities)
- LOG_INFOF("CSQC_Ent_Update(%d) with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", bIsNewEntity, this, this.entnum, this.enttype, it.netname, t);
- done = it.m_read(this, bIsNewEntity);
+ LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
+ done = it.m_read(this, isnew);
break;
));
time = savetime;
if (!done)
{
- //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), this.enttype));
- error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", this.enttype, num_for_edict(this), this.classname));
+ LOG_FATALF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
}
}
float drawframetime;
vector view_origin, view_forward, view_right, view_up;
-float button_zoom;
-float spectatorbutton_zoom;
-float button_attack2;
+bool button_zoom;
+bool spectatorbutton_zoom;
+bool button_attack2;
int activeweapon;
int switchingweapon;
-int switchweapon;
+#define switchweapon STAT(SWITCHWEAPON)
float current_viewzoom;
float zoomin_effect;
float warmup_stage;
float g_balance_electro_secondary_bouncestop;
float g_trueaim_minrange;
-entity entcs_receiver[255]; // 255 is the engine limit on maxclients
-
float hud;
float view_quality;
int framecount;
}
}
-vector getplayerorigin(int pl)
-{
- entity e;
-
- e = CSQCModel_server2csqc(pl + 1);
- if(e)
- return e.origin;
-
- e = entcs_receiver[pl];
- if(e)
- return e.origin;
-
- return GETPLAYERORIGIN_ERROR;
-}
-
-float getplayeralpha(float pl)
-{
- entity e;
-
- e = CSQCModel_server2csqc(pl + 1);
- if(e)
- return e.alpha;
-
- return 1;
-}
-
-vector getcsqcplayercolor(float pl)
-{
- entity e;
-
- e = CSQCModel_server2csqc(pl);
- if(e)
- {
- if(e.colormap > 0)
- return colormapPaletteColor(((e.colormap >= 1024) ? e.colormap : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 0x0F, true);
- }
-
- return '1 1 1';
-}
-
-float getplayerisdead(float pl)
-{
- entity e;
-
- e = CSQCModel_server2csqc(pl + 1);
- if(e)
- return e.csqcmodel_isdead;
-
- return false;
-}
-
/** engine callback */
void URI_Get_Callback(int id, float status, string data)
{
vector rotate(vector v, float a);
-string ColorTranslateRGB(string s);
-
// decolorizes and team colors the player name when needed
string playername(string thename, float teamid);
void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag);
-const vector GETPLAYERORIGIN_ERROR = '1123581321 2357111317 3141592653'; // way out of bounds for anything on the map
-vector getplayerorigin(int pl);
-
-float getplayeralpha(float pl);
-
-vector getcsqcplayercolor(float pl);
-
-float getplayerisdead(float pl);
-
const int MAX_ACCURACY_LEVELS = 10;
float acc_lev[MAX_ACCURACY_LEVELS];
vector acc_col[MAX_ACCURACY_LEVELS];
string checkmodel_input, checkmodel_command;
MUTATOR_HOOKABLE(GetModelParams, EV_GetModelParams);
-/** called when a player presses the jump key */
-#define EV_PlayerJump(i, o) \
- /**/ i(float, player_multijump) \
- /**/ i(float, player_jumpheight) \
- /**/ o(float, player_multijump) \
- /**/ o(float, player_jumpheight) \
- /**/
-float player_multijump;
-float player_jumpheight;
-MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
-
/** Called checking if 3rd person mode should be forced on */
#define EV_WantEventchase(i, o) \
/** entity id */ i(entity, __self) \
MUTATOR_HOOKABLE(AnnouncerOption, EV_AnnouncerOption);
MUTATOR_HOOKABLE(Ent_Init, EV_NO_ARGS);
+
+#define EV_HUD_Draw_overlay(i, o) \
+ /**/ o(vector, MUTATOR_ARGV_0_vector) \
+ /**/ o(float, MUTATOR_ARGV_0_float) \
+ /**/
+MUTATOR_HOOKABLE(HUD_Draw_overlay, EV_HUD_Draw_overlay);
+
+MUTATOR_HOOKABLE(HUD_Powerups_add, EV_NO_ARGS);
+
+/** Return true to not draw any vortex beam */
+#define EV_Particles_VortexBeam(i, o) \
+ /**/ i(vector, vbeam_shotorg) \
+ /**/ i(vector, vbeam_endpos) \
+ /**/
+vector vbeam_shotorg;
+vector vbeam_endpos;
+MUTATOR_HOOKABLE(Particles_VortexBeam, EV_Particles_VortexBeam);
+
+/** Return true to not draw any impact effect */
+#define EV_Weapon_ImpactEffect(i, o) \
+ /**/ i(entity, w_hitwep) \
+ /**/
+entity w_hitwep;
+MUTATOR_HOOKABLE(Weapon_ImpactEffect, EV_Weapon_ImpactEffect);
+
#endif
#include "../common/anim.qc"
#include "../common/animdecide.qc"
#include "../common/effects/effectinfo.qc"
+#include "../common/ent_cs.qc"
#include "../common/mapinfo.qc"
#include "../common/movetypes/include.qc"
#include "../common/net_notice.qc"
#include "../common/minigames/minigames.qc"
#include "../common/minigames/cl_minigames.qc"
-#include "../common/buffs/all.qc"
#include "../common/deathtypes/all.qc"
#include "../common/effects/all.qc"
#include "../common/gamemodes/all.qc"
#include "../common/items/all.qc"
#include "../common/monsters/all.qc"
#include "../common/mutators/all.qc"
-#include "../common/nades/all.qc"
#include "../common/turrets/all.qc"
#include "../common/vehicles/all.qc"
#include "../common/weapons/all.qc"
QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
QUICKMENU_ENTRY(CTX(_("QMCMD^Restart the map")), "vcall restart")
QUICKMENU_ENTRY(CTX(_("QMCMD^End match")), "vcall endmatch")
- if(getstatf(STAT_TIMELIMIT) > 0)
+ if(STAT(TIMELIMIT) > 0)
{
QUICKMENU_ENTRY(CTX(_("QMCMD^Reduce match time")), "vcall reducematchtime")
QUICKMENU_ENTRY(CTX(_("QMCMD^Extend match time")), "vcall extendmatchtime")
#define HUD_DefaultColumnLayout() \
"ping pl name | " \
-"-teams,rc,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,rc,ka/suicides +ft,tdm/suicides -rc,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
-"dmg dmgtaken " \
+"-teams,cts,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,rc,ka/suicides +ft,tdm/suicides -cts,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
+"-rc,cts,nb/dmg -rc,cts,nb/dmgtaken " \
"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes " \
"+lms/lives +lms/rank " \
"+kh/caps +kh/pushes +kh/destroyed " \
float initial_posx = pos.x;
int disownedcnt = 0;
for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- setself(get_weaponinfo(i));
+ Weapon e = get_weaponinfo(i);
+ setself(e);
if (!self.weapon) continue;
int weapon_stats = weapon_accuracy[i - WEP_FIRST];
- if (weapon_stats < 0 && !(weapons_stat & WepSet_FromWeapon(i) || weapons_inmap & WepSet_FromWeapon(i)))
+ WepSet set = e.m_wepset;
+ if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
++disownedcnt;
}
int column = 0;
for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- setself(get_weaponinfo(i));
+ Weapon e = get_weaponinfo(i);
+ setself(e);
if (!self.weapon) continue;
int weapon_stats = weapon_accuracy[i - WEP_FIRST];
- if (weapon_stats < 0 && !(weapons_stat & WepSet_FromWeapon(i) || weapons_inmap & WepSet_FromWeapon(i)))
+ WepSet set = e.m_wepset;
+ if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
continue;
float weapon_alpha;
string val;
// get monster stats
- stat_monsters_killed = getstatf(STAT_MONSTERS_KILLED);
- stat_monsters_total = getstatf(STAT_MONSTERS_TOTAL);
+ stat_monsters_killed = STAT(MONSTERS_KILLED);
+ stat_monsters_total = STAT(MONSTERS_TOTAL);
// get secrets stats
- stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
- stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
+ stat_secrets_found = STAT(SECRETS_FOUND);
+ stat_secrets_total = STAT(SECRETS_TOTAL);
// get number of rows
if(stat_secrets_total)
// Print info string
float tl, fl, ll;
str = sprintf(_("playing ^3%s^7 on ^2%s^7"), MapInfo_Type_ToText(gametype), shortmapname);
- tl = getstatf(STAT_TIMELIMIT);
- fl = getstatf(STAT_FRAGLIMIT);
- ll = getstatf(STAT_LEADLIMIT);
+ tl = STAT(TIMELIMIT);
+ fl = STAT(FRAGLIMIT);
+ ll = STAT(LEADLIMIT);
if(gametype == MAPINFO_TYPE_LMS)
{
if(tl > 0)
drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
// print information about respawn status
- float respawn_time = getstatf(STAT_RESPAWN_TIME);
+ float respawn_time = STAT(RESPAWN_TIME);
if(!intermission)
if(respawn_time)
{
#include "../lib/csqcmodel/cl_model.qh"
// self.isactive = player is in range and coordinates/status (health and armor) are up to date
-// self.origin = player origin TODO: should maybe move this so it's the origin of the shownames tag already in SSQC for culling?
+// self.origin = player origin
// self.healthvalue
// self.armorvalue
// self.sameteam = player is on same team as local client
// self.pointtime = last time you pointed at this player
// self.csqcmodel_isdead = value of csqcmodel_isdead to know when the player is dead or not
+LinkedList shownames_ent;
+STATIC_INIT(shownames_ent)
+{
+ shownames_ent = LL_NEW();
+ for (int i = 0; i < maxclients; ++i)
+ {
+ entity e = new(shownames_tag);
+ e.sv_entnum = i + 1;
+ LL_PUSH(shownames_ent, e);
+ }
+}
+
const float SHOWNAMES_FADESPEED = 4;
const float SHOWNAMES_FADEDELAY = 0.4;
-void Draw_ShowNames(entity ent)
+void Draw_ShowNames(entity this)
{
- if(!autocvar_hud_shownames)
- return;
-
- if(ent.sv_entnum == player_localentnum) // ent is me or person i'm spectating
- if(!(autocvar_hud_shownames_self && autocvar_chase_active))
- return;
-
- if(ent.sameteam || (!ent.sameteam && autocvar_hud_shownames_enemies))
+ if (this.sv_entnum == player_localentnum) // self or spectatee
+ if (!(autocvar_hud_shownames_self && autocvar_chase_active)) return;
+ if (!this.sameteam && !autocvar_hud_shownames_enemies) return;
+ bool hit;
+ if (!autocvar_hud_shownames_crosshairdistance && this.sameteam)
{
- ent.origin_z += autocvar_hud_shownames_offset;
-
- float hit;
- if(ent.sameteam && !autocvar_hud_shownames_crosshairdistance)
- {
- hit = 1;
- }
- else
- {
- traceline(view_origin, ent.origin, MOVE_NORMAL, ent);
- if(trace_fraction < 1 && (trace_networkentity != ent.sv_entnum && trace_ent.entnum != ent.sv_entnum))
- hit = 0;
- else
- hit = 1;
- }
-
- // handle tag fading
- float overlap = false, onscreen, crosshairdistance;
- vector o, eo;
-
- o = project_3d_to_2d(ent.origin);
-
- if(autocvar_hud_shownames_antioverlap)
- {
- // fade tag out if another tag that is closer to you overlaps
- entity e;
- for(e = world; (e = find(e, classname, "shownames_tag")); )
+ hit = true;
+ }
+ else
+ {
+ traceline(view_origin, this.origin, MOVE_NORMAL, this);
+ hit = !(trace_fraction < 1 && (trace_networkentity != this.sv_entnum && trace_ent.entnum != this.sv_entnum));
+ }
+ // handle tag fading
+ bool overlap = false;
+ vector o = project_3d_to_2d(this.origin + eZ * autocvar_hud_shownames_offset);
+ float dist = vlen(this.origin - view_origin);
+ if (autocvar_hud_shownames_antioverlap)
+ {
+ // fade tag out if another tag that is closer to you overlaps
+ LL_EACH(shownames_ent, it != this && entcs_receiver(i), LAMBDA(
+ vector eo = project_3d_to_2d(it.origin);
+ if (eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight) continue;
+ eo.z = 0;
+ if (vlen((eX * o.x + eY * o.y) - eo) < autocvar_hud_shownames_antioverlap_distance
+ && dist > vlen(it.origin - view_origin))
{
- if(e == ent)
- continue;
- eo = project_3d_to_2d(e.origin);
- if (!(eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight))
- {
- eo.z = 0;
- if(vlen((eX * o.x + eY * o.y) - eo) < autocvar_hud_shownames_antioverlap_distance && vlen(ent.origin - view_origin) > vlen(e.origin - view_origin))
- {
- overlap = true;
- break;
- }
- }
- }
- }
-
- onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
- crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
-
- if(autocvar_hud_shownames_crosshairdistance)
- {
- if(autocvar_hud_shownames_crosshairdistance > crosshairdistance)
- ent.pointtime = time;
-
- if (ent.pointtime + autocvar_hud_shownames_crosshairdistance_time <= time)
overlap = true;
- else
- overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : false); // override what antioverlap says unless allowed by cvar.
- }
-
- if(!ent.fadedelay)
- ent.fadedelay = time + SHOWNAMES_FADEDELAY;
-
- if(!ent.sameteam && (!onscreen || !hit)) // out of view, fade out
- {
- ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime);
- ent.fadedelay = 0; // reset fade in delay, enemy has left the view
- }
- else if(ent.csqcmodel_isdead) // dead player, fade out slowly
- ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime);
- else if(overlap) // tag overlap detected, fade out
- ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime);
- else if(ent.sameteam) // fade in for team mates
- ent.alpha = min(1, ent.alpha + SHOWNAMES_FADESPEED * frametime);
- else if(time > ent.fadedelay) // fade in for enemies
- ent.alpha = min(1, ent.alpha + SHOWNAMES_FADESPEED * frametime);
-
- // multiply by player alpha
- if(!ent.sameteam || (ent.sv_entnum == player_localentnum))
- ent.alpha *= getplayeralpha(ent.sv_entnum-1);
-
- if(ent.alpha < ALPHA_MIN_VISIBLE && gametype != MAPINFO_TYPE_CTS)
- return;
-
- float dist;
- dist = vlen(ent.origin - view_origin);
-
- float a;
- a = autocvar_hud_shownames_alpha;
- a *= ent.alpha;
- if(autocvar_hud_shownames_maxdistance)
- {
- if(dist >= autocvar_hud_shownames_maxdistance)
- return;
- a *= ((autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance) - max(0, dist - autocvar_hud_shownames_mindistance)) / (autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance);
- }
-
- if(!a)
- return;
-
- float resize;
- resize = 1;
- if(autocvar_hud_shownames_resize) // limit resize so its never smaller than 0.5... gets unreadable
- resize = 0.5 + 0.5 * ((autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance) - max(0, dist - autocvar_hud_shownames_mindistance)) / (autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance);
-
- // draw the sprite image
- if(o.z >= 0)
+ break;
+ }
+ ));
+ }
+ bool onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
+ float crosshairdistance = sqrt(pow(o.x - vid_conwidth / 2, 2) + pow(o.y - vid_conheight / 2, 2));
+ if (autocvar_hud_shownames_crosshairdistance)
+ {
+ if (autocvar_hud_shownames_crosshairdistance > crosshairdistance) this.pointtime = time;
+ if (this.pointtime + autocvar_hud_shownames_crosshairdistance_time <= time) overlap = true;
+ else overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : false); // override what antioverlap says unless allowed by cvar.
+ }
+ if (!this.fadedelay) this.fadedelay = time + SHOWNAMES_FADEDELAY;
+ if (this.csqcmodel_isdead) // dead player, fade out slowly
+ {
+ this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime);
+ }
+ else if (!this.sameteam && (!onscreen || !hit)) // out of view, fade out
+ {
+ this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
+ this.fadedelay = 0; // reset fade in delay, enemy has left the view
+ }
+ else if (overlap) // tag overlap detected, fade out
+ {
+ this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
+ }
+ else if (this.sameteam) // fade in for team mates
+ {
+ this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
+ }
+ else if (time > this.fadedelay) // fade in for enemies
+ {
+ this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
+ }
+ float a = autocvar_hud_shownames_alpha * this.alpha;
+ // multiply by player alpha
+ if (!this.sameteam || (this.sv_entnum == player_localentnum))
+ {
+ float f = getplayeralpha(this.sv_entnum - 1);
+ if (f == 0) f = 1;
+ if (f < 0) f = 0;
+ // FIXME: alpha is negative when dead, breaking death fade
+ if (!this.csqcmodel_isdead) a *= f;
+ }
+ if (a < ALPHA_MIN_VISIBLE && gametype != MAPINFO_TYPE_CTS) return;
+ if (autocvar_hud_shownames_maxdistance)
+ {
+ if (dist >= autocvar_hud_shownames_maxdistance) return;
+ float f = autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance;
+ a *= (f - max(0, dist - autocvar_hud_shownames_mindistance)) / f;
+ }
+ if (!a) return;
+ float resize = 1;
+ if (autocvar_hud_shownames_resize) // limit resize so its never smaller than 0.5... gets unreadable
+ {
+ float f = autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance;
+ resize = 0.5 + 0.5 * (f - max(0, dist - autocvar_hud_shownames_mindistance)) / f;
+ }
+ // draw the sprite image
+ if (o.z >= 0)
+ {
+ o.z = 0;
+ vector mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_fontsize;
+ vector myPos = o - '0.5 0 0' * mySize.x - '0 1 0' * mySize.y;
+ // size scaling
+ mySize.x *= resize;
+ mySize.y *= resize;
+ myPos.x += 0.5 * (mySize.x / resize - mySize.x);
+ myPos.y += (mySize.y / resize - mySize.y);
+ // this is where the origin of the string
+ vector namepos = myPos;
+ float namewidth = mySize.x;
+ if (autocvar_hud_shownames_status && this.sameteam)
{
- o.z = 0;
-
- vector myPos, mySize;
- mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_fontsize;
- myPos = o - '0.5 0 0' * mySize.x - '0 1 0' * mySize.y;
-
- // size scaling
- mySize.x *= resize;
- mySize.y *= resize;
-
- myPos.x += 0.5 * (mySize.x / resize - mySize.x);
- myPos.y += (mySize.y / resize - mySize.y);
-
- vector namepos; // this is where the origin of the string
- float namewidth;
-
- namepos = myPos;
- namewidth = mySize.x;
-
- if(autocvar_hud_shownames_status && teamplay)
+ vector v = namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize;
+ vector s = eX * 0.5 * mySize.x + eY * resize * autocvar_hud_shownames_statusbar_height;
+ if (this.healthvalue > 0)
{
- if(ent.sameteam)
- {
- if(ent.healthvalue > 0)
- {
- HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize, eX * 0.5 * mySize.x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", ent.healthvalue/autocvar_hud_panel_healtharmor_maxhealth, 0, 1, '1 0 0', a, DRAWFLAG_NORMAL);
-
- if(ent.armorvalue > 0)
- HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize + eX * 0.5 * mySize.x, eX * 0.5 * mySize.x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", ent.armorvalue/autocvar_hud_panel_healtharmor_maxarmor, 0, 0, '0 1 0', a, DRAWFLAG_NORMAL);
- }
- }
+ HUD_Panel_DrawProgressBar(v, s, "nametag_statusbar",
+ this.healthvalue / autocvar_hud_panel_healtharmor_maxhealth, false, 1, '1 0 0', a,
+ DRAWFLAG_NORMAL);
+ }
+ if (this.armorvalue > 0)
+ {
+ HUD_Panel_DrawProgressBar(v + eX * 0.5 * mySize.x, s, "nametag_statusbar",
+ this.armorvalue / autocvar_hud_panel_healtharmor_maxarmor, false, 0, '0 1 0', a,
+ DRAWFLAG_NORMAL);
}
-
- string s;
- s = GetPlayerName(ent.sv_entnum-1);
- if((autocvar_hud_shownames_decolorize == 1 && teamplay) || autocvar_hud_shownames_decolorize == 2)
- s = playername(s, GetPlayerColor(ent.sv_entnum-1));
-
- drawfontscale = '1 1 0' * resize;
- s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
-
- float width;
- width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
-
- if (width != namewidth)
- namepos.x += (namewidth - width) / 2;
- drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
- drawfontscale = '1 1 0';
}
+ string s = GetPlayerName(this.sv_entnum - 1);
+ if ((autocvar_hud_shownames_decolorize == 1 && teamplay)
+ || autocvar_hud_shownames_decolorize == 2) s = playername(s, GetPlayerColor(this.sv_entnum - 1));
+ drawfontscale = '1 1 0' * resize;
+ s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
+ float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
+ if (width != namewidth) namepos.x += (namewidth - width) / 2;
+ drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
+ drawfontscale = '1 1 0';
}
}
-entity shownames_ent[255];
void Draw_ShowNames_All()
{
- int i;
- for(i = 0; i < maxclients; ++i)
- {
- float t;
- t = GetPlayerColor(i);
- if(t == NUM_SPECTATOR)
- continue;
-
- entity e;
- e = shownames_ent[i];
- if(!e)
- {
- e = new(shownames_tag);
- e.sv_entnum = i+1;
- shownames_ent[i] = e;
- }
-
- entity entcs;
- entcs = entcs_receiver[i];
- if(entcs)
+ if (!autocvar_hud_shownames) return;
+ LL_EACH(shownames_ent, true, LAMBDA(
+ entity entcs = entcs_receiver(i);
+ if (!entcs) continue;
+ WITH(entity, self, entcs, entcs.think());
+ if (entcs.m_entcs_private)
{
- e.healthvalue = entcs.healthvalue;
- e.armorvalue = entcs.armorvalue;
- e.sameteam = 1; /* (teamplay && (t == myteam)); */
+ it.healthvalue = entcs.healthvalue;
+ it.armorvalue = entcs.armorvalue;
+ it.sameteam = true;
}
else
{
- e.healthvalue = 2342;
- e.armorvalue = 0;
- e.sameteam = 0;
+ it.healthvalue = 0;
+ it.armorvalue = 0;
+ it.sameteam = false;
}
-
- setorigin(e, getplayerorigin(i));
- if(e.origin == GETPLAYERORIGIN_ERROR)
- continue;
-
- e.csqcmodel_isdead = getplayerisdead(i);
-
- Draw_ShowNames(e);
- }
+ bool dead = getplayerisdead(i);
+ if (!it.csqcmodel_isdead && entcs.has_origin) setorigin(it, entcs.origin);
+ it.csqcmodel_isdead = dead;
+ Draw_ShowNames(it);
+ ));
}
-#include "../common/buffs/all.qh"
#include "../common/movetypes/movetypes.qh"
#include "../common/weapons/all.qh"
#include "../lib/csqcmodel/cl_model.qh"
{
int sendflags = ReadByte();
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
self.classname = "radarlink";
return = true;
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
}
#include "../common/debug.qh"
#include "../common/mapinfo.qh"
#include "../common/gamemodes/all.qh"
-#include "../common/nades/all.qh"
+#include "../common/physics.qh"
#include "../common/stats.qh"
#include "../common/triggers/target/music.qh"
#include "../common/teams.qh"
void viewmodel_animate(entity this)
{
static float prevtime;
- float frametime = (time - prevtime) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ float frametime = (time - prevtime) * STAT(MOVEVARS_TIMESCALE);
prevtime = time;
if (autocvar_chase_active) return;
if (getstati(STAT_HEALTH) <= 0) return;
- entity view = CSQCModel_server2csqc(player_localentnum);
+ entity view = CSQCModel_server2csqc(player_localentnum - 1);
bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
static bool oldonground;
float a = this.alpha;
int c = stof(getplayerkeyvalue(current_player, "colors"));
vector g = this.glowmod; // TODO: completely clientside: colormapPaletteColor(c & 0x0F, true) * 2;
- entity me = CSQCModel_server2csqc(player_localentnum);
+ entity me = CSQCModel_server2csqc(player_localentnum - 1);
int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
| EF_NODEPTHTEST)
&~ (EF_FULLBRIGHT); // can mask team color, so get rid of it
if (!this.animstate_override)
anim_set(this, this.anim_idle, true, false, false);
}
- float eta = (getstatf(STAT_WEAPON_NEXTTHINK) - time); // TODO: / W_WeaponRateFactor();
+ float eta = (STAT(WEAPON_NEXTTHINK) - time); // TODO: / W_WeaponRateFactor();
float f = 0; // 0..1; 0: fully active
switch (this.state)
{
break;
}
- vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
+ vector traceorigin = entcs_receiver(player_localentnum - 1).origin + (eZ * getstati(STAT_VIEWHEIGHT));
- vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+ vecs = decompressShotOrigin(STAT(SHOTORG));
traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
trueaimpoint = trace_endpos;
return true;
if(MUTATOR_CALLHOOK(WantEventchase, self))
return true;
- if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_NEXBALL.m_id)))
+ if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
return true;
if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
{
{
// accumulate damage with each stat update
static float damage_total_prev = 0;
- float damage_total = getstati(STAT_DAMAGE_DEALT_TOTAL);
+ float damage_total = STAT(DAMAGE_DEALT_TOTAL);
float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
damage_total_prev = damage_total;
static float damage_dealt_time_prev = 0;
- float damage_dealt_time = getstatf(STAT_HIT_TIME);
+ float damage_dealt_time = STAT(HIT_TIME);
if (damage_dealt_time != damage_dealt_time_prev)
{
unaccounted_damage += unaccounted_damage_new;
}
static float typehit_time_prev = 0;
- float typehit_time = getstatf(STAT_TYPEHIT_TIME);
+ float typehit_time = STAT(TYPEHIT_TIME);
if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
{
sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
if(autocvar_crosshair_pickup)
{
- float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
+ float stat_pickup_time = STAT(LAST_PICKUP);
if(pickup_crosshair_time < stat_pickup_time)
{
ring_scale = autocvar_crosshair_ring_size;
float weapon_clipload, weapon_clipsize;
- weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
- weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+ weapon_clipload = STAT(WEAPON_CLIPLOAD);
+ weapon_clipsize = STAT(WEAPON_CLIPSIZE);
float ok_ammo_charge, ok_ammo_chargepool;
- ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE);
- ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOL);
+ ok_ammo_charge = STAT(OK_AMMO_CHARGE);
+ ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
float vortex_charge, vortex_chargepool;
- vortex_charge = getstatf(STAT_VORTEX_CHARGE);
- vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+ vortex_charge = STAT(VORTEX_CHARGE);
+ vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
- float arc_heat = getstatf(STAT_ARC_HEAT);
+ float arc_heat = STAT(ARC_HEAT);
if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
vortex_charge_movingavg = vortex_charge;
}
else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER.m_id && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
{
- ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
+ ring_value = bound(0, STAT(LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
}
- else if (activeweapon == WEP_HAGAR.m_id && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+ else if (activeweapon == WEP_HAGAR.m_id && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
{
- ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
+ ring_value = bound(0, STAT(HAGAR_LOAD) / hagar_maxrockets, 1);
ring_alpha = autocvar_crosshair_ring_hagar_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
wcross_color = stov(autocvar_crosshair_dot_color);
CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha);
- // FIXME why don't we use wcross_alpha here?cl_notice_run();
+ // FIXME why don't we use wcross_alpha here?
wcross_color = wcross_color_old;
}
}
void HUD_Draw()
{
- if(getstati(STAT_FROZEN))
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
- else if (getstatf(STAT_HEALING_ORB)>time)
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, NADE_TYPE_HEAL.m_color, autocvar_hud_colorflash_alpha*getstatf(STAT_HEALING_ORB_ALPHA), DRAWFLAG_ADDITIVE);
+ vector rgb = '0 0 0';
+ float a = 1;
+ if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
+ {
+ rgb = MUTATOR_ARGV(0, vector);
+ a = MUTATOR_ARGV(0, float);
+ }
+ else if(STAT(FROZEN))
+ {
+ rgb = ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
+ }
+ drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, rgb, autocvar_hud_colorflash_alpha * a, DRAWFLAG_ADDITIVE);
if(!intermission)
- if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+ if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
{
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
}
- else if(getstatf(STAT_REVIVE_PROGRESS))
+ else if(STAT(REVIVE_PROGRESS))
{
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
}
float oldr_useportalculling;
float oldr_useinfinitefarclip;
-const int BUTTON_3 = 4;
-const int BUTTON_4 = 8;
-float cl_notice_run();
+void cl_notice_run();
float prev_myteam;
int lasthud;
float vh_notice_time;
++framecount;
- hud = getstati(STAT_HUD);
+ stats_get();
+ hud = STAT(HUD);
if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
vh_notice_time = time + autocvar_cl_vehicles_notify_time;
else
view_quality = 1;
- button_attack2 = (input_buttons & BUTTON_3);
- button_zoom = (input_buttons & BUTTON_4);
+ button_attack2 = PHYS_INPUT_BUTTON_ATCK2(self);
+ button_zoom = PHYS_INPUT_BUTTON_ZOOM(self);
vf_size = getpropertyvec(VF_SIZE);
vf_min = getpropertyvec(VF_MIN);
prev_myteam = myteam;
}
- ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
float is_dead = (getstati(STAT_HEALTH) <= 0);
if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
{
float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
- float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
+ float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && STAT(ROUNDLOST));
entity gen = world;
if(ons_roundlost)
ColorTranslateMode = autocvar_cl_stripcolorcodes;
- // next WANTED weapon (for HUD)
- switchweapon = getstati(STAT_SWITCHWEAPON);
-
// currently switching-to weapon (for crosshair)
- switchingweapon = getstati(STAT_SWITCHINGWEAPON);
+ switchingweapon = STAT(SWITCHINGWEAPON);
// actually active weapon (for zoom)
activeweapon = getstati(STAT_ACTIVEWEAPON);
mousepos = mousepos*0.5 + getmousepos();
*/
- for(entity e = NULL; (e = nextent(e)); ) if (e.draw) {
- WITH(entity, self, e, e.draw(e));
- }
+ FOREACH_ENTITY(it.draw, LAMBDA(WITH(entity, self, it, it.draw(it))));
addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
renderscene();
}
}
- if(autocvar_hud_damage && !getstati(STAT_FROZEN))
+ if(autocvar_hud_damage && !STAT(FROZEN))
{
splash_size.x = max(vid_conwidth, vid_conheight);
splash_size.y = max(vid_conwidth, vid_conheight);
}
// edge detection postprocess handling done second (used by hud_powerup)
- float sharpen_intensity = 0, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
+ float sharpen_intensity = 0, strength_finished = STAT(STRENGTH_FINISHED), invincible_finished = STAT(INVINCIBLE_FINISHED);
if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
} else */
// draw 2D entities
- for (entity e = NULL; (e = nextent(e)); ) if (e.draw2d) {
- WITH(entity, self, e, e.draw2d(e));
- }
+ FOREACH_ENTITY(it.draw2d, LAMBDA(WITH(entity, self, it, it.draw2d(it))));
Draw_ShowNames_All();
Debug_Draw();
}
}
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(self);
self.saved = self.(fld);
int f;
var .vector fld;
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
self.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
if(self.bgmscriptangular)
return = true;
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
self.saved = self.(fld);
#include "../../common/constants.qh"
#include "../../common/movetypes/movetypes.qh"
-#include "../../common/nades/all.qh"
#include "../../lib/csqcmodel/interpolate.qh"
}
}
+bool Projectile_isnade(int proj); // TODO: remove
+
void Projectile_Draw(entity this)
{
vector rot;
{
// self.move_flags &= ~FL_ONGROUND;
if (self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(self);
// the trivial movetypes do not have to match the
// server's ticrate as they are ticrate independent
// NOTE: this assumption is only true if MOVETYPE_FLY
// projectiles detonate on impact. If they continue
// moving, we might still be ticrate dependent.
else
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
if (!(self.move_flags & FL_ONGROUND))
if (self.velocity != '0 0 0')
self.move_angles = self.angles = vectoangles(self.velocity);
}
else
{
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(self);
}
if (self.count & 0x80)
break;
}
- if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
+ if (Projectile_isnade(self.cnt))
rot = self.avelocity;
self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
break;
}
- if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
+ if (Projectile_isnade(self.cnt))
trailorigin += v_up * 4;
if (drawn)
}
if (!(self.count & 0x80))
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
if (f & 1)
{
HANDLE(HOOKBOMB) self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
HANDLE(HAGAR) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
HANDLE(HAGAR_BOUNCING) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
- HANDLE(NAPALM_FOUNTAIN) // fallthrough // sself.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
HANDLE(FIREBALL) self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
HANDLE(FIREMINE) self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
HANDLE(TAG) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
if (MUTATOR_CALLHOOK(Ent_Projectile, self))
break;
- if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
- {
- setmodel(self, MDL_PROJECTILE_NADE);
- entity trail = Nade_TrailEffect(self.cnt, self.team);
- if (trail.eent_eff_name) self.traileffect = trail.m_id;
- break;
- }
error("Received invalid CSQC projectile, can't work with this!");
break;
}
self.move_movetype = MOVETYPE_BOUNCE;
self.move_touch = func_null;
break;
- case PROJECTILE_NAPALM_FOUNTAIN:
case PROJECTILE_FIREBALL:
loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY2), VOL_BASE, ATTEN_NORM);
self.mins = '-16 -16 -16';
break;
}
- if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
- {
- entity nade_type = Nade_FromProjectile(self.cnt);
- self.mins = '-16 -16 -16';
- self.maxs = '16 16 16';
- self.colormod = nade_type.m_color;
- self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = func_null;
- self.scale = 1.5;
- self.avelocity = randomvec() * 720;
-
- if (nade_type == NADE_TYPE_TRANSLOCATE || nade_type == NADE_TYPE_SPAWN)
- self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
- else
- self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
- }
-
MUTATOR_CALLHOOK(EditProjectile, self);
setsize(self, self.mins, self.maxs);
}
if (!(self.count & 0x80))
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
self.classname = "csqcprojectile";
self.draw = Projectile_Draw;
+++ /dev/null
-REGISTER_BUFF(AMMO) {
- this.m_prettyName = _("Ammo");
- this.m_name = "ammo";
- this.m_skin = 3;
- this.m_color = '0.76 1 0.1';
-}
-BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen, BUFF_AMMO)
-
-REGISTER_BUFF(RESISTANCE) {
- this.m_prettyName = _("Resistance");
- this.m_name = "resistance";
- this.m_skin = 0;
- this.m_color = '0.36 1 0.07';
-}
-BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
-
-REGISTER_BUFF(SPEED) {
- this.m_prettyName = _("Speed");
- this.m_name = "speed";
- this.m_skin = 9;
- this.m_color = '0.1 1 0.84';
-}
-BUFF_SPAWNFUNCS(speed, BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
-
-REGISTER_BUFF(MEDIC) {
- this.m_prettyName = _("Medic");
- this.m_name = "medic";
- this.m_skin = 1;
- this.m_color = '1 0.12 0';
-}
-BUFF_SPAWNFUNCS(medic, BUFF_MEDIC)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_MEDIC)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(medic, BUFF_MEDIC)
-
-REGISTER_BUFF(BASH) {
- this.m_prettyName = _("Bash");
- this.m_name = "bash";
- this.m_skin = 5;
- this.m_color = '1 0.39 0';
-}
-BUFF_SPAWNFUNCS(bash, BUFF_BASH)
-
-REGISTER_BUFF(VAMPIRE) {
- this.m_prettyName = _("Vampire");
- this.m_name = "vampire";
- this.m_skin = 2;
- this.m_color = '1 0 0.24';
-}
-BUFF_SPAWNFUNCS(vampire, BUFF_VAMPIRE)
-
-REGISTER_BUFF(DISABILITY) {
- this.m_prettyName = _("Disability");
- this.m_name = "disability";
- this.m_skin = 7;
- this.m_color = '0.94 0.3 1';
-}
-BUFF_SPAWNFUNCS(disability, BUFF_DISABILITY)
-
-REGISTER_BUFF(VENGEANCE) {
- this.m_prettyName = _("Vengeance");
- this.m_name = "vengeance";
- this.m_skin = 15;
- this.m_color = '1 0.23 0.61';
-}
-BUFF_SPAWNFUNCS(vengeance, BUFF_VENGEANCE)
-
-REGISTER_BUFF(JUMP) {
- this.m_prettyName = _("Jump");
- this.m_name = "jump";
- this.m_skin = 10;
- this.m_color = '0.24 0.78 1';
-}
-BUFF_SPAWNFUNCS(jump, BUFF_JUMP)
-
-REGISTER_BUFF(FLIGHT) {
- this.m_prettyName = _("Flight");
- this.m_name = "flight";
- this.m_skin = 11;
- this.m_color = '0.33 0.56 1';
-}
-BUFF_SPAWNFUNCS(flight, BUFF_FLIGHT)
-
-REGISTER_BUFF(INVISIBLE) {
- this.m_prettyName = _("Invisible");
- this.m_name = "invisible";
- this.m_skin = 12;
- this.m_color = '0.5 0.5 1';
-}
-BUFF_SPAWNFUNCS(invisible, BUFF_INVISIBLE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(invis, BUFF_INVISIBLE)
-
-REGISTER_BUFF(INFERNO) {
- this.m_prettyName = _("Inferno");
- this.m_name = "inferno";
- this.m_skin = 16;
- this.m_color = '1 0.62 0';
-}
-BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
-
-REGISTER_BUFF(SWAPPER) {
- this.m_prettyName = _("Swapper");
- this.m_name = "swapper";
- this.m_skin = 17;
- this.m_color = '0.63 0.36 1';
-}
-BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
-
-REGISTER_BUFF(MAGNET) {
- this.m_prettyName = _("Magnet");
- this.m_name = "magnet";
- this.m_skin = 18;
- this.m_color = '1 0.95 0.18';
-}
-BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
+++ /dev/null
-#if defined(CSQC)
- #include "../../client/defs.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-#include "all.qh"
-
+++ /dev/null
-#ifndef BUFFS_ALL_H
-#define BUFFS_ALL_H
-// Welcome to the stuff behind the scenes
-// Below, you will find the list of buffs
-// Add new buffs here!
-// Note: Buffs also need spawnfuncs, which are set below
-
-#include "../teams.qh"
-#include "../util.qh"
-
-REGISTRY(Buffs, BITS(4))
-#define Buffs_from(i) _Buffs_from(i, BUFF_Null)
-REGISTER_REGISTRY(RegisterBuffs)
-REGISTRY_CHECK(Buffs)
-
-#define REGISTER_BUFF(id) \
- REGISTER(RegisterBuffs, BUFF, Buffs, id, m_id, NEW(Buff)); \
- REGISTER_INIT_POST(BUFF, id) { \
- this.netname = this.m_name; \
- this.m_itemid = BIT(this.m_id - 1); \
- this.m_sprite = strzone(strcat("buff-", this.m_name)); \
- } \
- REGISTER_INIT(BUFF, id)
-
-#include "../items/item/pickup.qh"
-CLASS(Buff, Pickup)
- /** bit index */
- ATTRIB(Buff, m_itemid, int, 0)
- ATTRIB(Buff, m_name, string, "buff")
- ATTRIB(Buff, m_color, vector, '1 1 1')
- ATTRIB(Buff, m_prettyName, string, "Buff")
- ATTRIB(Buff, m_skin, int, 0)
- ATTRIB(Buff, m_sprite, string, "")
- METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
- returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
- }
-#ifdef SVQC
- METHOD(Buff, m_time, float(entity));
- float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
-#endif
-ENDCLASS(Buff)
-
-#ifdef SVQC
- .int buffs;
- void buff_Init(entity ent);
- void buff_Init_Compat(entity ent, entity replacement);
- #define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
- self.buffs = b.m_itemid; \
- self.team = t; \
- buff_Init(self); \
- }
- #define BUFF_SPAWNFUNCS(e, b) \
- BUFF_SPAWNFUNC(e, b, 0) \
- BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
- BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
- BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
- BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
- #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) spawnfunc(item_##o) { buff_Init_Compat(self, r); }
-#else
- #define BUFF_SPAWNFUNC(e, b, t)
- #define BUFF_SPAWNFUNCS(e, b)
- #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r)
-#endif
-
-REGISTER_BUFF(Null);
-BUFF_SPAWNFUNCS(random, BUFF_Null)
-
-#include "all.inc"
-
-#endif
#include "command.qh"
REGISTRY(GENERIC_COMMANDS, BITS(7))
#define GENERIC_COMMANDS_from(i) _GENERIC_COMMANDS_from(i, NULL)
-REGISTER_REGISTRY(RegisterGENERIC_COMMANDS)
-REGISTRY_SORT(GENERIC_COMMANDS, 0)
+REGISTER_REGISTRY(GENERIC_COMMANDS)
+REGISTRY_SORT(GENERIC_COMMANDS)
#define GENERIC_COMMAND(id, description) \
CLASS(genericcommand_##id, Command) \
ATTRIB(genericcommand_##id, m_name, string, #id); \
ATTRIB(genericcommand_##id, m_description, string, description); \
ENDCLASS(genericcommand_##id) \
- REGISTER(RegisterGENERIC_COMMANDS, CMD_G, GENERIC_COMMANDS, id, m_id, NEW(genericcommand_##id)); \
+ REGISTER(GENERIC_COMMANDS, CMD_G, id, m_id, NEW(genericcommand_##id)); \
METHOD(genericcommand_##id, m_invokecmd, void(int request, int arguments, string command))
STATIC_INIT(GENERIC_COMMANDS_aliases) {
// Revision 22: hook shot origin
#define CSQC_REVISION 22
-const int AS_STRING = 1;
-const int AS_INT = 2;
-const int AS_FLOAT_TRUNCATED = 2;
-const int AS_FLOAT = 8;
-
REGISTER_NET_TEMP(TE_CSQC_PICTURE)
REGISTER_NET_TEMP(TE_CSQC_RACE)
REGISTER_NET_TEMP(TE_CSQC_TEAMNAGGER)
/** Sent as a temp entity from a persistent linked entity */
REGISTER_NET_TEMP(ENT_CLIENT_INIT)
-REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO)
REGISTER_NET_LINKED(ENT_CLIENT_SCORES)
REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES)
///////////////////////////
// csqc communication stuff
-const int CTF_STATE_ATTACK = 1;
-const int CTF_STATE_DEFEND = 2;
-const int CTF_STATE_COMMANDER = 3;
-
const int HUD_NORMAL = 0;
const int HUD_BUMBLEBEE_GUN = 25;
const int SP_DMGTAKEN = 11;
// game mode specific indices are not in common/, but in server/scores_rules.qc!
-const int CH_INFO = 0;
-const int CH_TRIGGER = -3;
-const int CH_WEAPON_A = -1;
-const int CH_WEAPON_SINGLE = 1;
-const int CH_VOICE = -2;
-const int CH_BGM_SINGLE = 8;
-const int CH_AMBIENT = -9;
-const int CH_TRIGGER_SINGLE = 3;
-const int CH_SHOTS = -4;
-const int CH_SHOTS_SINGLE = 4;
-const int CH_WEAPON_B = -1;
-const int CH_PAIN = -6;
-const int CH_PAIN_SINGLE = 6;
-const int CH_PLAYER = -7;
-const int CH_PLAYER_SINGLE = 7;
-const int CH_TUBA_SINGLE = 5;
-
-const float ATTEN_NONE = 0;
-const float ATTEN_MIN = 0.015625;
-const float ATTEN_NORM = 0.5;
-const float ATTEN_LARGE = 1;
-const float ATTEN_IDLE = 2;
-const float ATTEN_STATIC = 3;
-const float ATTEN_MAX = 3.984375;
-
-const float VOL_BASE = 0.7;
-const float VOL_BASEVOICE = 1.0;
-
// WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc
const int PROJECTILE_ELECTRO = 1;
const int PROJECTILE_ROCKET = 2;
// not so constant
-#ifdef SVQC
-#define PL_VIEW_OFS autocvar_sv_player_viewoffset
-#define PL_MIN autocvar_sv_player_mins
-#define PL_MAX autocvar_sv_player_maxs
-#define PL_CROUCH_VIEW_OFS autocvar_sv_player_crouch_viewoffset
-#define PL_CROUCH_MIN autocvar_sv_player_crouch_mins
-#define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs
-#define PL_HEAD autocvar_sv_player_headsize
-#elif defined(CSQC)
-#define PL_VIEW_OFS vec3(getstatf(STAT_PL_VIEW_OFS1), getstatf(STAT_PL_VIEW_OFS2), getstatf(STAT_PL_VIEW_OFS3))
-#define PL_MIN vec3(getstatf(STAT_PL_MIN1), getstatf(STAT_PL_MIN2), getstatf(STAT_PL_MIN3))
-#define PL_MAX vec3(getstatf(STAT_PL_MAX1), getstatf(STAT_PL_MAX2), getstatf(STAT_PL_MAX3))
-#define PL_CROUCH_VIEW_OFS vec3(getstatf(STAT_PL_CROUCH_VIEW_OFS1), getstatf(STAT_PL_CROUCH_VIEW_OFS2), getstatf(STAT_PL_CROUCH_VIEW_OFS3))
-#define PL_CROUCH_MIN vec3(getstatf(STAT_PL_CROUCH_MIN1), getstatf(STAT_PL_CROUCH_MIN2), getstatf(STAT_PL_CROUCH_MIN3))
-#define PL_CROUCH_MAX vec3(getstatf(STAT_PL_CROUCH_MAX1), getstatf(STAT_PL_CROUCH_MAX2), getstatf(STAT_PL_CROUCH_MAX3))
-#endif
+#define PL_VIEW_OFS STAT(PL_VIEW_OFS, NULL)
+#define PL_CROUCH_VIEW_OFS STAT(PL_CROUCH_VIEW_OFS, NULL)
+#define PL_MIN STAT(PL_MIN, NULL)
+#define PL_CROUCH_MIN STAT(PL_CROUCH_MIN, NULL)
+#define PL_MAX STAT(PL_MAX, NULL)
+#define PL_CROUCH_MAX STAT(PL_CROUCH_MAX, NULL)
// a bit more constant
const vector PL_MAX_CONST = '16 16 45';
# define TAG_VIEWLOC_NAME tag_networkviewloc
# define TAG_VIEWLOC_TYPE int
.float tag_networkviewloc;
+
+# define MOVETYPE_NAME move_movetype
#else
# define TAG_ENTITY_NAME tag_entity
# define TAG_ENTITY_TYPE entity
# define TAG_VIEWLOC_NAME viewloc
# define TAG_VIEWLOC_TYPE entity
+
+# define MOVETYPE_NAME movetype
#endif
// new fields
CSQCMODEL_PROPERTY(BIT(11), int, ReadByte, WriteByte, traileffect) \
CSQCMODEL_PROPERTY_SCALED(BIT(12), float, ReadByte, WriteByte, scale, 16, 0, 255) \
CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
- CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME)
+ CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
+ CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count) \
+ CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, MOVETYPE_NAME)
// TODO get rid of colormod/glowmod here, find good solution for vortex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
// add hook function calls here
CSQCModel_Hook_PostUpdate(isnew, isplayer, islocalplayer);
#define CSQCMODEL_HOOK_PREDRAW \
CSQCModel_Hook_PreDraw(isplayer);
-#define CSQCPLAYER_HOOK_POSTCAMERASETUP \
- CSQCPlayer_SetViewLocation();
+#define CSQCPLAYER_HOOK_POSTCAMERASETUP() \
+ CSQCPlayer_SetViewLocation()
// force updates of player entities that often even if unchanged
#ifndef CSQCPLAYER_FORCE_UPDATES
REGISTRY(Deathtypes, BITS(8))
#define Deathtypes_from(i) _Deathtypes_from(i, NULL)
-REGISTER_REGISTRY(RegisterDeathtypes)
+REGISTER_REGISTRY(Deathtypes)
REGISTRY_CHECK(Deathtypes)
.entity death_msgself;
.string death_msgextra;
#define REGISTER_DEATHTYPE(id, msg_death, msg_death_by, extra) \
- REGISTER(RegisterDeathtypes, DEATH, Deathtypes, id, m_id, new(deathtype)) { \
+ REGISTER(Deathtypes, DEATH, id, m_id, new(deathtype)) { \
make_pure(this); \
this.m_id += DT_FIRST; \
this.nent_name = #id; \
static int debugdraw_frame;
++debugdraw_frame;
const int size = 8;
- for (entity e1 = NULL; (e1 = nextent(e1)); )
- {
- if (e1.debugdraw_last == debugdraw_frame) continue;
+ FOREACH_ENTITY(true, LAMBDA(
+ if (it.debugdraw_last == debugdraw_frame) continue;
int ofs = 0;
- for (entity e = findradius(e1.origin, 100); e; e = e.chain)
+ for (entity e = findradius(it.origin, 100); e; e = e.chain)
{
if (e.debugdraw_last == debugdraw_frame) continue;
e.debugdraw_last = debugdraw_frame;
size * '1 1 0', rgb, 0.5, DRAWFLAG_NORMAL);
++ofs;
}
- }
+ ));
}
#endif
EFFECT(0, SPAWNPOINT_NEUTRAL, "spawn_point_neutral")
EFFECT(0, SPAWN_NEUTRAL, "spawn_event_neutral")
-EFFECT(0, NADE_EXPLODE_RED, "nade_red_explode")
-EFFECT(0, NADE_EXPLODE_BLUE, "nade_blue_explode")
-EFFECT(0, NADE_EXPLODE_YELLOW, "nade_yellow_explode")
-EFFECT(0, NADE_EXPLODE_PINK, "nade_pink_explode")
-EFFECT(0, NADE_EXPLODE_NEUTRAL, "nade_neutral_explode")
-entity EFFECT_NADE_EXPLODE(int teamid)
-{
- switch (teamid) {
- case NUM_TEAM_1: return EFFECT_NADE_EXPLODE_RED;
- case NUM_TEAM_2: return EFFECT_NADE_EXPLODE_BLUE;
- case NUM_TEAM_3: return EFFECT_NADE_EXPLODE_YELLOW;
- case NUM_TEAM_4: return EFFECT_NADE_EXPLODE_PINK;
- default: return EFFECT_NADE_EXPLODE_NEUTRAL;
- }
-}
-
-EFFECT(1, NADE_TRAIL_RED, "nade_red")
-EFFECT(1, NADE_TRAIL_BLUE, "nade_blue")
-EFFECT(1, NADE_TRAIL_YELLOW, "nade_yellow")
-EFFECT(1, NADE_TRAIL_PINK, "nade_pink")
-EFFECT(1, NADE_TRAIL_NEUTRAL, "nade_neutral")
-entity EFFECT_NADE_TRAIL(int teamid)
-{
- switch (teamid) {
- case NUM_TEAM_1: return EFFECT_NADE_TRAIL_RED;
- case NUM_TEAM_2: return EFFECT_NADE_TRAIL_BLUE;
- case NUM_TEAM_3: return EFFECT_NADE_TRAIL_YELLOW;
- case NUM_TEAM_4: return EFFECT_NADE_TRAIL_PINK;
- default: return EFFECT_NADE_TRAIL_NEUTRAL;
- }
-}
-
-EFFECT(1, NADE_TRAIL_BURN_RED, "nade_red_burn")
-EFFECT(1, NADE_TRAIL_BURN_BLUE, "nade_blue_burn")
-EFFECT(1, NADE_TRAIL_BURN_YELLOW, "nade_yellow_burn")
-EFFECT(1, NADE_TRAIL_BURN_PINK, "nade_pink_burn")
-EFFECT(1, NADE_TRAIL_BURN_NEUTRAL, "nade_neutral_burn")
-entity EFFECT_NADE_TRAIL_BURN(int teamid)
-{
- switch (teamid) {
- case NUM_TEAM_1: return EFFECT_NADE_TRAIL_BURN_RED;
- case NUM_TEAM_2: return EFFECT_NADE_TRAIL_BURN_BLUE;
- case NUM_TEAM_3: return EFFECT_NADE_TRAIL_BURN_YELLOW;
- case NUM_TEAM_4: return EFFECT_NADE_TRAIL_BURN_PINK;
- default: return EFFECT_NADE_TRAIL_BURN_NEUTRAL;
- }
-}
-
EFFECT(0, ICEORGLASS, "iceorglass")
EFFECT(0, ICEFIELD, "icefield")
EFFECT(0, FIREFIELD, "firefield")
REGISTRY(Effects, BITS(8))
#define Effects_from(i) _Effects_from(i, EFFECT_Null)
-REGISTER_REGISTRY(RegisterEffects)
+REGISTER_REGISTRY(Effects)
REGISTRY_CHECK(Effects)
#define EFFECT(istrail, name, realname) \
- REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail));
+ REGISTER(Effects, EFFECT, name, m_id, Create_Effect_Entity(realname, istrail));
EFFECT(0, Null, string_null)
#include "all.inc"
REGISTRY(EffectInfos, BITS(9))
#define EffectInfos_from(i) _EffectInfos_from(i, NULL)
-REGISTER_REGISTRY(RegisterEffectInfos)
+REGISTER_REGISTRY(EffectInfos)
#define EFFECTINFO(name) \
[[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { } \
- REGISTER(RegisterEffectInfos, EFFECTINFO, EffectInfos, name, m_id, NEW(EffectInfoGroup)) { \
+ REGISTER(EffectInfos, EFFECTINFO, name, m_id, NEW(EffectInfoGroup)) { \
effectinfo_##name(this, NULL); \
}
#include "casings.qc"
#include "damageeffects.qc"
#include "gibs.qc"
+#include "globalsound.qc"
#include "lightningarc.qc"
#include "modeleffects.qc"
self.flags &= ~FL_ONGROUND;
}
- Movetype_Physics_MatchTicrate(autocvar_cl_casings_ticrate, autocvar_cl_casings_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_casings_ticrate, autocvar_cl_casings_sloppy);
if (wasfreed(self))
return; // deleted by touch function
#ifdef CSQC
#include "../../deathtypes/all.qh"
#include "../../movetypes/movetypes.qh"
+#include "../../../client/mutators/events.qh"
#include "../../vehicles/all.qh"
#include "../../weapons/all.qh"
#endif
w_backoff = -1 * normalize(force);
setorigin(self, w_org + w_backoff * 2); // for sound() calls
- if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) {
- hitwep.wr_impacteffect(hitwep);
+ if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
+ {
+ if(!MUTATOR_CALLHOOK(Weapon_ImpactEffect, hitwep))
+ hitwep.wr_impacteffect(hitwep);
}
}
}
vector oldorg;
oldorg = self.origin;
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
if(wasfreed(self))
return;
--- /dev/null
+#include "globalsound.qh"
+
+#include "../common/ent_cs.qh"
+
+#ifdef IMPLEMENTATION
+ #include "../../animdecide.qh"
+
+ #ifdef SVQC
+ #include "../../../server/cl_player.qh"
+ #endif
+
+ REGISTER_NET_TEMP(globalsound)
+ REGISTER_NET_TEMP(playersound)
+
+ #ifdef SVQC
+ /**
+ * @param from the source entity, its position is sent
+ * @param gs the global sound def
+ * @param r a random number in 0..1
+ */
+ void globalsound(int channel, entity from, entity gs, float r, int chan, float vol, float atten)
+ {
+ if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
+ WriteHeader(channel, globalsound);
+ WriteByte(channel, gs.m_id);
+ WriteByte(channel, r * 255);
+ WriteByte(channel, etof(from));
+ WriteByte(channel, fabs(chan));
+ WriteByte(channel, floor(vol * 255));
+ WriteByte(channel, floor(atten * 64));
+ entcs_force_origin(from);
+ vector o = from.origin + 0.5 * (from.mins + from.maxs);
+ WriteCoord(channel, o.x);
+ WriteCoord(channel, o.y);
+ WriteCoord(channel, o.z);
+ }
+
+ /**
+ * @param from the source entity, its position is sent
+ * @param ps the player sound def
+ * @param r a random number in 0..1
+ */
+ void playersound(int channel, entity from, entity ps, float r, int chan, float vol, float atten)
+ {
+ if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
+ WriteHeader(channel, playersound);
+ WriteByte(channel, ps.m_id);
+ WriteByte(channel, r * 255);
+ WriteByte(channel, etof(from));
+ WriteByte(channel, fabs(chan));
+ WriteByte(channel, floor(vol * 255));
+ WriteByte(channel, floor(atten * 64));
+ entcs_force_origin(from);
+ vector o = from.origin + 0.5 * (from.mins + from.maxs);
+ WriteCoord(channel, o.x);
+ WriteCoord(channel, o.y);
+ WriteCoord(channel, o.z);
+ }
+ #endif
+
+ string GlobalSound_sample(string pair, float r);
+
+ #ifdef CSQC
+
+ NET_HANDLE(globalsound, bool isnew)
+ {
+ entity gs = GlobalSounds_from(ReadByte());
+ float r = ReadByte() / 255;
+ string sample = GlobalSound_sample(gs.m_globalsoundstr, r);
+ int who = ReadByte();
+ entity e = entcs_receiver(who - 1);
+ int chan = ReadByte();
+ float vol = ReadByte() / 255;
+ float atten = ReadByte() / 64;
+ vector o;
+ o.x = ReadCoord();
+ o.y = ReadCoord();
+ o.z = ReadCoord();
+ // TODO: is this really what we want to be doing? Footsteps that follow the player at head height?
+ if (who == player_currententnum) e = findfloat(world, entnum, who); // play at camera position for full volume
+ else if (e) e.origin = o;
+ if (e)
+ {
+ sound7(e, chan, sample, vol, atten, 0, 0);
+ }
+ else
+ {
+ entity e = new(globalsound);
+ e.origin = o;
+ sound8(e, o, chan, sample, vol, atten, 0, 0);
+ remove(e); // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
+ }
+ return true;
+ }
+
+ NET_HANDLE(playersound, bool isnew)
+ {
+ entity ps = PlayerSounds_from(ReadByte());
+ float r = ReadByte() / 255;
+ int who = ReadByte();
+ entity e = entcs_receiver(who - 1);
+ UpdatePlayerSounds(e);
+ string s = e.(ps.m_playersoundfld);
+ string sample = GlobalSound_sample(s, r);
+ int chan = ReadByte();
+ float vol = ReadByte() / 255;
+ float atten = ReadByte() / 64;
+ vector o;
+ o.x = ReadCoord();
+ o.y = ReadCoord();
+ o.z = ReadCoord();
+ if (who == player_currententnum) e = findfloat(world, entnum, who); // play at camera position for full volume
+ else if (e) e.origin = o;
+ if (e)
+ {
+ // TODO: for non-visible players, origin should probably continue to be updated as long as the sound is playing
+ sound7(e, chan, sample, vol, atten, 0, 0);
+ }
+ else
+ {
+ LOG_WARNINGF("Missing entcs data for player %d\n", who);
+ // Can this happen?
+ entity e = new(playersound);
+ e.origin = o;
+ sound8(e, o, chan, sample, vol, atten, 0, 0);
+ remove(e); // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
+ }
+ return true;
+ }
+
+ #endif
+
+ string GlobalSound_sample(string pair, float r)
+ {
+ int n;
+ {
+ string s = cdr(pair);
+ if (s) n = stof(s);
+ else n = 0;
+ }
+ string sample = car(pair);
+ if (n > 0) sample = sprintf("%s%d.wav", sample, floor(r * n + 1)); // randomization
+ else sample = sprintf("%s.wav", sample);
+ return sample;
+ }
+
+ void PrecacheGlobalSound(string sample)
+ {
+ int n;
+ {
+ string s = cdr(sample);
+ if (s) n = stof(s);
+ else n = 0;
+ }
+ sample = car(sample);
+ if (n > 0)
+ {
+ for (int i = 1; i <= n; ++i)
+ precache_sound(sprintf("%s%d.wav", sample, i));
+ }
+ else
+ {
+ precache_sound(sprintf("%s.wav", sample));
+ }
+ }
+
+ entity GetVoiceMessage(string type)
+ {
+ FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == true, LAMBDA(return it));
+ return NULL;
+ }
+
+ entity GetPlayerSound(string type)
+ {
+ FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == false, LAMBDA(return it));
+ return NULL;
+ }
+
+ string allvoicesamples;
+ STATIC_INIT(allvoicesamples)
+ {
+ FOREACH(PlayerSounds, it.instanceOfVoiceMessage, LAMBDA(
+ allvoicesamples = strcat(allvoicesamples, " ", it.m_playersoundstr)
+ ));
+ allvoicesamples = strzone(substring(allvoicesamples, 1, -1));
+ }
+
+ .string _GetPlayerSoundSampleField(string type, bool voice)
+ {
+ GetPlayerSoundSampleField_notFound = false;
+ entity e = voice ? GetVoiceMessage(type) : GetPlayerSound(type);
+ if (e) return e.m_playersoundfld;
+ GetPlayerSoundSampleField_notFound = true;
+ return playersound_taunt.m_playersoundfld;
+ }
+
+ .string GetVoiceMessageSampleField(string type)
+ {
+ return _GetPlayerSoundSampleField(type, true);
+ }
+
+ void PrecachePlayerSounds(string f)
+ {
+ int fh = fopen(f, FILE_READ);
+ if (fh < 0)
+ {
+ LOG_WARNINGF("Player sound file not found: %s\n", f);
+ return;
+ }
+ for (string s; (s = fgets(fh)); )
+ {
+ int n = tokenize_console(s);
+ if (n != 3)
+ {
+ if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
+ continue;
+ }
+ string file = argv(1);
+ string variants = argv(2);
+ PrecacheGlobalSound(strcat(file, " ", variants));
+ }
+ fclose(fh);
+ }
+
+ #ifdef CSQC
+
+ .string GetPlayerSoundSampleField(string type)
+ {
+ return _GetPlayerSoundSampleField(type, false);
+ }
+
+ void ClearPlayerSounds(entity this)
+ {
+ FOREACH(PlayerSounds, true, LAMBDA(
+ .string fld = it.m_playersoundfld;
+ if (this.(fld))
+ {
+ strunzone(this.(fld));
+ this.(fld) = string_null;
+ }
+ ));
+ }
+
+ bool LoadPlayerSounds(entity this, string f, bool strict)
+ {
+ int fh = fopen(f, FILE_READ);
+ if (fh < 0)
+ {
+ if (strict) LOG_WARNINGF("Player sound file not found: %s\n", f);
+ return false;
+ }
+ for (string s; (s = fgets(fh)); )
+ {
+ int n = tokenize_console(s);
+ if (n != 3)
+ {
+ if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
+ continue;
+ }
+ string key = argv(0);
+ var.string field = GetPlayerSoundSampleField(key);
+ if (GetPlayerSoundSampleField_notFound) field = GetVoiceMessageSampleField(key);
+ if (GetPlayerSoundSampleField_notFound)
+ {
+ LOG_TRACEF("Invalid sound info field: %s\n", key);
+ continue;
+ }
+ string file = argv(1);
+ string variants = argv(2);
+ if (this.(field)) strunzone(this.(field));
+ this.(field) = strzone(strcat(file, " ", variants));
+ }
+ fclose(fh);
+ return true;
+ }
+
+ .string model_for_playersound;
+ .int skin_for_playersound;
+
+ bool autocvar_g_debug_defaultsounds;
+
+ void UpdatePlayerSounds(entity this)
+ {
+ if (this.model == this.model_for_playersound && this.skin == this.skin_for_playersound) return;
+ if (this.model_for_playersound) strunzone(this.model_for_playersound);
+ this.model_for_playersound = strzone(this.model);
+ this.skin_for_playersound = this.skin;
+ ClearPlayerSounds(this);
+ LoadPlayerSounds(this, "sound/player/default.sounds", true);
+ if (this.model == "null" || autocvar_g_debug_defaultsounds) return;
+ if (LoadPlayerSounds(this, get_model_datafilename(this.model, this.skin, "sounds"), false)) return;
+ LoadPlayerSounds(this, get_model_datafilename(this.model, 0, "sounds"), true);
+ }
+
+ #endif
+
+ #ifdef SVQC
+
+ void _GlobalSound(entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
+ {
+ SELFPARAM();
+ if (gs == NULL && ps == NULL && sample == "") return;
+ float r = random();
+ if (sample != "") sample = GlobalSound_sample(sample, r);
+ switch (voicetype)
+ {
+ case VOICETYPE_LASTATTACKER_ONLY:
+ case VOICETYPE_LASTATTACKER:
+ {
+ if (!fake)
+ {
+ if (!this.pusher) break;
+ msg_entity = this.pusher;
+ if (IS_REAL_CLIENT(msg_entity))
+ {
+ float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE;
+ if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten);
+ else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten);
+ else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten);
+ }
+ }
+ if (voicetype == VOICETYPE_LASTATTACKER_ONLY) break;
+ msg_entity = this;
+ if (IS_REAL_CLIENT(msg_entity))
+ {
+ if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NONE);
+ else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASE, ATTEN_NONE);
+ else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NONE);
+ }
+ break;
+ }
+ case VOICETYPE_TEAMRADIO:
+ {
+ #define X() \
+ do \
+ { \
+ float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \
+ if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \
+ else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten); \
+ else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
+ } \
+ while (0)
+
+ if (fake) { msg_entity = this; X(); }
+ else
+ {
+ FOR_EACH_REALCLIENT(msg_entity)
+ {
+ if (!teamplay || msg_entity.team == this.team) X();
+ }
+ }
+ #undef X
+ break;
+ }
+ case VOICETYPE_AUTOTAUNT:
+ case VOICETYPE_TAUNT:
+ {
+ if (voicetype == VOICETYPE_AUTOTAUNT) if (!sv_autotaunt) { break; }else {}
+ else if (IS_PLAYER(this) && this.deadflag == DEAD_NO) animdecide_setaction(this, ANIMACTION_TAUNT,
+ true);
+ if (!sv_taunt) break;
+ if (autocvar_sv_gentle) break;
+ float tauntrand = 0;
+ if (voicetype == VOICETYPE_AUTOTAUNT) tauntrand = random();
+ #define X() \
+ do \
+ { \
+ if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < msg_entity.cvar_cl_autotaunt) \
+ { \
+ float atten = (msg_entity.cvar_cl_voice_directional >= 1) \
+ ? bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, \
+ ATTEN_MAX) \
+ : ATTEN_NONE; \
+ if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \
+ else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten); \
+ else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
+ } \
+ } \
+ while (0)
+ if (fake)
+ {
+ msg_entity = this;
+ X();
+ }
+ else
+ {
+ FOR_EACH_REALCLIENT(msg_entity)
+ {
+ X();
+ }
+ }
+ #undef X
+ break;
+ }
+ case VOICETYPE_PLAYERSOUND:
+ {
+ msg_entity = this;
+ if (fake)
+ {
+ if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+ else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
+ else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NORM);
+ }
+ else
+ {
+ if (gs) globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+ else if (ps) playersound(MSG_ALL, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
+ else _sound(this, chan, sample, VOL_BASE, ATTEN_NORM);
+ }
+ break;
+ }
+ default:
+ {
+ backtrace("Invalid voice type!");
+ break;
+ }
+ }
+ }
+
+ #endif
+#endif
--- /dev/null
+#ifndef GLOBALSOUND_H
+#define GLOBALSOUND_H
+
+// player sounds, voice messages
+
+.string m_playersoundstr;
+..string m_playersoundfld;
+
+REGISTRY(PlayerSounds, BITS(8) - 1)
+#define PlayerSounds_from(i) _PlayerSounds_from(i, NULL)
+#define REGISTER_PLAYERSOUND(id) \
+ .string _playersound_##id; \
+ REGISTER(PlayerSounds, playersound, id, m_id, new(PlayerSound)) \
+ { \
+ make_pure(this); \
+ this.m_playersoundstr = #id; \
+ this.m_playersoundfld = _playersound_##id; \
+ }
+REGISTER_REGISTRY(PlayerSounds)
+REGISTRY_SORT(PlayerSounds)
+STATIC_INIT(PlayerSounds_renumber)
+{
+ FOREACH(PlayerSounds, true, LAMBDA(it.m_id = i));
+}
+REGISTRY_CHECK(PlayerSounds)
+
+// TODO implement fall and falling
+
+REGISTER_PLAYERSOUND(death)
+REGISTER_PLAYERSOUND(drown)
+REGISTER_PLAYERSOUND(fall)
+REGISTER_PLAYERSOUND(falling)
+REGISTER_PLAYERSOUND(gasp)
+REGISTER_PLAYERSOUND(jump)
+REGISTER_PLAYERSOUND(pain100)
+REGISTER_PLAYERSOUND(pain25)
+REGISTER_PLAYERSOUND(pain50)
+REGISTER_PLAYERSOUND(pain75)
+
+.bool instanceOfVoiceMessage;
+.int m_playersoundvt;
+#define REGISTER_VOICEMSG(id, vt) \
+ .string _playersound_##id; \
+ REGISTER(PlayerSounds, playersound, id, m_id, new(VoiceMessage)) \
+ { \
+ make_pure(this); \
+ this.instanceOfVoiceMessage = true; \
+ this.m_playersoundstr = #id; \
+ this.m_playersoundfld = _playersound_##id; \
+ this.m_playersoundvt = vt; \
+ }
+
+const int VOICETYPE_PLAYERSOUND = 10;
+const int VOICETYPE_TEAMRADIO = 11;
+const int VOICETYPE_LASTATTACKER = 12;
+const int VOICETYPE_LASTATTACKER_ONLY = 13;
+const int VOICETYPE_AUTOTAUNT = 14;
+const int VOICETYPE_TAUNT = 15;
+
+REGISTER_VOICEMSG(attack, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(attackinfive, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(coverme, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(defend, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(freelance, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(incoming, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(meet, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(needhelp, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(seenflag, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(taunt, VOICETYPE_TAUNT)
+REGISTER_VOICEMSG(teamshoot, VOICETYPE_LASTATTACKER)
+
+// reserved sound names for the future (some models lack sounds for them):
+// _VOICEMSG(flagcarriertakingdamage)
+// _VOICEMSG(getflag)
+// reserved sound names for the future (ALL models lack sounds for them):
+// _VOICEMSG(affirmative)
+// _VOICEMSG(attacking)
+// _VOICEMSG(defending)
+// _VOICEMSG(roaming)
+// _VOICEMSG(onmyway)
+// _VOICEMSG(droppedflag)
+// _VOICEMSG(negative)
+// _VOICEMSG(seenenemy)
+
+.string m_globalsoundstr;
+REGISTRY(GlobalSounds, BITS(8) - 1)
+#define GlobalSounds_from(i) _GlobalSounds_from(i, NULL)
+#define REGISTER_GLOBALSOUND(id, str) \
+ REGISTER(GlobalSounds, GS, id, m_id, new(GlobalSound)) \
+ { \
+ make_pure(this); \
+ this.m_globalsoundstr = str; \
+ }
+REGISTER_REGISTRY(GlobalSounds)
+REGISTRY_SORT(GlobalSounds)
+STATIC_INIT(GlobalSounds_renumber)
+{
+ FOREACH(GlobalSounds, true, LAMBDA(it.m_id = i));
+}
+REGISTRY_CHECK(GlobalSounds)
+void PrecacheGlobalSound(string samplestring);
+PRECACHE(GlobalSounds)
+{
+ FOREACH(GlobalSounds, true, LAMBDA(PrecacheGlobalSound(it.m_globalsoundstr)));
+}
+
+REGISTER_GLOBALSOUND(STEP, "misc/footstep0 6")
+REGISTER_GLOBALSOUND(STEP_METAL, "misc/metalfootstep0 6")
+REGISTER_GLOBALSOUND(FALL, "misc/hitground 4")
+REGISTER_GLOBALSOUND(FALL_METAL, "misc/metalhitground 4")
+
+bool GetPlayerSoundSampleField_notFound;
+void PrecachePlayerSounds(string f);
+#ifdef CSQC
+ .string GetVoiceMessageSampleField(string type);
+ .string GetPlayerSoundSampleField(string type);
+ void ClearPlayerSounds(entity this);
+ float LoadPlayerSounds(entity this, string f, bool strict);
+ void UpdatePlayerSounds(entity this);
+#endif
+
+#ifdef SVQC
+
+ void _GlobalSound(entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
+ #define GlobalSound(def, chan, voicetype) _GlobalSound(def, NULL, string_null, chan, voicetype, false)
+ #define GlobalSound_string(def, chan, voicetype) _GlobalSound(NULL, NULL, def, chan, voicetype, false)
+ #define PlayerSound(def, chan, voicetype) _GlobalSound(NULL, def, string_null, chan, voicetype, false)
+ #define VoiceMessage(def, msg) \
+ do \
+ { \
+ entity VM = def; \
+ int voicetype = VM.m_playersoundvt; \
+ bool ownteam = (voicetype == VOICETYPE_TEAMRADIO); \
+ int flood = Say(this, ownteam, world, msg, true); \
+ bool fake; \
+ if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true; \
+ else if (flood > 0) fake = false; \
+ else break; \
+ _GlobalSound(NULL, VM, string_null, CH_VOICE, voicetype, fake); \
+ } \
+ while (0)
+
+#endif
+
+#endif
--- /dev/null
+#include "ent_cs.qh"
+
+// #define PROP(public, fld, sv, cl)
+#define ENTCS_NETPROPS(PROP) \
+ PROP(true, sv_entnum, \
+ { WriteByte(MSG_ENTITY, etof(player) - 1); }, \
+ { this.sv_entnum = ReadByte(); }) \
+ \
+ PROP(false, origin, \
+ { WriteShort(MSG_ENTITY, this.origin.x); WriteShort(MSG_ENTITY, this.origin.y); \
+ WriteShort(MSG_ENTITY, this.origin.z); }, \
+ { this.has_sv_origin = true; vector v; v.x = ReadShort(); v.y = ReadShort(); v.z = ReadShort(); setorigin(this, v); }) \
+ \
+ PROP(false, angles_y, \
+ { WriteByte(MSG_ENTITY, this.angles.y / 360 * 256); }, \
+ { vector v = '0 0 0'; v.y = ReadByte() / 256 * 360; this.angles = v; }) \
+ \
+ PROP(false, health, \
+ { WriteByte(MSG_ENTITY, this.health / 10); /* FIXME: use a better scale? */ }, \
+ { this.healthvalue = ReadByte() * 10; }) \
+ \
+ PROP(false, armorvalue, \
+ { WriteByte(MSG_ENTITY, this.armorvalue / 10); /* FIXME: use a better scale? */ }, \
+ { this.armorvalue = ReadByte() * 10; }) \
+ \
+ PROP(true, netname, \
+ { WriteString(MSG_ENTITY, this.netname); }, \
+ { if (this.netname) strunzone(this.netname); this.netname = strzone(ReadString()); }) \
+ \
+ PROP(true, model, \
+ { WriteString(MSG_ENTITY, this.model); }, \
+ { if (this.model) strunzone(this.model); this.model = strzone(ReadString()); }) \
+ \
+ PROP(true, skin, \
+ { WriteByte(MSG_ENTITY, this.skin); }, \
+ { this.skin = ReadByte(); }) \
+ \
+ /**/
+
+#ifdef SVQC
+
+ int ENTCS_PUBLICMASK = 0;
+ STATIC_INIT(ENTCS_PUBLICMASK)
+ {
+ int i = 1;
+ #define X(public, fld, sv, cl) { if (public) ENTCS_PUBLICMASK |= BIT(i); } i += 1;
+ ENTCS_NETPROPS(X);
+ #undef X
+ if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded ENTCS_NETPROPS limit");
+ }
+
+ bool entcs_send(entity this, entity to, int sf)
+ {
+ entity player = this.owner;
+ sf |= BIT(0) | BIT(1);
+ if (IS_PLAYER(to) || to.caplayer) // unless spectating,
+ {
+ bool same_team = (to == player) || (teamplay && player.team == to.team);
+ if (!same_team && !radar_showennemies) sf &= ENTCS_PUBLICMASK; // no private updates
+ }
+ sf |= this.m_forceupdate;
+ this.m_forceupdate = 0;
+ bool valid =
+ IS_PLAYER(player) // player must be active
+ && player.deadflag == DEAD_NO // player must be alive
+ || player == to // player is self
+ ;
+ if (!valid) sf = 0;
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_ENTCS);
+ WriteShort(MSG_ENTITY, sf);
+ int i = 1;
+ #define X(public, fld, sv, cl) { if (sf & BIT(i)) sv; } i += 1;
+ ENTCS_NETPROPS(X);
+ #undef X
+ return true;
+ }
+
+ void entcs_think()
+ {
+ SELFPARAM();
+ this.nextthink = time + 0.033333333333; // TODO: increase this to like 0.15 once the client can do smoothing
+ entity o = this.owner;
+ int i = 1;
+ #define X(public, fld, sv, cl) \
+ if (o.fld != this.fld) \
+ { \
+ this.fld = o.fld; \
+ this.SendFlags |= BIT(i); \
+ } \
+ i += 1;
+ ENTCS_NETPROPS(X);
+ #undef X
+ }
+
+ void entcs_attach(entity player)
+ {
+ entity e = player.entcs = new(entcs_sender);
+ make_pure(e);
+ e.owner = player;
+ e.think = entcs_think;
+ e.nextthink = time;
+ Net_LinkEntity(e, false, 0, entcs_send);
+ }
+
+ void entcs_detach(entity player)
+ {
+ if (!player.entcs) return;
+ remove(player.entcs);
+ player.entcs = NULL;
+ }
+
+#endif
+
+#ifdef CSQC
+
+ void Ent_RemoveEntCS()
+ {
+ SELFPARAM();
+ entcs_receiver(this.sv_entnum, NULL);
+ }
+
+ void entcs_think()
+ {
+ SELFPARAM();
+ entity e = CSQCModel_server2csqc(this.sv_entnum);
+ if (e == NULL)
+ {
+ this.has_origin = this.has_sv_origin;
+ return;
+ }
+ this.has_origin = true;
+ this.origin = e.origin;
+ // `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
+ if (this.model != e.model)
+ {
+ if (this.model) strunzone(this.model);
+ this.model = strzone(e.model);
+ }
+ }
+
+ NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
+ {
+ if (isnew)
+ {
+ make_pure(this);
+ this.classname = "entcs_receiver";
+ this.entremove = Ent_RemoveEntCS;
+ this.think = entcs_think;
+ }
+ InterpolateOrigin_Undo(this);
+ int sf = ReadShort();
+ this.has_sv_origin = false;
+ this.m_entcs_private = boolean(sf & BIT(0));
+ int i = 1;
+ #define X(public, fld, sv, cl) { if (sf & BIT(i)) cl; } i += 1;
+ ENTCS_NETPROPS(X);
+ #undef X
+ entcs_receiver(this.sv_entnum, this);
+ this.iflags |= IFLAG_ORIGIN;
+ InterpolateOrigin_Note(this);
+ this.think();
+ return true;
+ }
+
+#endif
--- /dev/null
+#ifndef ENT_CS_H
+#define ENT_CS_H
+
+REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
+
+/** True when private information such as origin is available */
+.bool m_entcs_private;
+/** True when origin is available */
+.bool has_origin;
+/** True when a recent server sent origin has been received */
+.bool has_sv_origin;
+
+#ifdef SVQC
+/*
+ * The point of these entities is to avoid the problems
+ * with clientprediction.
+ * If you add SendEntity to players, the engine will not
+ * do any prediction anymore, and you'd have to write the whole
+ * prediction code in CSQC, you want that? :P
+ * Data can depend on gamemode. For now, it serves as GPS entities
+ * in onslaught... YAY ;)
+ */
+
+ .entity entcs;
+
+ bool entcs_send(entity this, entity to, int sf);
+
+ void entcs_think();
+
+ void entcs_attach(entity e);
+
+ void entcs_detach(entity e);
+
+ .int m_forceupdate;
+
+/** Force an origin update, for player sounds */
+ #define entcs_force_origin(e) ((e).entcs.m_forceupdate = BIT(2))
+
+#endif
+
+#ifdef CSQC
+
+ AL_declare(_entcs);
+ STATIC_INIT(_entcs)
+ {
+ AL_init(_entcs, 255, NULL, e); // 255 is the engine limit on maxclients
+ }
+ SHUTDOWN(_entcs)
+ {
+ AL_delete(_entcs);
+ }
+ #define entcs_receiver(...) EVAL(OVERLOAD(entcs_receiver, __VA_ARGS__))
+ #define entcs_receiver_1(i) AL_gete(_entcs, i)
+ #define entcs_receiver_2(i, v) AL_sete(_entcs, i, v)
+ #define entcs_is_self(e) ((e).sv_entnum == player_localentnum - 1)
+
+ /**
+ * @param i zero indexed player
+ * @returns 0 if not teamplay
+ */
+ int GetPlayerColorForce(int i)
+ {
+ return (!teamplay) ? 0 : stof(getplayerkeyvalue(i, "colors")) & 15;
+ }
+
+ /**
+ * @param i zero indexed player
+ * @returns 0 if not teamplay | NUM_TEAM_##N | NUM_SPECTATOR
+ */
+ int GetPlayerColor(int i)
+ {
+ bool unconnected = !playerslots[i].gotscores;
+ bool spec = unconnected || stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR;
+ return (spec) ? NUM_SPECTATOR : GetPlayerColorForce(i);
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ string GetPlayerName(int i)
+ {
+ return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ entity CSQCModel_server2csqc(int i);
+
+ .float alpha;
+
+ /**
+ * @param i zero indexed player
+ */
+ float getplayeralpha(int i)
+ {
+ entity e = CSQCModel_server2csqc(i);
+ return e ? e.alpha : 1;
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ vector getcsqcplayercolor(int i)
+ {
+ entity e = CSQCModel_server2csqc(i);
+ return (!e || e.colormap <= 0)
+ ? '1 1 1'
+ : colormapPaletteColor(((e.colormap >= 1024)
+ ? e.colormap
+ : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 15, true)
+ ;
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ bool getplayerisdead(int i)
+ {
+ entity e = CSQCModel_server2csqc(i);
+ return e ? e.csqcmodel_isdead : false;
+ }
+
+#endif
+
+#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-.float metertime;
+.float metertime = _STAT(NB_METERSTART);
int autocvar_g_nexball_goalleadlimit;
#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
GameLogEcho(s);
}
-void ball_restart()
-{SELFPARAM();
- if(self.owner)
- DropBall(self, self.owner.origin, '0 0 0');
+void ball_restart(entity this)
+{
+ if(this.owner)
+ DropBall(this, this.owner.origin, '0 0 0');
ResetBall();
}
W_SetupProjVelocity_Basic(missile, autocvar_g_balance_nexball_secondary_speed, 0);
missile.angles = vectoangles(missile.velocity);
missile.touch = W_Nexball_Touch;
- missile.think = SUB_Remove;
+ missile.think = SUB_Remove_self;
missile.nextthink = time + autocvar_g_balance_nexball_secondary_lifetime; //FIXME: use a distance instead?
missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
if(g_nexball_meter_period <= 0)
g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
- addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
// General settings
/*
.float teleport_antispam;
-.bool ons_roundlost;
+.bool ons_roundlost = _STAT(ROUNDLOST);
// waypoint sprites
.entity bot_basewaypoint; // generator waypointsprite
}
}
-void ons_CaptureShield_Reset()
-{SELFPARAM();
- self.colormap = self.enemy.colormap;
- self.team = self.enemy.team;
+void ons_CaptureShield_Reset(entity this)
+{
+ this.colormap = this.enemy.colormap;
+ this.team = this.enemy.team;
}
void ons_CaptureShield_Spawn(entity generator, bool is_generator)
CSQCMODEL_AUTOUPDATE(self);
}
-void ons_ControlPoint_Reset()
-{SELFPARAM();
- if(self.goalentity)
- remove(self.goalentity);
-
- self.goalentity = world;
- self.team = 0;
- self.colormap = 1024;
- self.iscaptured = false;
- self.islinked = false;
- self.isshielded = true;
- self.think = ons_ControlPoint_Think;
- self.ons_toucher = world;
- self.nextthink = time + ONS_CP_THINKRATE;
- setmodel_fixsize(self, MDL_ONS_CP_PAD1);
-
- WaypointSprite_UpdateMaxHealth(self.sprite, 0);
- WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
+void ons_ControlPoint_Reset(entity this)
+{
+ if(this.goalentity)
+ remove(this.goalentity);
+
+ this.goalentity = world;
+ this.team = 0;
+ this.colormap = 1024;
+ this.iscaptured = false;
+ this.islinked = false;
+ this.isshielded = true;
+ this.think = ons_ControlPoint_Think;
+ this.ons_toucher = world;
+ this.nextthink = time + ONS_CP_THINKRATE;
+ setmodel_fixsize(this, MDL_ONS_CP_PAD1);
+
+ WaypointSprite_UpdateMaxHealth(this.sprite, 0);
+ WaypointSprite_UpdateRule(this.sprite,this.team,SPRITERULE_TEAMPLAY);
onslaught_updatelinks();
- activator = self;
+ activator = this;
SUB_UseTargets(); // to reset the structures, playerspawns etc.
- CSQCMODEL_AUTOUPDATE(self);
+ CSQCMODEL_AUTOUPDATE(this);
}
void ons_DelayedControlPoint_Setup()
}
}
-void ons_GeneratorReset()
-{SELFPARAM();
- self.team = self.team_saved;
- self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
- self.takedamage = DAMAGE_AIM;
- self.bot_attack = true;
- self.iscaptured = true;
- self.islinked = true;
- self.isshielded = true;
- self.event_damage = ons_GeneratorDamage;
- self.think = ons_GeneratorThink;
- self.nextthink = time + GEN_THINKRATE;
-
- Net_LinkEntity(self, false, 0, generator_send);
-
- self.SendFlags = GSF_SETUP; // just incase
- self.SendFlags |= GSF_STATUS;
-
- WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.sprite, self.health);
- WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
+void ons_GeneratorReset(entity this)
+{
+ this.team = this.team_saved;
+ this.lasthealth = this.max_health = this.health = autocvar_g_onslaught_gen_health;
+ this.takedamage = DAMAGE_AIM;
+ this.bot_attack = true;
+ this.iscaptured = true;
+ this.islinked = true;
+ this.isshielded = true;
+ this.event_damage = ons_GeneratorDamage;
+ this.think = ons_GeneratorThink;
+ this.nextthink = time + GEN_THINKRATE;
+
+ Net_LinkEntity(this, false, 0, generator_send);
+
+ this.SendFlags = GSF_SETUP; // just incase
+ this.SendFlags |= GSF_STATUS;
+
+ WaypointSprite_UpdateMaxHealth(this.sprite, this.max_health);
+ WaypointSprite_UpdateHealth(this.sprite, this.health);
+ WaypointSprite_UpdateRule(this.sprite,this.team,SPRITERULE_TEAMPLAY);
onslaught_updatelinks();
}
g_onslaught = true;
ons_captureshield_force = autocvar_g_onslaught_shield_force;
- addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
-
InitializeEntity(world, ons_DelayedInit, INITPRIO_GAMETYPE);
}
REGISTRY(Items, BITS(5))
#define Items_from(i) _Items_from(i, NULL)
-REGISTER_REGISTRY(RegisterItems)
+REGISTER_REGISTRY(Items)
/** If you register a new item, make sure to add it to all.inc */
-#define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, Items, id, m_id, NEW(class))
+#define REGISTER_ITEM(id, class) REGISTER(Items, ITEM, id, m_id, NEW(class))
-REGISTRY_SORT(Items, 0)
+REGISTRY_SORT(Items)
REGISTRY_CHECK(Items)
STATIC_INIT(Items) { FOREACH(Items, true, LAMBDA(it.m_id = i)); }
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_INVENTORY);
entity e = self.owner;
- if (/*IS_SPEC(e)*/ (e.classname == "spectator")) e = e.enemy;
+ if (IS_SPEC(e)) e = e.enemy;
Inventory data = e.inventory;
Inventory_Write(data);
return true;
#if defined(CSQC)
#include "../client/defs.qh"
#include "util.qh"
- #include "buffs/all.qh"
#include "weapons/all.qh"
#include "mapinfo.qh"
#elif defined(MENUQC)
#elif defined(SVQC)
#include "util.qh"
- #include "buffs/all.qh"
#include "monsters/all.qh"
#include "mapinfo.qh"
#endif
{
MapInfo_Map_flags |= MAPINFO_FLAG_NOAUTOMAPLIST;
}
+ else if(t == "gameversion_min")
+ {
+ if (cvar("gameversion") < stof(s))
+ MapInfo_Map_flags |= MAPINFO_FLAG_NOAUTOMAPLIST;
+ }
else if(t == "type")
{
t = car(s); s = cdr(s);
REGISTRY(Gametypes, BITS(4))
#define Gametypes_from(i) _Gametypes_from(i, NULL)
-REGISTER_REGISTRY(RegisterGametypes)
+REGISTER_REGISTRY(Gametypes)
REGISTRY_CHECK(Gametypes)
int MAPINFO_TYPE_ALL;
#define REGISTER_GAMETYPE(hname, sname, g_name, NAME, gteamplay, mutators, defaults, gdescription) \
int MAPINFO_TYPE_##NAME; \
bool NAME##_mapinfo(string k, string v) { return = false; } \
- REGISTER(RegisterGametypes, MAPINFO_TYPE, Gametypes, g_name, m_id, \
+ REGISTER(Gametypes, MAPINFO_TYPE, g_name, m_id, \
NEW(Gametype, hname, #sname, #g_name, gteamplay, #sname " " mutators, defaults, gdescription) \
) { \
/* same as `1 << m_id` */ \
deactivate_minigame();
}
-vector ReadVector2D() { vector v; v_x = ReadCoord(); v_y = ReadCoord(); v_z = 0; return v; }
-vector ReadVector() { vector v; v_x = ReadCoord(); v_y = ReadCoord(); v_z = ReadCoord(); return v; }
string() ReadString_Raw = #366;
string ReadString_Zoned() { return strzone(ReadString_Raw()); }
#define ReadString ReadString_Zoned
while( (entityvar = findentity(entityvar,owner,active_minigame)) )
-REGISTRY(Minigames, BITS(3))
+REGISTRY(Minigames, BITS(4))
#define Minigames_from(i) _Minigames_from(i, NULL)
-REGISTER_REGISTRY(RegisterMinigames)
+REGISTER_REGISTRY(Minigames)
REGISTRY_CHECK(Minigames)
#define REGISTER_MINIGAME(name,nicename) \
- REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \
+ REGISTER(Minigames, MINIGAME_##name, m_id, new(minigame_descriptor)); \
void name##_hud_board(vector, vector); \
void name##_hud_status(vector, vector); \
int name##_client_event(entity, string, ...); \
- REGISTER_INIT_POST(MINIGAME, name) { \
+ REGISTER_INIT_POST(MINIGAME_##name) { \
make_pure(this); \
this.netname = strzone(strtolower(#name)); \
this.message = nicename; \
this.minigame_hud_status = name##_hud_status; \
this.minigame_event = name##_client_event; \
} \
- REGISTER_INIT(MINIGAME, name)
+ REGISTER_INIT(MINIGAME_##name)
#endif
// Whether the minigame menu panel is open
bool HUD_MinigameMenu_IsOpened()
{
- return !!HUD_MinigameMenu_entries;
+ return HUD_MinigameMenu_entries != NULL;
}
// Close the minigame menu panel
#include "ps.qc"
#include "pp.qc"
#include "snake.qc"
+#include "bd.qc"
/**
* Set up automatic entity read/write functionality
--- /dev/null
+REGISTER_MINIGAME(bd, "Bulldozer");
+
+const int BD_TURN_MOVE = 0x0100; // player must move the bulldozer
+const int BD_TURN_WIN = 0x0200; // victory
+const int BD_TURN_LOSS = 0x0400; // they did it?!
+const int BD_TURN_EDIT = 0x0800; // editing mode
+const int BD_TURN_TYPE = 0x0f00; // turn type mask
+
+const int BD_SF_PLAYERMOVES = MINIG_SF_CUSTOM;
+
+// 240 tiles...
+const int BD_LET_CNT = 20;
+const int BD_NUM_CNT = 20;
+
+const int BD_TILE_SIZE = 20;
+
+const int BD_TEAMS = 1;
+
+.vector bd_dir;
+
+.int bd_moves;
+
+.string bd_levelname;
+.string bd_nextlevel;
+
+#ifdef SVQC
+.bool bd_canedit;
+#endif
+
+.int bd_tiletype;
+const int BD_TILE_DOZER = 1;
+const int BD_TILE_TARGET = 2;
+const int BD_TILE_BOULDER = 3;
+const int BD_TILE_BRICK1 = 4;
+const int BD_TILE_BRICK2 = 5;
+const int BD_TILE_BRICK3 = 6;
+const int BD_TILE_BRICK4 = 7;
+const int BD_TILE_BRICK5 = 8;
+const int BD_TILE_BRICK6 = 9;
+const int BD_TILE_BRICK7 = 10;
+const int BD_TILE_BRICK8 = 11;
+const int BD_TILE_LAST = 11;
+
+string autocvar_sv_minigames_bulldozer_startlevel = "level1";
+
+// find same game piece given its tile name
+entity bd_find_piece(entity minig, string tile, bool check_target)
+{
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.netname == tile && ((check_target) ? e.bd_tiletype == BD_TILE_TARGET : e.bd_tiletype != BD_TILE_TARGET) )
+ return e;
+ return world;
+}
+
+// check if the tile name is valid (15x15 grid)
+bool bd_valid_tile(string tile)
+{
+ if ( !tile )
+ return false;
+ int number = minigame_tile_number(tile);
+ int letter = minigame_tile_letter(tile);
+ return 0 <= number && number < BD_NUM_CNT && 0 <= letter && letter < BD_LET_CNT;
+}
+
+entity bd_find_dozer(entity minig)
+{
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.bd_tiletype == BD_TILE_DOZER )
+ return e;
+ return world;
+}
+
+void bd_check_winner(entity minig)
+{
+ int total = 0, valid = 0;
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.bd_tiletype == BD_TILE_TARGET )
+ {
+ ++total;
+ if(bd_find_piece(minig, e.netname, false).bd_tiletype == BD_TILE_BOULDER)
+ ++valid;
+ }
+
+ if(valid >= total)
+ {
+ minig.minigame_flags = BD_TURN_WIN;
+ minigame_server_sendflags(minig,MINIG_SF_UPDATE);
+ }
+}
+
+bool bd_canfill(int ttype)
+{
+ switch(ttype)
+ {
+ case BD_TILE_BRICK8:
+ case BD_TILE_BRICK7:
+ case BD_TILE_BRICK6:
+ case BD_TILE_BRICK5:
+ case BD_TILE_BRICK4:
+ case BD_TILE_BRICK3:
+ case BD_TILE_BRICK2:
+ case BD_TILE_BRICK1: return true;
+ }
+
+ return false;
+}
+
+bool bd_move_dozer(entity minigame, entity dozer)
+{
+ if(!dozer.bd_dir_x && !dozer.bd_dir_y)
+ return false; // nope!
+
+ int myx = minigame_tile_letter(dozer.netname);
+ int myy = minigame_tile_number(dozer.netname);
+
+ myx += dozer.bd_dir_x;
+ myy += dozer.bd_dir_y;
+
+ string newpos = minigame_tile_buildname(myx, myy);
+ entity hit = bd_find_piece(minigame, newpos, false);
+
+ if(!bd_valid_tile(newpos))
+ return false;
+
+ if(hit)
+ switch(hit.bd_tiletype)
+ {
+ case BD_TILE_DOZER: // wtf, but let's do this incase
+ case BD_TILE_BRICK8:
+ case BD_TILE_BRICK7:
+ case BD_TILE_BRICK6:
+ case BD_TILE_BRICK5:
+ case BD_TILE_BRICK4:
+ case BD_TILE_BRICK3:
+ case BD_TILE_BRICK2:
+ case BD_TILE_BRICK1: return false;
+ case BD_TILE_BOULDER:
+ {
+ string testpos;
+ int tx = minigame_tile_letter(hit.netname);
+ int ty = minigame_tile_number(hit.netname);
+
+ tx += dozer.bd_dir_x;
+ ty += dozer.bd_dir_y;
+
+ testpos = minigame_tile_buildname(tx, ty);
+ entity testhit = bd_find_piece(minigame, testpos, false);
+
+ if(!bd_valid_tile(testpos) || testhit)
+ return false;
+
+ if(hit.netname) { strunzone(hit.netname); }
+ hit.netname = strzone(testpos);
+ minigame_server_sendflags(hit,MINIG_SF_UPDATE);
+ break;
+ }
+ }
+
+ if(dozer.netname) { strunzone(dozer.netname); }
+ dozer.netname = strzone(newpos);
+
+ return true;
+}
+
+// make a move
+void bd_move(entity minigame, entity player, string dir)
+{
+ if ( minigame.minigame_flags & BD_TURN_MOVE )
+ if ( dir )
+ {
+ //if ( bd_valid_tile(pos) )
+ //if ( bd_find_piece(minigame, pos, false) )
+ {
+ entity dozer = bd_find_dozer(minigame);
+ if(!dozer)
+ {
+ LOG_INFO("Dozer wasn't found!\n");
+ return; // should not happen... TODO: end match?
+ }
+
+ int dxs = 0, dys = 0;
+ string thedir = strtolower(dir);
+ if(thedir == "up" || thedir == "u") { dxs = 0; dys = 1; }
+ if(thedir == "down" || thedir == "dn" || thedir == "d") { dxs = 0; dys = -1; }
+ if(thedir == "left" || thedir == "lt" || thedir == "l") { dxs = -1; dys = 0; }
+ if(thedir == "right" || thedir == "rt" || thedir == "r") { dxs = 1; dys = 0; }
+
+ int dx = bound(-1, dxs, 1);
+ int dy = bound(-1, dys, 1);
+
+ dozer.bd_dir_x = dx;
+ dozer.bd_dir_y = dy;
+ dozer.bd_dir_z = 0;
+
+ if(bd_move_dozer(minigame, dozer))
+ player.bd_moves++;
+
+ bd_check_winner(minigame);
+
+ minigame_server_sendflags(dozer,MINIG_SF_UPDATE); // update anyway
+ minigame_server_sendflags(player,BD_SF_PLAYERMOVES);
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+ }
+}
+
+// editor
+void bd_editor_place(entity minigame, entity player, string pos, int thetile, string thedir)
+{
+ if ( minigame.minigame_flags & BD_TURN_EDIT )
+ if ( pos && thetile )
+ {
+ if ( bd_valid_tile(pos) )
+ {
+ entity found_piece = bd_find_piece(minigame, pos, false);
+ entity targ = bd_find_piece(minigame, pos, true);
+
+ if(found_piece.bd_tiletype == BD_TILE_DOZER && thedir != "")
+ {
+ int dxs = 0, dys = 0;
+ string newdir = strtolower(thedir);
+ if(newdir == "up" || newdir == "u") { dxs = 0; dys = 1; }
+ if(newdir == "down" || newdir == "dn" || newdir == "d") { dxs = 0; dys = -1; }
+ if(newdir == "left" || newdir == "lt" || newdir == "l") { dxs = -1; dys = 0; }
+ if(newdir == "right" || newdir == "rt" || newdir == "r") { dxs = 1; dys = 0; }
+
+ int dx = bound(-1, dxs, 1);
+ int dy = bound(-1, dys, 1);
+
+ found_piece.bd_dir_x = dx;
+ found_piece.bd_dir_y = dy;
+ found_piece.bd_dir_z = 0;
+ minigame_server_sendflags(found_piece,MINIG_SF_UPDATE); // update anyway
+ return;
+ }
+
+ entity dozer = bd_find_dozer(minigame);
+ if(dozer && thetile == BD_TILE_DOZER && pos != dozer.netname)
+ return; // nice try
+
+ if(found_piece || (targ && thetile != BD_TILE_BOULDER))
+ {
+ entity piece = bd_find_piece(minigame, pos, false);
+ if(!piece) piece = bd_find_piece(minigame, pos, true);
+ if(!piece)
+ return; // how?!
+
+ if(piece.netname) { strunzone(piece.netname); }
+ remove(piece);
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ return;
+ }
+
+ entity piece = msle_spawn(minigame,"minigame_board_piece");
+ piece.team = 1;
+ piece.netname = strzone(pos);
+ piece.bd_tiletype = thetile;
+ piece.bd_dir = '0 -1 0';
+ minigame_server_sendflags(piece,MINIG_SF_UPDATE);
+
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+ }
+}
+
+void bd_do_move(entity minigame, entity player, string dir, string thetile, string thedir)
+{
+ if(minigame.minigame_flags & BD_TURN_MOVE)
+ bd_move(minigame, player, dir);
+
+ if(minigame.minigame_flags & BD_TURN_EDIT)
+ bd_editor_place(minigame, player, dir, stof(thetile), thedir);
+}
+
+void bd_fill_recurse(entity minigame, entity player, int thetype, int letter, int number)
+{
+ string pos = minigame_tile_buildname(letter,number);
+ if(!bd_valid_tile(pos))
+ return;
+ if(bd_find_piece(minigame, pos, false) || bd_find_piece(minigame, pos, true))
+ return;
+
+ bd_editor_place(minigame, player, pos, thetype, "");
+
+ bd_fill_recurse(minigame, player, thetype, letter - 1, number);
+ bd_fill_recurse(minigame, player, thetype, letter + 1, number);
+ bd_fill_recurse(minigame, player, thetype, letter, number - 1);
+ bd_fill_recurse(minigame, player, thetype, letter, number + 1);
+}
+
+void bd_unfill_recurse(entity minigame, entity player, int thetype, int letter, int number)
+{
+ string pos = minigame_tile_buildname(letter,number);
+ if(!bd_valid_tile(pos))
+ return;
+
+ entity targ = bd_find_piece(minigame, pos, true);
+ entity piece = bd_find_piece(minigame, pos, false);
+
+ if(targ && thetype == targ.bd_tiletype)
+ {
+ if(targ.netname) { strunzone(targ.netname); }
+ remove(targ);
+ }
+ else if(piece && thetype == piece.bd_tiletype)
+ {
+ if(piece.netname) { strunzone(piece.netname); }
+ remove(piece);
+ }
+ else return;
+
+ bd_unfill_recurse(minigame, player, thetype, letter - 1, number);
+ bd_unfill_recurse(minigame, player, thetype, letter + 1, number);
+ bd_unfill_recurse(minigame, player, thetype, letter, number - 1);
+ bd_unfill_recurse(minigame, player, thetype, letter, number + 1);
+}
+
+void bd_do_fill(entity minigame, entity player, string dir, string thetile)
+{
+ if(minigame.minigame_flags & BD_TURN_EDIT)
+ {
+ int thetype = stof(thetile);
+
+ entity targ = bd_find_piece(minigame, dir, true);
+ entity piece = bd_find_piece(minigame, dir, false);
+
+ if(!bd_canfill(thetype) || (piece || targ))
+ {
+ int killtype = 0;
+
+ if(targ) { killtype = targ.bd_tiletype; }
+ if(piece) { killtype = piece.bd_tiletype; }
+
+ if(killtype)
+ {
+ int letter = minigame_tile_letter(dir);
+ int number = minigame_tile_number(dir);
+ bd_unfill_recurse(minigame, player, killtype, letter, number);
+ }
+
+ return;
+ }
+
+ int letter = minigame_tile_letter(dir);
+ int number = minigame_tile_number(dir);
+
+ bd_fill_recurse(minigame, player, thetype, letter, number);
+ }
+}
+
+void bd_reset_moves(entity minigame)
+{
+ entity e;
+#ifdef SVQC
+ for(e = minigame.minigame_players; e; e = e.list_next)
+#elif defined(CSQC)
+ e = world;
+ while( (e = findentity(e,owner,minigame)) )
+ if ( e.classname == "minigame_player" )
+#endif
+ {
+ e.bd_moves = 0;
+ minigame_server_sendflags(e,BD_SF_PLAYERMOVES);
+ }
+}
+
+void bd_load_level(entity minigame);
+void bd_setup_pieces(entity minigame)
+{
+ entity e = world;
+ while( (e = findentity(e, owner, minigame)) )
+ if(e.classname == "minigame_board_piece")
+ {
+ if(e.netname) { strunzone(e.netname); }
+ remove(e);
+ }
+
+ bd_load_level(minigame);
+}
+
+void bd_do_next_match(entity minigame, entity player)
+{
+ minigame.minigame_flags = BD_TURN_MOVE;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+
+ if(minigame.bd_nextlevel && minigame.bd_nextlevel != "")
+ {
+ if(minigame.bd_levelname) { strunzone(minigame.bd_levelname); }
+ minigame.bd_levelname = strzone(minigame.bd_nextlevel);
+ }
+
+ bd_setup_pieces(minigame);
+
+ bd_reset_moves(minigame);
+}
+
+void bd_set_next_match(entity minigame, string next)
+{
+ if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
+ minigame.bd_nextlevel = strzone(next);
+}
+
+void bd_next_match(entity minigame, entity player, string next)
+{
+ if(minigame.minigame_flags & BD_TURN_WIN)
+ bd_do_next_match(minigame, player);
+ if(minigame.minigame_flags & BD_TURN_EDIT)
+ bd_set_next_match(minigame, next);
+}
+
+// request a new match
+void bd_restart_match(entity minigame, entity player)
+{
+ minigame.minigame_flags = BD_TURN_MOVE;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+
+ bd_setup_pieces(minigame);
+
+ bd_reset_moves(minigame);
+}
+
+void bd_activate_editor(entity minigame, entity player)
+{
+#ifdef SVQC
+ if(!player.minigame_players.bd_canedit)
+ {
+ sprint(player.minigame_players, "You're not allowed to edit levels, sorry!\n");
+ return;
+ }
+#endif
+
+ minigame.minigame_flags = BD_TURN_EDIT;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+
+ bd_reset_moves(minigame);
+
+ bd_setup_pieces(minigame);
+}
+
+string bd_save_piece(entity minigame, entity e)
+{
+ string bd_string = "";
+
+ bd_string = strcat(bd_string, "\"", e.netname, "\" ");
+ bd_string = strcat(bd_string, ftos(e.bd_tiletype), " ");
+ bd_string = strcat(bd_string, sprintf("\"%.9v\"", e.bd_dir));
+
+ return bd_string;
+}
+
+void bd_set_nextlevel(entity minigame, string s)
+{
+ tokenize_console(s);
+
+ if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
+ minigame.bd_nextlevel = strzone(argv(2));
+}
+
+entity bd_load_piece(entity minigame, string s)
+{
+ // separate pieces between the ; symbols
+ string bd_string = s;
+
+ tokenize_console(bd_string);
+
+ entity e = msle_spawn(minigame,"minigame_board_piece");
+ e.team = 1;
+ e.bd_dir = '0 -1 0';
+
+ int argv_num = 0;
+ e.netname = strzone(argv(argv_num)); ++argv_num;
+ e.bd_tiletype = stof(argv(argv_num)); ++argv_num;
+ e.bd_dir = stov(argv(argv_num)); ++argv_num;
+
+ minigame_server_sendflags(e,MINIG_SF_ALL);
+
+ return e;
+}
+
+bool bd_save_level(entity minigame)
+{
+ if(minigame.bd_levelname && minigame.bd_levelname != "")
+ {
+ int target_count = 0, boulder_count = 0;
+ entity piece = world;
+ while((piece = findentity(piece,owner,minigame)))
+ if(piece.classname == "minigame_board_piece")
+ if(piece.bd_tiletype == BD_TILE_BOULDER)
+ ++boulder_count;
+ else if(piece.bd_tiletype == BD_TILE_TARGET)
+ ++target_count;
+
+ if(boulder_count != target_count)
+ {
+ LOG_INFO("Not enough targets or boulders, fix your level!\n");
+ return false;
+ }
+
+ // saves all objects to the database file
+ string file_name;
+ float file_get;
+
+ file_name = strcat("minigames/bulldozer/storage_", minigame.bd_levelname, ".txt");
+ file_get = fopen(file_name, FILE_WRITE);
+ fputs(file_get, strcat("// bulldozer storage \"", minigame.bd_levelname, "\" last updated ", strftime(true, "%d-%m-%Y %H:%M:%S"), "\n"));
+
+ if(minigame.bd_nextlevel && minigame.bd_nextlevel != "" && fexists(strcat("minigames/bulldozer/storage_", minigame.bd_nextlevel, ".txt")))
+ fputs(file_get, strcat("nextlevel = \"", minigame.bd_nextlevel, "\"\n"));
+
+ entity e = world;
+ while ( ( e = findentity(e,owner,minigame) ) )
+ if ( e.classname == "minigame_board_piece" )
+ {
+ // use a line of text for each object, listing all properties
+ fputs(file_get, strcat(bd_save_piece(minigame, e), "\n"));
+ }
+ fclose(file_get);
+
+ return true;
+ }
+
+ return false;
+}
+
+void bd_load_level(entity minigame)
+{
+ // loads all items from the database file
+ string file_read, file_name;
+ float file_get;
+
+ file_name = strcat("minigames/bulldozer/storage_", minigame.bd_levelname, ".txt");
+ file_get = fopen(file_name, FILE_READ);
+ if(file_get < 0)
+ {
+ LOG_INFO("^3BULLDOZER: ^7could not find storage file ^3", file_name, "^7, no items were loaded\n");
+ }
+ else
+ {
+ for(;;)
+ {
+ file_read = fgets(file_get);
+ if(file_read == "")
+ break;
+ if(substring(file_read, 0, 2) == "//")
+ continue;
+ if(substring(file_read, 0, 1) == "#")
+ continue;
+ if(substring(file_read, 0, 9) == "nextlevel")
+ {
+ bd_set_nextlevel(minigame, file_read);
+ continue;
+ }
+
+ entity e;
+ e = bd_load_piece(minigame, file_read);
+ }
+ }
+ fclose(file_get);
+}
+
+void bd_close_editor(entity minigame)
+{
+ entity dozer = bd_find_dozer(minigame);
+ if(!dozer)
+ {
+ LOG_INFO("You need to place a bulldozer on the level to save it!\n");
+ return;
+ }
+
+ if(bd_save_level(minigame))
+ {
+ minigame.minigame_flags = BD_TURN_MOVE;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+ else
+ {
+ LOG_INFO("You need to set the level name!\n");
+ return;
+ }
+}
+
+#ifdef SVQC
+
+// required function, handle server side events
+int bd_server_event(entity minigame, string event, ...)
+{
+ switch(event)
+ {
+ case "start":
+ {
+ if(minigame.bd_levelname) { strunzone(minigame.bd_levelname); }
+ minigame.bd_levelname = strzone(autocvar_sv_minigames_bulldozer_startlevel);
+ bd_setup_pieces(minigame);
+ minigame.minigame_flags = BD_TURN_MOVE;
+
+ return true;
+ }
+ case "end":
+ {
+ entity e = world;
+ while( (e = findentity(e, owner, minigame)) )
+ if(e.classname == "minigame_board_piece")
+ {
+ if(e.netname) { strunzone(e.netname); }
+ remove(e);
+ }
+
+ if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
+ if(minigame.bd_levelname) { strunzone(minigame.bd_levelname); }
+ return false;
+ }
+ case "join":
+ {
+ int pl_num = minigame_count_players(minigame);
+
+ if(pl_num >= BD_TEAMS) { return false; }
+
+ return 1;
+ }
+ case "cmd":
+ {
+ switch(argv(0))
+ {
+ case "move":
+ bd_do_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) >= 3 ? argv(2) : string_null), ((...(1,int)) >= 4 ? argv(3) : string_null));
+ return true;
+ case "next":
+ bd_next_match(minigame,...(0,entity), ((...(1,int) >= 2 ? argv(1) : string_null)));
+ return true;
+ case "restart":
+ bd_restart_match(minigame,...(0,entity));
+ return true;
+ case "edit":
+ bd_activate_editor(minigame,...(0,entity));
+ return true;
+ case "save":
+ bd_close_editor(minigame);
+ return true;
+ case "fill":
+ bd_do_fill(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) >= 3 ? argv(2) : string_null));
+ return true;
+ }
+
+ return false;
+ }
+ case "network_send":
+ {
+ entity sent = ...(0,entity);
+ int sf = ...(1,int);
+ if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
+ {
+ int letter = minigame_tile_letter(sent.netname);
+ int number = minigame_tile_number(sent.netname);
+
+ WriteByte(MSG_ENTITY,letter);
+ WriteByte(MSG_ENTITY,number);
+
+ WriteByte(MSG_ENTITY,sent.bd_tiletype);
+
+ int dx = sent.bd_dir_x;
+ int dy = sent.bd_dir_y;
+ if(dx == -1) dx = 2;
+ if(dy == -1) dy = 2;
+ WriteByte(MSG_ENTITY,dx);
+ WriteByte(MSG_ENTITY,dy);
+ }
+ else if(sent.classname == "minigame_player" && (sf & BD_SF_PLAYERMOVES))
+ WriteShort(MSG_ENTITY,sent.bd_moves);
+ return false;
+ }
+ }
+
+ return false;
+}
+
+
+#elif defined(CSQC)
+
+int bd_curr_tile;
+string bd_curr_pos;
+
+.entity bd_enemy;
+.bool bd_hide;
+
+vector bd_boardpos; // HUD board position
+vector bd_boardsize;// HUD board size
+
+string bd_get_tile_pic(int tileid)
+{
+ switch(tileid)
+ {
+ case BD_TILE_BOULDER: return "bd/boulder";
+ case BD_TILE_BRICK1: return "bd/brick1";
+ case BD_TILE_BRICK2: return "bd/brick2";
+ case BD_TILE_BRICK3: return "bd/brick3";
+ case BD_TILE_BRICK4: return "bd/brick4";
+ case BD_TILE_BRICK5: return "bd/brick5";
+ case BD_TILE_BRICK6: return "bd/brick6";
+ case BD_TILE_BRICK7: return "bd/brick7";
+ case BD_TILE_BRICK8: return "bd/brick8";
+ case BD_TILE_TARGET: return "bd/target";
+ case BD_TILE_DOZER: return "bd/dozer";
+ }
+
+ return string_null;
+}
+
+// Required function, draw the game board
+void bd_hud_board(vector pos, vector mySize)
+{
+ minigame_hud_fitsqare(pos, mySize);
+ bd_boardpos = pos;
+ bd_boardsize = mySize;
+
+ minigame_hud_simpleboard(pos,mySize,minigame_texture("bd/board"));
+
+ vector tile_size = minigame_hud_denormalize_size('1 1 0' / BD_TILE_SIZE,pos,mySize);
+ vector tile_pos;
+
+ entity e;
+ FOREACH_MINIGAME_ENTITY(e)
+ {
+ if(e.classname == "minigame_board_piece")
+ {
+ if(e.bd_tiletype == BD_TILE_TARGET)
+ {
+ e.bd_enemy = world;
+ e.bd_enemy = bd_find_piece(active_minigame, e.netname, false);
+ }
+ else if(e.bd_tiletype == BD_TILE_BOULDER)
+ {
+ e.bd_hide = false; // reset either way
+ e.bd_hide = ((bd_find_piece(active_minigame, e.netname, true)) != world);
+ }
+ }
+ }
+ FOREACH_MINIGAME_ENTITY(e)
+ {
+ if ( e.classname == "minigame_board_piece" )
+ {
+ if(e.bd_tiletype != BD_TILE_DOZER && !e.bd_hide) // hide boulders
+ {
+ tile_pos = minigame_tile_pos(e.netname,BD_NUM_CNT,BD_LET_CNT);
+ tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
+
+ string thepiece = bd_get_tile_pic(e.bd_tiletype);
+
+ if(e.bd_enemy)
+ thepiece = "bd/boulder_target";
+
+ minigame_drawpic_centered( tile_pos,
+ minigame_texture(thepiece),
+ tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
+ }
+ }
+ }
+
+ // draw dozers on top, always
+ FOREACH_MINIGAME_ENTITY(e)
+ {
+ if ( e.classname == "minigame_board_piece" && e.bd_tiletype == BD_TILE_DOZER )
+ {
+ tile_pos = minigame_tile_pos(e.netname,BD_NUM_CNT,BD_LET_CNT);
+ tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
+
+ vector thedir = e.bd_dir;
+ float theang = 0;
+
+ if(thedir_y == -1) { theang = M_PI; }
+ if(thedir_x == 1) { theang = M_PI/2; }
+ if(thedir_x == -1) { theang = M_PI*3/2; }
+
+ drawrotpic(tile_pos, theang, minigame_texture("bd/dozer"),
+ tile_size, tile_size/2, '1 1 1',
+ panel_fg_alpha, DRAWFLAG_NORMAL );
+ }
+ }
+
+ if(active_minigame.minigame_flags & BD_TURN_EDIT)
+ if(bd_valid_tile(bd_curr_pos))
+ {
+ entity piece = bd_find_piece(active_minigame, bd_curr_pos, false);
+ entity targ = bd_find_piece(active_minigame, bd_curr_pos, true);
+ string thepiece = ((piece || (targ && bd_curr_tile != BD_TILE_BOULDER)) ? "bd/delete" : bd_get_tile_pic(bd_curr_tile));
+
+ tile_pos = minigame_tile_pos(bd_curr_pos,BD_LET_CNT,BD_NUM_CNT);
+ tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
+ if(bd_curr_tile == BD_TILE_DOZER)
+ {
+ drawrotpic(tile_pos, M_PI, minigame_texture("bd/dozer"),
+ tile_size, tile_size/2, '1 1 1',
+ panel_fg_alpha/2, DRAWFLAG_NORMAL );
+ }
+ else
+ {
+ minigame_drawpic_centered( tile_pos,
+ minigame_texture(thepiece),
+ tile_size, '1 1 1', panel_fg_alpha/2, DRAWFLAG_NORMAL );
+ }
+ }
+
+ if ( (active_minigame.minigame_flags & BD_TURN_LOSS) || (active_minigame.minigame_flags & BD_TURN_WIN) )
+ {
+ vector winfs = hud_fontsize*2;
+ string victory_text = "Game over!";
+
+ if(active_minigame.minigame_flags & BD_TURN_WIN)
+ victory_text = "Well done! Click 'Next Level' to continue";
+
+ vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
+ vector win_sz;
+ win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
+ sprintf("%s", victory_text),
+ winfs, 0, DRAWFLAG_NORMAL, 0.5);
+
+ drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE);
+
+ minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
+ sprintf("%s", victory_text),
+ winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
+ }
+}
+
+
+// Required function, draw the game status panel
+void bd_hud_status(vector pos, vector mySize)
+{
+ HUD_Panel_DrawBg(1);
+ vector ts;
+ ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
+ hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
+
+ pos_y += ts_y;
+ mySize_y -= ts_y;
+
+ vector player_fontsize = hud_fontsize * 1.75;
+ ts_y = ( mySize_y - 2*player_fontsize_y ) / BD_TEAMS;
+ ts_x = mySize_x;
+ vector mypos;
+ vector tile_size = '48 48 0';
+
+ mypos = pos;
+ drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
+ mypos_y += player_fontsize_y;
+ drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
+
+ entity e;
+ FOREACH_MINIGAME_ENTITY(e)
+ {
+ if ( e.classname == "minigame_player" )
+ {
+ mypos = pos;
+ minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
+ GetPlayerName(e.minigame_playerslot-1),
+ player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ mypos_y += player_fontsize_y;
+ string thepiece = "bd/dozer";
+ if(active_minigame.minigame_flags & BD_TURN_EDIT)
+ thepiece = bd_get_tile_pic(bd_curr_tile);
+ drawpic( mypos,
+ minigame_texture(thepiece),
+ tile_size * 0.7, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
+
+ mypos_x += tile_size_x;
+
+ drawstring(mypos,ftos(e.bd_moves),tile_size,
+ '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+ }
+}
+
+// Turn a set of flags into a help message
+string bd_turn_to_string(int turnflags)
+{
+ if ( turnflags & BD_TURN_LOSS )
+ return _("Better luck next time!");
+
+ if ( turnflags & BD_TURN_WIN )
+ if(random() > 0.5)
+ return _("Tubular! Press \"Next Level\" to continue!");
+ else
+ return _("Wicked! Press \"Next Level\" to continue!");
+
+ if( turnflags & BD_TURN_EDIT )
+ return _("Press the space bar to change your currently selected tile");
+
+ if ( turnflags & BD_TURN_MOVE )
+ return _("Push the boulders onto the targets");
+
+ return "";
+}
+
+// Make the correct move
+void bd_make_move(entity minigame, string dir)
+{
+ if ( minigame.minigame_flags == BD_TURN_MOVE )
+ {
+ minigame_cmd("move ", dir);
+ }
+}
+
+void bd_editor_make_move(entity minigame, string dir)
+{
+ if ( minigame.minigame_flags == BD_TURN_EDIT )
+ {
+ minigame_cmd("move ", bd_curr_pos, " ", ftos(bd_curr_tile), " ", dir);
+ }
+}
+
+void bd_editor_fill(entity minigame)
+{
+ if ( minigame.minigame_flags == BD_TURN_EDIT )
+ {
+ minigame_cmd("fill ", bd_curr_pos, " ", ftos(bd_curr_tile));
+ }
+}
+
+void bd_set_curr_pos(string s)
+{
+ if ( bd_curr_pos )
+ strunzone(bd_curr_pos);
+ if ( s )
+ s = strzone(s);
+ bd_curr_pos = s;
+}
+
+bool bd_normal_move(entity minigame, int themove)
+{
+ switch ( themove )
+ {
+ case K_RIGHTARROW:
+ case K_KP_RIGHTARROW:
+ bd_make_move(minigame, "r");
+ return true;
+ case K_LEFTARROW:
+ case K_KP_LEFTARROW:
+ bd_make_move(minigame, "l");
+ return true;
+ case K_UPARROW:
+ case K_KP_UPARROW:
+ bd_make_move(minigame, "u");
+ return true;
+ case K_DOWNARROW:
+ case K_KP_DOWNARROW:
+ bd_make_move(minigame, "d");
+ return true;
+ }
+
+ return false;
+}
+
+bool bd_change_dozer_angle(entity minigame)
+{
+ entity dozer = bd_find_piece(minigame, bd_curr_pos, false);
+ if(!dozer || dozer.bd_tiletype != BD_TILE_DOZER)
+ return false;
+
+ string thedir = "";
+ vector dir = dozer.bd_dir;
+ if(dir.x == 0 && dir.y == 0) { thedir = "r"; }
+
+ if(dir.x == 0 && dir.y == 1) { thedir = "r"; }
+ if(dir.x == 0 && dir.y ==-1) { thedir = "l"; }
+ if(dir.x ==-1 && dir.y == 0) { thedir = "u"; }
+ if(dir.x == 1 && dir.y == 0) { thedir = "d"; }
+
+ bd_editor_make_move(minigame, thedir);
+ return true;
+}
+
+bool bd_editor_move(entity minigame, int themove)
+{
+ switch ( themove )
+ {
+ case K_RIGHTARROW:
+ case K_KP_RIGHTARROW:
+ if ( ! bd_curr_pos )
+ bd_set_curr_pos("a3");
+ else
+ bd_set_curr_pos(minigame_relative_tile(bd_curr_pos,1,0,BD_NUM_CNT,BD_LET_CNT));
+ return true;
+ case K_LEFTARROW:
+ case K_KP_LEFTARROW:
+ if ( ! bd_curr_pos )
+ bd_set_curr_pos("c3");
+ else
+ bd_set_curr_pos(minigame_relative_tile(bd_curr_pos,-1,0,BD_NUM_CNT,BD_LET_CNT));
+ return true;
+ case K_UPARROW:
+ case K_KP_UPARROW:
+ if ( ! bd_curr_pos )
+ bd_set_curr_pos("a1");
+ else
+ bd_set_curr_pos(minigame_relative_tile(bd_curr_pos,0,1,BD_NUM_CNT,BD_LET_CNT));
+ return true;
+ case K_DOWNARROW:
+ case K_KP_DOWNARROW:
+ if ( ! bd_curr_pos )
+ bd_set_curr_pos("a3");
+ else
+ bd_set_curr_pos(minigame_relative_tile(bd_curr_pos,0,-1,BD_NUM_CNT,BD_LET_CNT));
+ return true;
+ case K_ENTER:
+ case K_KP_ENTER:
+ bd_editor_make_move(minigame, "");
+ return true;
+ case K_SPACE:
+ if(bd_change_dozer_angle(minigame))
+ return true;
+ bd_curr_tile += 1;
+ if(bd_curr_tile > BD_TILE_LAST)
+ bd_curr_tile = 1;
+ return true;
+ }
+
+ return false;
+}
+
+// Required function, handle client events
+int bd_client_event(entity minigame, string event, ...)
+{
+ switch(event)
+ {
+ case "activate":
+ {
+ minigame.message = bd_turn_to_string(minigame.minigame_flags);
+ bd_set_curr_pos("");
+ bd_curr_tile = BD_TILE_BRICK1;
+ return false;
+ }
+ case "key_pressed":
+ {
+ if(minigame.minigame_flags & BD_TURN_MOVE)
+ {
+ if(bd_normal_move(minigame, ...(0,int)))
+ return true;
+ }
+
+ if(minigame.minigame_flags & BD_TURN_EDIT)
+ {
+ if(bd_editor_move(minigame, ...(0,int)))
+ return true;
+ }
+
+ return false;
+ }
+ case "mouse_pressed":
+ {
+ if(minigame.minigame_flags & BD_TURN_EDIT)
+ {
+ if(...(0,int) == K_MOUSE1)
+ {
+ bd_editor_make_move(minigame, "");
+ return true;
+ }
+
+ if(...(0,int) == K_MOUSE2)
+ {
+ bd_editor_fill(minigame);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ case "mouse_moved":
+ {
+ if(minigame.minigame_flags & BD_TURN_EDIT)
+ {
+ vector mouse_pos = minigame_hud_normalize(mousepos,bd_boardpos,bd_boardsize);
+ bd_set_curr_pos(minigame_tile_name(mouse_pos,BD_LET_CNT,BD_NUM_CNT));
+ if ( ! bd_valid_tile(bd_curr_pos) )
+ bd_set_curr_pos("");
+ }
+ return true;
+ }
+ case "network_receive":
+ {
+ entity sent = ...(0,entity);
+ int sf = ...(1,int);
+ if ( sent.classname == "minigame" )
+ {
+ if ( sf & MINIG_SF_UPDATE )
+ {
+ sent.message = bd_turn_to_string(sent.minigame_flags);
+ //if ( sent.minigame_flags & minigame_self.team )
+ minigame_prompt();
+ }
+ }
+ else if(sent.classname == "minigame_board_piece")
+ {
+ if(sf & MINIG_SF_UPDATE)
+ {
+ int letter = ReadByte();
+ int number = ReadByte();
+ if(sent.netname) { strunzone(sent.netname); }
+ sent.netname = strzone(minigame_tile_buildname(letter, number));
+
+ sent.bd_tiletype = ReadByte();
+
+ int dx = ReadByte();
+ int dy = ReadByte();
+
+ if(dx == 2) dx = -1;
+ if(dy == 2) dy = -1;
+
+ sent.bd_dir_x = dx;
+ sent.bd_dir_y = dy;
+ sent.bd_dir_z = 0;
+ }
+ }
+ else if(sent.classname == "minigame_player" && (sf & BD_SF_PLAYERMOVES))
+ sent.bd_moves = ReadShort(); // make this a byte when possible
+
+ return false;
+ }
+ case "menu_show":
+ {
+ HUD_MinigameMenu_CustomEntry(...(0,entity),_("Next Level"),"next");
+ HUD_MinigameMenu_CustomEntry(...(0,entity),_("Restart"),"restart");
+ HUD_MinigameMenu_CustomEntry(...(0,entity),_("Editor"),"edit");
+ HUD_MinigameMenu_CustomEntry(...(0,entity),_("Save"),"save");
+ return false;
+ }
+ case "menu_click":
+ {
+ if(...(0,string) == "next")
+ minigame_cmd("next");
+ if(...(0,string) == "restart")
+ minigame_cmd("restart");
+ if(...(0,string) == "edit")
+ minigame_cmd("edit");
+ if(...(0,string) == "save")
+ minigame_cmd("save");
+ return false;
+ }
+ }
+
+ return false;
+}
+
+#endif
\ No newline at end of file
#define FIELD(Flags, Type,Name) if ( sf & (Flags) ) Write##Type(MSG_ENTITY, self.Name);
-#define WriteVector(to,Name) WriteCoord(to,Name##_x); WriteCoord(to,Name##_y); WriteCoord(to,Name##_z)
-#define WriteVector2D(to,Name) WriteCoord(to,Name##_x); WriteCoord(to,Name##_y)
#define MSLE(Name,Fields) \
else if ( self.classname == #Name ) { \
if ( sf & MINIG_SF_CREATE ) WriteString(MSG_ENTITY,self.owner.netname); \
bool minigame_SendEntity(entity this, entity to, int sf);
-REGISTRY(Minigames, BITS(3))
+REGISTRY(Minigames, BITS(4))
#define Minigames_from(i) _Minigames_from(i, NULL)
-REGISTER_REGISTRY(RegisterMinigames)
+REGISTER_REGISTRY(Minigames)
REGISTRY_CHECK(Minigames)
#define REGISTER_MINIGAME(name,nicename) \
- REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \
+ REGISTER(Minigames, MINIGAME_##name, m_id, new(minigame_descriptor)); \
int name##_server_event(entity, string, ...); \
- REGISTER_INIT_POST(MINIGAME, name) { \
+ REGISTER_INIT_POST(MINIGAME_##name) { \
make_pure(this); \
this.netname = strzone(strtolower(#name)); \
this.message = nicename; \
this.minigame_event = name##_server_event; \
} \
- REGISTER_INIT(MINIGAME, name)
+ REGISTER_INIT(MINIGAME_##name)
#endif
REGISTRY(Models, BITS(9))
#define Models_from(i) _Models_from(i, MDL_Null)
-REGISTER_REGISTRY(RegisterModels)
+REGISTER_REGISTRY(Models)
#define MODEL(name, path) \
string MDL_##name##_get() { return path; } \
- REGISTER(RegisterModels, MDL, Models, name, m_id, NEW(Model, MDL_##name##_get))
+ REGISTER(Models, MDL, name, m_id, NEW(Model, MDL_##name##_get))
PRECACHE(Models) {
FOREACH(Models, true, LAMBDA({
REGISTRY(Monsters, BITS(5))
#define Monsters_from(i) _Monsters_from(i, MON_Null)
#define get_monsterinfo(i) Monsters_from(i)
-REGISTER_REGISTRY(RegisterMonsters)
+REGISTER_REGISTRY(Monsters)
REGISTRY_CHECK(Monsters)
const int MON_FIRST = 1;
#define MON_LAST (Monsters_COUNT - 1)
/** If you register a new monster, make sure to add it to all.inc */
-#define REGISTER_MONSTER(id, inst) REGISTER(RegisterMonsters, MON, Monsters, id, monsterid, inst)
+#define REGISTER_MONSTER(id, inst) REGISTER(Monsters, MON, id, monsterid, inst)
REGISTER_MONSTER(Null, NEW(Monster));
Damage(head, self, self.realowner, (autocvar_g_monster_shambler_attack_lightning_damage_zap) * MONSTER_SKILLMOD(self), DEATH_MONSTER_SHAMBLER_ZAP.m_id, head.origin, '0 0 0');
}
- self.think = SUB_Remove;
+ self.think = SUB_Remove_self;
self.nextthink = time + 0.2;
}
#ifdef SVQC
+.float spider_slowness; // effect time of slowness inflicted by spiders
+
.float spider_web_delay;
float autocvar_g_monster_spider_attack_web_damagetime;
void M_Spider_Attack_Web();
+REGISTER_MUTATOR(spiderweb, true);
+
+MUTATOR_HOOKFUNCTION(spiderweb, PlayerPhysics)
+{
+ if (time >= self.spider_slowness)
+ return false;
+ PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider
+ PHYS_MAXAIRSPEED(self) *= 0.5;
+ PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5;
+ PHYS_AIRSTRAFEACCELERATE(self) *= 0.5;
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(spiderweb, MonsterMove)
+{
+ if(time < self.spider_slowness)
+ {
+ monster_speed_run *= 0.5;
+ monster_speed_walk *= 0.5;
+ }
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(spiderweb, PlayerSpawn)
+{
+ self.spider_slowness = 0;
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(spiderweb, MonsterSpawn)
+{
+ self.spider_slowness = 0;
+ return false;
+}
+
SOUND(SpiderAttack_FIRE, W_Sound("electro_fire"));
METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, .entity weaponentity, int fire)) {
bool isPlayer = IS_PLAYER(actor);
}
else
{
- oldself.think = SUB_Remove;
+ oldself.think = SUB_Remove_self;
oldself.nextthink = time;
}
}
if(delaytoo)
if(time < self.msound_delay)
return; // too early
- GlobalSound(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
+ GlobalSound_string(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
self.msound_delay = time + sound_delay;
}
runspeed = bound(0, monster_speed_run * MONSTER_SKILLMOD(self), runspeed * 2.5); // limit maxspeed to prevent craziness
walkspeed = bound(0, monster_speed_walk * MONSTER_SKILLMOD(self), walkspeed * 2.5); // limit maxspeed to prevent craziness
- if(time < self.spider_slowness)
- {
- runspeed *= 0.5;
- walkspeed *= 0.5;
- }
-
if(teamplay)
if(autocvar_g_monsters_teams)
if(DIFF_TEAM(self.monster_follow, self))
return true;
}
-void Monster_Reset()
-{SELFPARAM();
- setorigin(self, self.pos1);
- self.angles = self.pos2;
+void Monster_Reset(entity this)
+{
+ setorigin(this, this.pos1);
+ this.angles = this.pos2;
- Unfreeze(self); // remove any icy remains
+ Unfreeze(this); // remove any icy remains
- self.health = self.max_health;
- self.velocity = '0 0 0';
- self.enemy = world;
- self.goalentity = world;
- self.attack_finished_single[0] = 0;
- self.moveto = self.origin;
+ this.health = this.max_health;
+ this.velocity = '0 0 0';
+ this.enemy = world;
+ this.goalentity = world;
+ this.attack_finished_single[0] = 0;
+ this.moveto = this.origin;
}
void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
// number of monsters spawned with mobspawn command
totalspawned -= 1;
- self.think = SUB_Remove;
+ self.think = SUB_Remove_self;
self.nextthink = time + 0.1;
self.event_damage = func_null;
}
{
Violence_GibSplash(self, 1, 0.5, attacker);
- self.think = SUB_Remove;
+ self.think = SUB_Remove_self;
self.nextthink = time + 0.1;
}
}
self.deadflag = DEAD_NO;
self.noalign = ((mon.spawnflags & MONSTER_TYPE_FLY) || (mon.spawnflags & MONSTER_TYPE_SWIM));
self.spawn_time = time;
- self.spider_slowness = 0;
self.gravity = 1;
self.monster_moveto = '0 0 0';
self.monster_face = '0 0 0';
// other properties
.bool monster_attack; // indicates whether an entity can be attacked by monsters
-.float spider_slowness; // effect time of slowness inflicted by spiders
// monster state declarations
const int MONSTER_MOVE_FOLLOW = 1; // monster will follow if in range, or stand still
-void _Movetype_Physics_Follow() // SV_Physics_Follow
-{SELFPARAM();
- entity e = self.move_aiment; // TODO: networking?
+void _Movetype_Physics_Follow(entity this) // SV_Physics_Follow
+{
+ entity e = this.move_aiment; // TODO: networking?
// LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
- if(self.move_angles == self.move_punchangle)
+ if(this.move_angles == this.move_punchangle)
{
- self.move_origin = e.move_origin + self.view_ofs;
+ this.move_origin = e.move_origin + this.view_ofs;
}
else
{
vector ang, v;
- ang_x = -self.move_punchangle_x;
- ang_y = self.move_punchangle_y;
- ang_z = self.move_punchangle_z;
+ ang_x = -this.move_punchangle_x;
+ ang_y = this.move_punchangle_y;
+ ang_z = this.move_punchangle_z;
makevectors(ang);
- v_x = self.view_ofs_x * v_forward_x + self.view_ofs_y * v_right_x + self.view_ofs_z * v_up_x;
- v_y = self.view_ofs_x * v_forward_y + self.view_ofs_y * v_right_y + self.view_ofs_z * v_up_y;
- v_z = self.view_ofs_x * v_forward_z + self.view_ofs_y * v_right_z + self.view_ofs_z * v_up_z;
+ v_x = this.view_ofs_x * v_forward_x + this.view_ofs_y * v_right_x + this.view_ofs_z * v_up_x;
+ v_y = this.view_ofs_x * v_forward_y + this.view_ofs_y * v_right_y + this.view_ofs_z * v_up_y;
+ v_z = this.view_ofs_x * v_forward_z + this.view_ofs_y * v_right_z + this.view_ofs_z * v_up_z;
ang_x = -e.move_angles_x;
ang_y = e.move_angles_y;
ang_z = e.move_angles_z;
makevectors(ang);
- self.move_origin_x = v_x * v_forward_x + v_y * v_forward_y + v_z * v_forward_z + e.move_origin_x;
- self.move_origin_x = v_x * v_right_x + v_y * v_right_y + v_z * v_right_z + e.move_origin_y;
- self.move_origin_x = v_x * v_up_x + v_y * v_up_y + v_z * v_up_z + e.move_origin_z;
+ this.move_origin_x = v_x * v_forward_x + v_y * v_forward_y + v_z * v_forward_z + e.move_origin_x;
+ this.move_origin_x = v_x * v_right_x + v_y * v_right_y + v_z * v_right_z + e.move_origin_y;
+ this.move_origin_x = v_x * v_up_x + v_y * v_up_y + v_z * v_up_z + e.move_origin_z;
}
- self.move_angles = e.move_angles + self.v_angle;
- _Movetype_LinkEdict(false);
+ this.move_angles = e.move_angles + this.v_angle;
+ _Movetype_LinkEdict(this, false);
}
#include "../../server/autocvars.qh"
#endif
-void _Movetype_WallFriction(vector stepnormal) // SV_WallFriction
+void _Movetype_WallFriction(entity this, vector stepnormal) // SV_WallFriction
{
/*float d, i;
vector into, side;
- makevectors(self.v_angle);
+ makevectors(this.v_angle);
d = (stepnormal * v_forward) + 0.5;
if(d < 0)
{
- i = (stepnormal * self.move_velocity);
+ i = (stepnormal * this.move_velocity);
into = i * stepnormal;
- side = self.move_velocity - into;
- self.move_velocity_x = side.x * (1 * d);
- self.move_velocity_y = side.y * (1 * d);
+ side = this.move_velocity - into;
+ this.move_velocity_x = side.x * (1 * d);
+ this.move_velocity_y = side.y * (1 * d);
}*/
}
vector planes[MAX_CLIP_PLANES];
-int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
-{SELFPARAM();
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
+{
int blocked = 0, bumpcount;
int i, j, numplanes = 0;
float time_left = dt, grav = 0;
if(applygravity)
{
- self.move_didgravity = 1;
- grav = dt * (PHYS_ENTGRAVITY(self) ? PHYS_ENTGRAVITY(self) : 1) * PHYS_GRAVITY;
+ this.move_didgravity = 1;
+ grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
- if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
{
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
- self.move_velocity_z -= grav * 0.5;
+ if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.move_velocity_z -= grav * 0.5;
else
- self.move_velocity_z -= grav;
+ this.move_velocity_z -= grav;
}
}
- original_velocity = primal_velocity = restore_velocity = self.move_velocity;
+ original_velocity = primal_velocity = restore_velocity = this.move_velocity;
for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
{
- if(self.move_velocity == '0 0 0')
+ if(this.move_velocity == '0 0 0')
break;
- push = self.move_velocity * time_left;
- vector prev_origin = self.move_origin;
- _Movetype_PushEntity(push, true);
- if(trace_startsolid && self.move_origin != prev_origin)
+ push = this.move_velocity * time_left;
+ _Movetype_PushEntity(this, push, true);
+ if(trace_startsolid)
{
// we got teleported by a touch function
// let's abort the move
// abort move if we're stuck in the world (and didn't make it out)
if(trace_startsolid && trace_allsolid)
{
- self.move_velocity = restore_velocity;
+ this.move_velocity = restore_velocity;
return 3;
}
float my_trace_fraction = trace_fraction;
vector my_trace_plane_normal = trace_plane_normal;
- if(trace_plane_normal_z)
+ if(trace_plane_normal.z)
{
- if(trace_plane_normal_z > 0.7)
+ if(trace_plane_normal.z > 0.7)
{
// floor
blocked |= 1;
trace_ent = world;
}
- self.move_flags |= FL_ONGROUND;
- self.move_groundentity = trace_ent;
+ this.move_flags |= FL_ONGROUND;
+ this.move_groundentity = trace_ent;
}
}
else if(stepheight)
{
// step - handle it immediately
- vector org = self.move_origin;
+ vector org = this.move_origin;
vector steppush = '0 0 1' * stepheight;
- _Movetype_PushEntity(steppush, true);
- if(trace_startsolid && self.move_origin != org)
+ _Movetype_PushEntity(this, steppush, true);
+ if(trace_startsolid)
{
blocked |= 8;
break;
}
- _Movetype_PushEntity(push, true);
- if(trace_startsolid && self.move_origin != org)
+ _Movetype_PushEntity(this, push, true);
+ if(trace_startsolid)
{
blocked |= 8;
break;
}
float trace2_fraction = trace_fraction;
- steppush = '0 0 1' * (org_z - self.move_origin_z);
- _Movetype_PushEntity(steppush, true);
- if(trace_startsolid && self.move_origin != org)
+ steppush = '0 0 1' * (org_z - this.move_origin_z);
+ _Movetype_PushEntity(this, steppush, true);
+ if(trace_startsolid)
{
blocked |= 8;
break;
}
// accept the new position if it made some progress...
- if(fabs(self.move_origin_x - org_x) >= 0.03125 || fabs(self.move_origin_y - org_y) >= 0.03125)
+ if(fabs(this.move_origin_x - org_x) >= 0.03125 || fabs(this.move_origin_y - org_y) >= 0.03125)
{
- trace_endpos = self.move_origin;
+ trace_endpos = this.move_origin;
time_left *= 1 - trace2_fraction;
numplanes = 0;
continue;
}
else
- self.move_origin = org;
+ this.move_origin = org;
}
else
{
if(my_trace_fraction >= 0.001)
{
// actually covered some distance
- original_velocity = self.move_velocity;
+ original_velocity = this.move_velocity;
numplanes = 0;
}
if(numplanes >= MAX_CLIP_PLANES)
{
// this shouldn't really happen
- self.move_velocity = '0 0 0';
+ this.move_velocity = '0 0 0';
blocked = 3;
break;
}
if(i != numplanes)
{
// go along this plane
- self.move_velocity = new_velocity;
+ this.move_velocity = new_velocity;
}
else
{
// go along the crease
if(numplanes != 2)
{
- self.move_velocity = '0 0 0';
+ this.move_velocity = '0 0 0';
blocked = 7;
break;
}
dir.x *= ilength;
dir.y *= ilength;
dir.z *= ilength;
- float d = (dir * self.move_velocity);
- self.move_velocity = dir * d;
+ float d = (dir * this.move_velocity);
+ this.move_velocity = dir * d;
}
// if current velocity is against the original velocity,
// stop dead to avoid tiny occilations in sloping corners
- if((self.move_velocity * primal_velocity) <= 0)
+ if((this.move_velocity * primal_velocity) <= 0)
{
- self.move_velocity = '0 0 0';
+ this.move_velocity = '0 0 0';
break;
}
}
// LordHavoc: this came from QW and allows you to get out of water more easily
- if(GAMEPLAYFIX_EASIERWATERJUMP && (self.move_flags & FL_WATERJUMP) && !(blocked & 8))
- self.move_velocity = primal_velocity;
+ if(GAMEPLAYFIX_EASIERWATERJUMP && (this.move_flags & FL_WATERJUMP) && !(blocked & 8))
+ this.move_velocity = primal_velocity;
if(applygravity)
{
- if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
{
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
- self.move_velocity_z -= grav * 0.5f;
+ if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.move_velocity_z -= grav * 0.5f;
}
}
return blocked;
}
-void _Movetype_CheckVelocity() // SV_CheckVelocity
+void _Movetype_CheckVelocity(entity this) // SV_CheckVelocity
{
- // if(vlen(self.move_velocity) < 0.0001)
- // self.move_velocity = '0 0 0';
+ // if(vlen(this.move_velocity) < 0.0001)
+ // this.move_velocity = '0 0 0';
}
bool _Movetype_CheckWater(entity ent) // SV_CheckWater
}
}
-void _Movetype_Impact(entity oth) // SV_Impact
-{SELFPARAM();
+void _Movetype_Impact(entity this, entity oth) // SV_Impact
+{
entity oldother = other;
- if(self.move_touch)
+ if(this.move_touch)
{
other = oth;
- self.move_touch();
+ WITH(entity, self, this, this.move_touch());
other = oldother;
}
if(oth.move_touch)
{
- other = self;
+ other = this;
WITH(entity, self, oth, oth.move_touch());
}
}
-void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
-{SELFPARAM();
+void _Movetype_LinkEdict_TouchAreaGrid(entity this) // SV_LinkEdict_TouchAreaGrid
+{
entity oldother = other;
- for (entity e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
+ for (entity e = findradius(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin)); e; e = e.chain)
{
+ if(e.move_nomonsters != MOVE_NOMONSTERS && e.move_nomonsters != MOVE_WORLDONLY)
if(e.move_touch && boxesoverlap(e.absmin, e.absmax, this.absmin, this.absmax))
{
- setself(e);
other = this;
trace_allsolid = false;
trace_plane_dist = 0;
trace_ent = this;
- e.move_touch();
+ WITH(entity, self, e, e.move_touch());
}
}
other = oldother;
- setself(this);
}
-void _Movetype_LinkEdict(bool touch_triggers) // SV_LinkEdict
-{SELFPARAM();
+void _Movetype_LinkEdict(entity this, bool touch_triggers) // SV_LinkEdict
+{
vector mi, ma;
- if(self.solid == SOLID_BSP)
+ if(this.solid == SOLID_BSP)
{
// TODO set the absolute bbox
- mi = self.mins;
- ma = self.maxs;
+ mi = this.mins;
+ ma = this.maxs;
}
else
{
- mi = self.mins;
- ma = self.maxs;
+ mi = this.mins;
+ ma = this.maxs;
}
- mi += self.move_origin;
- ma += self.move_origin;
+ mi += this.move_origin;
+ ma += this.move_origin;
- if(self.move_flags & FL_ITEM)
+ if(this.move_flags & FL_ITEM)
{
mi.x -= 15;
mi.y -= 15;
ma.z += 1;
}
- self.absmin = mi;
- self.absmax = ma;
+ this.absmin = mi;
+ this.absmax = ma;
if(touch_triggers)
- _Movetype_LinkEdict_TouchAreaGrid();
+ _Movetype_LinkEdict_TouchAreaGrid(this);
}
-bool _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
-{SELFPARAM();
-// vector org = self.move_origin + ofs;
+bool _Movetype_TestEntityPosition(entity this, vector ofs) // SV_TestEntityPosition
+{
+// vector org = this.move_origin + ofs;
- int cont = self.dphitcontentsmask;
- self.dphitcontentsmask = DPCONTENTS_SOLID;
- tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
- self.dphitcontentsmask = cont;
+ int cont = this.dphitcontentsmask;
+ this.dphitcontentsmask = DPCONTENTS_SOLID;
+ tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
+ this.dphitcontentsmask = cont;
if(trace_startsolid)
return true;
- if(vlen(trace_endpos - self.move_origin) > 0.0001)
- self.move_origin = trace_endpos;
+ if(vlen(trace_endpos - this.move_origin) > 0.0001)
+ this.move_origin = trace_endpos;
return false;
}
-bool _Movetype_UnstickEntity() // SV_UnstickEntity
-{SELFPARAM();
- if(!_Movetype_TestEntityPosition('0 0 0')) return true;
- if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
- if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
- if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
- if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
- if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
- if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
- if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
- if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
+bool _Movetype_UnstickEntity(entity this) // SV_UnstickEntity
+{
+ if(!_Movetype_TestEntityPosition(this, '0 0 0')) return true;
+ if(!_Movetype_TestEntityPosition(this, '-1 0 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '1 0 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 -1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '-1 -1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '1 -1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '-1 1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '1 1 0')) goto success;
for (int i = 1; i <= 17; ++i)
{
- if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
- if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 0 -1' * i)) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 0 1' * i)) goto success;
}
LOG_TRACEF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
- num_for_edict(self), self.classname, vtos(self.move_origin));
+ num_for_edict(this), this.classname, vtos(this.move_origin));
return false;
: success;
LOG_TRACEF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
- num_for_edict(self), self.classname, vtos(self.move_origin));
- _Movetype_LinkEdict(true);
+ num_for_edict(this), this.classname, vtos(this.move_origin));
+ _Movetype_LinkEdict(this, true);
return true;
}
return vel;
}
-void _Movetype_PushEntityTrace(vector push)
-{SELFPARAM();
- vector end = self.move_origin + push;
+void _Movetype_PushEntityTrace(entity this, vector push)
+{
+ vector end = this.move_origin + push;
int type;
- if(self.move_nomonsters)
- type = max(0, self.move_nomonsters);
- else if(self.move_movetype == MOVETYPE_FLYMISSILE)
+ if(this.move_nomonsters)
+ type = max(0, this.move_nomonsters);
+ else if(this.move_movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
- else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+ else if(this.move_movetype == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
+ else if(this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
type = MOVE_NOMONSTERS;
else
type = MOVE_NORMAL;
- tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
+ tracebox(this.move_origin, this.mins, this.maxs, end, type, this);
}
-float _Movetype_PushEntity(vector push, bool failonstartsolid) // SV_PushEntity
-{SELFPARAM();
- _Movetype_PushEntityTrace(push);
+float _Movetype_PushEntity(entity this, vector push, bool failonstartsolid) // SV_PushEntity
+{
+ _Movetype_PushEntityTrace(this, push);
if(trace_startsolid && failonstartsolid)
return trace_fraction;
- self.move_origin = trace_endpos;
+ this.move_origin = trace_endpos;
if(trace_fraction < 1)
- if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
- _Movetype_Impact(trace_ent);
+ if(this.solid >= SOLID_TRIGGER && (!(this.move_flags & FL_ONGROUND) || (this.move_groundentity != trace_ent)))
+ _Movetype_Impact(this, trace_ent);
return trace_fraction;
}
}
}
-void _Movetype_Physics_Frame(float movedt)
-{SELFPARAM();
- self.move_didgravity = -1;
- switch (self.move_movetype)
+void _Movetype_Physics_Frame(entity this, float movedt)
+{
+ this.move_didgravity = -1;
+ switch (this.move_movetype)
{
case MOVETYPE_PUSH:
case MOVETYPE_FAKEPUSH:
- _Movetype_Physics_Pusher(movedt);
+ _Movetype_Physics_Pusher(this, movedt);
break;
case MOVETYPE_NONE:
break;
case MOVETYPE_FOLLOW:
- _Movetype_Physics_Follow();
+ _Movetype_Physics_Follow(this);
break;
case MOVETYPE_NOCLIP:
- _Movetype_CheckWater(self);
- self.move_origin = self.move_origin + TICRATE * self.move_velocity;
- self.move_angles = self.move_angles + TICRATE * self.move_avelocity;
- _Movetype_LinkEdict(false);
+ _Movetype_CheckWater(this);
+ this.move_origin = this.move_origin + TICRATE * this.move_velocity;
+ this.move_angles = this.move_angles + TICRATE * this.move_avelocity;
+ _Movetype_LinkEdict(this, false);
break;
case MOVETYPE_STEP:
- _Movetype_Physics_Step(movedt);
+ _Movetype_Physics_Step(this, movedt);
break;
case MOVETYPE_WALK:
- _Movetype_Physics_Walk(movedt);
+ _Movetype_Physics_Walk(this, movedt);
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
case MOVETYPE_FLY:
- _Movetype_Physics_Toss(movedt);
+ case MOVETYPE_FLY_WORLDONLY:
+ _Movetype_Physics_Toss(this, movedt);
+ break;
+ }
+}
+
+void _Movetype_Physics_ClientFrame(entity this, float movedt)
+{
+ this.move_didgravity = -1;
+ switch (this.move_movetype)
+ {
+ case MOVETYPE_PUSH:
+ case MOVETYPE_FAKEPUSH:
+ _Movetype_Physics_Pusher(this, movedt);
+ break;
+ case MOVETYPE_NONE:
+ break;
+ case MOVETYPE_FOLLOW:
+ _Movetype_Physics_Follow(this);
+ break;
+ case MOVETYPE_NOCLIP:
+ _Movetype_CheckWater(this);
+ this.move_origin = this.move_origin + TICRATE * this.move_velocity;
+ this.move_angles = this.move_angles + TICRATE * this.move_avelocity;
+ _Movetype_LinkEdict(this, false);
+ break;
+ case MOVETYPE_STEP:
+ _Movetype_Physics_Step(this, movedt);
+ break;
+ case MOVETYPE_WALK:
+ case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
+ _Movetype_Physics_Walk(this, movedt);
+ break;
+ case MOVETYPE_TOSS:
+ case MOVETYPE_BOUNCE:
+ case MOVETYPE_BOUNCEMISSILE:
+ case MOVETYPE_FLYMISSILE:
+ _Movetype_Physics_Toss(this, movedt);
+ break;
+ case MOVETYPE_PHYSICS:
break;
}
}
-void Movetype_Physics_NoMatchServer() // optimized
-{SELFPARAM();
- float movedt = time - self.move_time;
- self.move_time = time;
+void Movetype_Physics_NoMatchServer(entity this) // optimized
+{
+ float movedt = time - this.move_time;
+ this.move_time = time;
- _Movetype_Physics_Frame(movedt);
- if(wasfreed(self))
+ _Movetype_Physics_Frame(this, movedt);
+ if(wasfreed(this))
return;
- self.avelocity = self.move_avelocity;
- self.velocity = self.move_velocity;
- self.angles = self.move_angles;
- setorigin(self, self.move_origin);
+ this.avelocity = this.move_avelocity;
+ this.velocity = this.move_velocity;
+ this.angles = this.move_angles;
+ setorigin(this, this.move_origin);
}
-void Movetype_Physics_MatchServer(bool sloppy)
+void Movetype_Physics_MatchServer(entity this, bool sloppy)
{
- Movetype_Physics_MatchTicrate(TICRATE, sloppy);
+ Movetype_Physics_MatchTicrate(this, TICRATE, sloppy);
}
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
-{SELFPARAM();
+void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy) // SV_Physics_Entity
+{
if(tr <= 0)
{
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(this);
return;
}
- float dt = time - self.move_time;
+ float dt = time - this.move_time;
int n = max(0, floor(dt / tr));
dt -= n * tr;
- self.move_time += n * tr;
+ this.move_time += n * tr;
- if(!self.move_didgravity)
- self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
+ if(!this.move_didgravity)
+ this.move_didgravity = ((this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS) && !(this.move_flags & FL_ONGROUND));
for (int i = 0; i < n; ++i)
{
- _Movetype_Physics_Frame(tr);
- if(wasfreed(self))
+ _Movetype_Physics_Frame(this, tr);
+ if(wasfreed(this))
return;
}
- self.avelocity = self.move_avelocity;
+ this.avelocity = this.move_avelocity;
- if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))
+ if(dt > 0 && this.move_movetype != MOVETYPE_NONE && !(this.move_flags & FL_ONGROUND))
{
// now continue the move from move_time to time
- self.velocity = self.move_velocity;
+ this.velocity = this.move_velocity;
- if(self.move_didgravity > 0)
+ if(this.move_didgravity > 0)
{
- self.velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+ this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (self.gravity ? self.gravity : 1)
- * PHYS_GRAVITY;
+ * (this.gravity ? this.gravity : 1)
+ * PHYS_GRAVITY(this);
}
- self.angles = self.move_angles + dt * self.avelocity;
+ this.angles = this.move_angles + dt * this.avelocity;
- if(sloppy || self.move_movetype == MOVETYPE_NOCLIP)
+ if(sloppy || this.move_movetype == MOVETYPE_NOCLIP)
{
- setorigin(self, self.move_origin + dt * self.velocity);
+ setorigin(this, this.move_origin + dt * this.velocity);
}
else
{
- _Movetype_PushEntityTrace(dt * self.velocity);
+ _Movetype_PushEntityTrace(this, dt * this.velocity);
if(!trace_startsolid)
- setorigin(self, trace_endpos);
+ setorigin(this, trace_endpos);
}
- if(self.move_didgravity > 0 && GRAVITY_UNAFFECTED_BY_TICRATE)
- self.velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
+ if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
}
else
{
- self.velocity = self.move_velocity;
- self.angles = self.move_angles;
- setorigin(self, self.move_origin);
+ this.velocity = this.move_velocity;
+ this.angles = this.move_angles;
+ setorigin(this, this.move_origin);
}
}
// should match sv_gameplayfix_fixedcheckwatertransition
float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1;
-#ifdef SVQC
-.int stat_gameplayfix_upvelocityclearsonground;
-
-#define GRAVITY_UNAFFECTED_BY_TICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
-#define UPWARD_VELOCITY_CLEARS_ONGROUND autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag
-
-#define TICRATE sys_frametime
-#elif defined(CSQC)
-#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
-#define UPWARD_VELOCITY_CLEARS_ONGROUND getstati(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
-
-#define TICRATE ticrate
-#endif
-
.entity move_groundentity; // FIXME add move_groundnetworkentity?
.float move_suspendedinair;
.float move_didgravity;
-void _Movetype_WallFriction(vector stepnormal);
-int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight);
-void _Movetype_CheckVelocity();
+void _Movetype_WallFriction(entity this, vector stepnormal);
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight);
+void _Movetype_CheckVelocity(entity this);
void _Movetype_CheckWaterTransition(entity ent);
float _Movetype_CheckWater(entity ent);
-void _Movetype_LinkEdict_TouchAreaGrid();
-void _Movetype_LinkEdict(float touch_triggers);
-float _Movetype_TestEntityPosition(vector ofs);
-float _Movetype_UnstickEntity();
+void _Movetype_LinkEdict_TouchAreaGrid(entity this);
+void _Movetype_LinkEdict(entity this, float touch_triggers);
+float _Movetype_TestEntityPosition(entity this, vector ofs);
+float _Movetype_UnstickEntity(entity this);
vector _Movetype_ClipVelocity(vector vel, vector norm, float f);
-void _Movetype_PushEntityTrace(vector push);
-float _Movetype_PushEntity(vector push, float failonstartsolid);
+void _Movetype_PushEntityTrace(entity this, vector push);
+float _Movetype_PushEntity(entity this, vector push, float failonstartsolid);
void makevectors_matrix(vector myangles);
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy);
-void Movetype_Physics_MatchServer(bool sloppy);
-void Movetype_Physics_NoMatchServer();
-void _Movetype_LinkEdict(float touch_triggers);
-void _Movetype_LinkEdict_TouchAreaGrid();
+void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy);
+void Movetype_Physics_MatchServer(entity this, bool sloppy);
+void Movetype_Physics_NoMatchServer(entity this);
+void _Movetype_LinkEdict(entity this, float touch_triggers);
+void _Movetype_LinkEdict_TouchAreaGrid(entity this);
-float _Movetype_UnstickEntity();
+float _Movetype_UnstickEntity(entity this);
const int MAX_CLIP_PLANES = 5;
const int MOVETYPE_BOUNCE = 10;
const int MOVETYPE_BOUNCEMISSILE = 11; // Like bounce but doesn't lose speed on bouncing
const int MOVETYPE_FOLLOW = 12;
+const int MOVETYPE_PHYSICS = 32;
const int MOVETYPE_FLY_WORLDONLY = 33;
const int FL_ITEM = 256;
const int MOVETYPE_FAKEPUSH = 13;
-const float MOVEFLAG_Q2AIRACCELERATE = 1;
-const float MOVEFLAG_NOGRAVITYONGROUND = 2;
-const float MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = 4;
+const int MOVEFLAG_VALID = BIT(23);
+const int MOVEFLAG_Q2AIRACCELERATE = BIT(0);
+const int MOVEFLAG_NOGRAVITYONGROUND = BIT(1);
+const int MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = BIT(2);
#ifdef CSQC
-// TODO: figure out server's version of this
-#define moveflags (getstati(STAT_MOVEFLAGS))
+#define moveflags STAT(MOVEFLAGS)
#endif
#endif
-void _Movetype_PushMove(float dt) // SV_PushMove
-{SELFPARAM();
- if (self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
+void _Movetype_PushMove(entity this, float dt) // SV_PushMove
+{
+ if (this.move_velocity == '0 0 0' && this.move_avelocity == '0 0 0')
{
- self.move_ltime += dt;
+ this.move_ltime += dt;
return;
}
- switch (self.solid)
+ switch (this.solid)
{
// LordHavoc: valid pusher types
case SOLID_BSP:
// LordHavoc: no collisions
case SOLID_NOT:
case SOLID_TRIGGER:
- self.move_origin = self.move_origin + dt * self.move_velocity;
- self.move_angles = self.move_angles + dt * self.move_avelocity;
- self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
- self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
- self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
- self.move_ltime += dt;
- _Movetype_LinkEdict(true);
+ this.move_origin = this.move_origin + dt * this.move_velocity;
+ this.move_angles = this.move_angles + dt * this.move_avelocity;
+ this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
+ this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
+ this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
+ this.move_ltime += dt;
+ _Movetype_LinkEdict(this, true);
return;
default:
- LOG_TRACEF("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", self, self.solid);
+ LOG_TRACEF("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", this, this.solid);
return;
}
- bool rotated = (self.move_angles * self.move_angles) + (self.move_avelocity * self.move_avelocity) > 0;
+ bool rotated = (this.move_angles * this.move_angles) + (this.move_avelocity * this.move_avelocity) > 0;
- vector move1 = self.move_velocity * dt;
- vector moveangle = self.move_avelocity * dt;
+ vector move1 = this.move_velocity * dt;
+ vector moveangle = this.move_avelocity * dt;
makevectors_matrix(-moveangle);
-// vector pushorig = self.move_origin;
-// vector pushang = self.move_angles;
-// float pushltime = self.move_ltime;
+// vector pushorig = this.move_origin;
+// vector pushang = this.move_angles;
+// float pushltime = this.move_ltime;
// move the pusher to its final position
- self.move_origin = self.move_origin + dt * self.move_velocity;
- self.move_angles = self.move_angles + dt * self.move_avelocity;
+ this.move_origin = this.move_origin + dt * this.move_velocity;
+ this.move_angles = this.move_angles + dt * this.move_avelocity;
- self.move_ltime += dt;
- _Movetype_LinkEdict(true);
+ this.move_ltime += dt;
+ _Movetype_LinkEdict(this, true);
- int savesolid = self.solid;
+ int savesolid = this.solid;
- if (self.move_movetype != MOVETYPE_FAKEPUSH)
+ if (this.move_movetype != MOVETYPE_FAKEPUSH)
{
- for (entity check = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); check; check = check.chain)
+ for (entity check = findradius(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin)); check; check = check.chain)
{
switch (check.move_movetype)
{
break;
}
- if (check.owner == self)
+ if (check.owner == this)
continue;
- if (self.owner == check)
+ if (this.owner == check)
continue;
vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
vector move;
if (rotated)
{
- vector org = (check.move_origin - self.move_origin) + pivot;
+ vector org = (check.move_origin - this.move_origin) + pivot;
vector org2;
org2.x = org * v_forward;
org2.y = org * v_right;
if (check.move_movetype == 32) // MOVETYPE_PHYSICS
{
check.move_origin = check.move_origin + move;
- WITH(entity, self, check, _Movetype_LinkEdict(true));
+ WITH(entity, this, check, _Movetype_LinkEdict(this, true));
continue;
}
// try moving the contacted entity
- self.solid = SOLID_NOT;
+ this.solid = SOLID_NOT;
bool flag;
- WITH(entity, self, check, {
- flag = _Movetype_PushEntity(move, true);
+ WITH(entity, this, check, {
+ flag = _Movetype_PushEntity(this, move, true);
});
if (!flag)
{
// entity "check" got teleported
check.move_angles_y += trace_fraction * moveangle.y;
- self.solid = savesolid;
+ this.solid = savesolid;
continue; // pushed enough
}
// FIXME: turn players specially
check.move_angles_y += trace_fraction * moveangle.y;
- self.solid = savesolid;
+ this.solid = savesolid;
// this trace.fraction < 1 check causes items to fall off of pushers
// if they pass under or through a wall
// the groundentity check causes items to fall off of ledges
- if (check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != self))
+ if (check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != this))
check.move_flags &= ~FL_ONGROUND;
}
}
- self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
- self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
- self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
+ this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
+ this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
+ this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
}
-void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher
-{SELFPARAM();
- float oldltime = self.move_ltime;
- float thinktime = self.move_nextthink;
+void _Movetype_Physics_Pusher(entity this, float dt) // SV_Physics_Pusher
+{
+ float oldltime = this.move_ltime;
+ float thinktime = this.move_nextthink;
float movetime;
- if (thinktime < self.move_ltime + dt)
+ if (thinktime < this.move_ltime + dt)
{
- movetime = thinktime - self.move_ltime;
+ movetime = thinktime - this.move_ltime;
if (movetime < 0)
movetime = 0;
}
}
if (movetime)
- // advances self.move_ltime if not blocked
- _Movetype_PushMove(movetime);
+ // advances this.move_ltime if not blocked
+ _Movetype_PushMove(this, movetime);
- if (thinktime > oldltime && thinktime <= self.move_ltime)
+ if (thinktime > oldltime && thinktime <= this.move_ltime)
{
- self.move_nextthink = 0;
- self.move_time = time;
+ this.move_nextthink = 0;
+ this.move_time = time;
other = world;
- if (self.move_think)
- self.move_think();
+ WITH(entity, self, this, this.move_think());
}
}
#ifndef MOVETYPE_PUSH_H
#define MOVETYPE_PUSH_H
-void _Movetype_Physics_Pusher(float dt);
+void _Movetype_Physics_Pusher(entity this, float dt);
#endif
-void _Movetype_Physics_Step(float dt) // SV_Physics_Step
-{SELFPARAM();
- if(self.move_flags & FL_ONGROUND)
+void _Movetype_Physics_Step(entity this, float dt) // SV_Physics_Step
+{
+ if(this.move_flags & FL_ONGROUND)
{
- if(self.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
+ if(this.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
{
- self.move_flags &= ~FL_ONGROUND;
- _Movetype_CheckVelocity();
- _Movetype_FlyMove(dt, true, '0 0 0', 0);
- _Movetype_LinkEdict(true);
+ this.move_flags &= ~FL_ONGROUND;
+ _Movetype_CheckVelocity(this);
+ _Movetype_FlyMove(this, dt, true, '0 0 0', 0);
+ _Movetype_LinkEdict(this, true);
}
}
else
{
- _Movetype_CheckVelocity();
- _Movetype_FlyMove(dt, true, '0 0 0', 0);
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_FlyMove(this, dt, true, '0 0 0', 0);
+ _Movetype_LinkEdict(this, true);
// TODO? movetypesteplandevent
}
- _Movetype_CheckWaterTransition(self);
+ _Movetype_CheckWaterTransition(this);
}
#include "../physics.qh"
-void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
-{SELFPARAM();
- if (self.move_flags & FL_ONGROUND)
+void _Movetype_Physics_Toss(entity this, float dt) // SV_Physics_Toss
+{
+ if (this.move_flags & FL_ONGROUND)
{
- if (self.move_velocity.z >= 1 / 32)
+ if (this.move_velocity.z >= 1 / 32)
{
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
}
- else if (!self.move_groundentity)
+ else if (!this.move_groundentity)
{
return;
}
- else if (self.move_suspendedinair && wasfreed(self.move_groundentity))
+ else if (this.move_suspendedinair && wasfreed(this.move_groundentity))
{
- self.move_groundentity = world;
+ this.move_groundentity = world;
return;
}
}
- self.move_suspendedinair = false;
+ this.move_suspendedinair = false;
- _Movetype_CheckVelocity();
+ _Movetype_CheckVelocity(this);
- if (self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
+ if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
{
- self.move_didgravity = 1;
- self.move_velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+ this.move_didgravity = 1;
+ this.move_velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (self.gravity ? self.gravity : 1)
- * PHYS_GRAVITY;
+ * (this.gravity ? this.gravity : 1)
+ * PHYS_GRAVITY(this);
}
- self.move_angles = self.move_angles + self.move_avelocity * dt;
+ this.move_angles = this.move_angles + this.move_avelocity * dt;
float movetime = dt;
for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
{
- vector move = self.move_velocity * movetime;
- _Movetype_PushEntity(move, true);
- if (wasfreed(self))
+ vector move = this.move_velocity * movetime;
+ _Movetype_PushEntity(this, move, true);
+ if (wasfreed(this))
return;
if (trace_startsolid)
{
- _Movetype_UnstickEntity();
- _Movetype_PushEntity(move, false);
- if (wasfreed(self))
+ _Movetype_UnstickEntity(this);
+ _Movetype_PushEntity(this, move, false);
+ if (wasfreed(this))
return;
}
movetime *= 1 - min(1, trace_fraction);
- if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
{
- self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
- self.move_flags &= ~FL_ONGROUND;
+ this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 2.0);
+ this.move_flags &= ~FL_ONGROUND;
}
- else if (self.move_movetype == MOVETYPE_BOUNCE)
+ else if (this.move_movetype == MOVETYPE_BOUNCE)
{
- float bouncefac = self.move_bounce_factor; if (!bouncefac) bouncefac = 0.5;
- float bouncestop = self.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
- bouncestop *= (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
+ float bouncefac = this.move_bounce_factor; if (!bouncefac) bouncefac = 0.5;
+ float bouncestop = this.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
+ bouncestop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
- self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
+ this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 1 + bouncefac);
- float d = trace_plane_normal * self.move_velocity;
+ float d = trace_plane_normal * this.move_velocity;
if (trace_plane_normal.z > 0.7 && d < bouncestop && d > -bouncestop)
{
- self.move_flags |= FL_ONGROUND;
- self.move_groundentity = trace_ent;
- self.move_velocity = '0 0 0';
- self.move_avelocity = '0 0 0';
+ this.move_flags |= FL_ONGROUND;
+ this.move_groundentity = trace_ent;
+ this.move_velocity = '0 0 0';
+ this.move_avelocity = '0 0 0';
}
else
{
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
}
}
else
{
- self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
+ this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 1.0);
if (trace_plane_normal.z > 0.7)
{
- self.move_flags |= FL_ONGROUND;
- self.move_groundentity = trace_ent;
+ this.move_flags |= FL_ONGROUND;
+ this.move_groundentity = trace_ent;
if (trace_ent.solid == SOLID_BSP)
- self.move_suspendedinair = true;
- self.move_velocity = '0 0 0';
- self.move_avelocity = '0 0 0';
+ this.move_suspendedinair = true;
+ this.move_velocity = '0 0 0';
+ this.move_avelocity = '0 0 0';
}
else
{
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
}
}
// DP revision 8905 (just, WHY...)
- if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
break;
// DP revision 8918 (WHY...)
- if (self.move_flags & FL_ONGROUND)
+ if (this.move_flags & FL_ONGROUND)
break;
}
- if (GRAVITY_UNAFFECTED_BY_TICRATE && self.move_didgravity > 0 && !(self.move_flags & FL_ONGROUND))
- self.move_velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !(this.move_flags & FL_ONGROUND))
+ this.move_velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
- _Movetype_CheckWaterTransition(self);
+ _Movetype_CheckWaterTransition(this);
}
#ifndef MOVETYPE_TOSS_H
#define MOVETYPE_TOSS_H
-void _Movetype_Physics_Toss(float dt);
+void _Movetype_Physics_Toss(entity this, float dt);
#endif
-void _Movetype_Physics_Walk(float dt) // SV_WalkMove
-{SELFPARAM();
+void _Movetype_Physics_Walk(entity this, float dt) // SV_WalkMove
+{
vector stepnormal = '0 0 0';
// if frametime is 0 (due to client sending the same timestamp twice), don't move
return;
if (GAMEPLAYFIX_UNSTICKPLAYERS)
- _Movetype_UnstickEntity();
+ _Movetype_UnstickEntity(this);
- bool applygravity = (!_Movetype_CheckWater(self) && self.move_movetype == MOVETYPE_WALK && !(self.move_flags & FL_WATERJUMP));
+ bool applygravity = (!_Movetype_CheckWater(this) && this.move_movetype == MOVETYPE_WALK && !(this.move_flags & FL_WATERJUMP));
- _Movetype_CheckVelocity();
+ _Movetype_CheckVelocity(this);
// do a regular slide move unless it looks like you ran into a step
- bool oldonground = (self.move_flags & FL_ONGROUND);
+ bool oldonground = (this.move_flags & FL_ONGROUND);
- vector start_origin = self.move_origin;
- vector start_velocity = self.move_velocity;
+ vector start_origin = this.move_origin;
+ vector start_velocity = this.move_velocity;
- int clip = _Movetype_FlyMove(dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES ? PHYS_STEPHEIGHT : 0);
+ int clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES ? PHYS_STEPHEIGHT : 0);
if (GAMEPLAYFIX_DOWNTRACEONGROUND && !(clip & 1))
{
// only try this if there was no floor in the way in the trace (no,
// this check seems to be not REALLY necessary, because if clip & 1,
// our trace will hit that thing too)
- vector upmove = self.move_origin + '0 0 1';
- vector downmove = self.move_origin - '0 0 1';
+ vector upmove = this.move_origin + '0 0 1';
+ vector downmove = this.move_origin - '0 0 1';
int type;
- if (self.move_movetype == MOVETYPE_FLYMISSILE)
+ if (this.move_movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
- else if (self.move_movetype == MOVETYPE_FLY_WORLDONLY)
+ else if (this.move_movetype == MOVETYPE_FLY_WORLDONLY)
type = MOVE_WORLDONLY;
- else if (self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+ else if (this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
type = MOVE_NOMONSTERS;
else type = MOVE_NORMAL;
- tracebox(upmove, self.mins, self.maxs, downmove, type, self);
+ tracebox(upmove, this.mins, this.maxs, downmove, type, this);
if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
clip |= 1; // but we HAVE found a floor
}
// if the move did not hit the ground at any point, we're not on ground
if (!(clip & 1))
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
- _Movetype_CheckVelocity();
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_LinkEdict(this, true);
if (clip & 8) // teleport
return;
- if (self.move_flags & FL_WATERJUMP)
+ if (this.move_flags & FL_WATERJUMP)
return;
if (PHYS_NOSTEP)
return;
- vector originalmove_origin = self.move_origin;
- vector originalmove_velocity = self.move_velocity;
+ vector originalmove_origin = this.move_origin;
+ vector originalmove_velocity = this.move_velocity;
// originalmove_clip = clip;
- int originalmove_flags = self.move_flags;
- entity originalmove_groundentity = self.move_groundentity;
+ int originalmove_flags = this.move_flags;
+ entity originalmove_groundentity = this.move_groundentity;
// if move didn't block on a step, return
if (clip & 2)
if (fabs(start_velocity.x) < 0.03125 && fabs(start_velocity.y) < 0.03125)
return;
- if (self.move_movetype != MOVETYPE_FLY)
+ if (this.move_movetype != MOVETYPE_FLY)
{
// return if gibbed by a trigger
- if (self.move_movetype != MOVETYPE_WALK)
+ if (this.move_movetype != MOVETYPE_WALK)
return;
// return if attempting to jump while airborn (unless sv_jumpstep)
if (!PHYS_JUMPSTEP)
- if (!oldonground && self.move_waterlevel == 0)
+ if (!oldonground && this.move_waterlevel == 0)
return;
}
// try moving up and forward to go up a step
// back to start pos
- self.move_origin = start_origin;
- self.move_velocity = start_velocity;
+ this.move_origin = start_origin;
+ this.move_velocity = start_velocity;
// move up
vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
- vector prev_origin = self.move_origin;
- _Movetype_PushEntity(upmove, true);
- if(wasfreed(self))
+ _Movetype_PushEntity(this, upmove, true);
+ if(wasfreed(this))
return;
- if(trace_startsolid && self.move_origin != prev_origin)
+ if(trace_startsolid)
{
// we got teleported when upstepping... must abort the move
return;
}
// move forward
- self.move_velocity_z = 0;
- clip = _Movetype_FlyMove(dt, applygravity, stepnormal, 0);
- self.move_velocity_z += start_velocity.z;
+ this.move_velocity_z = 0;
+ clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, 0);
+ this.move_velocity_z += start_velocity.z;
if (clip & 8)
{
// we got teleported when upstepping... must abort the move
return;
}
- _Movetype_CheckVelocity();
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_LinkEdict(this, true);
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if (clip
- && fabs(originalmove_origin.y - self.move_origin.y) < 0.03125
- && fabs(originalmove_origin.x - self.move_origin.x) < 0.03125)
+ && fabs(originalmove_origin.y - this.move_origin.y) < 0.03125
+ && fabs(originalmove_origin.x - this.move_origin.x) < 0.03125)
{
// Con_Printf("wall\n");
// stepping up didn't make any progress, revert to original move
- self.move_origin = originalmove_origin;
- self.move_velocity = originalmove_velocity;
+ this.move_origin = originalmove_origin;
+ this.move_velocity = originalmove_velocity;
// clip = originalmove_clip;
- self.move_flags = originalmove_flags;
- self.move_groundentity = originalmove_groundentity;
+ this.move_flags = originalmove_flags;
+ this.move_groundentity = originalmove_groundentity;
// now try to unstick if needed
// clip = SV_TryUnstick (ent, oldvel);
return;
// extra friction based on view angle
if ((clip & 2) && PHYS_WALLFRICTION)
- _Movetype_WallFriction(stepnormal);
+ _Movetype_WallFriction(this, stepnormal);
}
// don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
- else if (!GAMEPLAYFIX_STEPDOWN || self.move_waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || (self.move_flags & FL_ONGROUND))
+ else if (!GAMEPLAYFIX_STEPDOWN || this.move_waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || (this.move_flags & FL_ONGROUND))
{
return;
}
// move down
vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
- vector prev_origin = self.move_origin;
- _Movetype_PushEntity(downmove, true);
- if(wasfreed(self))
+ _Movetype_PushEntity(this, downmove, true);
+ if(wasfreed(this))
return;
- if(trace_startsolid && self.move_origin != prev_origin)
+ if(trace_startsolid)
{
// we got teleported when downstepping... must abort the move
return;
// if the push down didn't end up on good ground, use the move without
// the step up. This happens near wall / slope combinations, and can
// cause the player to hop up higher on a slope too steep to climb
- self.move_origin = originalmove_origin;
- self.move_velocity = originalmove_velocity;
- self.move_flags = originalmove_flags;
- self.move_groundentity = originalmove_groundentity;
+ this.move_origin = originalmove_origin;
+ this.move_velocity = originalmove_velocity;
+ this.move_flags = originalmove_flags;
+ this.move_groundentity = originalmove_groundentity;
}
- _Movetype_CheckVelocity();
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_LinkEdict(this, true);
}
#ifndef MOVETYPE_WALK_H
#define MOVETYPE_WALK_H
-void _Movetype_Physics_Walk(float dt);
+void _Movetype_Physics_Walk(entity this, float dt);
#endif
-#include "mutator/buffs/module.inc"
+#include "mutator/waypoints/module.inc"
+
#include "mutator/itemstime.qc"
#include "mutator/multijump/module.inc"
#include "mutator/nades/module.inc"
#include "mutator/superspec/module.inc"
-#include "mutator/waypoints/module.inc"
// completely self contained
#include "mutator/bloodloss/module.inc"
#include "mutator/breakablehook/module.inc"
+#include "mutator/buffs/module.inc"
+#include "mutator/bugrigs/module.inc"
#include "mutator/campcheck/module.inc"
#include "mutator/cloaked/module.inc"
#include "mutator/damagetext/module.inc"
#include "mutator/dodging/module.inc"
+#include "mutator/doublejump/module.inc"
#include "mutator/hook/module.inc"
#include "mutator/instagib/module.inc"
#include "mutator/invincibleproj/module.inc"
bool ret = MUTATORFUNCTION_##id##_hooks(mode); if (ret) return ret; \
} \
bool MUTATOR_##id##_check() { return dependence; } \
- REGISTER(RegisterMutators, MUTATOR, Mutators, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
+ REGISTER(Mutators, MUTATOR, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
{ this.mutatorcheck = MUTATOR_##id##_check; } \
[[accumulate]] bool MUTATORFUNCTION_##id(int mode)
/**/
MUTATOR_HOOKABLE(BuildGameplayTipsString, EV_BuildGameplayTipsString);
+#define EV_IsFlying(i, o) \
+ /**/ i(entity, MUTATOR_ARGV_0_entity) \
+ /**/
+MUTATOR_HOOKABLE(IsFlying, EV_IsFlying);
+
+#define EV_WP_Format(i, o) \
+ /**/ i(entity, MUTATOR_ARGV_0_entity) \
+ /**/ i(string, MUTATOR_ARGV_0_string) \
+ /**/ o(vector, MUTATOR_ARGV_0_vector) \
+ /**/ o(string, MUTATOR_ARGV_0_string) \
+ /**/
+MUTATOR_HOOKABLE(WP_Format, EV_WP_Format);
+
+/**
+ * called before any player physics, may adjust variables for movement,
+ * is run AFTER bot code and idle checking on the server
+ */
+#define EV_PlayerPhysics(i, o) \
+ /**/ i(entity, __self) \
+ /**/
+MUTATOR_HOOKABLE(PlayerPhysics, EV_PlayerPhysics);
+
+/** called when a player presses the jump key */
+#define EV_PlayerJump(i, o) \
+ /**/ i(entity, __self) \
+ /**/ i(float, player_multijump) \
+ /**/ i(float, player_jumpheight) \
+ /**/ o(float, player_multijump) \
+ /**/ o(float, player_jumpheight) \
+ /**/
+float player_multijump;
+float player_jumpheight;
+MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
+
+/** called during player physics, allows adjusting the movement type used */
+#define EV_PM_Physics(i, o) \
+ /**/ i(entity, __self) \
+ /**/ i(float, pm_maxspeed_mod) \
+ /**/
+float pm_maxspeed_mod;
+MUTATOR_HOOKABLE(PM_Physics, EV_PM_Physics);
+
#endif
--- /dev/null
+REGISTER_BUFF(AMMO) {
+ this.m_prettyName = _("Ammo");
+ this.m_name = "ammo";
+ this.m_skin = 3;
+ this.m_color = '0.76 1 0.1';
+}
+BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen, BUFF_AMMO)
+
+REGISTER_BUFF(RESISTANCE) {
+ this.m_prettyName = _("Resistance");
+ this.m_name = "resistance";
+ this.m_skin = 0;
+ this.m_color = '0.36 1 0.07';
+}
+BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
+
+REGISTER_BUFF(SPEED) {
+ this.m_prettyName = _("Speed");
+ this.m_name = "speed";
+ this.m_skin = 9;
+ this.m_color = '0.1 1 0.84';
+}
+BUFF_SPAWNFUNCS(speed, BUFF_SPEED)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
+
+REGISTER_BUFF(MEDIC) {
+ this.m_prettyName = _("Medic");
+ this.m_name = "medic";
+ this.m_skin = 1;
+ this.m_color = '1 0.12 0';
+}
+BUFF_SPAWNFUNCS(medic, BUFF_MEDIC)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_MEDIC)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(medic, BUFF_MEDIC)
+
+REGISTER_BUFF(BASH) {
+ this.m_prettyName = _("Bash");
+ this.m_name = "bash";
+ this.m_skin = 5;
+ this.m_color = '1 0.39 0';
+}
+BUFF_SPAWNFUNCS(bash, BUFF_BASH)
+
+REGISTER_BUFF(VAMPIRE) {
+ this.m_prettyName = _("Vampire");
+ this.m_name = "vampire";
+ this.m_skin = 2;
+ this.m_color = '1 0 0.24';
+}
+BUFF_SPAWNFUNCS(vampire, BUFF_VAMPIRE)
+
+REGISTER_BUFF(DISABILITY) {
+ this.m_prettyName = _("Disability");
+ this.m_name = "disability";
+ this.m_skin = 7;
+ this.m_color = '0.94 0.3 1';
+}
+BUFF_SPAWNFUNCS(disability, BUFF_DISABILITY)
+
+REGISTER_BUFF(VENGEANCE) {
+ this.m_prettyName = _("Vengeance");
+ this.m_name = "vengeance";
+ this.m_skin = 15;
+ this.m_color = '1 0.23 0.61';
+}
+BUFF_SPAWNFUNCS(vengeance, BUFF_VENGEANCE)
+
+REGISTER_BUFF(JUMP) {
+ this.m_prettyName = _("Jump");
+ this.m_name = "jump";
+ this.m_skin = 10;
+ this.m_color = '0.24 0.78 1';
+}
+BUFF_SPAWNFUNCS(jump, BUFF_JUMP)
+
+REGISTER_BUFF(FLIGHT) {
+ this.m_prettyName = _("Flight");
+ this.m_name = "flight";
+ this.m_skin = 11;
+ this.m_color = '0.33 0.56 1';
+}
+BUFF_SPAWNFUNCS(flight, BUFF_FLIGHT)
+
+REGISTER_BUFF(INVISIBLE) {
+ this.m_prettyName = _("Invisible");
+ this.m_name = "invisible";
+ this.m_skin = 12;
+ this.m_color = '0.5 0.5 1';
+}
+BUFF_SPAWNFUNCS(invisible, BUFF_INVISIBLE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(invis, BUFF_INVISIBLE)
+
+REGISTER_BUFF(INFERNO) {
+ this.m_prettyName = _("Inferno");
+ this.m_name = "inferno";
+ this.m_skin = 16;
+ this.m_color = '1 0.62 0';
+}
+BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
+
+REGISTER_BUFF(SWAPPER) {
+ this.m_prettyName = _("Swapper");
+ this.m_name = "swapper";
+ this.m_skin = 17;
+ this.m_color = '0.63 0.36 1';
+}
+BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
+
+REGISTER_BUFF(MAGNET) {
+ this.m_prettyName = _("Magnet");
+ this.m_name = "magnet";
+ this.m_skin = 18;
+ this.m_color = '1 0.95 0.18';
+}
+BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
--- /dev/null
+#include "all.qh"
--- /dev/null
+#ifndef BUFFS_ALL_H
+#define BUFFS_ALL_H
+// Welcome to the stuff behind the scenes
+// Below, you will find the list of buffs
+// Add new buffs here!
+// Note: Buffs also need spawnfuncs, which are set below
+
+#include "../../../teams.qh"
+#include "../../../util.qh"
+
+REGISTER_WAYPOINT(Buff, _("Buff"), '1 0.5 0', 1);
+REGISTER_RADARICON(Buff, 1);
+
+REGISTRY(Buffs, BITS(4))
+#define Buffs_from(i) _Buffs_from(i, BUFF_Null)
+REGISTER_REGISTRY(Buffs)
+REGISTRY_CHECK(Buffs)
+
+#define REGISTER_BUFF(id) \
+ REGISTER(Buffs, BUFF_##id, m_id, NEW(Buff)); \
+ REGISTER_INIT_POST(BUFF_##id) { \
+ this.netname = this.m_name; \
+ this.m_itemid = BIT(this.m_id - 1); \
+ this.m_sprite = strzone(strcat("buff-", this.m_name)); \
+ } \
+ REGISTER_INIT(BUFF_##id)
+
+#include "../../../items/item/pickup.qh"
+CLASS(Buff, Pickup)
+ /** bit index */
+ ATTRIB(Buff, m_itemid, int, 0)
+ ATTRIB(Buff, m_name, string, "buff")
+ ATTRIB(Buff, m_color, vector, '1 1 1')
+ ATTRIB(Buff, m_prettyName, string, "Buff")
+ ATTRIB(Buff, m_skin, int, 0)
+ ATTRIB(Buff, m_sprite, string, "")
+ METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
+ }
+#ifdef SVQC
+ METHOD(Buff, m_time, float(Buff this))
+ { return cvar(strcat("g_buffs_", this.netname, "_time")); }
+#endif
+ENDCLASS(Buff)
+
+#ifdef SVQC
+ // .int buffs = _STAT(BUFFS);
+ void buff_Init(entity ent);
+ void buff_Init_Compat(entity ent, entity replacement);
+ #define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
+ self.buffs = b.m_itemid; \
+ self.team = t; \
+ buff_Init(self); \
+ }
+ #define BUFF_SPAWNFUNCS(e, b) \
+ BUFF_SPAWNFUNC(e, b, 0) \
+ BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
+ BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
+ BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
+ BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
+ #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) spawnfunc(item_##o) { buff_Init_Compat(self, r); }
+#else
+ #define BUFF_SPAWNFUNC(e, b, t)
+ #define BUFF_SPAWNFUNCS(e, b)
+ #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r)
+#endif
+
+REGISTER_BUFF(Null);
+BUFF_SPAWNFUNCS(random, BUFF_Null)
+
+#include "all.inc"
+
+#endif
#include "../../../triggers/target/music.qh"
#include "../../../gamemodes/all.qh"
-#include "../../../buffs/all.qh"
-.float buff_time;
+.float buff_time = _STAT(BUFF_TIME);
void buffs_DelayedInit();
REGISTER_MUTATOR(buffs, cvar("g_buffs"))
{
MUTATOR_ONADD
{
- addstat(STAT_BUFFS, AS_INT, buffs);
- addstat(STAT_BUFF_TIME, AS_FLOAT, buff_time);
-
InitializeEntity(world, buffs_DelayedInit, INITPRIO_FINDTARGET);
}
}
if(!MoveToRandomMapLocation(ent, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, ((autocvar_g_buffs_random_location_attempts > 0) ? autocvar_g_buffs_random_location_attempts : 10), 1024, 256))
{
entity spot = SelectSpawnPoint(true);
- setorigin(ent, ((spot.origin + '0 0 200') + (randomvec() * 300)));
+ setorigin(ent, spot.origin + '0 0 200');
ent.angles = spot.angles;
}
if(self.buff_activetime) { buff_Waypoint_Spawn(self); }
}
-void buff_Reset()
-{SELFPARAM();
+void buff_Reset(entity this)
+{
if(autocvar_g_buffs_randomize)
- buff_NewType(self, self.buffs);
- self.owner = world;
+ buff_NewType(this, this.buffs);
+ this.owner = world;
buff_SetCooldown(autocvar_g_buffs_cooldown_activate);
buff_Waypoint_Reset();
- self.buff_activetime_updated = false;
+ this.buff_activetime_updated = false;
- if(autocvar_g_buffs_random_location || (self.spawnflags & 64))
- buff_Respawn(self);
+ if(autocvar_g_buffs_random_location || (this.spawnflags & 64))
+ buff_Respawn(this);
}
float buff_Customize()
MUTATOR_HOOKFUNCTION(buffs, OnEntityPreSpawn, CBC_ORDER_LAST)
{SELFPARAM();
+ if (self.classname == "item_flight" && cvar("g_buffs") && cvar("g_buffs_flight"))
+ {
+ buff_Init_Compat(self, BUFF_FLIGHT);
+ return true;
+ }
if(autocvar_g_buffs_replace_powerups)
switch(self.classname)
{
{
vh_vehicle.buffs = vh_player.buffs;
vh_player.buffs = 0;
- vh_vehicle.buff_time = vh_player.buff_time - time;
+ vh_vehicle.buff_time = max(0, time - vh_player.buff_time);
vh_player.buff_time = 0;
return false;
}
+#include "all.qc"
#ifdef SVQC
#include "buffs.qc"
#endif
+
+#ifdef IMPLEMENTATION
+
+string BUFF_NAME(int i)
+{
+ Buff b = Buffs_from(i);
+ return sprintf("%s%s", rgb_to_hexcolor(b.m_color), b.m_prettyName);
+}
+
+#ifndef MENUQC
+REGISTER_MUTATOR(buffs_flight, true);
+MUTATOR_HOOKFUNCTION(buffs_flight, IsFlying)
+{
+ noref entity e = MUTATOR_ARGV(0, entity);
+ return BUFFS_STAT(e) & BUFF_FLIGHT.m_itemid;
+}
+#endif
+
+#ifdef CSQC
+REGISTER_MUTATOR(cl_buffs, true);
+MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
+{
+ int allBuffs = STAT(BUFFS);
+ FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
+ addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
+ ));
+}
+MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
+{
+ entity this = MUTATOR_ARGV(0, entity);
+ string s = MUTATOR_ARGV(0, string);
+ if (s == WP_Buff.netname || s == RADARICON_Buff.netname)
+ {
+ Buff b = Buffs_from(this.wp_extra);
+ MUTATOR_ARGV(0, vector) = b.m_color;
+ MUTATOR_ARGV(0, string) = b.m_prettyName;
+ return true;
+ }
+}
+
+#endif
+#endif
--- /dev/null
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+ #include "../../../../server/antilag.qh"
+#endif
+#include "../../../physics.qh"
+
+
+#if defined(SVQC)
+void bugrigs_SetVars();
+
+REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
+{
+ MUTATOR_ONADD
+ {
+ bugrigs_SetVars();
+ }
+ return false;
+}
+#elif defined(CSQC)
+REGISTER_MUTATOR(bugrigs, true);
+#endif
+
+
+#define PHYS_BUGRIGS(s) STAT(BUGRIGS, s)
+#define PHYS_BUGRIGS_ACCEL(s) STAT(BUGRIGS_ACCEL, s)
+#define PHYS_BUGRIGS_AIR_STEERING(s) STAT(BUGRIGS_AIR_STEERING, s)
+#define PHYS_BUGRIGS_ANGLE_SMOOTHING(s) STAT(BUGRIGS_ANGLE_SMOOTHING, s)
+#define PHYS_BUGRIGS_CAR_JUMPING(s) STAT(BUGRIGS_CAR_JUMPING, s)
+#define PHYS_BUGRIGS_FRICTION_AIR(s) STAT(BUGRIGS_FRICTION_AIR, s)
+#define PHYS_BUGRIGS_FRICTION_BRAKE(s) STAT(BUGRIGS_FRICTION_BRAKE, s)
+#define PHYS_BUGRIGS_FRICTION_FLOOR(s) STAT(BUGRIGS_FRICTION_FLOOR, s)
+#define PHYS_BUGRIGS_PLANAR_MOVEMENT(s) STAT(BUGRIGS_PLANAR_MOVEMENT, s)
+#define PHYS_BUGRIGS_REVERSE_SPEEDING(s) STAT(BUGRIGS_REVERSE_SPEEDING, s)
+#define PHYS_BUGRIGS_REVERSE_SPINNING(s) STAT(BUGRIGS_REVERSE_SPINNING, s)
+#define PHYS_BUGRIGS_REVERSE_STOPPING(s) STAT(BUGRIGS_REVERSE_STOPPING, s)
+#define PHYS_BUGRIGS_SPEED_POW(s) STAT(BUGRIGS_SPEED_POW, s)
+#define PHYS_BUGRIGS_SPEED_REF(s) STAT(BUGRIGS_SPEED_REF, s)
+#define PHYS_BUGRIGS_STEER(s) STAT(BUGRIGS_STEER, s)
+
+#if defined(SVQC)
+
+void bugrigs_SetVars()
+{
+ g_bugrigs = cvar("g_bugrigs");
+ g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
+ g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
+ g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
+ g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
+ g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
+ g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
+ g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
+ g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
+ g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
+ g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
+ g_bugrigs_accel = cvar("g_bugrigs_accel");
+ g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
+ g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
+ g_bugrigs_steer = cvar("g_bugrigs_steer");
+}
+
+#endif
+
+void RaceCarPhysics(entity this)
+{
+ // using this move type for "big rigs"
+ // the engine does not push the entity!
+
+ vector rigvel;
+
+ vector angles_save = this.angles;
+ float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
+ float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
+
+ if (PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ {
+ if (accel < 0)
+ {
+ // back accel is DIGITAL
+ // to prevent speedhack
+ if (accel < -0.5)
+ accel = -1;
+ else
+ accel = 0;
+ }
+ }
+
+ this.angles_x = 0;
+ this.angles_z = 0;
+ makevectors(this.angles); // new forward direction!
+
+ if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING(this))
+ {
+ float myspeed = this.velocity * v_forward;
+ float upspeed = this.velocity * v_up;
+
+ // responsiveness factor for steering and acceleration
+ float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF(this), PHYS_BUGRIGS_SPEED_POW(this)));
+ //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF(this)) ^ PHYS_BUGRIGS_SPEED_POW(this));
+
+ float steerfactor;
+ if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING(this))
+ steerfactor = -myspeed * PHYS_BUGRIGS_STEER(this);
+ else
+ steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER(this);
+
+ float accelfactor;
+ if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ accelfactor = PHYS_BUGRIGS_ACCEL(this);
+ else
+ accelfactor = f * PHYS_BUGRIGS_ACCEL(this);
+ //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL(this);
+
+ if (accel < 0)
+ {
+ if (myspeed > 0)
+ {
+ myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
+ }
+ else
+ {
+ if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
+ }
+ }
+ else
+ {
+ if (myspeed >= 0)
+ {
+ myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
+ }
+ else
+ {
+ if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
+ myspeed = 0;
+ else
+ myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
+ }
+ }
+ // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
+ //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
+
+ this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+ makevectors(this.angles); // new forward direction!
+
+ myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
+
+ rigvel = myspeed * v_forward + '0 0 1' * upspeed;
+ }
+ else
+ {
+ float myspeed = vlen(this.velocity);
+
+ // responsiveness factor for steering and acceleration
+ float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)), PHYS_BUGRIGS_SPEED_POW(this)));
+ float steerfactor = -myspeed * f;
+ this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+
+ rigvel = this.velocity;
+ makevectors(this.angles); // new forward direction!
+ }
+
+ rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * PHYS_INPUT_TIMELENGTH);
+ //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
+ //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
+ //MAXIMA: solve(total_acceleration(v) = 0, v);
+
+ if (PHYS_BUGRIGS_PLANAR_MOVEMENT(this))
+ {
+ vector rigvel_xy, neworigin, up;
+ float mt;
+
+ rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
+ rigvel_xy = vec2(rigvel);
+
+ if (PHYS_BUGRIGS_CAR_JUMPING(this))
+ mt = MOVE_NORMAL;
+ else
+ mt = MOVE_NOMONSTERS;
+
+ tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 1024', mt, this);
+ up = trace_endpos - this.origin;
+
+ // BUG RIGS: align the move to the surface instead of doing collision testing
+ // can we move?
+ tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, this);
+
+ // align to surface
+ tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, this);
+
+ if (trace_fraction < 0.5)
+ {
+ trace_fraction = 1;
+ neworigin = this.origin;
+ }
+ else
+ neworigin = trace_endpos;
+
+ if (trace_fraction < 1)
+ {
+ // now set angles_x so that the car points parallel to the surface
+ this.angles = vectoangles(
+ '1 0 0' * v_forward_x * trace_plane_normal_z
+ +
+ '0 1 0' * v_forward_y * trace_plane_normal_z
+ +
+ '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
+ );
+ SET_ONGROUND(this);
+ }
+ else
+ {
+ // now set angles_x so that the car points forward, but is tilted in velocity direction
+ UNSET_ONGROUND(this);
+ }
+
+ this.velocity = (neworigin - this.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
+ this.movetype = MOVETYPE_NOCLIP;
+ }
+ else
+ {
+ rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
+ this.velocity = rigvel;
+ this.movetype = MOVETYPE_FLY;
+ }
+
+ trace_fraction = 1;
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4', MOVE_NORMAL, this);
+ if (trace_fraction != 1)
+ {
+ this.angles = vectoangles2(
+ '1 0 0' * v_forward_x * trace_plane_normal_z
+ +
+ '0 1 0' * v_forward_y * trace_plane_normal_z
+ +
+ '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
+ trace_plane_normal
+ );
+ }
+ else
+ {
+ vector vel_local;
+
+ vel_local_x = v_forward * this.velocity;
+ vel_local_y = v_right * this.velocity;
+ vel_local_z = v_up * this.velocity;
+
+ this.angles_x = racecar_angle(vel_local_x, vel_local_z);
+ this.angles_z = racecar_angle(-vel_local_y, vel_local_z);
+ }
+
+ // smooth the angles
+ vector vf1, vu1, smoothangles;
+ makevectors(this.angles);
+ float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
+ if (f == 0)
+ f = 1;
+ vf1 = v_forward * f;
+ vu1 = v_up * f;
+ makevectors(angles_save);
+ vf1 = vf1 + v_forward * (1 - f);
+ vu1 = vu1 + v_up * (1 - f);
+ smoothangles = vectoangles2(vf1, vu1);
+ this.angles_x = -smoothangles_x;
+ this.angles_z = smoothangles_z;
+
+ PM_ClientMovement_Move(this);
+}
+
+#ifdef SVQC
+.vector bugrigs_prevangles;
+#endif
+MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
+{
+ if(!PHYS_BUGRIGS(self) || !IS_PLAYER(self)) { return false; }
+
+#ifdef SVQC
+ self.angles = self.bugrigs_prevangles;
+#endif
+
+ RaceCarPhysics(self);
+ return true;
+}
+
+MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
+{
+ if(!PHYS_BUGRIGS(self)) { return false; }
+#ifdef SVQC
+ self.bugrigs_prevangles = self.angles;
+#endif
+ return false;
+}
+
+#ifdef SVQC
+
+MUTATOR_HOOKFUNCTION(bugrigs, ClientConnect)
+{
+ stuffcmd(self, "cl_cmd settemp chase_active 1\n");
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":bugrigs");
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", Bug rigs");
+ return false;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef MENUQC
+#include "bugrigs.qc"
+#endif
#ifdef IMPLEMENTATION
+#define PHYS_DODGING STAT(DODGING, this)
+#define PHYS_DODGING_DELAY STAT(DODGING_DELAY, this)
+#define PHYS_DODGING_DISTANCE_THRESHOLD STAT(DODGING_DISTANCE_THRESHOLD, this)
+#define PHYS_DODGING_FROZEN_NODOUBLETAP STAT(DODGING_FROZEN_NO_DOUBLETAP, this)
+#define PHYS_DODGING_HEIGHT_THRESHOLD STAT(DODGING_HEIGHT_THRESHOLD, this)
+#define PHYS_DODGING_HORIZ_SPEED STAT(DODGING_HORIZ_SPEED, this)
+#define PHYS_DODGING_HORIZ_SPEED_FROZEN STAT(DODGING_HORIZ_SPEED_FROZEN, this)
+#define PHYS_DODGING_RAMP_TIME STAT(DODGING_RAMP_TIME, this)
+#define PHYS_DODGING_UP_SPEED STAT(DODGING_UP_SPEED, this)
+#define PHYS_DODGING_WALL STAT(DODGING_WALL, this)
+#define PHYS_DODGING_PRESSED_KEYS(s) (s).pressedkeys
+
#ifdef CSQC
#define PHYS_DODGING_FRAMETIME (1 / (frametime <= 0 ? 60 : frametime))
- #define PHYS_DODGING getstati(STAT_DODGING)
- #define PHYS_DODGING_DELAY getstatf(STAT_DODGING_DELAY)
- #define PHYS_DODGING_TIMEOUT(s) getstatf(STAT_DODGING_TIMEOUT)
- #define PHYS_DODGING_HORIZ_SPEED_FROZEN getstatf(STAT_DODGING_HORIZ_SPEED_FROZEN)
- #define PHYS_DODGING_FROZEN_NODOUBLETAP getstati(STAT_DODGING_FROZEN_NO_DOUBLETAP)
- #define PHYS_DODGING_HORIZ_SPEED getstatf(STAT_DODGING_HORIZ_SPEED)
- #define PHYS_DODGING_PRESSED_KEYS(s) s.pressedkeys
- #define PHYS_DODGING_HEIGHT_THRESHOLD getstatf(STAT_DODGING_HEIGHT_THRESHOLD)
- #define PHYS_DODGING_DISTANCE_THRESHOLD getstatf(STAT_DODGING_DISTANCE_THRESHOLD)
- #define PHYS_DODGING_RAMP_TIME getstatf(STAT_DODGING_RAMP_TIME)
- #define PHYS_DODGING_UP_SPEED getstatf(STAT_DODGING_UP_SPEED)
- #define PHYS_DODGING_WALL getstatf(STAT_DODGING_WALL)
+ #define PHYS_DODGING_TIMEOUT(s) STAT(DODGING_TIMEOUT)
#elif defined(SVQC)
#define PHYS_DODGING_FRAMETIME sys_frametime
- #define PHYS_DODGING g_dodging
- #define PHYS_DODGING_DELAY autocvar_sv_dodging_delay
#define PHYS_DODGING_TIMEOUT(s) s.cvar_cl_dodging_timeout
- #define PHYS_DODGING_HORIZ_SPEED_FROZEN autocvar_sv_dodging_horiz_speed_frozen
- #define PHYS_DODGING_FROZEN_NODOUBLETAP autocvar_sv_dodging_frozen_doubletap
- #define PHYS_DODGING_HORIZ_SPEED autocvar_sv_dodging_horiz_speed
- #define PHYS_DODGING_PRESSED_KEYS(s) s.pressedkeys
- #define PHYS_DODGING_HEIGHT_THRESHOLD autocvar_sv_dodging_height_threshold
- #define PHYS_DODGING_DISTANCE_THRESHOLD autocvar_sv_dodging_wall_distance_threshold
- #define PHYS_DODGING_RAMP_TIME autocvar_sv_dodging_ramp_time
- #define PHYS_DODGING_UP_SPEED autocvar_sv_dodging_up_speed
- #define PHYS_DODGING_WALL autocvar_sv_dodging_wall_dodging
-
- float autocvar_sv_dodging_delay;
- float autocvar_sv_dodging_height_threshold;
- float autocvar_sv_dodging_horiz_speed;
- float autocvar_sv_dodging_horiz_speed_frozen;
- float autocvar_sv_dodging_ramp_time;
- bool autocvar_sv_dodging_sound;
- float autocvar_sv_dodging_up_speed;
- float autocvar_sv_dodging_wall_distance_threshold;
- bool autocvar_sv_dodging_wall_dodging;
- bool autocvar_sv_dodging_frozen_doubletap;
+
+
#endif
#ifdef SVQC
-float g_dodging;
+bool autocvar_sv_dodging_sound;
// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
.float dodging_action;
#include "../../../animdecide.qh"
#include "../../../physics.qh"
-.float cvar_cl_dodging_timeout;
-
-.float stat_dodging;
-.float stat_dodging_delay;
-.float stat_dodging_horiz_speed_frozen;
-.float stat_dodging_frozen_nodoubletap;
-.float stat_dodging_frozen;
-.float stat_dodging_horiz_speed;
-.float stat_dodging_height_threshold;
-.float stat_dodging_distance_threshold;
-.float stat_dodging_ramp_time;
-.float stat_dodging_up_speed;
-.float stat_dodging_wall;
+.float cvar_cl_dodging_timeout = _STAT(DODGING_TIMEOUT);
REGISTER_MUTATOR(dodging, cvar("g_dodging"))
{
MUTATOR_ONADD
{
g_dodging = cvar("g_dodging");
- addstat(STAT_DODGING, AS_INT, stat_dodging);
- addstat(STAT_DODGING_DELAY, AS_FLOAT, stat_dodging_delay);
- addstat(STAT_DODGING_TIMEOUT, AS_FLOAT, cvar_cl_dodging_timeout); // we stat this, so it is updated on the client when updated on server (otherwise, chaos)
- addstat(STAT_DODGING_FROZEN_NO_DOUBLETAP, AS_INT, stat_dodging_frozen_nodoubletap);
- addstat(STAT_DODGING_HORIZ_SPEED_FROZEN, AS_FLOAT, stat_dodging_horiz_speed_frozen);
- addstat(STAT_DODGING_FROZEN, AS_INT, stat_dodging_frozen);
- addstat(STAT_DODGING_HORIZ_SPEED, AS_FLOAT, stat_dodging_horiz_speed);
- addstat(STAT_DODGING_HEIGHT_THRESHOLD, AS_FLOAT, stat_dodging_height_threshold);
- addstat(STAT_DODGING_DISTANCE_THRESHOLD, AS_FLOAT, stat_dodging_distance_threshold);
- addstat(STAT_DODGING_RAMP_TIME, AS_FLOAT, stat_dodging_ramp_time);
- addstat(STAT_DODGING_UP_SPEED, AS_FLOAT, stat_dodging_up_speed);
- addstat(STAT_DODGING_WALL, AS_FLOAT, stat_dodging_wall);
}
// this just turns off the cvar.
return false;
}
+#elif defined(CSQC)
+REGISTER_MUTATOR(dodging, true);
#endif
// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
#ifdef CSQC
.int pressedkeys;
-
-#elif defined(SVQC)
-
-void dodging_UpdateStats()
-{SELFPARAM();
- self.stat_dodging = PHYS_DODGING;
- self.stat_dodging_delay = PHYS_DODGING_DELAY;
- self.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN;
- self.stat_dodging_frozen = PHYS_DODGING_FROZEN;
- self.stat_dodging_frozen_nodoubletap = PHYS_DODGING_FROZEN_NODOUBLETAP;
- self.stat_dodging_height_threshold = PHYS_DODGING_HEIGHT_THRESHOLD;
- self.stat_dodging_distance_threshold = PHYS_DODGING_DISTANCE_THRESHOLD;
- self.stat_dodging_ramp_time = PHYS_DODGING_RAMP_TIME;
- self.stat_dodging_up_speed = PHYS_DODGING_UP_SPEED;
- self.stat_dodging_wall = PHYS_DODGING_WALL;
-}
-
#endif
// returns 1 if the player is close to a wall
-bool check_close_to_wall(float threshold)
-{SELFPARAM();
+bool check_close_to_wall(entity this, float threshold)
+{
if (PHYS_DODGING_WALL == 0) { return false; }
#define X(OFFSET) \
- tracebox(self.origin, self.mins, self.maxs, self.origin + OFFSET, true, self); \
- if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold) \
+ tracebox(this.origin, this.mins, this.maxs, this.origin + OFFSET, true, this); \
+ if (trace_fraction < 1 && vlen (this.origin - trace_endpos) < threshold) \
return true;
X(1000*v_right);
X(-1000*v_right);
return false;
}
-bool check_close_to_ground(float threshold)
-{SELFPARAM();
- return IS_ONGROUND(self) ? true : false;
+bool check_close_to_ground(entity this, float threshold)
+{
+ return IS_ONGROUND(this) ? true : false;
}
-float PM_dodging_checkpressedkeys()
-{SELFPARAM();
+float PM_dodging_checkpressedkeys(entity this)
+{
if(!PHYS_DODGING)
return false;
- float frozen_dodging = (PHYS_FROZEN(self) && PHYS_DODGING_FROZEN);
+ float frozen_dodging = (PHYS_FROZEN(this) && PHYS_DODGING_FROZEN);
float frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP);
// first check if the last dodge is far enough back in time so we can dodge again
- if ((time - self.last_dodging_time) < PHYS_DODGING_DELAY)
+ if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
return false;
- makevectors(self.angles);
+ makevectors(this.angles);
- if (check_close_to_ground(PHYS_DODGING_HEIGHT_THRESHOLD) != 1
- && check_close_to_wall(PHYS_DODGING_DISTANCE_THRESHOLD) != 1)
+ if (check_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD) != 1
+ && check_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD) != 1)
return true;
float tap_direction_x = 0;
float tap_direction_y = 0;
- float dodge_detected = 0;
+ bool dodge_detected = false;
#define X(COND,BTN,RESULT) \
- if (self.movement_##COND) \
+ if (this.movement_##COND) \
/* is this a state change? */ \
- if(!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_##BTN) || frozen_no_doubletap) { \
+ if(!(PHYS_DODGING_PRESSED_KEYS(this) & KEY_##BTN) || frozen_no_doubletap) { \
tap_direction_##RESULT; \
- if ((time - self.last_##BTN##_KEY_time) < PHYS_DODGING_TIMEOUT(self)) \
- dodge_detected = 1; \
- self.last_##BTN##_KEY_time = time; \
+ if ((time - this.last_##BTN##_KEY_time) < PHYS_DODGING_TIMEOUT(this)) \
+ dodge_detected = true; \
+ this.last_##BTN##_KEY_time = time; \
}
X(x < 0, BACKWARD, x--);
X(x > 0, FORWARD, x++);
X(y > 0, RIGHT, y++);
#undef X
- if (dodge_detected == 1)
+ if (dodge_detected)
{
- self.last_dodging_time = time;
+ this.last_dodging_time = time;
- self.dodging_action = 1;
- self.dodging_single_action = 1;
+ this.dodging_action = 1;
+ this.dodging_single_action = 1;
- self.dodging_velocity_gain = PHYS_DODGING_HORIZ_SPEED;
+ this.dodging_velocity_gain = PHYS_DODGING_HORIZ_SPEED;
- self.dodging_direction_x = tap_direction_x;
- self.dodging_direction_y = tap_direction_y;
+ this.dodging_direction_x = tap_direction_x;
+ this.dodging_direction_y = tap_direction_y;
// normalize the dodging_direction vector.. (unlike UT99) XD
- float length = self.dodging_direction_x * self.dodging_direction_x
- + self.dodging_direction_y * self.dodging_direction_y;
+ float length = this.dodging_direction_x * this.dodging_direction_x
+ + this.dodging_direction_y * this.dodging_direction_y;
length = sqrt(length);
- self.dodging_direction_x = self.dodging_direction_x * 1.0 / length;
- self.dodging_direction_y = self.dodging_direction_y * 1.0 / length;
+ this.dodging_direction_x = this.dodging_direction_x * 1.0 / length;
+ this.dodging_direction_y = this.dodging_direction_y * 1.0 / length;
return true;
}
return false;
}
-void PM_dodging()
-{SELFPARAM();
+void PM_dodging(entity this)
+{
if (!PHYS_DODGING)
return;
-#ifdef SVQC
- dodging_UpdateStats();
-#endif
-
- if (PHYS_DEAD(self))
+ if (PHYS_DEAD(this))
return;
// when swimming, no dodging allowed..
- if (self.waterlevel >= WATERLEVEL_SWIMMING)
+ if (this.waterlevel >= WATERLEVEL_SWIMMING)
{
- self.dodging_action = 0;
- self.dodging_direction_x = 0;
- self.dodging_direction_y = 0;
+ this.dodging_action = 0;
+ this.dodging_direction_x = 0;
+ this.dodging_direction_y = 0;
return;
}
// make sure v_up, v_right and v_forward are sane
- makevectors(self.angles);
+ makevectors(this.angles);
// if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
// will be called ramp_time/frametime times = 2 times. so, we need to
// if ramp time is smaller than frametime we get problems ;D
common_factor = min(common_factor, 1);
- float horiz_speed = PHYS_FROZEN(self) ? PHYS_DODGING_HORIZ_SPEED_FROZEN : PHYS_DODGING_HORIZ_SPEED;
- float new_velocity_gain = self.dodging_velocity_gain - (common_factor * horiz_speed);
+ float horiz_speed = PHYS_FROZEN(this) ? PHYS_DODGING_HORIZ_SPEED_FROZEN : PHYS_DODGING_HORIZ_SPEED;
+ float new_velocity_gain = this.dodging_velocity_gain - (common_factor * horiz_speed);
new_velocity_gain = max(0, new_velocity_gain);
- float velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
+ float velocity_difference = this.dodging_velocity_gain - new_velocity_gain;
// ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
- if (self.dodging_action == 1)
+ if (this.dodging_action == 1)
{
//disable jump key during dodge accel phase
- if(self.movement_z > 0) { self.movement_z = 0; }
+ if(this.movement_z > 0) { this.movement_z = 0; }
- self.velocity += ((self.dodging_direction_y * velocity_difference) * v_right)
- + ((self.dodging_direction_x * velocity_difference) * v_forward);
+ this.velocity += ((this.dodging_direction_y * velocity_difference) * v_right)
+ + ((this.dodging_direction_x * velocity_difference) * v_forward);
- self.dodging_velocity_gain = self.dodging_velocity_gain - velocity_difference;
+ this.dodging_velocity_gain = this.dodging_velocity_gain - velocity_difference;
}
// the up part of the dodge is a single shot action
- if (self.dodging_single_action == 1)
+ if (this.dodging_single_action == 1)
{
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
- self.velocity += PHYS_DODGING_UP_SPEED * v_up;
+ this.velocity += PHYS_DODGING_UP_SPEED * v_up;
#ifdef SVQC
if (autocvar_sv_dodging_sound)
PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- animdecide_setaction(self, ANIMACTION_JUMP, true);
+ animdecide_setaction(this, ANIMACTION_JUMP, true);
#endif
- self.dodging_single_action = 0;
+ this.dodging_single_action = 0;
}
// are we done with the dodging ramp yet?
- if((self.dodging_action == 1) && ((time - self.last_dodging_time) > PHYS_DODGING_RAMP_TIME))
+ if((this.dodging_action == 1) && ((time - this.last_dodging_time) > PHYS_DODGING_RAMP_TIME))
{
// reset state so next dodge can be done correctly
- self.dodging_action = 0;
- self.dodging_direction_x = 0;
- self.dodging_direction_y = 0;
+ this.dodging_action = 0;
+ this.dodging_direction_x = 0;
+ this.dodging_direction_y = 0;
}
}
-#ifdef SVQC
-
-MUTATOR_HOOKFUNCTION(dodging, GetCvars)
+void PM_dodging_GetPressedKeys(entity this)
{
- GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
- return false;
+#ifdef CSQC
+ if(!PHYS_DODGING) { return; }
+
+ PM_dodging_checkpressedkeys(this);
+
+ int keys = this.pressedkeys;
+ keys = BITSET(keys, KEY_FORWARD, this.movement.x > 0);
+ keys = BITSET(keys, KEY_BACKWARD, this.movement.x < 0);
+ keys = BITSET(keys, KEY_RIGHT, this.movement.y > 0);
+ keys = BITSET(keys, KEY_LEFT, this.movement.y < 0);
+
+ keys = BITSET(keys, KEY_JUMP, PHYS_INPUT_BUTTON_JUMP(this));
+ keys = BITSET(keys, KEY_CROUCH, PHYS_INPUT_BUTTON_CROUCH(this));
+ keys = BITSET(keys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(this));
+ keys = BITSET(keys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(this));
+ this.pressedkeys = keys;
+#endif
}
MUTATOR_HOOKFUNCTION(dodging, PlayerPhysics)
{
// print("dodging_PlayerPhysics\n");
- PM_dodging();
+ PM_dodging_GetPressedKeys(self);
+ PM_dodging(self);
+ return false;
+}
+
+#ifdef SVQC
+MUTATOR_HOOKFUNCTION(dodging, GetCvars)
+{
+ GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
return false;
}
MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
{
- PM_dodging_checkpressedkeys();
-
+ PM_dodging_checkpressedkeys(self);
return false;
}
#endif
-
#endif
#ifdef SVQC
-#include "dodging.qc"
+ #include "dodging.qc"
#endif
--- /dev/null
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+ #include "../../../../server/antilag.qh"
+#endif
+#include "../../../physics.qh"
+
+REGISTER_MUTATOR(doublejump, true);
+
+#define PHYS_DOUBLEJUMP(s) STAT(DOUBLEJUMP, s)
+
+
+MUTATOR_HOOKFUNCTION(doublejump, PlayerJump)
+{
+ if (PHYS_DOUBLEJUMP(self))
+ {
+ tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+ if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
+ {
+ player_multijump = true;
+
+ // we MUST clip velocity here!
+ float f = self.velocity * trace_plane_normal;
+ if (f < 0)
+ self.velocity -= f * trace_plane_normal;
+ }
+ }
+ return false;
+}
+
+#ifdef SVQC
+
+MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":doublejump");
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", Double jump");
+ return false;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef MENUQC
+#include "doublejump.qc"
+#endif
float autocvar_g_instagib_speed_highspeed;
#include "../../../../server/cl_client.qh"
-#include "../../../buffs/all.qh"
#include "../../../items/all.qc"
void instagib_extralife()
{SELFPARAM();
- self.max_health = 1;
StartItem(this, ITEM_ExtraLife);
}
frag_mirrordamage = 0;
}
- if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Invisibility.m_itemid))
+ if(frag_target.alpha && frag_target.alpha < 1)
yoda = 1;
return false;
return MUT_ITEMTOUCH_CONTINUE;
}
- if(self.max_health)
+ if(self.itemdef == ITEM_ExtraLife)
{
other.armorvalue = bound(other.armorvalue, 999, other.armorvalue + autocvar_g_instagib_extralives);
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_EXTRALIVES);
float Item_ItemsTime_UpdateTime(entity e, float t)
{
bool isavailable = (t == 0);
- if (e.weapons & WEPSET_SUPERWEAPONS)
- {
- for (entity head = world; (head = nextent(head)); )
- {
- if (clienttype(head) != CLIENTTYPE_NOTACLIENT || !(head.weapons & WEPSET_SUPERWEAPONS) || head.instanceOfWeapon)
- continue;
- if (e == head)
- continue;
-
- if (head.scheduledrespawntime <= time)
- isavailable = true;
- else if (t == 0 || head.scheduledrespawntime < t)
- t = head.scheduledrespawntime;
- }
- }
- else
- {
- for (entity head = world; (head = nextent(head)); )
- {
- if (head.itemdef != e.itemdef)
- continue;
- if (e == head)
- continue;
-
- if (head.scheduledrespawntime <= time)
- isavailable = true;
- else if (t == 0 || head.scheduledrespawntime < t)
- t = head.scheduledrespawntime;
- }
- }
+ FOREACH_ENTITY(it.itemdef == e.itemdef || ((it.weapons & WEPSET_SUPERWEAPONS) && clienttype(it) == CLIENTTYPE_NOTACLIENT), LAMBDA(
+ if (e == it) continue;
+ if (it.scheduledrespawntime <= time)
+ isavailable = true;
+ else if (t == 0 || it.scheduledrespawntime < t)
+ t = it.scheduledrespawntime;
+ ));
if (isavailable)
t = -t; // let know the client there's another available item
return t;
Item_ItemsTime_ResetTimes();
// ALL the times need to be reset before .reset()ing each item
// since Item_Reset schedules respawn of superweapons and powerups
- for (entity e = NULL; (e = nextent(e)); )
- if (IS_NOT_A_CLIENT(e))
- {
- setself(e);
- if (self.reset)
- Item_ItemsTime_SetTime(self, 0);
- }
+ FOREACH_ENTITY(IS_NOT_A_CLIENT(it), LAMBDA(
+ if (it.reset) Item_ItemsTime_SetTime(it, 0);
+ ));
Item_ItemsTime_SetTimesForAllPlayers();
}
#endif
#include "../../../physics.qh"
-.int multijump_count;
-.bool multijump_ready;
-.bool cvar_cl_multijump;
-#ifdef CSQC
+#if defined(SVQC)
+REGISTER_MUTATOR(multijump, cvar("g_multijump"));
+#elif defined(CSQC)
+REGISTER_MUTATOR(multijump, true);
+#endif
-#define PHYS_MULTIJUMP getstati(STAT_MULTIJUMP)
-#define PHYS_MULTIJUMP_SPEED getstatf(STAT_MULTIJUMP_SPEED)
-#define PHYS_MULTIJUMP_ADD getstati(STAT_MULTIJUMP_ADD)
-#define PHYS_MULTIJUMP_MAXSPEED getstatf(STAT_MULTIJUMP_MAXSPEED)
-#define PHYS_MULTIJUMP_DODGING getstati(STAT_MULTIJUMP_DODGING)
+#define PHYS_MULTIJUMP STAT(MULTIJUMP, self)
+#define PHYS_MULTIJUMP_SPEED STAT(MULTIJUMP_SPEED, self)
+#define PHYS_MULTIJUMP_ADD STAT(MULTIJUMP_ADD, self)
+#define PHYS_MULTIJUMP_MAXSPEED STAT(MULTIJUMP_MAXSPEED, self)
+#define PHYS_MULTIJUMP_DODGING STAT(MULTIJUMP_DODGING, self)
+#define PHYS_MULTIJUMP_COUNT(s) STAT(MULTIJUMP_COUNT, s)
-#elif defined(SVQC)
+.bool multijump_ready;
-int autocvar_g_multijump;
-float autocvar_g_multijump_add;
-float autocvar_g_multijump_speed;
-float autocvar_g_multijump_maxspeed;
-float autocvar_g_multijump_dodging = 1;
-
-#define PHYS_MULTIJUMP autocvar_g_multijump
-#define PHYS_MULTIJUMP_SPEED autocvar_g_multijump_speed
-#define PHYS_MULTIJUMP_ADD autocvar_g_multijump_add
-#define PHYS_MULTIJUMP_MAXSPEED autocvar_g_multijump_maxspeed
-#define PHYS_MULTIJUMP_DODGING autocvar_g_multijump_dodging
-
-.float stat_multijump;
-.float stat_multijump_speed;
-.float stat_multijump_add;
-.float stat_multijump_maxspeed;
-.float stat_multijump_dodging;
-
-void multijump_UpdateStats()
-{SELFPARAM();
- self.stat_multijump = PHYS_MULTIJUMP;
- self.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
- self.stat_multijump_add = PHYS_MULTIJUMP_ADD;
- self.stat_multijump_maxspeed = PHYS_MULTIJUMP_MAXSPEED;
- self.stat_multijump_dodging = PHYS_MULTIJUMP_DODGING;
-}
+#ifdef CSQC
+bool autocvar_cl_multijump = false;
-void multijump_AddStats()
-{
- addstat(STAT_MULTIJUMP, AS_INT, stat_multijump);
- addstat(STAT_MULTIJUMP_SPEED, AS_FLOAT, stat_multijump_speed);
- addstat(STAT_MULTIJUMP_ADD, AS_INT, stat_multijump_add);
- addstat(STAT_MULTIJUMP_MAXSPEED, AS_FLOAT, stat_multijump_maxspeed);
- addstat(STAT_MULTIJUMP_DODGING, AS_INT, stat_multijump_dodging);
-}
+ #define PHYS_MULTIJUMP_CLIENT(s) autocvar_cl_multijump
+#elif defined(SVQC)
+.bool cvar_cl_multijump;
+ #define PHYS_MULTIJUMP_CLIENT(s) (s).cvar_cl_multijump
#endif
-void PM_multijump()
-{SELFPARAM();
- if(!PHYS_MULTIJUMP) { return; }
-
- if(IS_ONGROUND(self))
- {
- self.multijump_count = 0;
- }
-}
-
-bool PM_multijump_checkjump()
-{SELFPARAM();
+bool PM_multijump_checkjump(entity this)
+{
if(!PHYS_MULTIJUMP) { return false; }
-#ifdef SVQC
- bool client_multijump = self.cvar_cl_multijump;
-#elif defined(CSQC)
- bool client_multijump = cvar("cl_multijump");
-
- if(cvar("cl_multijump") > 1)
+ int client_multijump = PHYS_MULTIJUMP_CLIENT(this);
+ if(client_multijump > 1)
return false; // nope
-#endif
- if (!IS_JUMP_HELD(self) && !IS_ONGROUND(self) && client_multijump) // jump button pressed this frame and we are in midair
- self.multijump_ready = true; // this is necessary to check that we released the jump button and pressed it again
+ if (!IS_JUMP_HELD(this) && !IS_ONGROUND(this) && client_multijump) // jump button pressed this frame and we are in midair
+ this.multijump_ready = true; // this is necessary to check that we released the jump button and pressed it again
else
- self.multijump_ready = false;
+ this.multijump_ready = false;
int phys_multijump = PHYS_MULTIJUMP;
-#ifdef CSQC
- phys_multijump = (PHYS_MULTIJUMP) ? -1 : 0;
-#endif
-
- if(!player_multijump && self.multijump_ready && (self.multijump_count < phys_multijump || phys_multijump == -1) && self.velocity_z > PHYS_MULTIJUMP_SPEED && (!PHYS_MULTIJUMP_MAXSPEED || vlen(self.velocity) <= PHYS_MULTIJUMP_MAXSPEED))
+ if(!player_multijump && this.multijump_ready && (PHYS_MULTIJUMP_COUNT(this) < phys_multijump || phys_multijump == -1) && this.velocity_z > PHYS_MULTIJUMP_SPEED && (!PHYS_MULTIJUMP_MAXSPEED || vlen(this.velocity) <= PHYS_MULTIJUMP_MAXSPEED))
{
if (PHYS_MULTIJUMP)
{
if (!PHYS_MULTIJUMP_ADD) // in this case we make the z velocity == jumpvelocity
{
- if (self.velocity_z < PHYS_JUMPVELOCITY)
+ if (this.velocity_z < PHYS_JUMPVELOCITY(this))
{
player_multijump = true;
- self.velocity_z = 0;
+ this.velocity_z = 0;
}
}
else
if(player_multijump)
{
if(PHYS_MULTIJUMP_DODGING)
- if(self.movement_x != 0 || self.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
+ if(this.movement_x != 0 || this.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
{
float curspeed;
vector wishvel, wishdir;
/*#ifdef SVQC
curspeed = max(
- vlen(vec2(self.velocity)), // current xy speed
- vlen(vec2(antilag_takebackavgvelocity(self, max(self.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
+ vlen(vec2(this.velocity)), // current xy speed
+ vlen(vec2(antilag_takebackavgvelocity(this, max(this.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
);
#elif defined(CSQC)*/
- curspeed = vlen(vec2(self.velocity));
+ curspeed = vlen(vec2(this.velocity));
//#endif
- makevectors(self.v_angle_y * '0 1 0');
- wishvel = v_forward * self.movement_x + v_right * self.movement_y;
+ makevectors(this.v_angle_y * '0 1 0');
+ wishvel = v_forward * this.movement_x + v_right * this.movement_y;
wishdir = normalize(wishvel);
- self.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
- self.velocity_y = wishdir_y * curspeed;
+ this.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
+ this.velocity_y = wishdir_y * curspeed;
// keep velocity_z unchanged!
}
if (PHYS_MULTIJUMP > 0)
{
- self.multijump_count += 1;
+ this.multijump_count += 1;
}
}
}
- self.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
+ this.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
}
return false;
}
-#ifdef SVQC
-REGISTER_MUTATOR(multijump, cvar("g_multijump"))
-{
- MUTATOR_ONADD
- {
- multijump_AddStats();
- }
- return false;
-}
-
MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
{
- multijump_UpdateStats();
- PM_multijump();
+#ifdef CSQC
+ self.multijump_count = PHYS_MULTIJUMP_COUNT(self);
+#endif
+ if(!PHYS_MULTIJUMP) { return; }
+ if(IS_ONGROUND(self))
+ self.multijump_count = 0;
return false;
}
MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
{
- return PM_multijump_checkjump();
+ return PM_multijump_checkjump(self);
}
+#ifdef SVQC
+
MUTATOR_HOOKFUNCTION(multijump, GetCvars)
{
GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_multijump, "cl_multijump");
--- /dev/null
+EFFECT(0, NADE_EXPLODE_RED, "nade_red_explode")
+EFFECT(0, NADE_EXPLODE_BLUE, "nade_blue_explode")
+EFFECT(0, NADE_EXPLODE_YELLOW, "nade_yellow_explode")
+EFFECT(0, NADE_EXPLODE_PINK, "nade_pink_explode")
+EFFECT(0, NADE_EXPLODE_NEUTRAL, "nade_neutral_explode")
+entity EFFECT_NADE_EXPLODE(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_NADE_EXPLODE_RED;
+ case NUM_TEAM_2: return EFFECT_NADE_EXPLODE_BLUE;
+ case NUM_TEAM_3: return EFFECT_NADE_EXPLODE_YELLOW;
+ case NUM_TEAM_4: return EFFECT_NADE_EXPLODE_PINK;
+ default: return EFFECT_NADE_EXPLODE_NEUTRAL;
+ }
+}
+
+EFFECT(1, NADE_TRAIL_RED, "nade_red")
+EFFECT(1, NADE_TRAIL_BLUE, "nade_blue")
+EFFECT(1, NADE_TRAIL_YELLOW, "nade_yellow")
+EFFECT(1, NADE_TRAIL_PINK, "nade_pink")
+EFFECT(1, NADE_TRAIL_NEUTRAL, "nade_neutral")
+entity EFFECT_NADE_TRAIL(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_NADE_TRAIL_RED;
+ case NUM_TEAM_2: return EFFECT_NADE_TRAIL_BLUE;
+ case NUM_TEAM_3: return EFFECT_NADE_TRAIL_YELLOW;
+ case NUM_TEAM_4: return EFFECT_NADE_TRAIL_PINK;
+ default: return EFFECT_NADE_TRAIL_NEUTRAL;
+ }
+}
+
+EFFECT(1, NADE_TRAIL_BURN_RED, "nade_red_burn")
+EFFECT(1, NADE_TRAIL_BURN_BLUE, "nade_blue_burn")
+EFFECT(1, NADE_TRAIL_BURN_YELLOW, "nade_yellow_burn")
+EFFECT(1, NADE_TRAIL_BURN_PINK, "nade_pink_burn")
+EFFECT(1, NADE_TRAIL_BURN_NEUTRAL, "nade_neutral_burn")
+entity EFFECT_NADE_TRAIL_BURN(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_NADE_TRAIL_BURN_RED;
+ case NUM_TEAM_2: return EFFECT_NADE_TRAIL_BURN_BLUE;
+ case NUM_TEAM_3: return EFFECT_NADE_TRAIL_BURN_YELLOW;
+ case NUM_TEAM_4: return EFFECT_NADE_TRAIL_BURN_PINK;
+ default: return EFFECT_NADE_TRAIL_BURN_NEUTRAL;
+ }
+}
-#ifdef SVQC
#include "nades.qc"
+#ifndef MENUQC
+#include "net.qc"
#endif
--- /dev/null
+#ifndef MENUQC
+#define NADE_PROJECTILE(i, projectile, trail) do { \
+ this.m_projectile[i] = projectile; \
+ this.m_trail[i] = trail; \
+} while (0)
+#else
+#define NADE_PROJECTILE(i, projectile, trail)
+#endif
+
+REGISTER_NADE(NORMAL) {
+ this.m_color = '1 1 1';
+ NADE_PROJECTILE(0, PROJECTILE_NADE, EFFECT_Null);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, EFFECT_Null);
+}
+
+REGISTER_NADE(NAPALM) {
+ this.m_color = '2 0.5 0';
+ this.m_name = _("Napalm grenade");
+ this.m_icon = "nade_napalm";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, EFFECT_TR_ROCKET);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, EFFECT_SPIDERBOT_ROCKET_TRAIL);
+}
+
+REGISTER_NADE(ICE) {
+ this.m_color = '0 0.5 2';
+ this.m_name = _("Ice grenade");
+ this.m_icon = "nade_ice";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, EFFECT_TR_NEXUIZPLASMA);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, EFFECT_RACER_ROCKET_TRAIL);
+}
+
+REGISTER_NADE(TRANSLOCATE) {
+ this.m_color = '1 0 1';
+ this.m_name = _("Translocate grenade");
+ this.m_icon = "nade_translocate";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
+}
+
+REGISTER_NADE(SPAWN) {
+ this.m_color = '1 0.9 0';
+ this.m_name = _("Spawn grenade");
+ this.m_icon = "nade_spawn";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
+}
+
+REGISTER_NADE(HEAL) {
+ this.m_color = '1 0 0';
+ this.m_name = _("Heal grenade");
+ this.m_icon = "nade_heal";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, EFFECT_NADE_TRAIL_RED);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, EFFECT_NADE_TRAIL_BURN_RED);
+}
+
+REGISTER_NADE(MONSTER) {
+ this.m_color = '0.25 0.75 0';
+ this.m_name = _("Monster grenade");
+ this.m_icon = "nade_monster";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, EFFECT_NADE_TRAIL_RED);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, EFFECT_NADE_TRAIL_BURN_RED);
+}
-#ifndef MUTATOR_NADES_H
-#define MUTATOR_NADES_H
+#include "nades.qh"
-#ifdef SVQC
-#include "../../../../server/mutators/mutator/gamemode_freezetag.qc"
+#ifdef IMPLEMENTATION
+
+#ifndef MENUQC
+entity Nade_TrailEffect(int proj, int nade_team)
+{
+ switch (proj)
+ {
+ case PROJECTILE_NADE: return EFFECT_NADE_TRAIL(nade_team);
+ case PROJECTILE_NADE_BURN: return EFFECT_NADE_TRAIL_BURN(nade_team);
+ }
+
+ FOREACH(Nades, true, LAMBDA(
+ for (int j = 0; j < 2; j++)
+ {
+ if (it.m_projectile[j] == proj)
+ {
+ string trail = it.m_trail[j].eent_eff_name;
+ if (trail) return it.m_trail[j];
+ break;
+ }
+ }
+ ));
+
+ return EFFECT_Null;
+}
#endif
-.entity nade;
-.entity fake_nade;
-.float nade_timer;
-.float nade_refire;
-.float bonus_nades;
-.float nade_special_time;
-.float bonus_nade_score;
-.float nade_type;
-.string pokenade_type;
-.entity nade_damage_target;
-.float cvar_cl_nade_type;
-.string cvar_cl_pokenade_type;
-.float toss_time;
-.float stat_healing_orb;
-.float stat_healing_orb_alpha;
-.float nade_show_particles;
-
-// Remove nades that are being thrown
-void nades_Clear(entity player);
-
-// Give a bonus grenade to a player
-void(entity player, float score) nades_GiveBonus;
-
-/**
- * called to adjust nade damage and force on hit
- */
-#define EV_Nade_Damage(i, o) \
- /** weapon */ i(entity, MUTATOR_ARGV_0_entity) \
- /** force */ i(vector, MUTATOR_ARGV_0_vector) \
- /**/ o(vector, MUTATOR_ARGV_0_vector) \
- /** damage */ i(float, MUTATOR_ARGV_0_float) \
- /**/ o(float, MUTATOR_ARGV_0_float) \
- /**/
-MUTATOR_HOOKABLE(Nade_Damage, EV_Nade_Damage);
+#ifdef CSQC
+REGISTER_MUTATOR(cl_nades, true);
+MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
+{
+ if (STAT(HEALING_ORB) <= time) return false;
+ MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
+ MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA);
+ return true;
+}
+MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
+{
+ if (self.cnt == PROJECTILE_NAPALM_FOUNTAIN)
+ {
+ self.modelindex = 0;
+ self.traileffect = EFFECT_FIREBALL.m_id;
+ return true;
+ }
+ if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
+ {
+ setmodel(self, MDL_PROJECTILE_NADE);
+ entity trail = Nade_TrailEffect(self.cnt, self.team);
+ if (trail.eent_eff_name) self.traileffect = trail.m_id;
+ return true;
+ }
+}
+MUTATOR_HOOKFUNCTION(cl_nades, EditProjectile)
+{
+ if (self.cnt == PROJECTILE_NAPALM_FOUNTAIN)
+ {
+ loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY2), VOL_BASE, ATTEN_NORM);
+ self.mins = '-16 -16 -16';
+ self.maxs = '16 16 16';
+ }
+
+ entity nade_type = Nade_FromProjectile(self.cnt);
+ if (nade_type == NADE_TYPE_Null) return;
+ self.mins = '-16 -16 -16';
+ self.maxs = '16 16 16';
+ self.colormod = nade_type.m_color;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_touch = func_null;
+ self.scale = 1.5;
+ self.avelocity = randomvec() * 720;
+
+ if (nade_type == NADE_TYPE_TRANSLOCATE || nade_type == NADE_TYPE_SPAWN)
+ self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+ else
+ self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
+}
+bool Projectile_isnade(int p)
+{
+ return Nade_FromProjectile(p) != NADE_TYPE_Null;
+}
+void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
+{
+ float bonusNades = STAT(NADE_BONUS);
+ float bonusProgress = STAT(NADE_BONUS_SCORE);
+ float bonusType = STAT(NADE_BONUS_TYPE);
+ Nade def = Nades_from(bonusType);
+ vector nadeColor = def.m_color;
+ string nadeIcon = def.m_icon;
+ vector iconPos, textPos;
+
+ if(autocvar_hud_panel_ammo_iconalign)
+ {
+ iconPos = myPos + eX * 2 * mySize.y;
+ textPos = myPos;
+ }
+ else
+ {
+ iconPos = myPos;
+ textPos = myPos + eX * mySize.y;
+ }
+
+ if(bonusNades > 0 || bonusProgress > 0)
+ {
+ DrawNadeProgressBar(myPos, mySize, bonusProgress, nadeColor);
+
+ if(autocvar_hud_panel_ammo_text)
+ drawstring_aspect(textPos, ftos(bonusNades), eX * (2/3) * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ if(draw_expanding)
+ drawpic_aspect_skin_expanding(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, expand_time);
+
+ drawpic_aspect_skin(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+}
#endif
-#ifdef IMPLEMENTATION
+#ifdef SVQC
-#include "../../../nades/all.qh"
#include "../../../gamemodes/all.qh"
#include "../../../monsters/spawn.qh"
#include "../../../monsters/sv_monsters.qh"
#include "../../../../server/g_subs.qh"
-REGISTER_MUTATOR(nades, cvar("g_nades"))
-{
- MUTATOR_ONADD
- {
- addstat(STAT_NADE_TIMER, AS_FLOAT, nade_timer);
- addstat(STAT_NADE_BONUS, AS_FLOAT, bonus_nades);
- addstat(STAT_NADE_BONUS_TYPE, AS_INT, nade_type);
- addstat(STAT_NADE_BONUS_SCORE, AS_FLOAT, bonus_nade_score);
- addstat(STAT_HEALING_ORB, AS_FLOAT, stat_healing_orb);
- addstat(STAT_HEALING_ORB_ALPHA, AS_FLOAT, stat_healing_orb_alpha);
- }
-
- return false;
-}
+REGISTER_MUTATOR(nades, cvar("g_nades"));
.float nade_time_primed;
fn.colormod = Nades_from(n.nade_type).m_color;
fn.colormap = self.colormap;
fn.glowmod = self.glowmod;
- fn.think = SUB_Remove;
+ fn.think = SUB_Remove_self;
fn.nextthink = n.wait;
self.nade = n;
ret_string = strcat(ret_string, ", Nades");
return false;
}
+
+MUTATOR_HOOKFUNCTION(nades, BuildGameplayTipsString)
+{
+ ret_string = strcat(ret_string, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
+ return false;
+}
+
+#endif
#endif
--- /dev/null
+#ifndef NADES_ALL_H
+#define NADES_ALL_H
+
+#include "../../../teams.qh"
+
+// use slots 70-100
+const int PROJECTILE_NADE = 71;
+const int PROJECTILE_NADE_BURN = 72;
+const int PROJECTILE_NADE_NAPALM = 73;
+const int PROJECTILE_NADE_NAPALM_BURN = 74;
+const int PROJECTILE_NAPALM_FOUNTAIN = 75;
+const int PROJECTILE_NADE_ICE = 76;
+const int PROJECTILE_NADE_ICE_BURN = 77;
+const int PROJECTILE_NADE_TRANSLOCATE = 78;
+const int PROJECTILE_NADE_SPAWN = 79;
+const int PROJECTILE_NADE_HEAL = 80;
+const int PROJECTILE_NADE_HEAL_BURN = 81;
+const int PROJECTILE_NADE_MONSTER = 82;
+const int PROJECTILE_NADE_MONSTER_BURN = 83;
+
+REGISTRY(Nades, BITS(4))
+#define Nades_from(i) _Nades_from(i, NADE_TYPE_Null)
+REGISTER_REGISTRY(Nades)
+REGISTRY_CHECK(Nades)
+
+#define REGISTER_NADE(id) REGISTER(Nades, NADE_TYPE, id, m_id, NEW(Nade))
+
+CLASS(Nade, Object)
+ ATTRIB(Nade, m_id, int, 0)
+ ATTRIB(Nade, m_color, vector, '0 0 0')
+ ATTRIB(Nade, m_name, string, _("Grenade"))
+ ATTRIB(Nade, m_icon, string, "nade_normal")
+ ATTRIBARRAY(Nade, m_projectile, int, 2)
+ ATTRIBARRAY(Nade, m_trail, entity, 2)
+ METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
+ }
+ENDCLASS(Nade)
+
+REGISTER_NADE(Null);
+
+Nade Nade_FromProjectile(int proj)
+{
+ FOREACH(Nades, true, LAMBDA(
+ for (int j = 0; j < 2; j++)
+ {
+ if (it.m_projectile[j] == proj) return it;
+ }
+ ));
+ return NADE_TYPE_Null;
+}
+
+#ifndef MENUQC
+#include "effects.inc"
+#endif
+
+#include "nades.inc"
+
+.float healer_lifetime;
+.float healer_radius;
+
+#ifdef SVQC
+
+.entity nade;
+.entity fake_nade;
+.float nade_timer = _STAT(NADE_TIMER);
+.float nade_refire;
+.float bonus_nades = _STAT(NADE_BONUS);
+.float nade_special_time;
+.float bonus_nade_score = _STAT(NADE_BONUS_SCORE);
+.int nade_type = _STAT(NADE_BONUS_TYPE);
+.string pokenade_type;
+.entity nade_damage_target;
+.float cvar_cl_nade_type;
+.string cvar_cl_pokenade_type;
+.float toss_time;
+.float stat_healing_orb = _STAT(HEALING_ORB);
+.float stat_healing_orb_alpha = _STAT(HEALING_ORB_ALPHA);
+.float nade_show_particles;
+
+bool healer_send(entity this, entity to, int sf);
+
+// Remove nades that are being thrown
+void nades_Clear(entity player);
+
+// Give a bonus grenade to a player
+void(entity player, float score) nades_GiveBonus;
+
+/**
+ * called to adjust nade damage and force on hit
+ */
+#define EV_Nade_Damage(i, o) \
+ /** weapon */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** force */ i(vector, MUTATOR_ARGV_0_vector) \
+ /**/ o(vector, MUTATOR_ARGV_0_vector) \
+ /** damage */ i(float, MUTATOR_ARGV_0_float) \
+ /**/ o(float, MUTATOR_ARGV_0_float) \
+ /**/
+MUTATOR_HOOKABLE(Nade_Damage, EV_Nade_Damage);
+
+#endif
+
+#endif
--- /dev/null
+#include "nades.qh"
+
+#ifdef IMPLEMENTATION
+
+#ifdef CSQC
+.float ltime;
+void healer_draw(entity this)
+{
+ float dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ self.alpha = (self.ltime - time) / self.healer_lifetime;
+ self.scale = min((1 - self.alpha)*self.healer_lifetime*4,1)*self.healer_radius;
+}
+
+void healer_setup(entity e)
+{
+ setmodel(e, MDL_NADE_HEAL);
+
+ setorigin(e, e.origin);
+
+ float model_radius = e.maxs.x;
+ vector size = '1 1 1' * e.healer_radius / 2;
+ setsize(e,-size,size);
+ e.healer_radius = e.healer_radius/model_radius*0.6;
+
+ e.draw = healer_draw;
+ e.health = 255;
+ e.movetype = MOVETYPE_NONE;
+ e.solid = SOLID_NOT;
+ e.drawmask = MASK_NORMAL;
+ e.scale = 0.01;
+ e.avelocity = e.move_avelocity = '7 0 11';
+ e.colormod = '1 0 0';
+ e.renderflags |= RF_ADDITIVE;
+}
+#endif
+
+REGISTER_NET_LINKED(Nade_Heal)
+
+#ifdef CSQC
+NET_HANDLE(Nade_Heal, bool isNew)
+{
+ Net_Accept(Nade_Heal);
+ int sf = ReadByte();
+ if (sf & 1) {
+ this.origin_x = ReadCoord();
+ this.origin_y = ReadCoord();
+ this.origin_z = ReadCoord();
+ setorigin(this, this.origin);
+ this.healer_lifetime = ReadByte();
+ this.healer_radius = ReadShort();
+ this.ltime = time + ReadByte()/10.0;
+ // this.ltime = time + this.healer_lifetime;
+ healer_setup(this);
+ }
+ return true;
+}
+#endif
+
+#ifdef SVQC
+bool healer_send(entity this, entity to, int sf)
+{
+ int channel = MSG_ENTITY;
+ WriteHeader(channel, Nade_Heal);
+ WriteByte(channel, sf);
+ if (sf & 1) {
+ WriteCoord(channel, this.origin.x);
+ WriteCoord(channel, this.origin.y);
+ WriteCoord(channel, this.origin.z);
+
+ WriteByte(channel, this.healer_lifetime);
+ //WriteByte(MSG_ENTITY, this.ltime - time + 1);
+ WriteShort(channel, this.healer_radius);
+ // round time delta to a 1/10th of a second
+ WriteByte(channel, (this.ltime - time)*10.0+0.5);
+ }
+ return true;
+}
+#endif
+
+#endif
n = tokenize_console(nt_GetReplacement(e.netname, autocvar_g_new_toys_autoreplace));
- for(j = 0; j < n; ++j)
- for(k = WEP_FIRST; k <= WEP_LAST; ++k)
- if(get_weaponinfo(k).netname == argv(j))
+ for (j = 0; j < n; ++j)
+ for (k = WEP_FIRST; k <= WEP_LAST; ++k)
+ {
+ Weapon w = get_weaponinfo(k);
+ if (w.netname == argv(j))
{
- if(start_weapons & WepSet_FromWeapon(i))
- newdefault |= WepSet_FromWeapon(k);
- if(warmup_start_weapons & WepSet_FromWeapon(i))
- warmup_newdefault |= WepSet_FromWeapon(k);
+ WepSet seti = e.m_wepset;
+ WepSet setk = w.m_wepset;
+ if (start_weapons & seti) newdefault |= setk;
+ if (warmup_start_weapons & seti) warmup_newdefault |= setk;
}
+ }
}
newdefault &= start_weapons_defaultmask;
return false;
if(g_weaponarena)
{
- if(!(g_weaponarena_weapons & WepSet_FromWeapon(wpn)))
+ if(!(g_weaponarena_weapons & e.m_wepset))
return false;
}
else
else
Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
- Weapon w = get_weaponinfo(nix_weapon);
- w.wr_resetplayer(w);
+ e.wr_resetplayer(e);
// all weapons must be fully loaded when we spawn
if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
self.weapons = '0 0 0';
if(g_nix_with_blaster)
self.weapons |= WEPSET(BLASTER);
- self.weapons |= WepSet_FromWeapon(nix_weapon);
+ self.weapons |= e.m_wepset;
if(self.switchweapon != nix_weapon)
if(!client_hasweapon(self, self.switchweapon, true, false))
.float ok_notice_time;
.float ammo_charge[Weapons_MAX];
-.float ok_use_ammocharge;
-.float ok_ammo_charge;
+.float ok_use_ammocharge = _STAT(OK_AMMO_CHARGE);
+.float ok_ammo_charge = _STAT(OK_AMMO_CHARGEPOOL);
.float ok_pauseregen_finished;
return false;
}
-void _spawnfunc_weapon_hmg() { SELFPARAM(); spawnfunc_weapon_hmg(this); }
-void _spawnfunc_weapon_rpc() { SELFPARAM(); spawnfunc_weapon_rpc(this); }
+void self_spawnfunc_weapon_hmg() { SELFPARAM(); spawnfunc_weapon_hmg(this); }
+void self_spawnfunc_weapon_rpc() { SELFPARAM(); spawnfunc_weapon_rpc(this); }
MUTATOR_HOOKFUNCTION(ok, OnEntityPreSpawn)
{SELFPARAM();
wep.team = self.team;
wep.respawntime = autocvar_g_overkill_superguns_respawn_time;
wep.pickup_anyway = true;
- wep.think = _spawnfunc_weapon_hmg;
+ wep.think = self_spawnfunc_weapon_hmg;
wep.nextthink = time + 0.1;
return true;
}
wep.team = self.team;
wep.respawntime = autocvar_g_overkill_superguns_respawn_time;
wep.pickup_anyway = true;
- wep.think = _spawnfunc_weapon_rpc;
+ wep.think = self_spawnfunc_weapon_rpc;
wep.nextthink = time + 0.1;
return true;
}
precache_all_playermodels("models/ok_player/*.dpm");
- addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge);
- addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge);
-
WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
entity _item = self;
entity e;
- FOR_EACH_SPEC(e)
+ FOR_EACH_CLIENT(e) if (IS_SPEC(e) || IS_OBSERVER(e))
{
setself(e);
if(self.superspec_flags & SSF_ITEMMSG)
REGISTER_WAYPOINT(OnsGen, _("Generator"), '1 0.5 0', 1);
REGISTER_WAYPOINT(OnsGenShielded, _("Generator"), '1 0.5 0', 1);
-REGISTER_WAYPOINT(Buff, _("Buff"), '1 0.5 0', 1);
-
REGISTER_WAYPOINT(Weapon, _("Weapon"), '0 0 0', 1);
REGISTER_WAYPOINT(Monster, _("Monster"), '1 0 0', 1);
REGISTRY(Waypoints, BITS(6))
#define Waypoints_from(i) _Waypoints_from(i, WP_Null)
-REGISTER_REGISTRY(RegisterWaypoints)
+REGISTER_REGISTRY(Waypoints)
REGISTRY_CHECK(Waypoints)
/** If you register a new waypoint, make sure to add it to all.inc */
-#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, Waypoints, id, m_id, init)
+#define REGISTER_WAYPOINT_(id, init) REGISTER(Waypoints, WP, id, m_id, init)
CLASS(Waypoint, Object)
ATTRIB(Waypoint, m_id, int, 0)
REGISTRY(RadarIcons, BITS(7))
#define RadarIcons_from(i) _RadarIcons_from(i, RADARICON_NONE)
-REGISTER_REGISTRY(RegisterRadarIcons)
+REGISTER_REGISTRY(RadarIcons)
REGISTRY_CHECK(RadarIcons)
.int m_radaricon;
-#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { make_pure(this); this.m_radaricon = num; this.netname = #id; }
+#define REGISTER_RADARICON(id, num) REGISTER(RadarIcons, RADARICON, id, m_id, new(RadarIcon)) { make_pure(this); this.m_radaricon = num; this.netname = #id; }
REGISTER_WAYPOINT(Null, "", '0 0 0', 1);
REGISTER_RADARICON(DOMPOINT, 1);
REGISTER_RADARICON(TAGGED, 1);
-REGISTER_RADARICON(Buff, 1);
REGISTER_RADARICON(Item, 1);
REGISTER_RADARICON(Vehicle, 1);
REGISTER_RADARICON(Weapon, 1);
self.draw2d = Draw_WaypointSprite;
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
self.iflags |= IFLAG_ORIGIN;
if (sendflags & 0x80)
self.helpme += servertime;
}
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
self.entremove = Ent_RemoveWaypointSprite;
}
{
if (s == WP_Weapon.netname || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
if (s == WP_Item.netname || s == RADARICON_Item.netname) return Items_from(this.wp_extra).m_color;
- if (s == WP_Buff.netname || s == RADARICON_Buff.netname) return Buffs_from(this.wp_extra).m_color;
+ if (MUTATOR_CALLHOOK(WP_Format, this, s))
+ {
+ return MUTATOR_ARGV(0, vector);
+ }
return def;
}
if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).m_name;
if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypoint;
- if (s == WP_Buff.netname) return Buffs_from(self.wp_extra).m_prettyName;
if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
+ if (MUTATOR_CALLHOOK(WP_Format, this, s))
+ {
+ return MUTATOR_ARGV(0, string);
+ }
// need to loop, as our netname could be one of three
FOREACH(Waypoints, it.netname == s, LAMBDA(
if (fabs(sa) > fabs(ca))
{
algnx = (sa < 0);
- algny = 0.5 - 0.5 * ca / fabs(sa);
+ float f = fabs(sa);
+ algny = 0.5 - 0.5 * (f ? (ca / f) : 0);
}
else
{
- algnx = 0.5 - 0.5 * sa / fabs(ca);
+ float f = fabs(ca);
+ algnx = 0.5 - 0.5 * (f ? (sa / f) : 0);
algny = (ca < 0);
}
if (autocvar_cl_hidewaypoints)
return; // fixed waypoint
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(self);
float t = GetPlayerColor(player_localnum) + 1;
+++ /dev/null
-#define NADE_PROJECTILE(i, projectile, trail) do { \
- this.m_projectile[i] = projectile; \
- this.m_trail[i] = trail; \
-} while (0)
-
-REGISTER_NADE(NORMAL) {
- this.m_color = '1 1 1';
- NADE_PROJECTILE(0, PROJECTILE_NADE, EFFECT_Null);
- NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, EFFECT_Null);
-}
-
-REGISTER_NADE(NAPALM) {
- this.m_color = '2 0.5 0';
- this.m_name = _("Napalm grenade");
- this.m_icon = "nade_napalm";
- NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, EFFECT_TR_ROCKET);
- NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, EFFECT_SPIDERBOT_ROCKET_TRAIL);
-}
-
-REGISTER_NADE(ICE) {
- this.m_color = '0 0.5 2';
- this.m_name = _("Ice grenade");
- this.m_icon = "nade_ice";
- NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, EFFECT_TR_NEXUIZPLASMA);
- NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, EFFECT_RACER_ROCKET_TRAIL);
-}
-
-REGISTER_NADE(TRANSLOCATE) {
- this.m_color = '1 0 1';
- this.m_name = _("Translocate grenade");
- this.m_icon = "nade_translocate";
- NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
- NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
-}
-
-REGISTER_NADE(SPAWN) {
- this.m_color = '1 0.9 0';
- this.m_name = _("Spawn grenade");
- this.m_icon = "nade_spawn";
- NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
- NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
-}
-
-REGISTER_NADE(HEAL) {
- this.m_color = '1 0 0';
- this.m_name = _("Heal grenade");
- this.m_icon = "nade_heal";
- NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, EFFECT_NADE_TRAIL_RED);
- NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, EFFECT_NADE_TRAIL_BURN_RED);
-}
-
-REGISTER_NADE(MONSTER) {
- this.m_color = '0.25 0.75 0';
- this.m_name = _("Monster grenade");
- this.m_icon = "nade_monster";
- NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, EFFECT_NADE_TRAIL_RED);
- NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, EFFECT_NADE_TRAIL_BURN_RED);
-}
+++ /dev/null
-#include "all.qh"
-
-#if defined(CSQC)
- #include "../../client/defs.qh"
- #include "../buffs/all.qh"
- #include "../movetypes/movetypes.qh"
- #include "../../client/main.qh"
- #include "../../lib/csqcmodel/cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include "../constants.qh"
- #include "../../server/constants.qh"
- #include "../turrets/sv_turrets.qh"
-#endif
-
-
-#ifdef CSQC
-.float ltime;
-void healer_draw(entity this)
-{
- float dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- self.alpha = (self.ltime - time) / self.healer_lifetime;
- self.scale = min((1 - self.alpha)*self.healer_lifetime*4,1)*self.healer_radius;
-}
-
-void healer_setup(entity e)
-{
- setmodel(e, MDL_NADE_HEAL);
-
- setorigin(e, e.origin);
-
- float model_radius = e.maxs.x;
- vector size = '1 1 1' * e.healer_radius / 2;
- setsize(e,-size,size);
- e.healer_radius = e.healer_radius/model_radius*0.6;
-
- e.draw = healer_draw;
- e.health = 255;
- e.movetype = MOVETYPE_NONE;
- e.solid = SOLID_NOT;
- e.drawmask = MASK_NORMAL;
- e.scale = 0.01;
- e.avelocity = e.move_avelocity = '7 0 11';
- e.colormod = '1 0 0';
- e.renderflags |= RF_ADDITIVE;
-}
-#endif // CSQC
-
-REGISTER_NET_LINKED(Nade_Heal)
-#ifdef CSQC
-NET_HANDLE(Nade_Heal, bool isNew)
-{
- Net_Accept(Nade_Heal);
- int sf = ReadByte();
- if (sf & 1) {
- this.origin_x = ReadCoord();
- this.origin_y = ReadCoord();
- this.origin_z = ReadCoord();
- setorigin(this, this.origin);
- this.healer_lifetime = ReadByte();
- this.healer_radius = ReadShort();
- this.ltime = time + ReadByte()/10.0;
- // this.ltime = time + this.healer_lifetime;
- healer_setup(this);
- }
- return true;
-}
-#endif
-
-#ifdef SVQC
-bool healer_send(entity this, entity to, int sf)
-{
- int channel = MSG_ENTITY;
- WriteHeader(channel, Nade_Heal);
- WriteByte(channel, sf);
- if (sf & 1) {
- WriteCoord(channel, this.origin.x);
- WriteCoord(channel, this.origin.y);
- WriteCoord(channel, this.origin.z);
-
- WriteByte(channel, this.healer_lifetime);
- //WriteByte(MSG_ENTITY, this.ltime - time + 1);
- WriteShort(channel, this.healer_radius);
- // round time delta to a 1/10th of a second
- WriteByte(channel, (this.ltime - time)*10.0+0.5);
- }
- return true;
-}
-#endif // SVQC
+++ /dev/null
-#ifndef NADES_ALL_H
-#define NADES_ALL_H
-
-#include "../teams.qh"
-
-.float healer_lifetime;
-.float healer_radius;
-
-// use slots 70-100
-const int PROJECTILE_NADE = 71;
-const int PROJECTILE_NADE_BURN = 72;
-const int PROJECTILE_NADE_NAPALM = 73;
-const int PROJECTILE_NADE_NAPALM_BURN = 74;
-const int PROJECTILE_NAPALM_FOUNTAIN = 75;
-const int PROJECTILE_NADE_ICE = 76;
-const int PROJECTILE_NADE_ICE_BURN = 77;
-const int PROJECTILE_NADE_TRANSLOCATE = 78;
-const int PROJECTILE_NADE_SPAWN = 79;
-const int PROJECTILE_NADE_HEAL = 80;
-const int PROJECTILE_NADE_HEAL_BURN = 81;
-const int PROJECTILE_NADE_MONSTER = 82;
-const int PROJECTILE_NADE_MONSTER_BURN = 83;
-
-REGISTRY(Nades, BITS(4))
-#define Nades_from(i) _Nades_from(i, NADE_TYPE_Null)
-REGISTER_REGISTRY(RegisterNades)
-REGISTRY_CHECK(Nades)
-
-#define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, Nades, id, m_id, NEW(Nade))
-
-CLASS(Nade, Object)
- ATTRIB(Nade, m_id, int, 0)
- ATTRIB(Nade, m_color, vector, '0 0 0')
- ATTRIB(Nade, m_name, string, _("Grenade"))
- ATTRIB(Nade, m_icon, string, "nade_normal")
- ATTRIBARRAY(Nade, m_projectile, int, 2)
- ATTRIBARRAY(Nade, m_trail, entity, 2)
- METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
- returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
- }
-ENDCLASS(Nade)
-
-REGISTER_NADE(Null);
-
-#ifdef SVQC
-bool healer_send(entity this, entity to, int sf);
-#endif
-
-entity Nade_FromProjectile(float proj)
-{
- FOREACH(Nades, true, LAMBDA(
- for (int j = 0; j < 2; j++)
- {
- if (it.m_projectile[j] == proj) return it;
- }
- ));
- return NADE_TYPE_Null;
-}
-
-entity Nade_TrailEffect(int proj, int nade_team)
-{
- switch (proj)
- {
- case PROJECTILE_NADE: return EFFECT_NADE_TRAIL(nade_team);
- case PROJECTILE_NADE_BURN: return EFFECT_NADE_TRAIL_BURN(nade_team);
- }
-
- FOREACH(Nades, true, LAMBDA(
- for (int j = 0; j < 2; j++)
- {
- if (it.m_projectile[j] == proj)
- {
- string trail = it.m_trail[j].eent_eff_name;
- if (trail) return it.m_trail[j];
- break;
- }
- }
- ));
-
- return EFFECT_Null;
-}
-
-#include "all.inc"
-
-#endif
#ifdef SVQC
void sv_notice_join_think()
-{SELFPARAM();
- //NextLevel();
- float argc = tokenizebyseparator(autocvar_sv_join_notices, "|");
- if(argc > 0)
- {
- float i;
- for(i = argc - 1; i >= 0; --i)
- sv_notice_to(self.owner, argv(i), autocvar_sv_join_notices_time, false);
- }
- remove(self);
+{
+ SELFPARAM();
+ int argc = tokenizebyseparator(autocvar_sv_join_notices, "|");
+ if (argc <= 0) return;
+ for (int i = 0; i < argc; ++i)
+ sv_notice_to(this, argv(i), autocvar_sv_join_notices_time, false);
}
-void sv_notice_join()
-{SELFPARAM();
+void sv_notice_join(entity _to)
+{
// to-do: make sv_join_notices support per-entry times
- if(autocvar_sv_join_notices == "")
- return;
-
- entity n = spawn();
- n.owner = self;
- n.think = sv_notice_join_think;
- n.nextthink = time + 1;
+ if (autocvar_sv_join_notices == "") return;
+ defer(_to, 1, sv_notice_join_think);
}
void sv_notice_to(entity _to, string _notice, float _howlong, float _modal)
cl_notice_read();
return true;
}
+entity cl_notices;
+STATIC_INIT(cl_notice)
+{
+ cl_notices = LL_NEW();
+}
void cl_notice_read()
{
- //float _done;
- //float _modal;
entity _notice = new(sv_notice);
+ make_pure(_notice);
_notice.netname = strzone(ReadString());
_notice.alpha = ReadLong() + time;
_notice.skin = ReadByte();
+ LL_PUSH(cl_notices, _notice);
}
-float cl_notice_run()
+void cl_notice_run()
{
- entity _notes;
- string _notice;
- float m = false;
-
- _notes = findchain(classname, "sv_notice");
- if(!_notes)
- return false;
- #define M1 30
- #define M2 10
-
- vector v1, v2 = '0 0 0', v3;
- v1 = '1 1 0' * M1;
- v2_x = vid_conwidth - (2 * M1);
- v2_y = vid_conheight - (2 * M1);
-
+ bool flag = false;
+ LL_EACH(cl_notices, it.alpha > time, LAMBDA(flag = true; break));
+ if (!flag) return;
+ const int M1 = 30;
+ const int M2 = 10;
+
+ vector v1 = '1 1 0' * M1;
+ vector v2 = '0 0 0';
+ v2.x = vid_conwidth - (2 * M1);
+ v2.y = vid_conheight - (2 * M1);
drawfill(v1, v2, '0 0 0', 0.5, DRAWFLAG_NORMAL);
+
v1 = '1 1 0' * (M1 + M2);
- v2_x = vid_conwidth - (2 * (M1 + M2));
- v2_y = vid_conheight - (2 * (M1 + M2));
+ v2.x = vid_conwidth - (2 * (M1 + M2));
+ v2.y = vid_conheight - (2 * (M1 + M2));
drawfill(v1, v2, '0.5 0.5 0.5', 0.5, DRAWFLAG_NORMAL);
- v3 = v1 + '10 10 0';
- #define OUT(s,z) drawcolorcodedstring(v3, s, '1 1 0' * z, 1, DRAWFLAG_NORMAL); v3_y += z + 4
+ vector v3 = v1 + '10 10 0';
+ #define OUT(s, z) do { drawcolorcodedstring(v3, s, '1 1 0' * z, 1, DRAWFLAG_NORMAL); v3.y += z + 4; } while (0)
OUT(_("^1Server notices:"), 32);
-
- //drawcolorcodedstring(v1 + '5 5 0', "^1Server notices:", '32 32 0', 1, DRAWFLAG_NORMAL);
- while(_notes)
- {
-
- _notice = sprintf(_("^7%s (^3%d sec left)"), _notes.netname , rint(_notes.alpha - time));
- OUT(_notice, 16);
-
- if(_notes.skin)
- m = true;
-
- if(_notes.alpha <= time)
- {
- _notes.think = SUB_Remove;
- _notes.nextthink = time;
- }
-
- _notes = _notes.chain;
- }
-
+ LL_EACH(cl_notices, it.alpha > time, LAMBDA(
+ string s = sprintf(_("^7%s (^3%d sec left)"), it.netname , rint(it.alpha - time));
+ OUT(s, 16);
+ ));
#undef OUT
- #undef M1
- #undef M2
-
- return m;
}
#endif // CSQC
void sv_notice_to(entity _to, string _notice, float _howlong, float _modal);
void sv_notice_toall(string _notice, float _howlong, float _modal);
-void sv_notice_join();
+void sv_notice_join(entity _to);
#endif
#ifdef CSQC
// todo possible idea.... declare how many floats/strings each arg needs, and then dynamically increment the input
// this way, we don't need to have duplicates like i.e. s2loc and s3loc?
+string BUFF_NAME(int i);
+
#define NOTIF_ARGUMENT_LIST \
ARG_CASE(ARG_CS_SV_HA, "s1", s1) \
ARG_CASE(ARG_CS_SV_HA, "s2", s2) \
ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
ARG_CASE(ARG_CS_SV, "spree_lost", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
ARG_CASE(ARG_CS_SV, "item_wepname", WEP_NAME(f1)) \
- ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buffs_from(f1).m_color), Buffs_from(f1).m_prettyName)) \
- ARG_CASE(ARG_CS_SV, "f3buffname", sprintf("%s%s", rgb_to_hexcolor(Buffs_from(f3).m_color), Buffs_from(f3).m_prettyName)) \
+ ARG_CASE(ARG_CS_SV, "item_buffname", BUFF_NAME(f1)) \
+ ARG_CASE(ARG_CS_SV, "f3buffname", BUFF_NAME(f3)) \
ARG_CASE(ARG_CS_SV, "item_wepammo", (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
ARG_CASE(ARG_DC, "item_centime", ftos(autocvar_notification_item_centerprinttime)) \
ARG_CASE(ARG_SV, "death_team", Team_ColoredFullName(f1)) \
return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar);
}
-float Physics_ClientOption(entity pl, string option)
+float Physics_ClientOption(entity this, string option)
{
- if(Physics_Valid(pl.cvar_cl_physics))
+ if(Physics_Valid(this.cvar_cl_physics))
{
- string s = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+ string s = sprintf("g_physics_%s_%s", this.cvar_cl_physics, option);
if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
return cvar(s);
}
return cvar(strcat("sv_", option));
}
-void Physics_AddStats()
+void Physics_UpdateStats(entity this, float maxspd_mod)
{
- // static view offset and hitbox vectors
- // networked for all you bandwidth pigs out there
- addstat(STAT_PL_VIEW_OFS1, AS_FLOAT, stat_pl_view_ofs_x);
- addstat(STAT_PL_VIEW_OFS2, AS_FLOAT, stat_pl_view_ofs_y);
- addstat(STAT_PL_VIEW_OFS3, AS_FLOAT, stat_pl_view_ofs_z);
- addstat(STAT_PL_CROUCH_VIEW_OFS1, AS_FLOAT, stat_pl_crouch_view_ofs_x);
- addstat(STAT_PL_CROUCH_VIEW_OFS2, AS_FLOAT, stat_pl_crouch_view_ofs_y);
- addstat(STAT_PL_CROUCH_VIEW_OFS3, AS_FLOAT, stat_pl_crouch_view_ofs_z);
-
- addstat(STAT_PL_MIN1, AS_FLOAT, stat_pl_min_x);
- addstat(STAT_PL_MIN2, AS_FLOAT, stat_pl_min_y);
- addstat(STAT_PL_MIN3, AS_FLOAT, stat_pl_min_z);
- addstat(STAT_PL_MAX1, AS_FLOAT, stat_pl_max_x);
- addstat(STAT_PL_MAX2, AS_FLOAT, stat_pl_max_y);
- addstat(STAT_PL_MAX3, AS_FLOAT, stat_pl_max_z);
- addstat(STAT_PL_CROUCH_MIN1, AS_FLOAT, stat_pl_crouch_min_x);
- addstat(STAT_PL_CROUCH_MIN2, AS_FLOAT, stat_pl_crouch_min_y);
- addstat(STAT_PL_CROUCH_MIN3, AS_FLOAT, stat_pl_crouch_min_z);
- addstat(STAT_PL_CROUCH_MAX1, AS_FLOAT, stat_pl_crouch_max_x);
- addstat(STAT_PL_CROUCH_MAX2, AS_FLOAT, stat_pl_crouch_max_y);
- addstat(STAT_PL_CROUCH_MAX3, AS_FLOAT, stat_pl_crouch_max_z);
-
- // g_movementspeed hack
- addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
- addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
- addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
- addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
- addstat(STAT_MOVEVARS_HIGHSPEED, AS_FLOAT, stat_movement_highspeed);
-
- // jet pack
- addstat(STAT_JETPACK_ACCEL_SIDE, AS_FLOAT, stat_jetpack_accel_side);
- addstat(STAT_JETPACK_ACCEL_UP, AS_FLOAT, stat_jetpack_accel_up);
- addstat(STAT_JETPACK_ANTIGRAVITY, AS_FLOAT, stat_jetpack_antigravity);
- addstat(STAT_JETPACK_FUEL, AS_FLOAT, stat_jetpack_fuel);
- addstat(STAT_JETPACK_MAXSPEED_UP, AS_FLOAT, stat_jetpack_maxspeed_up);
- addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
-
- // hack to fix track_canjump
- addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
- addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
-
- // double jump
- addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
-
- // jump speed caps
- addstat(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, AS_INT, stat_jumpspeedcap_disable_onramps);
-
- // hacks
- addstat(STAT_MOVEVARS_FRICTION_ONLAND, AS_FLOAT, stat_sv_friction_on_land);
- addstat(STAT_MOVEVARS_FRICTION_SLICK, AS_FLOAT, stat_sv_friction_slick);
- addstat(STAT_GAMEPLAYFIX_EASIERWATERJUMP, AS_INT, stat_gameplayfix_easierwaterjump);
-
- // new properties
- addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
- addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
- addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
- addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
- addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
- addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
- addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
- addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
- addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
- addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
- addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
- addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
- addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
- addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-
- addstat(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, AS_INT, stat_gameplayfix_upvelocityclearsonground);
-}
-
-void Physics_UpdateStats(float maxspd_mod)
-{SELFPARAM();
- // blah
- self.stat_pl_view_ofs = PL_VIEW_OFS;
- self.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
-
- self.stat_pl_min = PL_MIN;
- self.stat_pl_max = PL_MAX;
- self.stat_pl_crouch_min = PL_CROUCH_MIN;
- self.stat_pl_crouch_max = PL_CROUCH_MAX;
-
-
- self.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airaccel_qw"), maxspd_mod);
- if(Physics_ClientOption(self, "airstrafeaccel_qw"))
- self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airstrafeaccel_qw"), maxspd_mod);
- else
- self.stat_sv_airstrafeaccel_qw = 0;
- self.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(self, "airspeedlimit_nonqw") * maxspd_mod;
- self.stat_sv_maxspeed = Physics_ClientOption(self, "maxspeed") * maxspd_mod; // also slow walking
- self.stat_movement_highspeed = PHYS_HIGHSPEED; // TODO: remove this!
-
- self.stat_doublejump = PHYS_DOUBLEJUMP;
-
- self.stat_jetpack_antigravity = PHYS_JETPACK_ANTIGRAVITY;
- self.stat_jetpack_accel_up = PHYS_JETPACK_ACCEL_UP;
- self.stat_jetpack_accel_side = PHYS_JETPACK_ACCEL_SIDE;
- self.stat_jetpack_maxspeed_side = PHYS_JETPACK_MAXSPEED_SIDE;
- self.stat_jetpack_maxspeed_up = PHYS_JETPACK_MAXSPEED_UP;
- self.stat_jetpack_fuel = PHYS_JETPACK_FUEL;
-
- self.stat_jumpspeedcap_disable_onramps = PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS;
-
- self.stat_sv_friction_on_land = PHYS_FRICTION_ONLAND;
- self.stat_sv_friction_slick = PHYS_FRICTION_SLICK;
-
- self.stat_gameplayfix_easierwaterjump = GAMEPLAYFIX_EASIERWATERJUMP;
-
+ STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw"), maxspd_mod);
+ STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw"))
+ ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw"), maxspd_mod)
+ : 0;
+ STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw") * maxspd_mod;
+ STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed") * maxspd_mod; // also slow walking
// old stats
// fix some new settings
- self.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(self, "airaccel_qw_stretchfactor");
- self.stat_sv_maxairstrafespeed = Physics_ClientOption(self, "maxairstrafespeed");
- self.stat_sv_maxairspeed = Physics_ClientOption(self, "maxairspeed");
- self.stat_sv_airstrafeaccelerate = Physics_ClientOption(self, "airstrafeaccelerate");
- self.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(self, "warsowbunny_turnaccel");
- self.stat_sv_airaccel_sideways_friction = Physics_ClientOption(self, "airaccel_sideways_friction");
- self.stat_sv_aircontrol = Physics_ClientOption(self, "aircontrol");
- self.stat_sv_aircontrol_power = Physics_ClientOption(self, "aircontrol_power");
- self.stat_sv_aircontrol_penalty = Physics_ClientOption(self, "aircontrol_penalty");
- self.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(self, "warsowbunny_airforwardaccel");
- self.stat_sv_warsowbunny_topspeed = Physics_ClientOption(self, "warsowbunny_topspeed");
- self.stat_sv_warsowbunny_accel = Physics_ClientOption(self, "warsowbunny_accel");
- self.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(self, "warsowbunny_backtosideratio");
- self.stat_sv_friction = Physics_ClientOption(self, "friction");
- self.stat_sv_accelerate = Physics_ClientOption(self, "accelerate");
- self.stat_sv_stopspeed = Physics_ClientOption(self, "stopspeed");
- self.stat_sv_airaccelerate = Physics_ClientOption(self, "airaccelerate");
- self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
- self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
-
- self.stat_sv_track_canjump = Physics_ClientOption(self, "track_canjump");
-
- self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
+ STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor");
+ STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed");
+ STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed");
+ STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate");
+ STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel");
+ STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction");
+ STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol");
+ STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power");
+ STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty");
+ STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel");
+ STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed");
+ STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel");
+ STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio");
+ STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction");
+ STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate");
+ STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed");
+ STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate");
+ STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate");
+ STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity");
+ STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump");
}
#endif
noref float pmove_waterjumptime;
-const float unstick_count = 27;
-vector unstick_offsets[unstick_count] =
+#define unstick_offsets(X) \
+/* 1 no nudge (just return the original if this test passes) */ \
+ X(' 0.000 0.000 0.000') \
+/* 6 simple nudges */ \
+ X(' 0.000 0.000 0.125') X('0.000 0.000 -0.125') \
+ X('-0.125 0.000 0.000') X('0.125 0.000 0.000') \
+ X(' 0.000 -0.125 0.000') X('0.000 0.125 0.000') \
+/* 4 diagonal flat nudges */ \
+ X('-0.125 -0.125 0.000') X('0.125 -0.125 0.000') \
+ X('-0.125 0.125 0.000') X('0.125 0.125 0.000') \
+/* 8 diagonal upward nudges */ \
+ X('-0.125 0.000 0.125') X('0.125 0.000 0.125') \
+ X(' 0.000 -0.125 0.125') X('0.000 0.125 0.125') \
+ X('-0.125 -0.125 0.125') X('0.125 -0.125 0.125') \
+ X('-0.125 0.125 0.125') X('0.125 0.125 0.125') \
+/* 8 diagonal downward nudges */ \
+ X('-0.125 0.000 -0.125') X('0.125 0.000 -0.125') \
+ X(' 0.000 -0.125 -0.125') X('0.000 0.125 -0.125') \
+ X('-0.125 -0.125 -0.125') X('0.125 -0.125 -0.125') \
+ X('-0.125 0.125 -0.125') X('0.125 0.125 -0.125') \
+/**/
+
+void PM_ClientMovement_Unstick(entity this)
{
-// 1 no nudge (just return the original if this test passes)
- '0.000 0.000 0.000',
-// 6 simple nudges
- ' 0.000 0.000 0.125', '0.000 0.000 -0.125',
- '-0.125 0.000 0.000', '0.125 0.000 0.000',
- ' 0.000 -0.125 0.000', '0.000 0.125 0.000',
-// 4 diagonal flat nudges
- '-0.125 -0.125 0.000', '0.125 -0.125 0.000',
- '-0.125 0.125 0.000', '0.125 0.125 0.000',
-// 8 diagonal upward nudges
- '-0.125 0.000 0.125', '0.125 0.000 0.125',
- ' 0.000 -0.125 0.125', '0.000 0.125 0.125',
- '-0.125 -0.125 0.125', '0.125 -0.125 0.125',
- '-0.125 0.125 0.125', '0.125 0.125 0.125',
-// 8 diagonal downward nudges
- '-0.125 0.000 -0.125', '0.125 0.000 -0.125',
- ' 0.000 -0.125 -0.125', '0.000 0.125 -0.125',
- '-0.125 -0.125 -0.125', '0.125 -0.125 -0.125',
- '-0.125 0.125 -0.125', '0.125 0.125 -0.125',
-};
-
-void PM_ClientMovement_Unstick()
-{SELFPARAM();
- float i;
- for (i = 0; i < unstick_count; i++)
- {
- vector neworigin = unstick_offsets[i] + self.origin;
- tracebox(neworigin, PL_CROUCH_MIN, PL_CROUCH_MAX, neworigin, MOVE_NORMAL, self);
- if (!trace_startsolid)
- {
- setorigin(self, neworigin);
- return;// true;
- }
+ #define X(unstick_offset) \
+ { \
+ vector neworigin = unstick_offset + this.origin; \
+ tracebox(neworigin, PL_CROUCH_MIN, PL_CROUCH_MAX, neworigin, MOVE_NORMAL, this); \
+ if (!trace_startsolid) \
+ { \
+ setorigin(this, neworigin); \
+ return; \
+ } \
}
+ unstick_offsets(X);
+ #undef X
}
-void PM_ClientMovement_UpdateStatus(bool ground)
-{SELFPARAM();
+void PM_ClientMovement_UpdateStatus(entity this, bool ground)
+{
// make sure player is not stuck
- PM_ClientMovement_Unstick();
+ PM_ClientMovement_Unstick(this);
// set crouched
- if (PHYS_INPUT_BUTTON_CROUCH(self))
+ if (PHYS_INPUT_BUTTON_CROUCH(this))
{
- // wants to crouch, this always works..
- if (!IS_DUCKED(self))
- SET_DUCKED(self);
+ // wants to crouch, this always works
+ if (!IS_DUCKED(this)) SET_DUCKED(this);
}
else
{
- // wants to stand, if currently crouching we need to check for a
- // low ceiling first
- if (IS_DUCKED(self))
+ // wants to stand, if currently crouching we need to check for a low ceiling first
+ if (IS_DUCKED(this))
{
- tracebox(self.origin, PL_MIN, PL_MAX, self.origin, MOVE_NORMAL, self);
- if (!trace_startsolid)
- UNSET_DUCKED(self);
+ tracebox(this.origin, PL_MIN, PL_MAX, this.origin, MOVE_NORMAL, this);
+ if (!trace_startsolid) UNSET_DUCKED(this);
}
}
// set onground
- vector origin1 = self.origin + '0 0 1';
- vector origin2 = self.origin - '0 0 1';
+ vector origin1 = this.origin + '0 0 1';
+ vector origin2 = this.origin - '0 0 1';
- if(ground)
+ if (ground)
{
- tracebox(origin1, self.mins, self.maxs, origin2, MOVE_NORMAL, self);
- if (trace_fraction < 1.0 && trace_plane_normal_z > 0.7)
+ tracebox(origin1, this.mins, this.maxs, origin2, MOVE_NORMAL, this);
+ if (trace_fraction < 1.0 && trace_plane_normal.z > 0.7)
{
- SET_ONGROUND(self);
+ SET_ONGROUND(this);
// this code actually "predicts" an impact; so let's clip velocity first
- float f = self.velocity * trace_plane_normal;
- self.velocity -= f * trace_plane_normal;
+ this.velocity -= this.velocity * trace_plane_normal * trace_plane_normal;
}
else
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
}
// set watertype/waterlevel
- origin1 = self.origin;
- origin1_z += self.mins_z + 1;
- self.waterlevel = WATERLEVEL_NONE;
+ origin1 = this.origin;
+ origin1.z += this.mins_z + 1;
+ this.waterlevel = WATERLEVEL_NONE;
int thepoint = pointcontents(origin1);
- self.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
+ this.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
- if(self.watertype)
+ if (this.watertype)
{
- self.waterlevel = WATERLEVEL_WETFEET;
- origin1_z = self.origin_z + (self.mins_z + self.maxs_z) * 0.5;
+ this.waterlevel = WATERLEVEL_WETFEET;
+ origin1.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5;
thepoint = pointcontents(origin1);
- if(thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+ if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
{
- self.waterlevel = WATERLEVEL_SWIMMING;
- origin1_z = self.origin_z + 22;
+ this.waterlevel = WATERLEVEL_SWIMMING;
+ origin1.z = this.origin.z + 22;
thepoint = pointcontents(origin1);
- if(thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
- self.waterlevel = WATERLEVEL_SUBMERGED;
+ if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+ this.waterlevel = WATERLEVEL_SUBMERGED;
}
}
- if(IS_ONGROUND(self) || self.velocity_z <= 0 || pmove_waterjumptime <= 0)
+ if (IS_ONGROUND(this) || this.velocity.z <= 0 || pmove_waterjumptime <= 0)
pmove_waterjumptime = 0;
}
-void PM_ClientMovement_Move()
-{SELFPARAM();
+void PM_ClientMovement_Move(entity this)
+{
#ifdef CSQC
+
+ PM_ClientMovement_UpdateStatus(this, false);
+ if(autocvar_cl_movement == 3)
+ return;
+
int bump;
float t;
float f;
vector trace2_plane_normal = '0 0 0';
vector trace3_plane_normal = '0 0 0';
-
- PM_ClientMovement_UpdateStatus(false);
- primalvelocity = self.velocity;
- for(bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && (self.velocity * self.velocity) > 0; bump++)
+ primalvelocity = this.velocity;
+ for(bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && (this.velocity * this.velocity) > 0; bump++)
{
- neworigin = self.origin + t * self.velocity;
- tracebox(self.origin, self.mins, self.maxs, neworigin, MOVE_NORMAL, self);
+ neworigin = this.origin + t * this.velocity;
+ tracebox(this.origin, this.mins, this.maxs, neworigin, MOVE_NORMAL, this);
trace1_endpos = trace_endpos;
trace1_fraction = trace_fraction;
trace1_plane_normal = trace_plane_normal;
{
// may be a step or wall, try stepping up
// first move forward at a higher level
- currentorigin2 = self.origin;
+ currentorigin2 = this.origin;
currentorigin2_z += PHYS_STEPHEIGHT;
neworigin2 = neworigin;
neworigin2_z += PHYS_STEPHEIGHT;
- tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+ tracebox(currentorigin2, this.mins, this.maxs, neworigin2, MOVE_NORMAL, this);
trace2_endpos = trace_endpos;
trace2_fraction = trace_fraction;
trace2_plane_normal = trace_plane_normal;
// then move down from there
currentorigin2 = trace2_endpos;
neworigin2 = trace2_endpos;
- neworigin2_z = self.origin_z;
- tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+ neworigin2_z = this.origin_z;
+ tracebox(currentorigin2, this.mins, this.maxs, neworigin2, MOVE_NORMAL, this);
trace3_endpos = trace_endpos;
trace3_fraction = trace_fraction;
trace3_plane_normal = trace_plane_normal;
// check if it moved at all
if(trace1_fraction >= 0.001)
- setorigin(self, trace1_endpos);
+ setorigin(this, trace1_endpos);
// check if it moved all the way
if(trace1_fraction == 1)
// this got commented out in a change that supposedly makes the code match QW better
// so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block
if(trace1_plane_normal_z > 0.7)
- SET_ONGROUND(self);
+ SET_ONGROUND(this);
t -= t * trace1_fraction;
- f = (self.velocity * trace1_plane_normal);
- self.velocity = self.velocity + -f * trace1_plane_normal;
+ f = (this.velocity * trace1_plane_normal);
+ this.velocity = this.velocity + -f * trace1_plane_normal;
}
if(pmove_waterjumptime > 0)
- self.velocity = primalvelocity;
+ this.velocity = primalvelocity;
#endif
}
-void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{SELFPARAM();
- float k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
+void CPM_PM_Aircontrol(entity this, vector wishdir, float wishspeed)
+{
+ float k = 32 * (2 * IsMoveInDirection(this.movement, 0) - 1);
if (k <= 0)
return;
- k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(self), 1);
+ k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(this), 1);
- float zspeed = self.velocity_z;
- self.velocity_z = 0;
- float xyspeed = vlen(self.velocity);
- self.velocity = normalize(self.velocity);
+ float zspeed = this.velocity_z;
+ this.velocity_z = 0;
+ float xyspeed = vlen(this.velocity);
+ this.velocity = normalize(this.velocity);
- float dot = self.velocity * wishdir;
+ float dot = this.velocity * wishdir;
if (dot > 0) // we can't change direction while slowing down
{
- k *= pow(dot, PHYS_AIRCONTROL_POWER) * PHYS_INPUT_TIMELENGTH;
- xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY * sqrt(max(0, 1 - dot*dot)) * k/32);
- k *= PHYS_AIRCONTROL;
- self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
+ k *= pow(dot, PHYS_AIRCONTROL_POWER(this)) * PHYS_INPUT_TIMELENGTH;
+ xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k/32);
+ k *= PHYS_AIRCONTROL(this);
+ this.velocity = normalize(this.velocity * xyspeed + wishdir * k);
}
- self.velocity = self.velocity * xyspeed;
- self.velocity_z = zspeed;
+ this.velocity = this.velocity * xyspeed;
+ this.velocity_z = zspeed;
}
float AdjustAirAccelQW(float accelqw, float factor)
// sv_airaccel_sideways_friction 0
// prvm_globalset server speedclamp_mode 1
// (or 2)
-void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{SELFPARAM();
+void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
+{
float speedclamp = stretchfactor > 0 ? stretchfactor
: accelqw < 0 ? 1 // full clamping, no stretch
: -1; // no clamping
if (GAMEPLAYFIX_Q2AIRACCELERATE)
wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
- float vel_straight = self.velocity * wishdir;
- float vel_z = self.velocity_z;
- vector vel_xy = vec2(self.velocity);
+ float vel_straight = this.velocity * wishdir;
+ float vel_z = this.velocity_z;
+ vector vel_xy = vec2(this.velocity);
vector vel_perpend = vel_xy - vel_straight * wishdir;
float step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
// negative: only apply so much sideways friction to stay below the speed you could get by "braking"
{
float f = max(0, 1 + PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
- float fmin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
- // assume: fmin > 1
+ float themin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
+ // assume: themin > 1
// vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
// vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
// vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
// obviously, this cannot be
- if (fmin <= 0)
+ if (themin <= 0)
vel_perpend *= f;
else
{
- fmin = sqrt(fmin);
- vel_perpend *= max(fmin, f);
+ themin = sqrt(themin);
+ vel_perpend *= max(themin, f);
}
}
else
}
}
- self.velocity = vel_xy + vel_z * '0 0 1';
+ this.velocity = vel_xy + vel_z * '0 0 1';
}
-void PM_AirAccelerate(vector wishdir, float wishspeed)
-{SELFPARAM();
+void PM_AirAccelerate(entity this, vector wishdir, float wishspeed)
+{
if (wishspeed == 0)
return;
- vector curvel = self.velocity;
+ vector curvel = this.velocity;
curvel_z = 0;
float curspeed = vlen(curvel);
if (wishspeed > curspeed * 1.01)
- wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH);
+ wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH);
else
{
- float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED - PHYS_MAXSPEED(self)));
- wishspeed = max(curspeed, PHYS_MAXSPEED(self)) + PHYS_WARSOWBUNNY_ACCEL * f * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH;
+ float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED(this) - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED(this) - PHYS_MAXSPEED(this)));
+ wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH;
}
vector wishvel = wishdir * wishspeed;
vector acceldir = wishvel - curvel;
float addspeed = vlen(acceldir);
acceldir = normalize(acceldir);
- float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH);
+ float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH);
- if (PHYS_WARSOWBUNNY_BACKTOSIDERATIO < 1)
+ if (PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this) < 1)
{
vector curdir = normalize(curvel);
float dot = acceldir * curdir;
if (dot < 0)
- acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO) * dot * curdir;
+ acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this)) * dot * curdir;
}
- self.velocity += accelspeed * acceldir;
+ this.velocity += accelspeed * acceldir;
}
returns true if handled
=============
*/
-bool PlayerJump ()
-{SELFPARAM();
- if (PHYS_FROZEN(self))
+bool PlayerJump(entity this)
+{
+ if (PHYS_FROZEN(this))
return true; // no jumping in freezetag when frozen
#ifdef SVQC
- if (self.player_blocked)
+ if (this.player_blocked)
return true; // no jumping while blocked
#endif
bool doublejump = false;
- float mjumpheight = PHYS_JUMPVELOCITY;
-#ifdef CSQC
- player_multijump = doublejump;
- player_jumpheight = mjumpheight;
-#endif
+ float mjumpheight = PHYS_JUMPVELOCITY(this);
- if (MUTATOR_CALLHOOK(PlayerJump, doublejump, mjumpheight)
-#ifdef CSQC
- || PM_multijump_checkjump()
-#endif
- ) { return true; }
+ if (MUTATOR_CALLHOOK(PlayerJump, this, doublejump, mjumpheight))
+ return true;
doublejump = player_multijump;
mjumpheight = player_jumpheight;
- if (PHYS_DOUBLEJUMP)
+ if (this.waterlevel >= WATERLEVEL_SWIMMING)
{
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
- if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
- {
- doublejump = true;
-
- // we MUST clip velocity here!
- float f;
- f = self.velocity * trace_plane_normal;
- if (f < 0)
- self.velocity -= f * trace_plane_normal;
- }
- }
-
- if (self.waterlevel >= WATERLEVEL_SWIMMING)
- {
- self.velocity_z = PHYS_MAXSPEED(self) * 0.7;
+ this.velocity_z = PHYS_MAXSPEED(this) * 0.7;
return true;
}
if (!doublejump)
- if (!IS_ONGROUND(self))
- return IS_JUMP_HELD(self);
+ if (!IS_ONGROUND(this))
+ return IS_JUMP_HELD(this);
- bool track_jump = PHYS_CL_TRACK_CANJUMP(self);
- if(PHYS_TRACK_CANJUMP(self))
+ bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
+ if(PHYS_TRACK_CANJUMP(this))
track_jump = true;
if (track_jump)
- if (IS_JUMP_HELD(self))
+ if (IS_JUMP_HELD(this))
return true;
// sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
{
float minjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MIN);
- if (self.velocity_z < minjumpspeed)
- mjumpheight += minjumpspeed - self.velocity_z;
+ if (this.velocity_z < minjumpspeed)
+ mjumpheight += minjumpspeed - this.velocity_z;
}
if(PHYS_JUMPSPEEDCAP_MAX != "")
{
// don't do jump speedcaps on ramps to preserve old xonotic ramjump style
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+ tracebox(this.origin + '0 0 0.01', this.mins, this.maxs, this.origin - '0 0 0.01', MOVE_NORMAL, this);
if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS))
{
float maxjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MAX);
- if (self.velocity_z > maxjumpspeed)
- mjumpheight -= self.velocity_z - maxjumpspeed;
+ if (this.velocity_z > maxjumpspeed)
+ mjumpheight -= this.velocity_z - maxjumpspeed;
}
}
- if (!WAS_ONGROUND(self))
+ if (!WAS_ONGROUND(this))
{
#ifdef SVQC
if(autocvar_speedmeter)
- LOG_TRACE(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+ LOG_TRACE(strcat("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")\n"));
#endif
- if(self.lastground < time - 0.3)
+ if(this.lastground < time - 0.3)
{
- self.velocity_x *= (1 - PHYS_FRICTION_ONLAND);
- self.velocity_y *= (1 - PHYS_FRICTION_ONLAND);
+ this.velocity_x *= (1 - PHYS_FRICTION_ONLAND);
+ this.velocity_y *= (1 - PHYS_FRICTION_ONLAND);
}
#ifdef SVQC
- if(self.jumppadcount > 1)
- LOG_TRACE(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
- self.jumppadcount = 0;
+ if(this.jumppadcount > 1)
+ LOG_TRACE(strcat(ftos(this.jumppadcount), "x jumppad combo\n"));
+ this.jumppadcount = 0;
#endif
}
- self.velocity_z += mjumpheight;
+ this.velocity_z += mjumpheight;
- UNSET_ONGROUND(self);
- SET_JUMP_HELD(self);
+ UNSET_ONGROUND(this);
+ SET_JUMP_HELD(this);
#ifdef SVQC
- self.oldvelocity_z = self.velocity_z;
+ this.oldvelocity_z = this.velocity_z;
- animdecide_setaction(self, ANIMACTION_JUMP, true);
+ animdecide_setaction(this, ANIMACTION_JUMP, true);
if (autocvar_g_jump_grunt)
- PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ WITH(entity, this, this, PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND));
#endif
return true;
}
-void CheckWaterJump()
-{SELFPARAM();
+void CheckWaterJump(entity this)
+{
// check for a jump-out-of-water
- makevectors(self.v_angle);
- vector start = self.origin;
+ makevectors(this.v_angle);
+ vector start = this.origin;
start_z += 8;
v_forward_z = 0;
normalize(v_forward);
vector end = start + v_forward*24;
- traceline (start, end, true, self);
+ traceline (start, end, true, this);
if (trace_fraction < 1)
{ // solid at waist
- start_z = start_z + self.maxs_z - 8;
+ start_z = start_z + this.maxs_z - 8;
end = start + v_forward*24;
- self.movedir = trace_plane_normal * -50;
- traceline(start, end, true, self);
+ this.movedir = trace_plane_normal * -50;
+ traceline(start, end, true, this);
if (trace_fraction == 1)
{ // open at eye level
- self.velocity_z = 225;
- self.flags |= FL_WATERJUMP;
- SET_JUMP_HELD(self);
+ this.velocity_z = 225;
+ this.flags |= FL_WATERJUMP;
+ SET_JUMP_HELD(this);
#ifdef SVQC
- self.teleport_time = time + 2; // safety net
+ this.teleport_time = time + 2; // safety net
#elif defined(CSQC)
pmove_waterjumptime = time + 2;
#endif
#define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
#endif
.float jetpack_stopped;
-// Hack: shouldn't need to know about this
-.float multijump_count;
-void CheckPlayerJump()
-{SELFPARAM();
+void CheckPlayerJump(entity this)
+{
#ifdef SVQC
- float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK;
+ float was_flying = ITEMS_STAT(this) & IT_USING_JETPACK;
#endif
- if (JETPACK_JUMP(self) < 2)
- ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+ if (JETPACK_JUMP(this) < 2)
+ ITEMS_STAT(this) &= ~IT_USING_JETPACK;
- if(PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self))
+ if(PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this))
{
- float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects
- float activate = JETPACK_JUMP(self) && air_jump && PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self);
- float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO;
+ float air_jump = !PlayerJump(this) || player_multijump; // PlayerJump() has important side effects
+ float activate = JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this);
+ float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(this) || ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO;
- if (!(ITEMS_STAT(self) & ITEM_Jetpack.m_itemid)) { }
- else if (self.jetpack_stopped) { }
+ if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
+ else if (this.jetpack_stopped) { }
else if (!has_fuel)
{
#ifdef SVQC
if (was_flying) // TODO: ran out of fuel message
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
+ Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
else if (activate)
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
+ Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
#endif
- self.jetpack_stopped = true;
- ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+ this.jetpack_stopped = true;
+ ITEMS_STAT(this) &= ~IT_USING_JETPACK;
}
- else if (activate && !PHYS_FROZEN(self))
- ITEMS_STAT(self) |= IT_USING_JETPACK;
+ else if (activate && !PHYS_FROZEN(this))
+ ITEMS_STAT(this) |= IT_USING_JETPACK;
}
else
{
- self.jetpack_stopped = false;
- ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+ this.jetpack_stopped = false;
+ ITEMS_STAT(this) &= ~IT_USING_JETPACK;
}
- if (!PHYS_INPUT_BUTTON_JUMP(self))
- UNSET_JUMP_HELD(self);
+ if (!PHYS_INPUT_BUTTON_JUMP(this))
+ UNSET_JUMP_HELD(this);
- if (self.waterlevel == WATERLEVEL_SWIMMING)
- CheckWaterJump();
+ if (this.waterlevel == WATERLEVEL_SWIMMING)
+ CheckWaterJump(this);
}
float racecar_angle(float forward, float down)
return ret * angle_mult;
}
-void RaceCarPhysics()
-{SELFPARAM();
-#ifdef SVQC
- // using this move type for "big rigs"
- // the engine does not push the entity!
-
- vector rigvel;
-
- vector angles_save = self.angles;
- float accel = bound(-1, self.movement.x / PHYS_MAXSPEED(self), 1);
- float steer = bound(-1, self.movement.y / PHYS_MAXSPEED(self), 1);
-
- if (g_bugrigs_reverse_speeding)
- {
- if (accel < 0)
- {
- // back accel is DIGITAL
- // to prevent speedhack
- if (accel < -0.5)
- accel = -1;
- else
- accel = 0;
- }
- }
-
- self.angles_x = 0;
- self.angles_z = 0;
- makevectors(self.angles); // new forward direction!
-
- if (IS_ONGROUND(self) || g_bugrigs_air_steering)
- {
- float myspeed = self.velocity * v_forward;
- float upspeed = self.velocity * v_up;
-
- // responsiveness factor for steering and acceleration
- float f = 1 / (1 + pow(max(-myspeed, myspeed) / g_bugrigs_speed_ref, g_bugrigs_speed_pow));
- //MAXIMA: f(v) := 1 / (1 + (v / g_bugrigs_speed_ref) ^ g_bugrigs_speed_pow);
-
- float steerfactor;
- if (myspeed < 0 && g_bugrigs_reverse_spinning)
- steerfactor = -myspeed * g_bugrigs_steer;
- else
- steerfactor = -myspeed * f * g_bugrigs_steer;
-
- float accelfactor;
- if (myspeed < 0 && g_bugrigs_reverse_speeding)
- accelfactor = g_bugrigs_accel;
- else
- accelfactor = f * g_bugrigs_accel;
- //MAXIMA: accel(v) := f(v) * g_bugrigs_accel;
-
- if (accel < 0)
- {
- if (myspeed > 0)
- {
- myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (g_bugrigs_friction_floor - g_bugrigs_friction_brake * accel));
- }
- else
- {
- if (!g_bugrigs_reverse_speeding)
- myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * g_bugrigs_friction_floor);
- }
- }
- else
- {
- if (myspeed >= 0)
- {
- myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * g_bugrigs_friction_floor);
- }
- else
- {
- if (g_bugrigs_reverse_stopping)
- myspeed = 0;
- else
- myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (g_bugrigs_friction_floor + g_bugrigs_friction_brake * accel));
- }
- }
- // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
- //MAXIMA: friction(v) := g_bugrigs_friction_floor;
-
- self.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
- makevectors(self.angles); // new forward direction!
-
- myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
-
- rigvel = myspeed * v_forward + '0 0 1' * upspeed;
- }
- else
- {
- float myspeed = vlen(self.velocity);
-
- // responsiveness factor for steering and acceleration
- float f = 1 / (1 + pow(max(0, myspeed / g_bugrigs_speed_ref), g_bugrigs_speed_pow));
- float steerfactor = -myspeed * f;
- self.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
-
- rigvel = self.velocity;
- makevectors(self.angles); // new forward direction!
- }
-
- rigvel *= max(0, 1 - vlen(rigvel) * g_bugrigs_friction_air * PHYS_INPUT_TIMELENGTH);
- //MAXIMA: airfriction(v) := v * v * g_bugrigs_friction_air;
- //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
- //MAXIMA: solve(total_acceleration(v) = 0, v);
-
- if (g_bugrigs_planar_movement)
- {
- vector rigvel_xy, neworigin, up;
- float mt;
-
- rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
- rigvel_xy = vec2(rigvel);
-
- if (g_bugrigs_planar_movement_car_jumping)
- mt = MOVE_NORMAL;
- else
- mt = MOVE_NOMONSTERS;
-
- tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 1024', mt, self);
- up = trace_endpos - self.origin;
-
- // BUG RIGS: align the move to the surface instead of doing collision testing
- // can we move?
- tracebox(trace_endpos, self.mins, self.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, self);
-
- // align to surface
- tracebox(trace_endpos, self.mins, self.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, self);
-
- if (trace_fraction < 0.5)
- {
- trace_fraction = 1;
- neworigin = self.origin;
- }
- else
- neworigin = trace_endpos;
-
- if (trace_fraction < 1)
- {
- // now set angles_x so that the car points parallel to the surface
- self.angles = vectoangles(
- '1 0 0' * v_forward_x * trace_plane_normal_z
- +
- '0 1 0' * v_forward_y * trace_plane_normal_z
- +
- '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
- );
- SET_ONGROUND(self);
- }
- else
- {
- // now set angles_x so that the car points forward, but is tilted in velocity direction
- UNSET_ONGROUND(self);
- }
-
- self.velocity = (neworigin - self.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
- self.movetype = MOVETYPE_NOCLIP;
- }
- else
- {
- rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
- self.velocity = rigvel;
- self.movetype = MOVETYPE_FLY;
- }
-
- trace_fraction = 1;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 4', MOVE_NORMAL, self);
- if (trace_fraction != 1)
- {
- self.angles = vectoangles2(
- '1 0 0' * v_forward_x * trace_plane_normal_z
- +
- '0 1 0' * v_forward_y * trace_plane_normal_z
- +
- '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
- trace_plane_normal
- );
- }
- else
- {
- vector vel_local;
-
- vel_local_x = v_forward * self.velocity;
- vel_local_y = v_right * self.velocity;
- vel_local_z = v_up * self.velocity;
-
- self.angles_x = racecar_angle(vel_local_x, vel_local_z);
- self.angles_z = racecar_angle(-vel_local_y, vel_local_z);
- }
-
- // smooth the angles
- vector vf1, vu1, smoothangles;
- makevectors(self.angles);
- float f = bound(0, PHYS_INPUT_TIMELENGTH * g_bugrigs_angle_smoothing, 1);
- if (f == 0)
- f = 1;
- vf1 = v_forward * f;
- vu1 = v_up * f;
- makevectors(angles_save);
- vf1 = vf1 + v_forward * (1 - f);
- vu1 = vu1 + v_up * (1 - f);
- smoothangles = vectoangles2(vf1, vu1);
- self.angles_x = -smoothangles_x;
- self.angles_z = smoothangles_z;
-#endif
-}
-
string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
.float specialcommand_pos;
void SpecialCommand()
{
#ifdef SVQC
-#ifdef TETRIS
- TetrisImpulse();
-#else
if (!CheatImpulse(99))
LOG_INFO("A hollow voice says \"Plugh\".\n");
#endif
-#endif
}
-float PM_check_specialcommand(float buttons)
-{SELFPARAM();
+float PM_check_specialcommand(entity this, float buttons)
+{
#ifdef SVQC
string c;
if (!buttons)
else
c = "?";
- if (c == substring(specialcommand, self.specialcommand_pos, 1))
+ if (c == substring(specialcommand, this.specialcommand_pos, 1))
{
- self.specialcommand_pos += 1;
- if (self.specialcommand_pos >= strlen(specialcommand))
+ this.specialcommand_pos += 1;
+ if (this.specialcommand_pos >= strlen(specialcommand))
{
- self.specialcommand_pos = 0;
+ this.specialcommand_pos = 0;
SpecialCommand();
return true;
}
}
- else if (self.specialcommand_pos && (c != substring(specialcommand, self.specialcommand_pos - 1, 1)))
- self.specialcommand_pos = 0;
+ else if (this.specialcommand_pos && (c != substring(specialcommand, this.specialcommand_pos - 1, 1)))
+ this.specialcommand_pos = 0;
#endif
return false;
}
-void PM_check_nickspam()
-{SELFPARAM();
+void PM_check_nickspam(entity this)
+{
#ifdef SVQC
- if (time >= self.nickspamtime)
+ if (time >= this.nickspamtime)
return;
- if (self.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
+ if (this.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
{
// slight annoyance for nick change scripts
- self.movement = -1 * self.movement;
- self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = self.BUTTON_ZOOM = self.BUTTON_CROUCH = self.BUTTON_HOOK = self.BUTTON_USE = 0;
+ this.movement = -1 * this.movement;
+ this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = this.BUTTON_ZOOM = this.BUTTON_CROUCH = this.BUTTON_HOOK = this.BUTTON_USE = 0;
- if (self.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
+ if (this.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
{
- self.v_angle_x = random() * 360;
- self.v_angle_y = random() * 360;
+ this.v_angle_x = random() * 360;
+ this.v_angle_y = random() * 360;
// at least I'm not forcing retardedview by also assigning to angles_z
- self.fixangle = true;
+ this.fixangle = true;
}
}
#endif
}
-void PM_check_punch()
-{SELFPARAM();
+void PM_check_punch(entity this)
+{
#ifdef SVQC
- if (self.punchangle != '0 0 0')
+ if (this.punchangle != '0 0 0')
{
- float f = vlen(self.punchangle) - 10 * PHYS_INPUT_TIMELENGTH;
+ float f = vlen(this.punchangle) - 10 * PHYS_INPUT_TIMELENGTH;
if (f > 0)
- self.punchangle = normalize(self.punchangle) * f;
+ this.punchangle = normalize(this.punchangle) * f;
else
- self.punchangle = '0 0 0';
+ this.punchangle = '0 0 0';
}
- if (self.punchvector != '0 0 0')
+ if (this.punchvector != '0 0 0')
{
- float f = vlen(self.punchvector) - 30 * PHYS_INPUT_TIMELENGTH;
+ float f = vlen(this.punchvector) - 30 * PHYS_INPUT_TIMELENGTH;
if (f > 0)
- self.punchvector = normalize(self.punchvector) * f;
+ this.punchvector = normalize(this.punchvector) * f;
else
- self.punchvector = '0 0 0';
+ this.punchvector = '0 0 0';
}
#endif
}
-void PM_check_spider()
-{SELFPARAM();
-#ifdef SVQC
- if (time >= self.spider_slowness)
- return;
- PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider
- PHYS_MAXAIRSPEED(self) *= 0.5;
- PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5;
- PHYS_AIRSTRAFEACCELERATE(self) *= 0.5;
-#endif
-}
-
// predict frozen movement, as frozen players CAN move in some cases
-void PM_check_frozen()
-{SELFPARAM();
- if (!PHYS_FROZEN(self))
+void PM_check_frozen(entity this)
+{
+ if (!PHYS_FROZEN(this))
return;
if (PHYS_DODGING_FROZEN
#ifdef SVQC
- && IS_REAL_CLIENT(self)
+ && IS_REAL_CLIENT(this)
#endif
)
{
- self.movement_x = bound(-5, self.movement.x, 5);
- self.movement_y = bound(-5, self.movement.y, 5);
- self.movement_z = bound(-5, self.movement.z, 5);
+ this.movement_x = bound(-5, this.movement.x, 5);
+ this.movement_y = bound(-5, this.movement.y, 5);
+ this.movement_z = bound(-5, this.movement.z, 5);
}
else
- self.movement = '0 0 0';
+ this.movement = '0 0 0';
- vector midpoint = ((self.absmin + self.absmax) * 0.5);
+ vector midpoint = ((this.absmin + this.absmax) * 0.5);
if (pointcontents(midpoint) == CONTENT_WATER)
{
- self.velocity = self.velocity * 0.5;
+ this.velocity = this.velocity * 0.5;
if (pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
- self.velocity_z = 200;
+ this.velocity_z = 200;
}
}
-void PM_check_hitground()
-{SELFPARAM();
+void PM_check_hitground(entity this)
+{
#ifdef SVQC
- if (IS_ONGROUND(self))
- if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
- if (self.wasFlying)
- {
- self.wasFlying = 0;
- if (self.waterlevel < WATERLEVEL_SWIMMING)
- if (time >= self.ladder_time)
- if (!self.hook)
- {
- self.nextstep = time + 0.3 + random() * 0.1;
- trace_dphitq3surfaceflags = 0;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
- if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
- {
- if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
- GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- else
- GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- }
- }
- }
+ if (!IS_PLAYER(this)) return; // no fall sounds for observers thank you very much
+ if (!IS_ONGROUND(this)) return;
+ if (!this.wasFlying) return;
+ this.wasFlying = false;
+ if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
+ if (time < this.ladder_time) return;
+ if (this.hook) return;
+ this.nextstep = time + 0.3 + random() * 0.1;
+ trace_dphitq3surfaceflags = 0;
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+ if ((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS)) return;
+ entity fall = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) ? GS_FALL_METAL : GS_FALL;
+ WITH(entity, self, this, GlobalSound(fall, CH_PLAYER, VOICETYPE_PLAYERSOUND));
#endif
}
-void PM_check_blocked()
-{SELFPARAM();
+void PM_check_blocked(entity this)
+{
#ifdef SVQC
- if (!self.player_blocked)
+ if (!this.player_blocked)
return;
- self.movement = '0 0 0';
- self.disableclientprediction = 1;
-#endif
-}
-
-void PM_check_vortex()
-{SELFPARAM();
-#ifdef SVQC
- // WEAPONTODO
- float xyspeed = vlen(vec2(self.velocity));
- if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
- {
- // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
- xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
- float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
- // add the extra charge
- self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
- }
+ this.movement = '0 0 0';
+ this.disableclientprediction = 1;
#endif
}
-void PM_fly(float maxspd_mod)
-{SELFPARAM();
+void PM_fly(entity this, float maxspd_mod)
+{
// noclipping or flying
- UNSET_ONGROUND(self);
-
- self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y
- + '0 0 1' * self.movement.z;
+ UNSET_ONGROUND(this);
+
+ this.velocity = this.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this));
+ makevectors(this.v_angle);
+ //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+ vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y
+ + '0 0 1' * this.movement.z;
// acceleration
vector wishdir = normalize(wishvel);
- float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod);
+ float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
#ifdef SVQC
- if (time >= self.teleport_time)
+ if (time >= this.teleport_time)
#endif
- PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE * maxspd_mod, 1, 0, 0, 0);
- PM_ClientMovement_Move();
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
+ PM_ClientMovement_Move(this);
}
-void PM_swim(float maxspd_mod)
-{SELFPARAM();
+void PM_swim(entity this, float maxspd_mod)
+{
// swimming
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
- float jump = PHYS_INPUT_BUTTON_JUMP(self);
+ float jump = PHYS_INPUT_BUTTON_JUMP(this);
// water jump only in certain situations
// this mimics quakeworld code
- if (jump && self.waterlevel == WATERLEVEL_SWIMMING && self.velocity_z >= -180)
+ if (jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180)
{
- vector yawangles = '0 1 0' * self.v_angle.y;
+ vector yawangles = '0 1 0' * this.v_angle.y;
makevectors(yawangles);
vector forward = v_forward;
- vector spot = self.origin + 24 * forward;
+ vector spot = this.origin + 24 * forward;
spot_z += 8;
- traceline(spot, spot, MOVE_NOMONSTERS, self);
+ traceline(spot, spot, MOVE_NOMONSTERS, this);
if (trace_startsolid)
{
spot_z += 24;
- traceline(spot, spot, MOVE_NOMONSTERS, self);
+ traceline(spot, spot, MOVE_NOMONSTERS, this);
if (!trace_startsolid)
{
- self.velocity = forward * 50;
- self.velocity_z = 310;
+ this.velocity = forward * 50;
+ this.velocity_z = 310;
pmove_waterjumptime = 2;
- UNSET_ONGROUND(self);
- SET_JUMP_HELD(self);
+ UNSET_ONGROUND(this);
+ SET_JUMP_HELD(this);
}
}
}
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y
- + '0 0 1' * self.movement.z;
+ makevectors(this.v_angle);
+ //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+ vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y
+ + '0 0 1' * this.movement.z;
if (wishvel == '0 0 0')
wishvel = '0 0 -60'; // drift towards bottom
vector wishdir = normalize(wishvel);
- float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod) * 0.7;
+ float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod) * 0.7;
- if (IS_DUCKED(self))
+ if (IS_DUCKED(this))
wishspeed *= 0.5;
// if (pmove_waterjumptime <= 0) // TODO: use
{
// water friction
- float f = 1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION;
+ float f = 1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this);
f = min(max(0, f), 1);
- self.velocity *= f;
+ this.velocity *= f;
- f = wishspeed - self.velocity * wishdir;
+ f = wishspeed - this.velocity * wishdir;
if (f > 0)
{
- float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, f);
- self.velocity += accelspeed * wishdir;
+ float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, f);
+ this.velocity += accelspeed * wishdir;
}
// holding jump button swims upward slowly
if (jump)
{
#if 0
- if (self.watertype & CONTENT_LAVA)
- self.velocity_z = 50;
- else if (self.watertype & CONTENT_SLIME)
- self.velocity_z = 80;
+ if (this.watertype & CONTENT_LAVA)
+ this.velocity_z = 50;
+ else if (this.watertype & CONTENT_SLIME)
+ this.velocity_z = 80;
else
{
if (IS_NEXUIZ_DERIVED(gamemode))
#endif
- self.velocity_z = 200;
+ this.velocity_z = 200;
#if 0
else
- self.velocity_z = 100;
+ this.velocity_z = 100;
}
#endif
}
}
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE * maxspd_mod, 1, 0, 0, 0);
- PM_ClientMovement_Move();
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
+ PM_ClientMovement_Move(this);
}
-void PM_ladder(float maxspd_mod)
-{SELFPARAM();
+void PM_ladder(entity this, float maxspd_mod)
+{
// on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
float g;
- g = PHYS_GRAVITY * PHYS_INPUT_TIMELENGTH;
- if (PHYS_ENTGRAVITY(self))
- g *= PHYS_ENTGRAVITY(self);
+ g = PHYS_GRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if (PHYS_ENTGRAVITY(this))
+ g *= PHYS_ENTGRAVITY(this);
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
{
g *= 0.5;
- self.velocity_z += g;
+ this.velocity_z += g;
}
- self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
- vector wishvel = v_forward * self.movement_x
- + v_right * self.movement_y
- + '0 0 1' * self.movement_z;
- self.velocity_z += g;
- if (self.ladder_entity.classname == "func_water")
+ this.velocity = this.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this));
+ makevectors(this.v_angle);
+ //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+ vector wishvel = v_forward * this.movement_x
+ + v_right * this.movement_y
+ + '0 0 1' * this.movement_z;
+ this.velocity_z += g;
+ if (this.ladder_entity.classname == "func_water")
{
float f = vlen(wishvel);
- if (f > self.ladder_entity.speed)
- wishvel *= (self.ladder_entity.speed / f);
-
- self.watertype = self.ladder_entity.skin;
- f = self.ladder_entity.origin_z + self.ladder_entity.maxs_z;
- if ((self.origin_z + self.view_ofs_z) < f)
- self.waterlevel = WATERLEVEL_SUBMERGED;
- else if ((self.origin_z + (self.mins_z + self.maxs_z) * 0.5) < f)
- self.waterlevel = WATERLEVEL_SWIMMING;
- else if ((self.origin_z + self.mins_z + 1) < f)
- self.waterlevel = WATERLEVEL_WETFEET;
+ if (f > this.ladder_entity.speed)
+ wishvel *= (this.ladder_entity.speed / f);
+
+ this.watertype = this.ladder_entity.skin;
+ f = this.ladder_entity.origin_z + this.ladder_entity.maxs_z;
+ if ((this.origin_z + this.view_ofs_z) < f)
+ this.waterlevel = WATERLEVEL_SUBMERGED;
+ else if ((this.origin_z + (this.mins_z + this.maxs_z) * 0.5) < f)
+ this.waterlevel = WATERLEVEL_SWIMMING;
+ else if ((this.origin_z + this.mins_z + 1) < f)
+ this.waterlevel = WATERLEVEL_WETFEET;
else
{
- self.waterlevel = WATERLEVEL_NONE;
- self.watertype = CONTENT_EMPTY;
+ this.waterlevel = WATERLEVEL_NONE;
+ this.watertype = CONTENT_EMPTY;
}
}
// acceleration
vector wishdir = normalize(wishvel);
- float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod);
+ float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
#ifdef SVQC
- if (time >= self.teleport_time)
+ if (time >= this.teleport_time)
#endif
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE*maxspd_mod, 1, 0, 0, 0);
- PM_ClientMovement_Move();
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this)*maxspd_mod, 1, 0, 0, 0);
+ PM_ClientMovement_Move(this);
}
-void PM_jetpack(float maxspd_mod)
-{SELFPARAM();
- //makevectors(self.v_angle.y * '0 1 0');
- makevectors(self.v_angle);
- vector wishvel = v_forward * self.movement_x
- + v_right * self.movement_y;
+void PM_jetpack(entity this, float maxspd_mod)
+{
+ //makevectors(this.v_angle.y * '0 1 0');
+ makevectors(this.v_angle);
+ vector wishvel = v_forward * this.movement_x
+ + v_right * this.movement_y;
// add remaining speed as Z component
- float maxairspd = PHYS_MAXAIRSPEED(self) * max(1, maxspd_mod);
+ float maxairspd = PHYS_MAXAIRSPEED(this) * max(1, maxspd_mod);
// fix speedhacks :P
wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
// add the unused velocity as up component
wishvel_z = 0;
- // if (self.BUTTON_JUMP)
+ // if (this.BUTTON_JUMP)
wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
// it is now normalized, so...
float a_side = PHYS_JETPACK_ACCEL_SIDE;
float a_up = PHYS_JETPACK_ACCEL_UP;
- float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY;
+ float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY(this);
wishvel_x *= a_side;
wishvel_y *= a_side;
//print("best possible acceleration: ", ftos(best), "\n");
float fxy, fz;
- fxy = bound(0, 1 - (self.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
- if (wishvel_z - PHYS_GRAVITY > 0)
- fz = bound(0, 1 - self.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
+ fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
+ if (wishvel_z - PHYS_GRAVITY(this) > 0)
+ fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
else
- fz = bound(0, 1 + self.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
+ fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
float fvel;
fvel = vlen(wishvel);
wishvel_x *= fxy;
wishvel_y *= fxy;
- wishvel_z = (wishvel_z - PHYS_GRAVITY) * fz + PHYS_GRAVITY;
+ wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
fvel = min(1, vlen(wishvel) / best);
- if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO))
- f = min(1, PHYS_AMMO_FUEL(self) / (PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel));
+ if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
+ f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel));
else
f = 1;
if (f > 0 && wishvel != '0 0 0')
{
- self.velocity = self.velocity + wishvel * f * PHYS_INPUT_TIMELENGTH;
- UNSET_ONGROUND(self);
+ this.velocity = this.velocity + wishvel * f * PHYS_INPUT_TIMELENGTH;
+ UNSET_ONGROUND(this);
#ifdef SVQC
- if (!(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO))
- self.ammo_fuel -= PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel * f;
+ if (!(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
+ this.ammo_fuel -= PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel * f;
- ITEMS_STAT(self) |= IT_USING_JETPACK;
+ ITEMS_STAT(this) |= IT_USING_JETPACK;
// jetpack also inhibits health regeneration, but only for 1 second
- self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+ this.pauseregen_finished = max(this.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
#endif
}
#ifdef CSQC
- float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
- if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
- else
- self.velocity_z -= g;
- PM_ClientMovement_Move();
- if (!IS_ONGROUND(self) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if(autocvar_cl_movement != 3)
+ {
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
+ this.velocity_z -= g * 0.5;
+ else
+ this.velocity_z -= g;
+ }
+ PM_ClientMovement_Move(this);
+ if(autocvar_cl_movement != 3)
+ {
+ if (!IS_ONGROUND(this) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.velocity_z -= g * 0.5;
+ }
#endif
}
-void PM_walk(float buttons_prev, float maxspd_mod)
-{SELFPARAM();
- if (!WAS_ONGROUND(self))
+void PM_walk(entity this, float maxspd_mod)
+{
+ if (!WAS_ONGROUND(this))
{
#ifdef SVQC
if (autocvar_speedmeter)
- LOG_TRACE(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+ LOG_TRACE(strcat("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")\n"));
#endif
- if (self.lastground < time - 0.3)
- self.velocity *= (1 - PHYS_FRICTION_ONLAND);
+ if (this.lastground < time - 0.3)
+ this.velocity *= (1 - PHYS_FRICTION_ONLAND);
#ifdef SVQC
- if (self.jumppadcount > 1)
- LOG_TRACE(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
- self.jumppadcount = 0;
+ if (this.jumppadcount > 1)
+ LOG_TRACE(strcat(ftos(this.jumppadcount), "x jumppad combo\n"));
+ this.jumppadcount = 0;
#endif
}
// walking
- makevectors(self.v_angle.y * '0 1 0');
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y;
+ makevectors(this.v_angle.y * '0 1 0');
+ const vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y;
// acceleration
- vector wishdir = normalize(wishvel);
+ const vector wishdir = normalize(wishvel);
float wishspeed = vlen(wishvel);
-
- wishspeed = min(wishspeed, PHYS_MAXSPEED(self) * maxspd_mod);
- if (IS_DUCKED(self))
- wishspeed *= 0.5;
+ wishspeed = min(wishspeed, PHYS_MAXSPEED(this) * maxspd_mod);
+ if (IS_DUCKED(this)) wishspeed *= 0.5;
// apply edge friction
- float f = vlen(vec2(self.velocity));
- if (f > 0)
+ const float f2 = vlen2(vec2(this.velocity));
+ if (f2 > 0)
{
- float realfriction;
trace_dphitq3surfaceflags = 0;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
// TODO: apply edge friction
// apply ground friction
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
- realfriction = PHYS_FRICTION_SLICK;
- else
- realfriction = PHYS_FRICTION;
+ const int realfriction = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
+ ? PHYS_FRICTION_SLICK
+ : PHYS_FRICTION(this);
- f = 1 - PHYS_INPUT_TIMELENGTH * realfriction * ((f < PHYS_STOPSPEED) ? (PHYS_STOPSPEED / f) : 1);
+ float f = sqrt(f2);
+ f = 1 - PHYS_INPUT_TIMELENGTH * realfriction * ((f < PHYS_STOPSPEED(this)) ? (PHYS_STOPSPEED(this) / f) : 1);
f = max(0, f);
- self.velocity *= f;
+ this.velocity *= f;
/*
Mathematical analysis time!
Our goal is to invert this mess.
For the two cases we get:
- v = v0 * (1 - PHYS_INPUT_TIMELENGTH * (PHYS_STOPSPEED / v0) * PHYS_FRICTION)
- = v0 - PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION
- v0 = v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION
+ v = v0 * (1 - PHYS_INPUT_TIMELENGTH * (PHYS_STOPSPEED(this) / v0) * PHYS_FRICTION(this))
+ = v0 - PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
+ v0 = v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
and
- v = v0 * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
- v0 = v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+ v = v0 * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
+ v0 = v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
These cases would be chosen ONLY if:
- v0 < PHYS_STOPSPEED
- v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION < PHYS_STOPSPEED
- v < PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+ v0 < PHYS_STOPSPEED(this)
+ v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this) < PHYS_STOPSPEED(this)
+ v < PHYS_STOPSPEED(this) * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
and, respectively:
- v0 >= PHYS_STOPSPEED
- v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION) >= PHYS_STOPSPEED
- v >= PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+ v0 >= PHYS_STOPSPEED(this)
+ v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this)) >= PHYS_STOPSPEED(this)
+ v >= PHYS_STOPSPEED(this) * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
*/
}
- float addspeed = wishspeed - self.velocity * wishdir;
+ const float addspeed = wishspeed - this.velocity * wishdir;
if (addspeed > 0)
{
- float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
- self.velocity += accelspeed * wishdir;
+ const float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
+ this.velocity += accelspeed * wishdir;
}
- float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
- if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
- self.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
- if (self.velocity * self.velocity)
- PM_ClientMovement_Move();
- if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- if (!IS_ONGROUND(self) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
- self.velocity_z -= g * 0.5;
+#ifdef CSQC
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if(autocvar_cl_movement != 3)
+ {
+ if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ this.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
+ }
+ if (vdist(this.velocity, >, 0))
+ PM_ClientMovement_Move(this);
+ if(autocvar_cl_movement != 3)
+ {
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ if (!IS_ONGROUND(this) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
+ this.velocity_z -= g * 0.5;
+ }
+#endif
}
-void PM_air(float buttons_prev, float maxspd_mod)
-{SELFPARAM();
- makevectors(self.v_angle.y * '0 1 0');
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y;
+void PM_air(entity this, float buttons_prev, float maxspd_mod)
+{
+ makevectors(this.v_angle.y * '0 1 0');
+ vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y;
// acceleration
vector wishdir = normalize(wishvel);
float wishspeed = vlen(wishvel);
#ifdef SVQC
- if (time >= self.teleport_time)
+ if (time >= this.teleport_time)
#else
if (pmove_waterjumptime <= 0)
#endif
{
- float maxairspd = PHYS_MAXAIRSPEED(self) * min(maxspd_mod, 1);
+ float maxairspd = PHYS_MAXAIRSPEED(this) * min(maxspd_mod, 1);
// apply air speed limit
- float airaccelqw = PHYS_AIRACCEL_QW(self);
+ float airaccelqw = PHYS_AIRACCEL_QW(this);
float wishspeed0 = wishspeed;
wishspeed = min(wishspeed, maxairspd);
- if (IS_DUCKED(self))
+ if (IS_DUCKED(this))
wishspeed *= 0.5;
- float airaccel = PHYS_AIRACCELERATE * min(maxspd_mod, 1);
+ float airaccel = PHYS_AIRACCELERATE(this) * min(maxspd_mod, 1);
- float accelerating = (self.velocity * wishdir > 0);
+ float accelerating = (this.velocity * wishdir > 0);
float wishspeed2 = wishspeed;
// CPM: air control
- if (PHYS_AIRSTOPACCELERATE)
+ if (PHYS_AIRSTOPACCELERATE(this))
{
- vector curdir = normalize(vec2(self.velocity));
- airaccel += (PHYS_AIRSTOPACCELERATE*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
+ vector curdir = normalize(vec2(this.velocity));
+ airaccel += (PHYS_AIRSTOPACCELERATE(this)*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
}
// note that for straight forward jumping:
// step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
// dv/dt = accel * maxspeed * (1 - accelqw) (when fast)
// log dv/dt = logaccel + logmaxspeed (when slow)
// log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
- float strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
- if (PHYS_MAXAIRSTRAFESPEED)
- wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(self)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod));
- if (PHYS_AIRSTRAFEACCELERATE(self))
- airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(self)*maxspd_mod);
- if (PHYS_AIRSTRAFEACCEL_QW(self))
+ float strafity = IsMoveInDirection(this.movement, -90) + IsMoveInDirection(this.movement, +90); // if one is nonzero, other is always zero
+ if (PHYS_MAXAIRSTRAFESPEED(this))
+ wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(this)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED(this)*maxspd_mod));
+ if (PHYS_AIRSTRAFEACCELERATE(this))
+ airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(this)*maxspd_mod);
+ if (PHYS_AIRSTRAFEACCEL_QW(this))
airaccelqw =
- (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(self) : PHYS_AIRACCEL_QW(self)) >= 0) ? +1 : -1)
+ (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(this) : PHYS_AIRACCEL_QW(this)) >= 0) ? +1 : -1)
*
- (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(self)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(self))));
+ (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(this)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(this))));
// !CPM
- if (PHYS_WARSOWBUNNY_TURNACCEL && accelerating && self.movement.y == 0 && self.movement.x != 0)
- PM_AirAccelerate(wishdir, wishspeed2);
+ if (PHYS_WARSOWBUNNY_TURNACCEL(this) && accelerating && this.movement.y == 0 && this.movement.x != 0)
+ PM_AirAccelerate(this, wishdir, wishspeed2);
else
- PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(self), PHYS_AIRACCEL_SIDEWAYS_FRICTION / maxairspd, PHYS_AIRSPEEDLIMIT_NONQW(self));
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(this), PHYS_AIRACCEL_SIDEWAYS_FRICTION(this) / maxairspd, PHYS_AIRSPEEDLIMIT_NONQW(this));
- if (PHYS_AIRCONTROL)
- CPM_PM_Aircontrol(wishdir, wishspeed2);
+ if (PHYS_AIRCONTROL(this))
+ CPM_PM_Aircontrol(this, wishdir, wishspeed2);
}
- float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
+#ifdef CSQC
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if(autocvar_cl_movement != 3)
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
+ this.velocity_z -= g * 0.5;
else
- self.velocity_z -= g;
- PM_ClientMovement_Move();
- if (!IS_ONGROUND(self) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ this.velocity_z -= g;
+#endif
+ PM_ClientMovement_Move(this);
+#ifdef CSQC
+ if(autocvar_cl_movement != 3)
+ if (!IS_ONGROUND(this) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
+ this.velocity_z -= g * 0.5;
+#endif
}
// used for calculating airshots
-bool IsFlying(entity a)
+bool IsFlying(entity this)
{
- if(IS_ONGROUND(a))
+ if(IS_ONGROUND(this))
return false;
- if(a.waterlevel >= WATERLEVEL_SWIMMING)
+ if(this.waterlevel >= WATERLEVEL_SWIMMING)
return false;
- traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
+ traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
if(trace_fraction < 1)
return false;
return true;
}
-void PM_Main()
-{SELFPARAM();
- int buttons = PHYS_INPUT_BUTTON_MASK(self);
+void PM_Main(entity this)
+{
+ int buttons = PHYS_INPUT_BUTTON_MASK(this);
#ifdef CSQC
- self.items = getstati(STAT_ITEMS, 0, 24);
+ this.items = getstati(STAT_ITEMS, 0, 24);
- self.movement = PHYS_INPUT_MOVEVALUES(self);
+ this.movement = PHYS_INPUT_MOVEVALUES(this);
- vector oldv_angle = self.v_angle;
- vector oldangles = self.angles; // we need to save these, as they're abused by other code
- self.v_angle = PHYS_INPUT_ANGLES(self);
- self.angles = PHYS_WORLD_ANGLES(self);
+ vector oldv_angle = this.v_angle;
+ vector oldangles = this.angles; // we need to save these, as they're abused by other code
+ this.v_angle = PHYS_INPUT_ANGLES(this);
+ this.angles = PHYS_WORLD_ANGLES(this);
- self.team = myteam + 1; // is this correct?
- if (!(PHYS_INPUT_BUTTON_JUMP(self))) // !jump
- UNSET_JUMP_HELD(self); // canjump = true
+ this.team = myteam + 1; // is this correct?
+ if (!(PHYS_INPUT_BUTTON_JUMP(this))) // !jump
+ UNSET_JUMP_HELD(this); // canjump = true
pmove_waterjumptime -= PHYS_INPUT_TIMELENGTH;
- PM_ClientMovement_UpdateStatus(true);
+ PM_ClientMovement_UpdateStatus(this, true);
#endif
maxspeed_mod *= PHYS_HIGHSPEED;
#ifdef SVQC
- Physics_UpdateStats(maxspeed_mod);
+ Physics_UpdateStats(this, maxspeed_mod);
- if (self.PlayerPhysplug)
- if (self.PlayerPhysplug())
+ if (this.PlayerPhysplug)
+ if (this.PlayerPhysplug())
return;
#endif
#ifdef SVQC
- anticheat_physics();
+ anticheat_physics(this);
#endif
- if (PM_check_specialcommand(buttons))
+ if (PM_check_specialcommand(this, buttons))
return;
#ifdef SVQC
if (sv_maxidle > 0)
{
- if (buttons != self.buttons_old || self.movement != self.movement_old || self.v_angle != self.v_angle_old)
- self.parm_idlesince = time;
+ if (buttons != this.buttons_old || this.movement != this.movement_old || this.v_angle != this.v_angle_old)
+ this.parm_idlesince = time;
}
#endif
- int buttons_prev = self.buttons_old;
- self.buttons_old = buttons;
- self.movement_old = self.movement;
- self.v_angle_old = self.v_angle;
+ int buttons_prev = this.buttons_old;
+ this.buttons_old = buttons;
+ this.movement_old = this.movement;
+ this.v_angle_old = this.v_angle;
- PM_check_nickspam();
+ PM_check_nickspam(this);
- PM_check_punch();
+ PM_check_punch(this);
#ifdef SVQC
- if (IS_BOT_CLIENT(self))
+ if (IS_BOT_CLIENT(this))
{
- if (playerdemo_read())
+ if (playerdemo_read(this))
return;
- bot_think();
+ WITH(entity, self, this, bot_think());
}
-
- if (IS_PLAYER(self))
-#endif
- {
- bool not_allowed_to_move = false;
-#ifdef SVQC
- if (time < game_starttime)
- not_allowed_to_move = true;
#endif
- if (not_allowed_to_move)
- {
- self.velocity = '0 0 0';
- self.movetype = MOVETYPE_NONE;
#ifdef SVQC
- self.disableclientprediction = 2;
-#endif
+ if (IS_PLAYER(this))
+ {
+ const bool allowed_to_move = (time >= game_starttime);
+ if (!allowed_to_move)
+ {
+ this.velocity = '0 0 0';
+ this.movetype = MOVETYPE_NONE;
+ this.disableclientprediction = 2;
}
-#ifdef SVQC
- else if (self.disableclientprediction == 2)
+ else if (this.disableclientprediction == 2)
{
- if (self.movetype == MOVETYPE_NONE)
- self.movetype = MOVETYPE_WALK;
- self.disableclientprediction = 0;
+ if (this.movetype == MOVETYPE_NONE)
+ this.movetype = MOVETYPE_WALK;
+ this.disableclientprediction = 0;
}
-#endif
}
+#endif
#ifdef SVQC
- if (self.movetype == MOVETYPE_NONE)
+ if (this.movetype == MOVETYPE_NONE)
return;
// when we get here, disableclientprediction cannot be 2
- self.disableclientprediction = 0;
+ this.disableclientprediction = 0;
#endif
- viewloc_PlayerPhysics();
+ viewloc_PlayerPhysics(this);
- PM_check_spider();
+ PM_check_frozen(this);
- PM_check_frozen();
-
- PM_check_blocked();
+ PM_check_blocked(this);
maxspeed_mod = 1;
- if (self.in_swamp)
- maxspeed_mod *= self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
+ if (this.in_swamp)
+ maxspeed_mod *= this.swamp_slowdown; //cvar("g_balance_swamp_moverate");
// conveyors: first fix velocity
- if (self.conveyor.state)
- self.velocity -= self.conveyor.movedir;
+ if (this.conveyor.state)
+ this.velocity -= this.conveyor.movedir;
-#ifdef SVQC
- MUTATOR_CALLHOOK(PlayerPhysics);
-#endif
-#ifdef CSQC
- PM_multijump();
-#endif
-
-// float forcedodge = 1;
-// if(forcedodge) {
-//#ifdef CSQC
-// PM_dodging_checkpressedkeys();
-//#endif
-// PM_dodging();
-// PM_ClientMovement_Move();
-// return;
-// }
+ MUTATOR_CALLHOOK(PlayerPhysics, this);
#ifdef SVQC
- if (!IS_PLAYER(self))
+ if (!IS_PLAYER(this))
{
maxspeed_mod = autocvar_sv_spectator_speed_multiplier;
- if (!self.spectatorspeed)
- self.spectatorspeed = maxspeed_mod;
- if (self.impulse && self.impulse <= 19 || (self.impulse >= 200 && self.impulse <= 209) || (self.impulse >= 220 && self.impulse <= 229))
+ if (!this.spectatorspeed)
+ this.spectatorspeed = maxspeed_mod;
+ if (this.impulse && this.impulse <= 19 || (this.impulse >= 200 && this.impulse <= 209) || (this.impulse >= 220 && this.impulse <= 229))
{
- if (self.lastclassname != "player")
+ if (this.lastclassname != "player")
{
- if (self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || (self.impulse >= 200 && self.impulse <= 209))
- self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
- else if (self.impulse == 11)
- self.spectatorspeed = maxspeed_mod;
- else if (self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || (self.impulse >= 220 && self.impulse <= 229))
- self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
- else if (self.impulse >= 1 && self.impulse <= 9)
- self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
+ if (this.impulse == 10 || this.impulse == 15 || this.impulse == 18 || (this.impulse >= 200 && this.impulse <= 209))
+ this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5);
+ else if (this.impulse == 11)
+ this.spectatorspeed = maxspeed_mod;
+ else if (this.impulse == 12 || this.impulse == 16 || this.impulse == 19 || (this.impulse >= 220 && this.impulse <= 229))
+ this.spectatorspeed = bound(1, this.spectatorspeed - 0.5, 5);
+ else if (this.impulse >= 1 && this.impulse <= 9)
+ this.spectatorspeed = 1 + 0.5 * (this.impulse - 1);
} // otherwise just clear
- self.impulse = 0;
+ this.impulse = 0;
}
- maxspeed_mod = self.spectatorspeed;
+ maxspeed_mod = this.spectatorspeed;
}
- float spd = max(PHYS_MAXSPEED(self), PHYS_MAXAIRSPEED(self)) * maxspeed_mod;
- if(self.speed != spd)
+ float spd = max(PHYS_MAXSPEED(this), PHYS_MAXAIRSPEED(this)) * maxspeed_mod;
+ if(this.speed != spd)
{
- self.speed = spd;
+ this.speed = spd;
string temps = ftos(spd);
- stuffcmd(self, strcat("cl_forwardspeed ", temps, "\n"));
- stuffcmd(self, strcat("cl_backspeed ", temps, "\n"));
- stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
- stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
+ stuffcmd(this, strcat("cl_forwardspeed ", temps, "\n"));
+ stuffcmd(this, strcat("cl_backspeed ", temps, "\n"));
+ stuffcmd(this, strcat("cl_sidespeed ", temps, "\n"));
+ stuffcmd(this, strcat("cl_upspeed ", temps, "\n"));
}
- if(self.stat_jumpspeedcap_min != PHYS_JUMPSPEEDCAP_MIN)
+ if(this.stat_jumpspeedcap_min != PHYS_JUMPSPEEDCAP_MIN)
{
- self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
- stuffcmd(self, strcat("cl_jumpspeedcap_min ", PHYS_JUMPSPEEDCAP_MIN, "\n"));
+ this.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
+ stuffcmd(this, strcat("cl_jumpspeedcap_min ", PHYS_JUMPSPEEDCAP_MIN, "\n"));
}
- if(self.stat_jumpspeedcap_max != PHYS_JUMPSPEEDCAP_MAX)
+ if(this.stat_jumpspeedcap_max != PHYS_JUMPSPEEDCAP_MAX)
{
- self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MAX;
- stuffcmd(self, strcat("cl_jumpspeedcap_max ", PHYS_JUMPSPEEDCAP_MAX, "\n"));
+ this.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MAX;
+ stuffcmd(this, strcat("cl_jumpspeedcap_max ", PHYS_JUMPSPEEDCAP_MAX, "\n"));
}
#endif
- if(PHYS_DEAD(self))
+ if(PHYS_DEAD(this))
{
// handle water here
- vector midpoint = ((self.absmin + self.absmax) * 0.5);
+ vector midpoint = ((this.absmin + this.absmax) * 0.5);
if(pointcontents(midpoint) == CONTENT_WATER)
{
- self.velocity = self.velocity * 0.5;
+ this.velocity = this.velocity * 0.5;
// do we want this?
//if(pointcontents(midpoint + '0 0 2') == CONTENT_WATER)
- //{ self.velocity_z = 70; }
+ //{ this.velocity_z = 70; }
}
goto end;
}
#ifdef SVQC
- if (!self.fixangle && !g_bugrigs)
- self.angles = '0 1 0' * self.v_angle.y;
+ if (!this.fixangle)
+ this.angles = '0 1 0' * this.v_angle.y;
#endif
- PM_check_hitground();
+ PM_check_hitground(this);
- if(IsFlying(self))
- self.wasFlying = 1;
+ if(IsFlying(this))
+ this.wasFlying = 1;
- if (IS_PLAYER(self))
- CheckPlayerJump();
+ if (IS_PLAYER(this))
+ CheckPlayerJump(this);
- if (self.flags & FL_WATERJUMP)
+ if (this.flags & FL_WATERJUMP)
{
- self.velocity_x = self.movedir_x;
- self.velocity_y = self.movedir_y;
- if (time > self.teleport_time || self.waterlevel == WATERLEVEL_NONE)
+ this.velocity_x = this.movedir.x;
+ this.velocity_y = this.movedir.y;
+ if (time > this.teleport_time || this.waterlevel == WATERLEVEL_NONE)
{
- self.flags &= ~FL_WATERJUMP;
- self.teleport_time = 0;
+ this.flags &= ~FL_WATERJUMP;
+ this.teleport_time = 0;
}
}
+ else if (MUTATOR_CALLHOOK(PM_Physics, this, maxspeed_mod))
+ { }
+
#ifdef SVQC
- else if (g_bugrigs && IS_PLAYER(self))
- RaceCarPhysics();
+ else if (this.movetype == MOVETYPE_NOCLIP || this.movetype == MOVETYPE_FLY || this.movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
+#elif defined(CSQC)
+ else if (this.move_movetype == MOVETYPE_NOCLIP || this.move_movetype == MOVETYPE_FLY || this.move_movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
#endif
+ PM_fly(this, maxspeed_mod);
- else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS_STAT(self) & BUFF_FLIGHT.m_itemid))
- PM_fly(maxspeed_mod);
-
- else if (self.waterlevel >= WATERLEVEL_SWIMMING)
- PM_swim(maxspeed_mod);
+ else if (this.waterlevel >= WATERLEVEL_SWIMMING)
+ PM_swim(this, maxspeed_mod);
- else if (time < self.ladder_time)
- PM_ladder(maxspeed_mod);
+ else if (time < this.ladder_time)
+ PM_ladder(this, maxspeed_mod);
- else if (ITEMS_STAT(self) & IT_USING_JETPACK)
- PM_jetpack(maxspeed_mod);
+ else if (ITEMS_STAT(this) & IT_USING_JETPACK)
+ PM_jetpack(this, maxspeed_mod);
- else if (IS_ONGROUND(self))
- PM_walk(buttons_prev, maxspeed_mod);
+ else if (IS_ONGROUND(this))
+ PM_walk(this, maxspeed_mod);
else
- PM_air(buttons_prev, maxspeed_mod);
-
- PM_check_vortex();
+ PM_air(this, buttons_prev, maxspeed_mod);
:end
- if (IS_ONGROUND(self))
- self.lastground = time;
+ if (IS_ONGROUND(this))
+ this.lastground = time;
// conveyors: then break velocity again
- if(self.conveyor.state)
- self.velocity += self.conveyor.movedir;
+ if(this.conveyor.state)
+ this.velocity += this.conveyor.movedir;
- self.lastflags = self.flags;
+ this.lastflags = this.flags;
- self.lastclassname = self.classname;
+ this.lastclassname = this.classname;
#ifdef CSQC
- self.v_angle = oldv_angle;
- self.angles = oldangles;
+ this.v_angle = oldv_angle;
+ this.angles = oldangles;
#endif
}
-#ifdef SVQC
+#if defined(SVQC)
void SV_PlayerPhysics()
#elif defined(CSQC)
-void CSQC_ClientMovement_PlayerMove_Frame()
+void CSQC_ClientMovement_PlayerMove_Frame(entity this)
#endif
-{SELFPARAM();
- PM_Main();
-
+{
+#ifdef SVQC
+ SELFPARAM();
+#endif
+ PM_Main(this);
#ifdef CSQC
- self.pmove_flags =
- ((self.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
- (!(self.flags & FL_JUMPRELEASED) ? 0 : PMF_JUMP_HELD) |
- ((self.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
+ this.pmove_flags =
+ ((this.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
+ (!(this.flags & FL_JUMPRELEASED) ? PMF_JUMP_HELD : 0) |
+ ((this.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
#endif
}
bool IsFlying(entity a);
+#define BUFFS_STAT(s) STAT(BUFFS, s)
+
+#define GAMEPLAYFIX_DOWNTRACEONGROUND STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, this)
+#define GAMEPLAYFIX_EASIERWATERJUMP STAT(GAMEPLAYFIX_EASIERWATERJUMP, this)
+#define GAMEPLAYFIX_STEPDOWN STAT(GAMEPLAYFIX_STEPDOWN, this)
+#define GAMEPLAYFIX_STEPMULTIPLETIMES STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, this)
+#define GAMEPLAYFIX_UNSTICKPLAYERS STAT(GAMEPLAYFIX_UNSTICKPLAYERS, this)
+
+#define PHYS_ACCELERATE(s) STAT(MOVEVARS_ACCELERATE, s)
+#define PHYS_AIRACCELERATE(s) STAT(MOVEVARS_AIRACCELERATE, s)
+#define PHYS_AIRACCEL_QW(s) STAT(MOVEVARS_AIRACCEL_QW, s)
+#define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, s)
+#define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s) STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, s)
+#define PHYS_AIRCONTROL(s) STAT(MOVEVARS_AIRCONTROL, s)
+#define PHYS_AIRCONTROL_PENALTY(s) STAT(MOVEVARS_AIRCONTROL_PENALTY, s)
+#define PHYS_AIRCONTROL_POWER(s) STAT(MOVEVARS_AIRCONTROL_POWER, s)
+#define PHYS_AIRSPEEDLIMIT_NONQW(s) STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, s)
+#define PHYS_AIRSTOPACCELERATE(s) STAT(MOVEVARS_AIRSTOPACCELERATE, s)
+#define PHYS_AIRSTRAFEACCELERATE(s) STAT(MOVEVARS_AIRSTRAFEACCELERATE, s)
+#define PHYS_AIRSTRAFEACCEL_QW(s) STAT(MOVEVARS_AIRSTRAFEACCEL_QW, s)
+
+#define PHYS_AMMO_FUEL(s) STAT(FUEL, s)
+
+#define PHYS_DODGING_FROZEN STAT(DODGING_FROZEN, this)
+
+#define PHYS_FRICTION(s) STAT(MOVEVARS_FRICTION, s)
+#define PHYS_FRICTION_ONLAND STAT(MOVEVARS_FRICTION_ONLAND, this)
+#define PHYS_FRICTION_SLICK STAT(MOVEVARS_FRICTION_SLICK, this)
+
+#define PHYS_FROZEN(s) STAT(FROZEN, s)
+
+#define PHYS_GRAVITY(s) STAT(MOVEVARS_GRAVITY, s)
+
+#define PHYS_HIGHSPEED STAT(MOVEVARS_HIGHSPEED, this)
+
+#define PHYS_JETPACK_ACCEL_SIDE STAT(JETPACK_ACCEL_SIDE, this)
+#define PHYS_JETPACK_ACCEL_UP STAT(JETPACK_ACCEL_UP, this)
+#define PHYS_JETPACK_ANTIGRAVITY STAT(JETPACK_ANTIGRAVITY, this)
+#define PHYS_JETPACK_FUEL STAT(JETPACK_FUEL, this)
+#define PHYS_JETPACK_MAXSPEED_SIDE STAT(JETPACK_MAXSPEED_SIDE, this)
+#define PHYS_JETPACK_MAXSPEED_UP STAT(JETPACK_MAXSPEED_UP, this)
+
+#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, this)
+#define PHYS_JUMPSTEP STAT(MOVEVARS_JUMPSTEP, this)
+#define PHYS_JUMPVELOCITY(s) STAT(MOVEVARS_JUMPVELOCITY, s)
+
+#define PHYS_MAXAIRSPEED(s) STAT(MOVEVARS_MAXAIRSPEED, s)
+#define PHYS_MAXAIRSTRAFESPEED(s) STAT(MOVEVARS_MAXAIRSTRAFESPEED, s)
+#define PHYS_MAXSPEED(s) STAT(MOVEVARS_MAXSPEED, s)
+
+#define PHYS_NOSTEP STAT(NOSTEP, this)
+#define PHYS_STEPHEIGHT STAT(MOVEVARS_STEPHEIGHT, this)
+
+#define PHYS_STOPSPEED(s) STAT(MOVEVARS_STOPSPEED, s)
+
+#define PHYS_TRACK_CANJUMP(s) STAT(MOVEVARS_TRACK_CANJUMP, s)
+
+#define PHYS_WALLFRICTION STAT(MOVEVARS_WALLFRICTION, this)
+
+#define PHYS_WARSOWBUNNY_ACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_ACCEL, s)
+#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, s)
+#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s) STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, s)
+#define PHYS_WARSOWBUNNY_TOPSPEED(s) STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, s)
+#define PHYS_WARSOWBUNNY_TURNACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, s)
+
+#define UPWARD_VELOCITY_CLEARS_ONGROUND STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, this)
+
#ifdef CSQC
const int FL_WATERJUMP = 2048; // player jumping out of water
const int FL_JUMPRELEASED = 4096; // for jump debouncing
- float PM_multijump_checkjump();
- void PM_multijump();
-
.float watertype;
.float waterlevel;
.int items;
//float player_multijump;
//float player_jumpheight;
+ #define TICRATE ticrate
+
#define PHYS_INPUT_ANGLES(s) input_angles
// TODO
#define PHYS_WORLD_ANGLES(s) input_angles
#define PHYS_INPUT_MOVEVALUES(s) input_movevalues
- #define PHYS_INPUT_BUTTON_MASK(s) (input_buttons | 128 * (input_movevalues_x < 0) | 256 * (input_movevalues_x > 0) | 512 * (input_movevalues_y < 0) | 1024 * (input_movevalues_y > 0))
- #define PHYS_INPUT_BUTTON_ATCK(s) !!(input_buttons & 1)
- #define PHYS_INPUT_BUTTON_JUMP(s) !!(input_buttons & 2)
- #define PHYS_INPUT_BUTTON_ATCK2(s) !!(input_buttons & 4)
- #define PHYS_INPUT_BUTTON_ZOOM(s) !!(input_buttons & 8)
- #define PHYS_INPUT_BUTTON_CROUCH(s) !!(input_buttons & 16)
- #define PHYS_INPUT_BUTTON_HOOK(s) !!(input_buttons & 32)
- #define PHYS_INPUT_BUTTON_USE(s) !!(input_buttons & 64)
- #define PHYS_INPUT_BUTTON_BACKWARD(s) !!(input_buttons & 128)
- #define PHYS_INPUT_BUTTON_FORWARD(s) !!(input_buttons & 256)
- #define PHYS_INPUT_BUTTON_LEFT(s) !!(input_buttons & 512)
- #define PHYS_INPUT_BUTTON_RIGHT(s) !!(input_buttons & 1024)
- #define PHYS_INPUT_BUTTON_JETPACK(s) !!(input_buttons & 4096)
+ #define PHYS_INPUT_BUTTON_MASK(s) (input_buttons | BIT(7) * (input_movevalues.x < 0) | BIT(8) * (input_movevalues.x > 0) | BIT(9) * (input_movevalues.y < 0) | BIT(10) * (input_movevalues.y > 0))
+ #define PHYS_INPUT_BUTTON_ATCK(s) boolean(input_buttons & BIT(0))
+ #define PHYS_INPUT_BUTTON_JUMP(s) boolean(input_buttons & BIT(1))
+ #define PHYS_INPUT_BUTTON_ATCK2(s) boolean(input_buttons & BIT(2))
+ #define PHYS_INPUT_BUTTON_ZOOM(s) boolean(input_buttons & BIT(3))
+ #define PHYS_INPUT_BUTTON_CROUCH(s) boolean(input_buttons & BIT(4))
+ #define PHYS_INPUT_BUTTON_HOOK(s) boolean(input_buttons & BIT(5))
+ #define PHYS_INPUT_BUTTON_USE(s) boolean(input_buttons & BIT(6))
+ #define PHYS_INPUT_BUTTON_BACKWARD(s) boolean(input_buttons & BIT(7))
+ #define PHYS_INPUT_BUTTON_FORWARD(s) boolean(input_buttons & BIT(8))
+ #define PHYS_INPUT_BUTTON_LEFT(s) boolean(input_buttons & BIT(9))
+ #define PHYS_INPUT_BUTTON_RIGHT(s) boolean(input_buttons & BIT(10))
+ #define PHYS_INPUT_BUTTON_JETPACK(s) boolean(input_buttons & BIT(12))
#define PHYS_DEAD(s) s.csqcmodel_isdead
- #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE !!(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
- #define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
- #define GAMEPLAYFIX_Q2AIRACCELERATE cvar("sv_gameplayfix_q2airaccelerate")
- #define GAMEPLAYFIX_EASIERWATERJUMP getstati(STAT_GAMEPLAYFIX_EASIERWATERJUMP)
- #define GAMEPLAYFIX_DOWNTRACEONGROUND getstati(STAT_GAMEPLAYFIX_DOWNTRACEONGROUND)
- #define GAMEPLAYFIX_STEPMULTIPLETIMES getstati(STAT_GAMEPLAYFIX_STEPMULTIPLETIMES)
- #define GAMEPLAYFIX_UNSTICKPLAYERS getstati(STAT_GAMEPLAYFIX_UNSTICKPLAYERS)
- #define GAMEPLAYFIX_STEPDOWN getstati(STAT_GAMEPLAYFIX_STEPDOWN)
+ #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE (boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE))
+ #define GAMEPLAYFIX_NOGRAVITYONGROUND (boolean(moveflags & MOVEFLAG_NOGRAVITYONGROUND))
+ #define GAMEPLAYFIX_Q2AIRACCELERATE (boolean(moveflags & MOVEFLAG_Q2AIRACCELERATE))
- #define IS_DUCKED(s) !!(s.flags & FL_DUCKED)
+ #define IS_DUCKED(s) boolean(s.flags & FL_DUCKED)
#define SET_DUCKED(s) s.flags |= FL_DUCKED
#define UNSET_DUCKED(s) s.flags &= ~FL_DUCKED
#define SET_JUMP_HELD(s) s.flags &= ~FL_JUMPRELEASED
#define UNSET_JUMP_HELD(s) s.flags |= FL_JUMPRELEASED
- #define IS_ONGROUND(s) !!(s.flags & FL_ONGROUND)
+ #define IS_ONGROUND(s) boolean(s.flags & FL_ONGROUND)
#define SET_ONGROUND(s) s.flags |= FL_ONGROUND
#define UNSET_ONGROUND(s) s.flags &= ~FL_ONGROUND
- #define WAS_ONGROUND(s) !!(s.lastflags & FL_ONGROUND)
+ #define WAS_ONGROUND(s) boolean(s.lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) (s).items
- #define BUFFS_STAT(s) getstati(STAT_BUFFS)
-
- #define PHYS_AMMO_FUEL(s) getstati(STAT_FUEL)
-
- #define PHYS_FROZEN(s) getstati(STAT_FROZEN)
-
- #define PHYS_DOUBLEJUMP getstati(STAT_DOUBLEJUMP)
-
- #define PHYS_BUGRIGS getstati(STAT_BUGRIGS)
- #define PHYS_BUGRIGS_ANGLE_SMOOTHING getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
- #define PHYS_BUGRIGS_PLANAR_MOVEMENT getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
- #define PHYS_BUGRIGS_REVERSE_SPEEDING getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
- #define PHYS_BUGRIGS_FRICTION_FLOOR getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
- #define PHYS_BUGRIGS_AIR_STEERING getstati(STAT_BUGRIGS_AIR_STEERING)
- #define PHYS_BUGRIGS_FRICTION_BRAKE getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
- #define PHYS_BUGRIGS_ACCEL getstatf(STAT_BUGRIGS_ACCEL)
- #define PHYS_BUGRIGS_SPEED_REF getstatf(STAT_BUGRIGS_SPEED_REF)
- #define PHYS_BUGRIGS_SPEED_POW getstatf(STAT_BUGRIGS_SPEED_POW)
- #define PHYS_BUGRIGS_STEER getstatf(STAT_BUGRIGS_STEER)
- #define PHYS_BUGRIGS_FRICTION_AIR getstatf(STAT_BUGRIGS_FRICTION_AIR)
- #define PHYS_BUGRIGS_CAR_JUMPING getstatf(STAT_BUGRIGS_CAR_JUMPING)
- #define PHYS_BUGRIGS_REVERSE_SPINNING getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
- #define PHYS_BUGRIGS_REVERSE_STOPPING getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
#define PHYS_JUMPSPEEDCAP_MIN cvar_string("cl_jumpspeedcap_min")
#define PHYS_JUMPSPEEDCAP_MAX cvar_string("cl_jumpspeedcap_max")
- #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
-
- #define PHYS_CL_TRACK_CANJUMP(s) getstati(STAT_MOVEVARS_CL_TRACK_CANJUMP)
- #define PHYS_TRACK_CANJUMP(s) getstati(STAT_MOVEVARS_TRACK_CANJUMP)
- #define PHYS_ACCELERATE getstatf(STAT_MOVEVARS_ACCELERATE)
- #define PHYS_AIRACCEL_QW(s) getstatf(STAT_MOVEVARS_AIRACCEL_QW)
- #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) getstatf(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR)
- #define PHYS_AIRACCEL_SIDEWAYS_FRICTION getstatf(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION)
- #define PHYS_AIRACCELERATE getstatf(STAT_MOVEVARS_AIRACCELERATE)
- #define PHYS_AIRCONTROL getstatf(STAT_MOVEVARS_AIRCONTROL)
- #define PHYS_AIRCONTROL_PENALTY getstatf(STAT_MOVEVARS_AIRCONTROL_PENALTY)
- #define PHYS_AIRCONTROL_POWER getstatf(STAT_MOVEVARS_AIRCONTROL_POWER)
- #define PHYS_AIRSPEEDLIMIT_NONQW(s) getstatf(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW)
- #define PHYS_AIRSTOPACCELERATE getstatf(STAT_MOVEVARS_AIRSTOPACCELERATE)
- #define PHYS_AIRSTRAFEACCEL_QW(s) getstatf(STAT_MOVEVARS_AIRSTRAFEACCEL_QW)
- #define PHYS_AIRSTRAFEACCELERATE(s) getstatf(STAT_MOVEVARS_AIRSTRAFEACCELERATE)
- #define PHYS_ENTGRAVITY(s) getstatf(STAT_MOVEVARS_ENTGRAVITY)
- #define PHYS_FRICTION getstatf(STAT_MOVEVARS_FRICTION)
- #define PHYS_FRICTION_SLICK getstatf(STAT_MOVEVARS_FRICTION_SLICK)
- #define PHYS_FRICTION_ONLAND getstatf(STAT_MOVEVARS_FRICTION_ONLAND)
- #define PHYS_GRAVITY getstatf(STAT_MOVEVARS_GRAVITY)
- #define PHYS_HIGHSPEED getstatf(STAT_MOVEVARS_HIGHSPEED)
- #define PHYS_JUMPVELOCITY getstatf(STAT_MOVEVARS_JUMPVELOCITY)
- #define PHYS_MAXAIRSPEED(s) getstatf(STAT_MOVEVARS_MAXAIRSPEED)
- #define PHYS_MAXAIRSTRAFESPEED getstatf(STAT_MOVEVARS_MAXAIRSTRAFESPEED)
- #define PHYS_MAXSPEED(s) getstatf(STAT_MOVEVARS_MAXSPEED)
- #define PHYS_STEPHEIGHT getstatf(STAT_MOVEVARS_STEPHEIGHT)
- #define PHYS_STOPSPEED getstatf(STAT_MOVEVARS_STOPSPEED)
- #define PHYS_WARSOWBUNNY_ACCEL getstatf(STAT_MOVEVARS_WARSOWBUNNY_ACCEL)
- #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO getstatf(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO)
- #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL getstatf(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL)
- #define PHYS_WARSOWBUNNY_TOPSPEED getstatf(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED)
- #define PHYS_WARSOWBUNNY_TURNACCEL getstatf(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL)
-
- #define PHYS_WALLFRICTION getstati(STAT_MOVEVARS_WALLFRICTION)
-
- #define PHYS_JETPACK_ACCEL_UP getstatf(STAT_JETPACK_ACCEL_UP)
- #define PHYS_JETPACK_ACCEL_SIDE getstatf(STAT_JETPACK_ACCEL_SIDE)
- #define PHYS_JETPACK_ANTIGRAVITY getstatf(STAT_JETPACK_ANTIGRAVITY)
- #define PHYS_JETPACK_FUEL getstatf(STAT_JETPACK_FUEL)
- #define PHYS_JETPACK_MAXSPEED_UP getstatf(STAT_JETPACK_MAXSPEED_UP)
- #define PHYS_JETPACK_MAXSPEED_SIDE getstatf(STAT_JETPACK_MAXSPEED_SIDE)
-
- #define PHYS_DODGING_FROZEN getstati(STAT_DODGING_FROZEN)
-
- #define PHYS_NOSTEP getstati(STAT_NOSTEP)
- #define PHYS_JUMPSTEP getstati(STAT_MOVEVARS_JUMPSTEP)
+
+ #define PHYS_CL_TRACK_CANJUMP(s) STAT(MOVEVARS_CL_TRACK_CANJUMP, s)
+ // FIXME: 0 doesn't mean zero gravity
+ #define PHYS_ENTGRAVITY(s) STAT(MOVEVARS_ENTGRAVITY, s)
#elif defined(SVQC)
bool Physics_Valid(string thecvar);
- .vector stat_pl_view_ofs;
- .vector stat_pl_crouch_view_ofs;
-
- .vector stat_pl_min;
- .vector stat_pl_max;
- .vector stat_pl_crouch_min;
- .vector stat_pl_crouch_max;
-
- .float stat_sv_airaccel_qw;
- .float stat_sv_airstrafeaccel_qw;
- .float stat_sv_airspeedlimit_nonqw;
- .float stat_sv_maxspeed;
- .float stat_movement_highspeed;
-
- .float stat_sv_friction_on_land;
- .float stat_sv_friction_slick;
-
- .float stat_doublejump;
-
- .string stat_jumpspeedcap_min;
- .string stat_jumpspeedcap_max;
- .float stat_jumpspeedcap_disable_onramps;
-
- .float stat_jetpack_accel_side;
- .float stat_jetpack_accel_up;
- .float stat_jetpack_antigravity;
- .float stat_jetpack_fuel;
- .float stat_jetpack_maxspeed_up;
- .float stat_jetpack_maxspeed_side;
- .float stat_gameplayfix_easierwaterjump;
- .float stat_gameplayfix_downtracesupportsongroundflag;
- .float stat_gameplayfix_stepmultipletimes;
- .float stat_gameplayfix_unstickplayers;
- .float stat_gameplayfix_stepdown;
-
- .float stat_bugrigs;
- .float stat_bugrigs_angle_smoothing;
- .float stat_bugrigs_planar_movement;
- .float stat_bugrigs_reverse_speeding;
- .float stat_bugrigs_friction_floor;
- .float stat_bugrigs_air_steering;
- .float stat_bugrigs_friction_brake;
- .float stat_bugrigs_accel;
- .float stat_bugrigs_speed_ref;
- .float stat_bugrigs_speed_pow;
- .float stat_bugrigs_steer;
- .float stat_bugrigs_friction_air;
- .float stat_bugrigs_car_jumping;
- .float stat_bugrigs_reverse_spinning;
- .float stat_bugrigs_reverse_stopping;
-
- // new properties
- .float stat_sv_jumpvelocity;
- .float stat_sv_airaccel_qw_stretchfactor;
- .float stat_sv_maxairstrafespeed;
- .float stat_sv_maxairspeed;
- .float stat_sv_airstrafeaccelerate;
- .float stat_sv_warsowbunny_turnaccel;
- .float stat_sv_airaccel_sideways_friction;
- .float stat_sv_aircontrol;
- .float stat_sv_aircontrol_power;
- .float stat_sv_aircontrol_penalty;
- .float stat_sv_warsowbunny_airforwardaccel;
- .float stat_sv_warsowbunny_topspeed;
- .float stat_sv_warsowbunny_accel;
- .float stat_sv_warsowbunny_backtosideratio;
- .float stat_sv_friction;
- .float stat_sv_accelerate;
- .float stat_sv_stopspeed;
- .float stat_sv_airaccelerate;
- .float stat_sv_airstopaccelerate;
-
- .float stat_nostep;
- .float stat_jumpstep;
-
- .bool stat_sv_track_canjump;
+ .float stat_sv_airspeedlimit_nonqw = _STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW);
+ .float stat_sv_maxspeed = _STAT(MOVEVARS_MAXSPEED);
+
+ /** Not real stats */
+ .string stat_jumpspeedcap_min, stat_jumpspeedcap_max;
+
+ #define TICRATE sys_frametime
#define PHYS_INPUT_ANGLES(s) s.v_angle
#define PHYS_WORLD_ANGLES(s) s.angles
#define PHYS_DEAD(s) s.deadflag != DEAD_NO
#define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
- #define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
+ #define GAMEPLAYFIX_NOGRAVITYONGROUND autocvar_sv_gameplayfix_nogravityonground
#define GAMEPLAYFIX_Q2AIRACCELERATE autocvar_sv_gameplayfix_q2airaccelerate
- #define GAMEPLAYFIX_EASIERWATERJUMP cvar("sv_gameplayfix_easierwaterjump")
- #define GAMEPLAYFIX_DOWNTRACEONGROUND cvar("sv_gameplayfix_downtracesupportsongroundflag")
- #define GAMEPLAYFIX_STEPMULTIPLETIMES cvar("sv_gameplayfix_stepmultipletimes")
- #define GAMEPLAYFIX_UNSTICKPLAYERS cvar("sv_gameplayfix_unstickplayers")
- #define GAMEPLAYFIX_STEPDOWN cvar("sv_gameplayfix_stepdown")
#define IS_DUCKED(s) s.crouch
#define SET_DUCKED(s) s.crouch = true
#define SET_JUMP_HELD(s) s.flags &= ~FL_JUMPRELEASED
#define UNSET_JUMP_HELD(s) s.flags |= FL_JUMPRELEASED
- #define IS_ONGROUND(s) !!(s.flags & FL_ONGROUND)
+ #define IS_ONGROUND(s) boolean(s.flags & FL_ONGROUND)
#define SET_ONGROUND(s) s.flags |= FL_ONGROUND
#define UNSET_ONGROUND(s) s.flags &= ~FL_ONGROUND
- #define WAS_ONGROUND(s) !!((s).lastflags & FL_ONGROUND)
+ #define WAS_ONGROUND(s) boolean((s).lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) s.items
- #define BUFFS_STAT(s) (s).buffs
-
- #define PHYS_AMMO_FUEL(s) s.ammo_fuel
-
- #define PHYS_FROZEN(s) s.frozen
-
- #define PHYS_DOUBLEJUMP autocvar_sv_doublejump
-
- #define PHYS_BUGRIGS g_bugrigs
- #define PHYS_BUGRIGS_ANGLE_SMOOTHING g_bugrigs_angle_smoothing
- #define PHYS_BUGRIGS_PLANAR_MOVEMENT g_bugrigs_planar_movement
- #define PHYS_BUGRIGS_REVERSE_SPEEDING g_bugrigs_reverse_speeding
- #define PHYS_BUGRIGS_FRICTION_FLOOR g_bugrigs_friction_floor
- #define PHYS_BUGRIGS_AIR_STEERING g_bugrigs_air_steering
- #define PHYS_BUGRIGS_FRICTION_BRAKE g_bugrigs_friction_brake
- #define PHYS_BUGRIGS_ACCEL g_bugrigs_accel
- #define PHYS_BUGRIGS_SPEED_REF g_bugrigs_speed_ref
- #define PHYS_BUGRIGS_SPEED_POW g_bugrigs_speed_pow
- #define PHYS_BUGRIGS_STEER g_bugrigs_steer
- #define PHYS_BUGRIGS_FRICTION_AIR g_bugrigs_friction_air
- #define PHYS_BUGRIGS_CAR_JUMPING g_bugrigs_planar_movement_car_jumping
- #define PHYS_BUGRIGS_REVERSE_SPINNING g_bugrigs_reverse_spinning
- #define PHYS_BUGRIGS_REVERSE_STOPPING g_bugrigs_reverse_stopping
#define PHYS_JUMPSPEEDCAP_MIN autocvar_sv_jumpspeedcap_min
#define PHYS_JUMPSPEEDCAP_MAX autocvar_sv_jumpspeedcap_max
- #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS autocvar_sv_jumpspeedcap_max_disable_on_ramps
#define PHYS_CL_TRACK_CANJUMP(s) s.cvar_cl_movement_track_canjump
- #define PHYS_TRACK_CANJUMP(s) s.stat_sv_track_canjump
- #define PHYS_ACCELERATE self.stat_sv_accelerate
- #define PHYS_AIRACCEL_QW(s) s.stat_sv_airaccel_qw
- #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) self.stat_sv_airaccel_qw_stretchfactor
- #define PHYS_AIRACCEL_SIDEWAYS_FRICTION self.stat_sv_airaccel_sideways_friction
- #define PHYS_AIRACCELERATE self.stat_sv_airaccelerate
- #define PHYS_AIRCONTROL self.stat_sv_aircontrol
- #define PHYS_AIRCONTROL_PENALTY self.stat_sv_aircontrol_penalty
- #define PHYS_AIRCONTROL_POWER self.stat_sv_aircontrol_power
- #define PHYS_AIRSPEEDLIMIT_NONQW(s) s.stat_sv_airspeedlimit_nonqw
- #define PHYS_AIRSTOPACCELERATE self.stat_sv_airstopaccelerate
- #define PHYS_AIRSTRAFEACCEL_QW(s) s.stat_sv_airstrafeaccel_qw
- #define PHYS_AIRSTRAFEACCELERATE(s) s.stat_sv_airstrafeaccelerate
#define PHYS_ENTGRAVITY(s) s.gravity
- #define PHYS_FRICTION self.stat_sv_friction
- #define PHYS_FRICTION_SLICK autocvar_sv_friction_slick
- #define PHYS_FRICTION_ONLAND autocvar_sv_friction_on_land
- #define PHYS_GRAVITY autocvar_sv_gravity
- #define PHYS_HIGHSPEED autocvar_g_movement_highspeed
- #define PHYS_JUMPVELOCITY self.stat_sv_jumpvelocity
- #define PHYS_MAXAIRSPEED(s) self.stat_sv_maxairspeed
- #define PHYS_MAXAIRSTRAFESPEED self.stat_sv_maxairstrafespeed
- #define PHYS_MAXSPEED(s) s.stat_sv_maxspeed
- #define PHYS_STEPHEIGHT autocvar_sv_stepheight
- #define PHYS_STOPSPEED self.stat_sv_stopspeed
- #define PHYS_WARSOWBUNNY_ACCEL self.stat_sv_warsowbunny_accel
- #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO self.stat_sv_warsowbunny_backtosideratio
- #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL self.stat_sv_warsowbunny_airforwardaccel
- #define PHYS_WARSOWBUNNY_TOPSPEED self.stat_sv_warsowbunny_topspeed
- #define PHYS_WARSOWBUNNY_TURNACCEL self.stat_sv_warsowbunny_turnaccel
-
- #define PHYS_WALLFRICTION cvar("sv_wallfriction")
-
- #define PHYS_JETPACK_ACCEL_UP autocvar_g_jetpack_acceleration_up
- #define PHYS_JETPACK_ACCEL_SIDE autocvar_g_jetpack_acceleration_side
- #define PHYS_JETPACK_ANTIGRAVITY autocvar_g_jetpack_antigravity
- #define PHYS_JETPACK_FUEL autocvar_g_jetpack_fuel
- #define PHYS_JETPACK_MAXSPEED_UP autocvar_g_jetpack_maxspeed_up
- #define PHYS_JETPACK_MAXSPEED_SIDE autocvar_g_jetpack_maxspeed_side
-
- #define PHYS_DODGING_FROZEN autocvar_sv_dodging_frozen
-
- #define PHYS_NOSTEP cvar("sv_nostep")
- #define PHYS_JUMPSTEP cvar("sv_jumpstep")
#endif
#endif
--- /dev/null
+#ifdef SVQC
+
+bool autocvar_bot_sound_monopoly;
+
+.entity realowner;
+bool sound_allowed(int to, entity e)
+{
+ for ( ; ; )
+ {
+ if (e.classname == "body") e = e.enemy;
+ else if (e.realowner && e.realowner != e) e = e.realowner;
+ else if (e.owner && e.owner != e) e = e.owner;
+ else break;
+ }
+ // sounds to self may always pass
+ if (to == MSG_ONE && e == msg_entity) return true;
+ // sounds by players can be removed
+ if (autocvar_bot_sound_monopoly && IS_REAL_CLIENT(e)) return false;
+ // anything else may pass
+ return true;
+}
+
+/** hack: string precache_sound(string s) = #19; */
+int precache_sound_index(string s) = #19;
+
+const int SVC_SOUND = 6;
+const int SVC_STOPSOUND = 16;
+
+const int SND_VOLUME = BIT(0);
+const int SND_ATTENUATION = BIT(1);
+const int SND_LARGEENTITY = BIT(3);
+const int SND_LARGESOUND = BIT(4);
+
+void soundtoat(int to, entity e, vector o, int chan, string samp, float vol, float attenu)
+{
+ if (!sound_allowed(to, e)) return;
+ int entno = etof(e);
+ int idx = precache_sound_index(samp);
+ attenu = floor(attenu * 64);
+ vol = floor(vol * 255);
+ int sflags = 0;
+ if (vol != 255) sflags |= SND_VOLUME;
+ if (attenu != 64) sflags |= SND_ATTENUATION;
+ if (entno >= 8192 || chan < 0 || chan > 7) sflags |= SND_LARGEENTITY;
+ if (idx >= 256) sflags |= SND_LARGESOUND;
+ WriteByte(to, SVC_SOUND);
+ WriteByte(to, sflags);
+ if (sflags & SND_VOLUME) WriteByte(to, vol);
+ if (sflags & SND_ATTENUATION) WriteByte(to, attenu);
+ if (sflags & SND_LARGEENTITY)
+ {
+ WriteShort(to, entno);
+ WriteByte(to, chan);
+ }
+ else
+ {
+ WriteShort(to, (entno << 3) | chan);
+ }
+ if (sflags & SND_LARGESOUND) WriteShort(to, idx);
+ else WriteByte(to, idx);
+ WriteCoord(to, o.x);
+ WriteCoord(to, o.y);
+ WriteCoord(to, o.z);
+}
+
+void soundto(int _dest, entity e, int chan, string samp, float vol, float _atten)
+{
+ if (!sound_allowed(_dest, e)) return;
+ vector o = e.origin + 0.5 * (e.mins + e.maxs);
+ soundtoat(_dest, e, o, chan, samp, vol, _atten);
+}
+void soundat(entity e, vector o, int chan, string samp, float vol, float _atten)
+{
+ soundtoat(((chan & 8) ? MSG_ALL : MSG_BROADCAST), e, o, chan, samp, vol, _atten);
+}
+void stopsoundto(int _dest, entity e, int chan)
+{
+ if (!sound_allowed(_dest, e)) return;
+ int entno = num_for_edict(e);
+ if (entno >= 8192 || chan < 0 || chan > 7)
+ {
+ int idx = precache_sound_index(SND(Null));
+ int sflags = SND_LARGEENTITY;
+ if (idx >= 256) sflags |= SND_LARGESOUND;
+ WriteByte(_dest, SVC_SOUND);
+ WriteByte(_dest, sflags);
+ WriteShort(_dest, entno);
+ WriteByte(_dest, chan);
+ if (sflags & SND_LARGESOUND) WriteShort(_dest, idx);
+ else WriteByte(_dest, idx);
+ WriteCoord(_dest, e.origin.x);
+ WriteCoord(_dest, e.origin.y);
+ WriteCoord(_dest, e.origin.z);
+ }
+ else
+ {
+ WriteByte(_dest, SVC_STOPSOUND);
+ WriteShort(_dest, entno * 8 + chan);
+ }
+}
+void stopsound(entity e, int chan)
+{
+ if (!sound_allowed(MSG_BROADCAST, e)) return;
+ stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
+ stopsoundto(MSG_ALL, e, chan); // in case of packet loss
+}
+
+void play2(entity e, string filename)
+{
+ msg_entity = e;
+ soundtoat(MSG_ONE, world, '0 0 0', CH_INFO, filename, VOL_BASE, ATTEN_NONE);
+}
+
+.float spamtime;
+/** use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame) */
+float spamsound(entity e, int chan, string samp, float vol, float _atten)
+{
+ if (!sound_allowed(MSG_BROADCAST, e)) return false;
+ if (time > e.spamtime)
+ {
+ e.spamtime = time;
+ _sound(e, chan, samp, vol, _atten);
+ return true;
+ }
+ return false;
+}
+
+void play2team(float t, string filename)
+{
+ if (autocvar_bot_sound_monopoly) return;
+ entity head;
+ FOR_EACH_REALPLAYER(head)
+ {
+ if (head.team == t) play2(head, filename);
+ }
+}
+
+void play2all(string samp)
+{
+ if (autocvar_bot_sound_monopoly) return;
+ _sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
+}
+
+#endif
REGISTRY(Sounds, BITS(8))
#define Sounds_from(i) _Sounds_from(i, SND_Null)
-REGISTER_REGISTRY(RegisterSounds)
+REGISTER_REGISTRY(Sounds)
#define SOUND(name, path) \
string SND_##name##_get() { return path; } \
- REGISTER(RegisterSounds, SND, Sounds, name, m_id, NEW(Sound, SND_##name##_get))
+ REGISTER(Sounds, SND, name, m_id, NEW(Sound, SND_##name##_get))
// Used in places where a string is required
#define SND(id) Sound_fixpath(SND_##id)
SOUND(Null, "misc/null");
#include "all.inc"
-
+#include "all.qc"
#endif
#ifndef SOUND_H
#define SOUND_H
+// negative = SVQC autochannels
+// positive = one per entity
+
+const int CH_INFO = 0;
+const int CH_WEAPON_A = -1;
+const int CH_WEAPON_B = -1;
+const int CH_WEAPON_SINGLE = 1;
+const int CH_VOICE = -2;
+// const int CH_VOICE_SINGLE = 2;
+const int CH_TRIGGER = -3;
+const int CH_TRIGGER_SINGLE = 3;
+const int CH_SHOTS = -4;
+const int CH_SHOTS_SINGLE = 4;
+// const int CH_TUBA = -5;
+const int CH_TUBA_SINGLE = 5;
+const int CH_PAIN = -6;
+const int CH_PAIN_SINGLE = 6;
+const int CH_PLAYER = -7;
+const int CH_PLAYER_SINGLE = 7;
+// const int CH_BGM_SINGLE = -8;
+const int CH_BGM_SINGLE = 8;
+const int CH_AMBIENT = -9;
+// const int CH_AMBIENT_SINGLE = 9;
+
+const float ATTEN_NONE = 0;
+const float ATTEN_MIN = 0.015625;
+const float ATTEN_NORM = 0.5;
+const float ATTEN_LARGE = 1;
+const float ATTEN_IDLE = 2;
+const float ATTEN_STATIC = 3;
+const float ATTEN_MAX = 3.984375;
+
+const float VOL_BASE = 0.7;
+const float VOL_BASEVOICE = 1.0;
+
// Play all sounds via sound7, for access to the extra channels.
// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
#ifdef SVQC
#endif
#define sound(e, c, s, v, a) _sound(e, c, Sound_fixpath(s), v, a)
+/**
+ * because sound7 didn't have origin
+ *
+ * @param e sound owner
+ * @param o sound origin
+ * @param chan sound channel
+ * @param samp sound filename
+ * @param vol sound volume
+ * @param atten sound attenuation
+ * @param speed
+ * @param sf
+ */
+#define sound8(e, o, chan, samp, vol, atten, speed, sf) \
+ do \
+ { \
+ entity __e = e; \
+ vector old_origin = __e.origin; \
+ vector old_mins = __e.mins; \
+ vector old_maxs = __e.maxs; \
+ setorigin(__e, o); \
+ setsize(__e, '0 0 0', '0 0 0'); \
+ sound7(__e, chan, samp, vol, atten, speed, sf); \
+ setorigin(__e, old_origin); \
+ setsize(__e, old_mins, old_maxs); \
+ } \
+ while (0)
+
CLASS(Sound, Object)
ATTRIB(Sound, m_id, int, 0)
ATTRIB(Sound, sound_str, string(), func_null)
#define Sound_fixpath(this) _Sound_fixpath((this).sound_str())
string _Sound_fixpath(string base)
{
- if (base == "") return string_null;
- #define extensions(x) \
- x(wav) \
- x(ogg) \
- x(flac) \
- /**/
- string full, relative;
- #define tryext(ext) { if (fexists(full = strcat("sound/", relative = strcat(base, "." #ext)))) break; }
- do
- {
- extensions(tryext);
+ if (base == "") return string_null;
+ #define extensions(x) \
+ x(wav) \
+ x(ogg) \
+ x(flac) \
+ /**/
+ string full, relative;
+ #define tryext(ext) { if (fexists(full = strcat("sound/", relative = strcat(base, "." #ext)))) break; }
+ do
+ {
+ extensions(tryext);
#undef tryext
#undef extensions
- LOG_WARNINGF("Missing sound: \"%s\"\n", full);
- return string_null;
- }
- while (0);
- return relative;
+ LOG_WARNINGF("Missing sound: \"%s\"\n", full);
+ return string_null;
+ }
+ while (0);
+ return relative;
}
METHOD(Sound, sound_precache, void(entity this))
{
// Full list of all stat constants, included in a single location for easy reference
// 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
-const int MAX_CL_STATS = 256;
-// -Wdouble-declaration
-// const int STAT_HEALTH = 0;
-// 1 empty?
-const int STAT_WEAPON = 2;
-// -Wdouble-declaration
-// const int STAT_AMMO = 3;
-// -Wdouble-declaration
-// const int STAT_ARMOR = 4;
-// -Wdouble-declaration
-// const int STAT_WEAPONFRAME = 5;
-// -Wdouble-declaration
-// const int STAT_SHELLS = 6;
-// -Wdouble-declaration
-// const int STAT_NAILS = 7;
-// -Wdouble-declaration
-// const int STAT_ROCKETS = 8;
-// -Wdouble-declaration
-// const int STAT_CELLS = 9;
-// -Wdouble-declaration
-// const int STAT_ACTIVEWEAPON = 10;
-// -Wdouble-declaration
-// const int STAT_TOTALSECRETS = 11;
-// -Wdouble-declaration
-// const int STAT_TOTALMONSTERS = 12;
-// -Wdouble-declaration
-// const int STAT_SECRETS = 13;
-// -Wdouble-declaration
-// const int STAT_MONSTERS = 14;
-// -Wdouble-declaration
-// const int STAT_ITEMS = 15;
-// -Wdouble-declaration
-// const int STAT_VIEWHEIGHT = 16;
-// 17 empty?
-// 18 empty?
-// 19 empty?
-// 20 empty?
-const int STAT_VIEWZOOM = 21;
-// 22 empty?
-// 23 empty?
-// 24 empty?
-// 25 empty?
-// 26 empty?
-// 27 empty?
-// 28 empty?
-// 29 empty?
-// 30 empty?
-// 31 empty?
-const int STAT_KH_KEYS = 32;
-const int STAT_CTF_STATE = 33;
-// 34 empty?
-const int STAT_WEAPONS = 35;
-const int STAT_SWITCHWEAPON = 36;
-const int STAT_GAMESTARTTIME = 37;
-const int STAT_STRENGTH_FINISHED = 38;
-const int STAT_INVINCIBLE_FINISHED = 39;
-// 40 empty?
-const int STAT_ARC_HEAT = 41;
-const int STAT_PRESSED_KEYS = 42;
-const int STAT_ALLOW_OLDVORTEXBEAM = 43; // this stat could later contain some other bits of info, like, more server-side particle config
-const int STAT_FUEL = 44;
-const int STAT_NB_METERSTART = 45;
-const int STAT_SHOTORG = 46; // compressShotOrigin
-const int STAT_LEADLIMIT = 47;
-const int STAT_WEAPON_CLIPLOAD = 48;
-const int STAT_WEAPON_CLIPSIZE = 49;
-const int STAT_VORTEX_CHARGE = 50;
-const int STAT_LAST_PICKUP = 51;
-const int STAT_HUD = 52;
-const int STAT_VORTEX_CHARGEPOOL = 53;
-const int STAT_HIT_TIME = 54;
-const int STAT_DAMAGE_DEALT_TOTAL = 55;
-const int STAT_TYPEHIT_TIME = 56;
-const int STAT_LAYED_MINES = 57;
-const int STAT_HAGAR_LOAD = 58;
-const int STAT_SWITCHINGWEAPON = 59;
-const int STAT_SUPERWEAPONS_FINISHED = 60;
-const int STAT_VEHICLESTAT_HEALTH = 61;
-const int STAT_VEHICLESTAT_SHIELD = 62;
-const int STAT_VEHICLESTAT_ENERGY = 63;
-const int STAT_VEHICLESTAT_AMMO1 = 64;
-const int STAT_VEHICLESTAT_RELOAD1 = 65;
-const int STAT_VEHICLESTAT_AMMO2 = 66;
-const int STAT_VEHICLESTAT_RELOAD2 = 67;
-const int STAT_VEHICLESTAT_W2MODE = 68;
-const int STAT_NADE_TIMER = 69;
-const int STAT_SECRETS_TOTAL = 70;
-const int STAT_SECRETS_FOUND = 71;
-const int STAT_RESPAWN_TIME = 72;
-const int STAT_ROUNDSTARTTIME = 73;
-const int STAT_WEAPONS2 = 74;
-const int STAT_WEAPONS3 = 75;
-const int STAT_MONSTERS_TOTAL = 76;
-const int STAT_MONSTERS_KILLED = 77;
-const int STAT_BUFFS = 78;
-const int STAT_NADE_BONUS = 79;
-const int STAT_NADE_BONUS_TYPE = 80;
-const int STAT_NADE_BONUS_SCORE = 81;
-const int STAT_HEALING_ORB = 82;
-const int STAT_HEALING_ORB_ALPHA = 83;
-const int STAT_PLASMA = 84;
-const int STAT_OK_AMMO_CHARGE = 85;
-const int STAT_OK_AMMO_CHARGEPOOL = 86;
-const int STAT_FROZEN = 87;
-const int STAT_REVIVE_PROGRESS = 88;
-const int STAT_WEAPON_NEXTTHINK = 89;
-// 90 empty?
-// 91 empty?
-// 92 empty?
-// 93 empty?
-// 94 empty?
-// 95 empty?
-// 96 empty?
-// 97 empty?
-// 98 empty?
-const int STAT_ROUNDLOST = 99;
+const int MAX_CL_STATS = 256;
+#ifndef CSQC
+const int STAT_HEALTH = 0; // .health
+const int STAT_ARMOR = 4; // .armorvalue
+const int STAT_SHELLS = 6; // .ammo_shells
+const int STAT_NAILS = 7; // .ammo_nails
+const int STAT_ROCKETS = 8; // .ammo_rockets
+const int STAT_CELLS = 9; // .ammo_cells
+const int STAT_ACTIVEWEAPON = 10; // .weapon
+const int STAT_ITEMS = 15; // .items | .items2 << 23 | serverflags << 28
+const int STAT_VIEWHEIGHT = 16; // .view_ofs_z
+#endif
+
+REGISTER_STAT(WEAPONS, vectori)
+REGISTER_STAT(WEAPONSINMAP, vectori)
+
+REGISTER_STAT(PL_VIEW_OFS, vector, autocvar_sv_player_viewoffset)
+REGISTER_STAT(PL_CROUCH_VIEW_OFS, vector, autocvar_sv_player_crouch_viewoffset)
+
+REGISTER_STAT(PL_MIN, vector, autocvar_sv_player_mins)
+REGISTER_STAT(PL_CROUCH_MIN, vector, autocvar_sv_player_crouch_mins)
+
+REGISTER_STAT(PL_MAX, vector, autocvar_sv_player_maxs)
+REGISTER_STAT(PL_CROUCH_MAX, vector, autocvar_sv_player_crouch_maxs)
+
+REGISTER_STAT(KH_KEYS, int)
+
+/** weapon requested to switch to; next WANTED weapon (for HUD) */
+REGISTER_STAT(SWITCHWEAPON, int)
+/** weapon currently being switched to (is copied from switchweapon once switch is possible) */
+REGISTER_STAT(SWITCHINGWEAPON, int)
+REGISTER_STAT(WEAPON_NEXTTHINK, float)
+
+REGISTER_STAT(GAMESTARTTIME, float)
+REGISTER_STAT(STRENGTH_FINISHED, float)
+REGISTER_STAT(INVINCIBLE_FINISHED, float)
+/** arc heat in [0,1] */
+REGISTER_STAT(ARC_HEAT, float)
+REGISTER_STAT(PRESSED_KEYS, int)
+/** this stat could later contain some other bits of info, like, more server-side particle config */
+REGISTER_STAT(ALLOW_OLDVORTEXBEAM, bool)
+REGISTER_STAT(FUEL, int)
+REGISTER_STAT(NB_METERSTART, float)
+/** compressShotOrigin */
+REGISTER_STAT(SHOTORG, int)
+REGISTER_STAT(LEADLIMIT, float)
+REGISTER_STAT(WEAPON_CLIPLOAD, int)
+REGISTER_STAT(WEAPON_CLIPSIZE, int)
+
+REGISTER_STAT(VORTEX_CHARGE, float)
+REGISTER_STAT(LAST_PICKUP, float)
+REGISTER_STAT(HUD, int)
+REGISTER_STAT(VORTEX_CHARGEPOOL, float)
+REGISTER_STAT(HIT_TIME, float)
+REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
+REGISTER_STAT(TYPEHIT_TIME, float)
+REGISTER_STAT(LAYED_MINES, int)
+REGISTER_STAT(HAGAR_LOAD, int)
+REGISTER_STAT(SUPERWEAPONS_FINISHED, float)
+REGISTER_STAT(VEHICLESTAT_HEALTH, int)
+REGISTER_STAT(VEHICLESTAT_SHIELD, int)
+REGISTER_STAT(VEHICLESTAT_ENERGY, int)
+REGISTER_STAT(VEHICLESTAT_AMMO1, int)
+REGISTER_STAT(VEHICLESTAT_RELOAD1, int)
+REGISTER_STAT(VEHICLESTAT_AMMO2, int)
+REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
+REGISTER_STAT(VEHICLESTAT_W2MODE, int)
+REGISTER_STAT(NADE_TIMER, float)
+REGISTER_STAT(SECRETS_TOTAL, float)
+REGISTER_STAT(SECRETS_FOUND, float)
+REGISTER_STAT(RESPAWN_TIME, float)
+REGISTER_STAT(ROUNDSTARTTIME, float)
+REGISTER_STAT(MONSTERS_TOTAL, int)
+REGISTER_STAT(MONSTERS_KILLED, int)
+REGISTER_STAT(BUFFS, int)
+REGISTER_STAT(NADE_BONUS, float)
+REGISTER_STAT(NADE_BONUS_TYPE, int)
+REGISTER_STAT(NADE_BONUS_SCORE, float)
+REGISTER_STAT(HEALING_ORB, float)
+REGISTER_STAT(HEALING_ORB_ALPHA, float)
+REGISTER_STAT(PLASMA, int)
+REGISTER_STAT(OK_AMMO_CHARGE, float)
+REGISTER_STAT(OK_AMMO_CHARGEPOOL, float)
+REGISTER_STAT(FROZEN, int)
+REGISTER_STAT(REVIVE_PROGRESS, float)
+REGISTER_STAT(ROUNDLOST, int)
+REGISTER_STAT(BUFF_TIME, float)
+REGISTER_STAT(CTF_FLAGSTATUS, int)
+
+#ifdef SVQC
+int autocvar_g_multijump;
+float autocvar_g_multijump_add;
+float autocvar_g_multijump_speed;
+float autocvar_g_multijump_maxspeed;
+float autocvar_g_multijump_dodging = 1;
+#endif
+REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging)
+REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
+REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
+REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+.int multijump_count;
+REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count)
+REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
+REGISTER_STAT(DOUBLEJUMP, int, autocvar_sv_doublejump)
+
+#ifdef SVQC
+bool g_bugrigs;
+bool g_bugrigs_planar_movement;
+bool g_bugrigs_planar_movement_car_jumping;
+float g_bugrigs_reverse_spinning;
+float g_bugrigs_reverse_speeding;
+float g_bugrigs_reverse_stopping;
+float g_bugrigs_air_steering;
+float g_bugrigs_angle_smoothing;
+float g_bugrigs_friction_floor;
+float g_bugrigs_friction_brake;
+float g_bugrigs_friction_air;
+float g_bugrigs_accel;
+float g_bugrigs_speed_ref;
+float g_bugrigs_speed_pow;
+float g_bugrigs_steer;
+#endif
+REGISTER_STAT(BUGRIGS, int, g_bugrigs)
+REGISTER_STAT(BUGRIGS_ACCEL, float, g_bugrigs_accel)
+REGISTER_STAT(BUGRIGS_AIR_STEERING, int, g_bugrigs_air_steering)
+REGISTER_STAT(BUGRIGS_ANGLE_SMOOTHING, int, g_bugrigs_angle_smoothing)
+REGISTER_STAT(BUGRIGS_CAR_JUMPING, int, g_bugrigs_planar_movement_car_jumping)
+REGISTER_STAT(BUGRIGS_FRICTION_AIR, float, g_bugrigs_friction_air)
+REGISTER_STAT(BUGRIGS_FRICTION_BRAKE, float, g_bugrigs_friction_brake)
+REGISTER_STAT(BUGRIGS_FRICTION_FLOOR, float, g_bugrigs_friction_floor)
+REGISTER_STAT(BUGRIGS_PLANAR_MOVEMENT, int, g_bugrigs_planar_movement)
+REGISTER_STAT(BUGRIGS_REVERSE_SPEEDING, int, g_bugrigs_reverse_speeding)
+REGISTER_STAT(BUGRIGS_REVERSE_SPINNING, int, g_bugrigs_reverse_spinning)
+REGISTER_STAT(BUGRIGS_REVERSE_STOPPING, int, g_bugrigs_reverse_stopping)
+REGISTER_STAT(BUGRIGS_SPEED_POW, float, g_bugrigs_speed_pow)
+REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref)
+REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer)
+
+REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, cvar("sv_gameplayfix_downtracesupportsongroundflag"))
+REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, cvar("sv_gameplayfix_easierwaterjump"))
+REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, cvar("sv_gameplayfix_stepdown"))
+REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, cvar("sv_gameplayfix_stepmultipletimes"))
+REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, cvar("sv_gameplayfix_unstickplayers"))
+REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
+
+REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
+REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))
+
+REGISTER_STAT(MOVEVARS_FRICTION, float)
+REGISTER_STAT(MOVEVARS_FRICTION_SLICK, float, autocvar_sv_friction_slick)
+REGISTER_STAT(MOVEVARS_FRICTION_ONLAND, float, autocvar_sv_friction_on_land)
+
+REGISTER_STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, int, autocvar_sv_jumpspeedcap_max_disable_on_ramps)
+REGISTER_STAT(MOVEVARS_TRACK_CANJUMP, int)
+/** cvar loopback */
+REGISTER_STAT(MOVEVARS_CL_TRACK_CANJUMP, int)
+
+#ifdef SVQC
+int g_dodging;
+float autocvar_sv_dodging_delay;
+float autocvar_sv_dodging_wall_distance_threshold;
+bool autocvar_sv_dodging_frozen;
+bool autocvar_sv_dodging_frozen_doubletap;
+float autocvar_sv_dodging_height_threshold;
+float autocvar_sv_dodging_horiz_speed;
+float autocvar_sv_dodging_horiz_speed_frozen;
+float autocvar_sv_dodging_ramp_time;
+float autocvar_sv_dodging_up_speed;
+bool autocvar_sv_dodging_wall_dodging;
+#endif
+
+REGISTER_STAT(DODGING, int, g_dodging)
+REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay)
+REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold)
+REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
+REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap)
+REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold)
+REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed)
+REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen)
+REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time)
+/** cvar loopback */
+REGISTER_STAT(DODGING_TIMEOUT, float)
+REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed)
+REGISTER_STAT(DODGING_WALL, int, autocvar_sv_dodging_wall_dodging)
+
+REGISTER_STAT(JETPACK_ACCEL_SIDE, float, autocvar_g_jetpack_acceleration_side)
+REGISTER_STAT(JETPACK_ACCEL_UP, float, autocvar_g_jetpack_acceleration_up)
+REGISTER_STAT(JETPACK_ANTIGRAVITY, float, autocvar_g_jetpack_antigravity)
+REGISTER_STAT(JETPACK_FUEL, float, autocvar_g_jetpack_fuel)
+REGISTER_STAT(JETPACK_MAXSPEED_SIDE, float, autocvar_g_jetpack_maxspeed_side)
+REGISTER_STAT(JETPACK_MAXSPEED_UP, float, autocvar_g_jetpack_maxspeed_up)
-/* The following stats change depending on the gamemode, so can share the same ID */
-// IDs 100 to 104 reserved for gamemodes
+REGISTER_STAT(MOVEVARS_HIGHSPEED, float, autocvar_g_movement_highspeed)
-// freeze tag, clan arena, jailbreak
-const int STAT_REDALIVE = 100;
-const int STAT_BLUEALIVE = 101;
-const int STAT_YELLOWALIVE = 102;
-const int STAT_PINKALIVE = 103;
+// freeze tag, clan arena
+REGISTER_STAT(REDALIVE, int)
+REGISTER_STAT(BLUEALIVE, int)
+REGISTER_STAT(YELLOWALIVE, int)
+REGISTER_STAT(PINKALIVE, int)
// domination
-const int STAT_DOM_TOTAL_PPS = 100;
-const int STAT_DOM_PPS_RED = 101;
-const int STAT_DOM_PPS_BLUE = 102;
-const int STAT_DOM_PPS_YELLOW = 103;
-const int STAT_DOM_PPS_PINK = 104;
+REGISTER_STAT(DOM_TOTAL_PPS, float)
+REGISTER_STAT(DOM_PPS_RED, float)
+REGISTER_STAT(DOM_PPS_BLUE, float)
+REGISTER_STAT(DOM_PPS_YELLOW, float)
+REGISTER_STAT(DOM_PPS_PINK, float)
-// vip
-const int STAT_VIP = 100;
-const int STAT_VIP_RED = 101;
-const int STAT_VIP_BLUE = 102;
-const int STAT_VIP_YELLOW = 103;
-const int STAT_VIP_PINK = 104;
+REGISTER_STAT(TELEPORT_MAXSPEED, float, autocvar_g_teleport_maxspeed)
+REGISTER_STAT(TELEPORT_TELEFRAG_AVOID, int, autocvar_g_telefrags_avoid)
-// key hunt
-const int STAT_KH_REDKEY_TEAM = 100;
-const int STAT_KH_BLUEKEY_TEAM = 101;
-const int STAT_KH_YELLOWKEY_TEAM = 102;
-const int STAT_KH_PINKKEY_TEAM = 103;
+#ifdef SVQC
+#include "movetypes/movetypes.qh"
+#endif
+
+REGISTER_STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL_PENALTY, float)
+REGISTER_STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, float)
+REGISTER_STAT(MOVEVARS_AIRSTRAFEACCEL_QW, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL_POWER, float)
+noref bool autocvar_sv_gameplayfix_nogravityonground;
+REGISTER_STAT(MOVEFLAGS, int, MOVEFLAG_VALID
+ | (autocvar_sv_gameplayfix_q2airaccelerate ? MOVEFLAG_Q2AIRACCELERATE : 0)
+ | (autocvar_sv_gameplayfix_nogravityonground ? MOVEFLAG_NOGRAVITYONGROUND : 0)
+ | (autocvar_sv_gameplayfix_gravityunaffectedbyticrate ? MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE : 0))
-/* Gamemode-specific stats end here */
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_ACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, float)
-const int STAT_PL_VIEW_OFS1 = 105;
-const int STAT_PL_VIEW_OFS2 = 106;
-const int STAT_PL_VIEW_OFS3 = 107;
-const int STAT_PL_MIN1 = 108;
-const int STAT_PL_MIN2 = 109;
-const int STAT_PL_MIN3 = 110;
-const int STAT_PL_MAX1 = 111;
-const int STAT_PL_MAX2 = 112;
-const int STAT_PL_MAX3 = 113;
-const int STAT_PL_CROUCH_MIN1 = 114;
-const int STAT_PL_CROUCH_MIN2 = 115;
-const int STAT_PL_CROUCH_MIN3 = 116;
-const int STAT_PL_CROUCH_MAX1 = 117;
-const int STAT_PL_CROUCH_MAX2 = 118;
-const int STAT_PL_CROUCH_MAX3 = 119;
-const int STAT_PL_CROUCH_VIEW_OFS1 = 117;
-const int STAT_PL_CROUCH_VIEW_OFS2 = 118;
-const int STAT_PL_CROUCH_VIEW_OFS3 = 119;
-const int STAT_WEAPONSINMAP = 120;
-const int STAT_WEAPONSINMAP2 = 121;
-const int STAT_WEAPONSINMAP3 = 122;
-const int STAT_BUFF_TIME = 123;
-const int STAT_CTF_FLAGSTATUS = 124;
-// 125 empty?
-// 126 empty?
-// 127 empty?
-// 128 empty?
-// 129 empty?
-// 130 empty?
-// 131 empty?
-// 132 empty?
-// 133 empty?
-// 134 empty?
-// 135 empty?
-// 136 empty?
-// 137 empty?
-// 138 empty?
-// 139 empty?
-// 140 reserved
-// 141 reserved
-// 142 reserved
-// 143 reserved
-// 144 reserved
-// 145 reserved
-// 146 reserved
-// 147 reserved
-// 148 reserved
-// 149 reserved
-// 150 reserved
-// 151 reserved
-// 152 reserved
-// 153 reserved
-// 154 reserved
-// 155 reserved
-// 156 empty?
-// 157 empty?
-// 158 empty?
-// 159 empty?
-// 160 empty?
-// 161 empty?
-// 162 empty?
-// 162 empty?
-// 163 empty?
-// 164 empty?
-// 165 empty?
-const int STAT_MULTIJUMP_DODGING = 166;
-const int STAT_MULTIJUMP_MAXSPEED = 167;
-const int STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND = 168;
-const int STAT_BUGRIGS_REVERSE_STOPPING = 169;
-const int STAT_BUGRIGS_REVERSE_SPINNING = 170;
-const int STAT_BUGRIGS_CAR_JUMPING = 171;
-const int STAT_BUGRIGS_FRICTION_AIR = 172;
-const int STAT_BUGRIGS_STEER = 173;
-const int STAT_BUGRIGS_SPEED_POW = 174;
-const int STAT_BUGRIGS_SPEED_REF = 175;
-const int STAT_BUGRIGS_ACCEL = 176;
-const int STAT_BUGRIGS_FRICTION_BRAKE = 177;
-const int STAT_BUGRIGS_AIR_STEERING = 178;
-const int STAT_BUGRIGS_FRICTION_FLOOR = 179;
-const int STAT_BUGRIGS_REVERSE_SPEEDING = 180;
-const int STAT_BUGRIGS_PLANAR_MOVEMENT = 181;
-const int STAT_BUGRIGS_ANGLE_SMOOTHING = 182;
-const int STAT_BUGRIGS = 183;
-const int STAT_GAMEPLAYFIX_STEPDOWN = 184;
-const int STAT_MOVEVARS_JUMPSTEP = 185;
-const int STAT_NOSTEP = 186;
-const int STAT_GAMEPLAYFIX_UNSTICKPLAYERS = 187;
-const int STAT_GAMEPLAYFIX_STEPMULTIPLETIMES = 188;
-const int STAT_GAMEPLAYFIX_DOWNTRACEONGROUND = 189;
-const int STAT_GAMEPLAYFIX_EASIERWATERJUMP = 190;
-const int STAT_MOVEVARS_FRICTION_SLICK = 191;
-const int STAT_MOVEVARS_FRICTION_ONLAND = 192;
-const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS = 193;
-const int STAT_MOVEVARS_TRACK_CANJUMP = 194;
-// 195 empty?
-const int STAT_DOUBLEJUMP = 196;
-const int STAT_MOVEVARS_CL_TRACK_CANJUMP = 197;
-const int STAT_MULTIJUMP_ADD = 198;
-const int STAT_MULTIJUMP_SPEED = 199;
-const int STAT_MULTIJUMP = 200;
-const int STAT_DODGING_TIMEOUT = 201;
-const int STAT_DODGING_WALL = 202;
-const int STAT_DODGING_UP_SPEED = 203;
-const int STAT_DODGING_RAMP_TIME = 204;
-const int STAT_DODGING_HEIGHT_THRESHOLD = 205;
-const int STAT_DODGING_DISTANCE_THRESHOLD = 206;
-const int STAT_DODGING_HORIZ_SPEED = 207;
-const int STAT_DODGING_DELAY = 208;
-const int STAT_DODGING_FROZEN_NO_DOUBLETAP = 209;
-const int STAT_DODGING_HORIZ_SPEED_FROZEN = 210;
-const int STAT_DODGING = 211;
-const int STAT_DODGING_FROZEN = 212;
-const int STAT_JETPACK_MAXSPEED_UP = 213;
-const int STAT_JETPACK_MAXSPEED_SIDE = 214;
-const int STAT_JETPACK_FUEL = 215;
-const int STAT_JETPACK_ANTIGRAVITY = 216;
-const int STAT_JETPACK_ACCEL_SIDE = 217;
-const int STAT_JETPACK_ACCEL_UP = 218;
-const int STAT_MOVEVARS_HIGHSPEED = 219;
-const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR = 220;
-const int STAT_MOVEVARS_AIRCONTROL_PENALTY = 221;
-const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
-const int STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
-const int STAT_MOVEVARS_AIRCONTROL_POWER = 224;
-const int STAT_MOVEFLAGS = 225;
-const int STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL = 226;
-const int STAT_MOVEVARS_WARSOWBUNNY_ACCEL = 227;
-const int STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED = 228;
-const int STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL = 229;
-const int STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO = 230;
-const int STAT_MOVEVARS_AIRSTOPACCELERATE = 231;
-const int STAT_MOVEVARS_AIRSTRAFEACCELERATE = 232;
-const int STAT_MOVEVARS_MAXAIRSTRAFESPEED = 233;
-const int STAT_MOVEVARS_AIRCONTROL = 234;
-// -Wdouble-declaration
-// const int STAT_FRAGLIMIT = 235;
-// -Wdouble-declaration
-// const int STAT_TIMELIMIT = 236;
-const int STAT_MOVEVARS_WALLFRICTION = 237;
-const int STAT_MOVEVARS_FRICTION = 238;
-const int STAT_MOVEVARS_WATERFRICTION = 239;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_TICRATE = 240;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_TIMESCALE = 241;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_GRAVITY = 242;
-const int STAT_MOVEVARS_STOPSPEED = 243;
-const int STAT_MOVEVARS_MAXSPEED = 244;
-const int STAT_MOVEVARS_SPECTATORMAXSPEED = 245;
-const int STAT_MOVEVARS_ACCELERATE = 246;
-const int STAT_MOVEVARS_AIRACCELERATE = 247;
-const int STAT_MOVEVARS_WATERACCELERATE = 248;
-const int STAT_MOVEVARS_ENTGRAVITY = 249;
-const int STAT_MOVEVARS_JUMPVELOCITY = 250;
-const int STAT_MOVEVARS_EDGEFRICTION = 251;
-const int STAT_MOVEVARS_MAXAIRSPEED = 252;
-const int STAT_MOVEVARS_STEPHEIGHT = 253;
-const int STAT_MOVEVARS_AIRACCEL_QW = 254;
-const int STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255;
+REGISTER_STAT(MOVEVARS_AIRSTOPACCELERATE, float)
+REGISTER_STAT(MOVEVARS_AIRSTRAFEACCELERATE, float)
+REGISTER_STAT(MOVEVARS_MAXAIRSTRAFESPEED, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL, float)
+REGISTER_STAT(FRAGLIMIT, float, autocvar_fraglimit)
+REGISTER_STAT(TIMELIMIT, float, autocvar_timelimit)
+#ifdef SVQC
+float autocvar_sv_wallfriction;
+#endif
+REGISTER_STAT(MOVEVARS_WALLFRICTION, int, autocvar_sv_wallfriction)
+REGISTER_STAT(MOVEVARS_TICRATE, float, autocvar_sys_ticrate)
+REGISTER_STAT(MOVEVARS_TIMESCALE, float, autocvar_slowmo)
+REGISTER_STAT(MOVEVARS_GRAVITY, float, autocvar_sv_gravity)
+REGISTER_STAT(MOVEVARS_STOPSPEED, float)
+REGISTER_STAT(MOVEVARS_MAXSPEED, float)
+REGISTER_STAT(MOVEVARS_ACCELERATE, float)
+REGISTER_STAT(MOVEVARS_AIRACCELERATE, float)
+.float gravity;
+// FIXME: Was 0 on server, 1 on client. Still want that?
+REGISTER_STAT(MOVEVARS_ENTGRAVITY, float, (this.gravity) ? this.gravity : 1)
+REGISTER_STAT(MOVEVARS_JUMPVELOCITY, float)
+REGISTER_STAT(MOVEVARS_MAXAIRSPEED, float)
+REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
+REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
+REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float)
#endif
}
}
-void func_breakable_reset()
-{SELFPARAM();
- self.team = self.team_saved;
+void func_breakable_reset(entity this)
+{
+ this.team = this.team_saved;
func_breakable_look_restore();
- if(self.spawnflags & 1)
+ if(this.spawnflags & 1)
func_breakable_behave_destroyed();
else
func_breakable_behave_restore();
- CSQCMODEL_AUTOUPDATE(self);
+ CSQCMODEL_AUTOUPDATE(this);
}
// destructible walls that can be used to trigger target_objective_decrease
spawnfunc(func_breakable)
{
float n, i;
- if(!self.health)
- self.health = 100;
- self.max_health = self.health;
+ if(!this.health)
+ this.health = 100;
+ this.max_health = this.health;
// yes, I know, MOVETYPE_NONE is not available here, not that one would want it here anyway
- if(!self.debrismovetype) self.debrismovetype = MOVETYPE_BOUNCE;
- if(!self.debrissolid) self.debrissolid = SOLID_NOT;
- if(self.debrisvelocity == '0 0 0') self.debrisvelocity = '0 0 140';
- if(self.debrisvelocityjitter == '0 0 0') self.debrisvelocityjitter = '70 70 70';
- if(self.debrisavelocityjitter == '0 0 0') self.debrisavelocityjitter = '600 600 600';
- if(!self.debristime) self.debristime = 3.5;
- if(!self.debristimejitter) self.debristime = 2.5;
-
- if(self.mdl != "")
- self.cnt = _particleeffectnum(self.mdl);
- if(self.count == 0)
- self.count = 1;
-
- if(self.message == "")
- self.message = "got too close to an explosion";
- if(self.message2 == "")
- self.message2 = "was pushed into an explosion by";
- if(!self.dmg_radius)
- self.dmg_radius = 150;
- if(!self.dmg_force)
- self.dmg_force = 200;
-
- self.mdl = self.model;
+ if(!this.debrismovetype) this.debrismovetype = MOVETYPE_BOUNCE;
+ if(!this.debrissolid) this.debrissolid = SOLID_NOT;
+ if(this.debrisvelocity == '0 0 0') this.debrisvelocity = '0 0 140';
+ if(this.debrisvelocityjitter == '0 0 0') this.debrisvelocityjitter = '70 70 70';
+ if(this.debrisavelocityjitter == '0 0 0') this.debrisavelocityjitter = '600 600 600';
+ if(!this.debristime) this.debristime = 3.5;
+ if(!this.debristimejitter) this.debristime = 2.5;
+
+ if(this.mdl != "")
+ this.cnt = _particleeffectnum(this.mdl);
+ if(this.count == 0)
+ this.count = 1;
+
+ if(this.message == "")
+ this.message = "got too close to an explosion";
+ if(this.message2 == "")
+ this.message2 = "was pushed into an explosion by";
+ if(!this.dmg_radius)
+ this.dmg_radius = 150;
+ if(!this.dmg_force)
+ this.dmg_force = 200;
+
+ this.mdl = this.model;
SetBrushEntityModel();
- if(self.spawnflags & 4)
- self.use = func_breakable_destroy;
+ if(this.spawnflags & 4)
+ this.use = func_breakable_destroy;
else
- self.use = func_breakable_restore;
+ this.use = func_breakable_restore;
- if(self.spawnflags & 4)
+ if(this.spawnflags & 4)
{
- self.takedamage = DAMAGE_NO;
- self.event_damage = func_null;
- self.bot_attack = false;
+ this.takedamage = DAMAGE_NO;
+ this.event_damage = func_null;
+ this.bot_attack = false;
}
// precache all the models
- if (self.mdl_dead)
- precache_model(self.mdl_dead);
- n = tokenize_console(self.debris);
+ if (this.mdl_dead)
+ precache_model(this.mdl_dead);
+ n = tokenize_console(this.debris);
for(i = 0; i < n; ++i)
precache_model(argv(i));
- if(self.noise)
- precache_sound(self.noise);
- if(self.noise1)
- precache_sound(self.noise1);
+ if(this.noise)
+ precache_sound(this.noise);
+ if(this.noise1)
+ precache_sound(this.noise1);
- self.team_saved = self.team;
- self.dropped_origin = self.origin;
+ this.team_saved = this.team;
+ this.dropped_origin = this.origin;
- self.reset = func_breakable_reset;
- func_breakable_reset();
+ this.reset = func_breakable_reset;
+ this.reset(this);
- self.init_for_player_needed = 1;
- self.init_for_player = func_breakable_init_for_player;
+ this.init_for_player_needed = 1;
+ this.init_for_player = func_breakable_init_for_player;
- CSQCMODEL_AUTOINIT(self);
+ CSQCMODEL_AUTOINIT(this);
}
// for use in maps with a "model" key set
self.SendFlags |= 2;
}
-void conveyor_reset()
-{SELFPARAM();
- self.state = (self.spawnflags & 1);
+void conveyor_reset(entity this)
+{
+ this.state = (this.spawnflags & 1);
- self.SendFlags |= 2;
+ this.SendFlags |= 2;
}
bool conveyor_send(entity this, entity to, int sf)
void conveyor_init()
{SELFPARAM();
- if (!self.speed)
- self.speed = 200;
- self.movedir = self.movedir * self.speed;
- self.think = conveyor_think;
- self.nextthink = time;
+ if (!this.speed) this.speed = 200;
+ this.movedir *= this.speed;
+ this.think = conveyor_think;
+ this.nextthink = time;
IFTARGETED
{
- self.use = conveyor_use;
- self.reset = conveyor_reset;
- conveyor_reset();
+ this.use = conveyor_use;
+ this.reset = conveyor_reset;
+ this.reset(this);
}
else
- self.state = 1;
+ this.state = 1;
- FixSize(self);
+ FixSize(this);
- Net_LinkEntity(self, 0, false, conveyor_send);
+ Net_LinkEntity(this, 0, false, conveyor_send);
- self.SendFlags |= 1;
+ this.SendFlags |= 1;
}
spawnfunc(trigger_conveyor)
#endif
}
-void door_reset()
-{SELFPARAM();
- SUB_SETORIGIN(self, self.pos1);
- self.SUB_VELOCITY = '0 0 0';
- self.state = STATE_BOTTOM;
- self.SUB_THINK = func_null;
- self.SUB_NEXTTHINK = 0;
+void door_reset(entity this)
+{
+ SUB_SETORIGIN(this, this.pos1);
+ this.SUB_VELOCITY = '0 0 0';
+ this.state = STATE_BOTTOM;
+ this.SUB_THINK = func_null;
+ this.SUB_NEXTTHINK = 0;
#ifdef SVQC
- self.SendFlags |= SF_TRIGGER_RESET;
+ this.SendFlags |= SF_TRIGGER_RESET;
#endif
}
void door_draw(entity this)
{
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(this);
trigger_draw_generic(this);
}
if(sf & SF_TRIGGER_INIT)
{
- self.classname = strzone(ReadString());
- self.spawnflags = ReadByte();
+ this.classname = strzone(ReadString());
+ this.spawnflags = ReadByte();
- self.mdl = strzone(ReadString());
- _setmodel(self, self.mdl);
+ this.mdl = strzone(ReadString());
+ _setmodel(this, this.mdl);
trigger_common_read(true);
- self.pos1_x = ReadCoord();
- self.pos1_y = ReadCoord();
- self.pos1_z = ReadCoord();
- self.pos2_x = ReadCoord();
- self.pos2_y = ReadCoord();
- self.pos2_z = ReadCoord();
-
- self.size_x = ReadCoord();
- self.size_y = ReadCoord();
- self.size_z = ReadCoord();
-
- self.wait = ReadShort();
- self.speed = ReadShort();
- self.lip = ReadByte();
- self.state = ReadByte();
- self.SUB_LTIME = ReadCoord();
-
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- self.trigger_touch = door_touch;
- self.draw = door_draw;
- self.drawmask = MASK_NORMAL;
- self.use = door_use;
+ vector v;
+
+ v.x = ReadCoord();
+ v.y = ReadCoord();
+ v.z = ReadCoord();
+ this.pos1 = v;
+
+ v.x = ReadCoord();
+ v.y = ReadCoord();
+ v.z = ReadCoord();
+ this.pos2 = v;
+
+ v.x = ReadCoord();
+ v.y = ReadCoord();
+ v.z = ReadCoord();
+ this.size = v;
+
+ this.wait = ReadShort();
+ this.speed = ReadShort();
+ this.lip = ReadByte();
+ this.state = ReadByte();
+ this.SUB_LTIME = ReadCoord();
+
+ this.solid = SOLID_BSP;
+ this.movetype = MOVETYPE_PUSH;
+ this.trigger_touch = door_touch;
+ this.draw = door_draw;
+ this.drawmask = MASK_NORMAL;
+ this.use = door_use;
LinkDoors();
- if(self.spawnflags & DOOR_START_OPEN)
+ if(this.spawnflags & DOOR_START_OPEN)
door_init_startopen();
- self.move_time = time;
- self.move_origin = self.origin;
- self.move_movetype = MOVETYPE_PUSH;
- self.move_angles = self.angles;
- self.move_blocked = door_blocked;
+ this.move_time = time;
+ this.move_origin = this.origin;
+ this.move_movetype = MOVETYPE_PUSH;
+ this.move_angles = this.angles;
+ this.move_blocked = door_blocked;
}
if(sf & SF_TRIGGER_RESET)
{
- door_reset();
+ door_reset(this);
}
if(sf & SF_TRIGGER_UPDATE)
{
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
- self.move_origin = self.origin;
-
- self.pos1_x = ReadCoord();
- self.pos1_y = ReadCoord();
- self.pos1_z = ReadCoord();
- self.pos2_x = ReadCoord();
- self.pos2_y = ReadCoord();
- self.pos2_z = ReadCoord();
+ this.origin_x = ReadCoord();
+ this.origin_y = ReadCoord();
+ this.origin_z = ReadCoord();
+ setorigin(this, this.origin);
+ this.move_origin = this.origin;
+
+ this.pos1_x = ReadCoord();
+ this.pos1_y = ReadCoord();
+ this.pos1_z = ReadCoord();
+ this.pos2_x = ReadCoord();
+ this.pos2_y = ReadCoord();
+ this.pos2_z = ReadCoord();
}
return true;
}
FIXME: only one sound set available at the time being
*/
-void door_rotating_reset()
-{SELFPARAM();
- self.angles = self.pos1;
- self.avelocity = '0 0 0';
- self.state = STATE_BOTTOM;
- self.think = func_null;
- self.nextthink = 0;
+void door_rotating_reset(entity this)
+{
+ this.angles = this.pos1;
+ this.avelocity = '0 0 0';
+ this.state = STATE_BOTTOM;
+ this.think = func_null;
+ this.nextthink = 0;
}
void door_rotating_init_startopen()
}
}
-void secret_reset()
-{SELFPARAM();
- if (self.spawnflags&SECRET_YES_SHOOT)
+void secret_reset(entity this)
+{
+ if (this.spawnflags & SECRET_YES_SHOOT)
{
- self.health = 10000;
- self.takedamage = DAMAGE_YES;
+ this.health = 10000;
+ this.takedamage = DAMAGE_YES;
}
- setorigin(self, self.oldorigin);
- self.think = func_null;
- self.SUB_NEXTTHINK = 0;
+ setorigin(this, this.oldorigin);
+ this.think = func_null;
+ this.SUB_NEXTTHINK = 0;
}
/*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
spawnfunc(func_door_secret)
{
- /*if (!self.deathtype) // map makers can override this
- self.deathtype = " got in the way";*/
+ /*if (!this.deathtype) // map makers can override this
+ this.deathtype = " got in the way";*/
- if (!self.dmg)
- self.dmg = 2;
+ if (!this.dmg) this.dmg = 2;
// Magic formula...
- self.mangle = self.angles;
- self.angles = '0 0 0';
- self.classname = "door";
- if (!InitMovingBrushTrigger())
- return;
- self.effects |= EF_LOWPRECISION;
-
- if(self.noise == "")
- self.noise = "misc/talk.wav";
- precache_sound(self.noise);
-
- self.touch = secret_touch;
- self.blocked = secret_blocked;
- self.speed = 50;
- self.use = fd_secret_use;
+ this.mangle = this.angles;
+ this.angles = '0 0 0';
+ this.classname = "door";
+ if (!InitMovingBrushTrigger()) return;
+ this.effects |= EF_LOWPRECISION;
+
+ if (this.noise == "") this.noise = "misc/talk.wav";
+ precache_sound(this.noise);
+
+ this.touch = secret_touch;
+ this.blocked = secret_blocked;
+ this.speed = 50;
+ this.use = fd_secret_use;
IFTARGETED
{
}
else
- self.spawnflags |= SECRET_YES_SHOOT;
+ this.spawnflags |= SECRET_YES_SHOOT;
- if(self.spawnflags&SECRET_YES_SHOOT)
+ if (this.spawnflags & SECRET_YES_SHOOT)
{
- self.health = 10000;
- self.takedamage = DAMAGE_YES;
- self.event_damage = fd_secret_damage;
+ this.health = 10000;
+ this.takedamage = DAMAGE_YES;
+ this.event_damage = fd_secret_damage;
}
- self.oldorigin = self.origin;
- if (!self.wait)
- self.wait = 5; // 5 seconds before closing
+ this.oldorigin = this.origin;
+ if (!this.wait) this.wait = 5; // seconds before closing
- self.reset = secret_reset;
- secret_reset();
+ this.reset = secret_reset;
+ this.reset(this);
}
#endif
spawnfunc(func_plat)
{
- if (self.sounds == 0)
- self.sounds = 2;
+ if (this.sounds == 0) this.sounds = 2;
- if(self.spawnflags & 4)
- self.dmg = 10000;
+ if (this.spawnflags & 4) this.dmg = 10000;
- if(self.dmg && (self.message == ""))
- self.message = "was squished";
- if(self.dmg && (self.message2 == ""))
- self.message2 = "was squished by";
+ if (this.dmg && (this.message == "")) this.message = "was squished";
+ if (this.dmg && (this.message2 == "")) this.message2 = "was squished by";
- if (self.sounds == 1)
+ if (this.sounds == 1)
{
precache_sound ("plats/plat1.wav");
precache_sound ("plats/plat2.wav");
- self.noise = "plats/plat1.wav";
- self.noise1 = "plats/plat2.wav";
+ this.noise = "plats/plat1.wav";
+ this.noise1 = "plats/plat2.wav";
}
- if (self.sounds == 2)
+ if (this.sounds == 2)
{
precache_sound ("plats/medplat1.wav");
precache_sound ("plats/medplat2.wav");
- self.noise = "plats/medplat1.wav";
- self.noise1 = "plats/medplat2.wav";
+ this.noise = "plats/medplat1.wav";
+ this.noise1 = "plats/medplat2.wav";
}
- if (self.sound1)
+ if (this.sound1)
{
- precache_sound (self.sound1);
- self.noise = self.sound1;
+ precache_sound (this.sound1);
+ this.noise = this.sound1;
}
- if (self.sound2)
+ if (this.sound2)
{
- precache_sound (self.sound2);
- self.noise1 = self.sound2;
+ precache_sound (this.sound2);
+ this.noise1 = this.sound2;
}
- self.mangle = self.angles;
- self.angles = '0 0 0';
+ this.mangle = this.angles;
+ this.angles = '0 0 0';
- self.classname = "plat";
+ this.classname = "plat";
if (!InitMovingBrushTrigger())
return;
- self.effects |= EF_LOWPRECISION;
- setsize (self, self.mins , self.maxs);
+ this.effects |= EF_LOWPRECISION;
+ setsize (this, this.mins , this.maxs);
- self.blocked = plat_crush;
+ this.blocked = plat_crush;
- if (!self.speed)
- self.speed = 150;
- if (!self.lip)
- self.lip = 16;
- if (!self.height)
- self.height = self.size_z - self.lip;
+ if (!this.speed) this.speed = 150;
+ if (!this.lip) this.lip = 16;
+ if (!this.height) this.height = this.size.z - this.lip;
- self.pos1 = self.origin;
- self.pos2 = self.origin;
- self.pos2_z = self.origin_z - self.height;
+ this.pos1 = this.origin;
+ this.pos2 = this.origin;
+ this.pos2_z = this.origin.z - this.height;
- self.reset = plat_reset;
- plat_reset();
+ this.reset = plat_reset;
+ this.reset(this);
- InitializeEntity(self, plat_delayedinit, INITPRIO_FINDTARGET);
+ InitializeEntity(this, plat_delayedinit, INITPRIO_FINDTARGET);
}
#elif defined(CSQC)
void plat_draw(entity this)
{
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(this);
//Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
}
if(sf & SF_TRIGGER_INIT)
{
- self.platmovetype_start = ReadByte();
- self.platmovetype_turn = ReadByte();
- self.platmovetype_end = ReadByte();
- self.spawnflags = ReadByte();
+ this.platmovetype_start = ReadByte();
+ this.platmovetype_turn = ReadByte();
+ this.platmovetype_end = ReadByte();
+ this.spawnflags = ReadByte();
- self.model = strzone(ReadString());
- _setmodel(self, self.model);
+ this.model = strzone(ReadString());
+ _setmodel(this, this.model);
trigger_common_read(true);
- self.pos1_x = ReadCoord();
- self.pos1_y = ReadCoord();
- self.pos1_z = ReadCoord();
- self.pos2_x = ReadCoord();
- self.pos2_y = ReadCoord();
- self.pos2_z = ReadCoord();
+ this.pos1_x = ReadCoord();
+ this.pos1_y = ReadCoord();
+ this.pos1_z = ReadCoord();
+ this.pos2_x = ReadCoord();
+ this.pos2_y = ReadCoord();
+ this.pos2_z = ReadCoord();
- self.size_x = ReadCoord();
- self.size_y = ReadCoord();
- self.size_z = ReadCoord();
+ this.size_x = ReadCoord();
+ this.size_y = ReadCoord();
+ this.size_z = ReadCoord();
- self.mangle_x = ReadAngle();
- self.mangle_y = ReadAngle();
- self.mangle_z = ReadAngle();
+ this.mangle_x = ReadAngle();
+ this.mangle_y = ReadAngle();
+ this.mangle_z = ReadAngle();
- self.speed = ReadShort();
- self.height = ReadShort();
- self.lip = ReadByte();
- self.state = ReadByte();
+ this.speed = ReadShort();
+ this.height = ReadShort();
+ this.lip = ReadByte();
+ this.state = ReadByte();
- self.dmg = ReadShort();
+ this.dmg = ReadShort();
- self.classname = "plat";
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- self.drawmask = MASK_NORMAL;
- self.draw = plat_draw;
- self.use = plat_use;
- self.entremove = trigger_remove_generic;
+ this.classname = "plat";
+ this.solid = SOLID_BSP;
+ this.movetype = MOVETYPE_PUSH;
+ this.drawmask = MASK_NORMAL;
+ this.draw = plat_draw;
+ this.use = plat_use;
+ this.entremove = trigger_remove_generic;
- plat_reset(); // also called here
+ plat_reset(this); // also called here
- self.move_movetype = MOVETYPE_PUSH;
- self.move_origin = self.origin;
- self.move_angles = self.angles;
- self.move_time = time;
+ this.move_movetype = MOVETYPE_PUSH;
+ this.move_origin = this.origin;
+ this.move_angles = this.angles;
+ this.move_time = time;
plat_spawn_inside_trigger();
}
if(sf & SF_TRIGGER_RESET)
{
- plat_reset();
+ plat_reset(this);
- self.move_origin = self.origin;
- self.move_angles = self.angles;
- self.move_time = time;
+ this.move_origin = this.origin;
+ this.move_angles = this.angles;
+ this.move_time = time;
}
return true;
}
self.nextthink = time;
}
-void pointparticles_reset()
-{SELFPARAM();
- if(self.spawnflags & 1)
- self.state = 1;
+void pointparticles_reset(entity this)
+{
+ if(this.spawnflags & 1)
+ this.state = 1;
else
- self.state = 0;
+ this.state = 0;
}
spawnfunc(func_pointparticles)
{
- if(self.model != "")
- _setmodel(self, self.model);
- if(self.noise != "")
- precache_sound (self.noise);
+ if(this.model != "") _setmodel(this, this.model);
+ if(this.noise != "") precache_sound(this.noise);
- if(!self.bgmscriptsustain)
- self.bgmscriptsustain = 1;
- else if(self.bgmscriptsustain < 0)
- self.bgmscriptsustain = 0;
+ if(!this.bgmscriptsustain) this.bgmscriptsustain = 1;
+ else if(this.bgmscriptsustain < 0) this.bgmscriptsustain = 0;
- if(!self.atten)
- self.atten = ATTEN_NORM;
- else if(self.atten < 0)
- self.atten = 0;
- if(!self.volume)
- self.volume = 1;
- if(!self.count)
- self.count = 1;
- if(!self.impulse)
- self.impulse = 1;
+ if(!this.atten) this.atten = ATTEN_NORM;
+ else if(this.atten < 0) this.atten = 0;
+ if(!this.volume) this.volume = 1;
+ if(!this.count) this.count = 1;
+ if(!this.impulse) this.impulse = 1;
- if(!self.modelindex)
+ if(!this.modelindex)
{
- setorigin(self, self.origin + self.mins);
- setsize(self, '0 0 0', self.maxs - self.mins);
+ setorigin(this, this.origin + this.mins);
+ setsize(this, '0 0 0', this.maxs - this.mins);
}
- if(!self.cnt)
- self.cnt = _particleeffectnum(self.mdl);
+ if(!this.cnt) this.cnt = _particleeffectnum(this.mdl);
- Net_LinkEntity(self, (self.spawnflags & 4), 0, pointparticles_SendEntity);
+ Net_LinkEntity(this, (this.spawnflags & 4), 0, pointparticles_SendEntity);
IFTARGETED
{
- self.use = pointparticles_use;
- self.reset = pointparticles_reset;
- self.reset();
+ this.use = pointparticles_use;
+ this.reset = pointparticles_reset;
+ this.reset(this);
}
else
- self.state = 1;
- self.think = pointparticles_think;
- self.nextthink = time;
+ this.state = 1;
+ this.think = pointparticles_think;
+ this.nextthink = time;
}
spawnfunc(func_sparks)
void train_draw(entity this)
{
//Movetype_Physics_NoMatchServer();
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(this, autocvar_cl_projectiles_sloppy);
}
NET_HANDLE(ENT_CLIENT_TRAIN, bool isnew)
#if defined(CSQC)
- #include "../../buffs/all.qh"
#include "../../../lib/csqcmodel/interpolate.qh"
#include "../../../client/main.qh"
#include "../../../lib/csqcmodel/cl_model.qh"
misc_laser_aim();
}
-void laser_reset()
-{SELFPARAM();
- if(self.spawnflags & 1)
- self.state = 1;
+void laser_reset(entity this)
+{
+ if(this.spawnflags & 1)
+ this.state = 1;
else
- self.state = 0;
+ this.state = 0;
}
spawnfunc(misc_laser)
{
- if(self.mdl)
+ if(this.mdl)
{
- if(self.mdl == "none")
- self.cnt = -1;
+ if(this.mdl == "none")
+ this.cnt = -1;
else
{
- self.cnt = _particleeffectnum(self.mdl);
- if(self.cnt < 0)
- if(self.dmg)
- self.cnt = particleeffectnum(EFFECT_LASER_DEADLY);
+ this.cnt = _particleeffectnum(this.mdl);
+ if(this.cnt < 0 && this.dmg)
+ this.cnt = particleeffectnum(EFFECT_LASER_DEADLY);
}
}
- else if(!self.cnt)
+ else if(!this.cnt)
{
- if(self.dmg)
- self.cnt = particleeffectnum(EFFECT_LASER_DEADLY);
+ if(this.dmg)
+ this.cnt = particleeffectnum(EFFECT_LASER_DEADLY);
else
- self.cnt = -1;
+ this.cnt = -1;
}
- if(self.cnt < 0)
- self.cnt = -1;
+ if(this.cnt < 0)
+ this.cnt = -1;
- if(self.colormod == '0 0 0')
- if(!self.alpha)
- self.colormod = '1 0 0';
- if(self.message == "")
- self.message = "saw the light";
- if (self.message2 == "")
- self.message2 = "was pushed into a laser by";
- if(!self.scale)
- self.scale = 1;
- if(!self.modelscale)
- self.modelscale = 1;
- else if(self.modelscale < 0)
- self.modelscale = 0;
- self.think = misc_laser_think;
- self.nextthink = time;
- InitializeEntity(self, misc_laser_init, INITPRIO_FINDTARGET);
+ if(this.colormod == '0 0 0')
+ if(!this.alpha)
+ this.colormod = '1 0 0';
+ if(this.message == "") this.message = "saw the light";
+ if (this.message2 == "") this.message2 = "was pushed into a laser by";
+ if(!this.scale) this.scale = 1;
+ if(!this.modelscale) this.modelscale = 1;
+ else if(this.modelscale < 0) this.modelscale = 0;
+ this.think = misc_laser_think;
+ this.nextthink = time;
+ InitializeEntity(this, misc_laser_init, INITPRIO_FINDTARGET);
- self.mangle = self.angles;
+ this.mangle = this.angles;
- Net_LinkEntity(self, false, 0, laser_SendEntity);
+ Net_LinkEntity(this, false, 0, laser_SendEntity);
IFTARGETED
{
- self.reset = laser_reset;
- laser_reset();
- self.use = laser_use;
+ this.reset = laser_reset;
+ this.reset(this);
+ this.use = laser_use;
}
else
- self.state = 1;
+ this.state = 1;
}
#elif defined(CSQC)
{
if(!self.state)
return;
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(self);
if(self.count & 0x80)
{
if(self.count & 0x10)
NET_HANDLE(ENT_CLIENT_LASER, bool isnew)
{
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
// 30 bytes, or 13 bytes for just moving
int f = ReadByte();
return = true;
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
self.draw = Draw_Laser;
}
#endif
+REGISTER_NET_LINKED(ENT_CLIENT_TELEPORT_DEST)
+
#ifdef SVQC
+bool teleport_dest_send(entity this, entity to, float sf)
+{
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_TELEPORT_DEST);
+
+ WriteByte(MSG_ENTITY, self.cnt);
+ WriteCoord(MSG_ENTITY, self.speed);
+ WriteString(MSG_ENTITY, self.targetname);
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteAngle(MSG_ENTITY, self.mangle_x);
+ WriteAngle(MSG_ENTITY, self.mangle_y);
+ WriteAngle(MSG_ENTITY, self.mangle_z);
+
+ return true;
+}
+
+void teleport_dest_link()
+{SELFPARAM();
+ Net_LinkEntity(self, false, 0, teleport_dest_send);
+ //self.SendFlags |= 1; // update
+}
+
spawnfunc(info_teleport_destination)
{
self.classname = "info_teleport_destination";
}
else
objerror ("^3Teleport destination without a targetname");
+
+ teleport_dest_link();
}
spawnfunc(misc_teleporter_dest)
spawnfunc_info_teleport_destination(this);
}
+#elif defined(CSQC)
+
+void teleport_dest_remove()
+{SELFPARAM();
+ //if(self.classname)
+ //strunzone(self.classname);
+ //self.classname = string_null;
+
+ if(self.targetname)
+ strunzone(self.targetname);
+ self.targetname = string_null;
+}
+
+NET_HANDLE(ENT_CLIENT_TELEPORT_DEST, bool isnew)
+{
+ self.classname = "info_teleport_destination";
+ self.cnt = ReadByte();
+ self.speed = ReadCoord();
+ self.targetname = strzone(ReadString());
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+
+ self.mangle_x = ReadAngle();
+ self.mangle_y = ReadAngle();
+ self.mangle_z = ReadAngle();
+
+ return = true;
+
+ setorigin(self, self.origin);
+
+ self.drawmask = MASK_NORMAL;
+ self.entremove = teleport_dest_remove;
+}
+
#endif
.string sound1, sound2;
-void plat_reset()
-{SELFPARAM();
+void plat_reset(entity this)
+{
IFTARGETED
{
- setorigin (self, self.pos1);
- self.state = 4;
- self.use = plat_use;
+ setorigin (this, this.pos1);
+ this.state = 4;
+ this.use = plat_use;
}
else
{
- setorigin (self, self.pos2);
- self.state = 2;
- self.use = plat_trigger_use;
+ setorigin (this, this.pos2);
+ this.state = 2;
+ this.use = plat_trigger_use;
}
#ifdef SVQC
- self.SendFlags |= SF_TRIGGER_RESET;
+ this.SendFlags |= SF_TRIGGER_RESET;
#endif
}
#elif defined(CSQC)
- void _Movetype_LinkEdict(float touch_triggers);
+ void _Movetype_LinkEdict(entity this, float touch_triggers);
#define SUB_ANGLES(s) (s).move_angles
#define SUB_VELOCITY move_velocity
void SUB_SETORIGIN(entity s, vector v)
{SELFPARAM();
s.move_origin = v;
- WITH(entity, self, s, _Movetype_LinkEdict(true));
+ _Movetype_LinkEdict(s, true);
}
#endif
-void SUB_Remove();
void SUB_SetFade (entity ent, float when, float fading_time);
void SUB_VanishOrRemove (entity ent);
WriteByte(to, self.lifetime);
WriteString(to, self.noise);
}
-void target_music_reset()
-{SELFPARAM();
- if(self.targetname == "")
- target_music_sendto(MSG_ALL, 1);
+void target_music_reset(entity this)
+{
+ if (this.targetname == "") target_music_sendto(MSG_ALL, 1);
}
void target_music_kill()
{
}
return 1;
}
-void trigger_music_reset()
-{SELFPARAM();
- self.cnt = !(self.spawnflags & 1);
- self.SendFlags |= 0x80;
+void trigger_music_reset(entity this)
+{
+ this.cnt = !(this.spawnflags & 1);
+ this.SendFlags |= 0x80;
}
void trigger_music_use()
{SELFPARAM();
}
spawnfunc(trigger_music)
{
- if(self.model != "")
- _setmodel(self, self.model);
- if(!self.volume)
- self.volume = 1;
- if(!self.modelindex)
+ if(this.model != "") _setmodel(this, this.model);
+ if(!this.volume) this.volume = 1;
+ if(!this.modelindex)
{
- setorigin(self, self.origin + self.mins);
- setsize(self, '0 0 0', self.maxs - self.mins);
+ setorigin(this, this.origin + this.mins);
+ setsize(this, '0 0 0', this.maxs - this.mins);
}
- trigger_music_reset();
+ trigger_music_reset(this);
- self.use = trigger_music_use;
- self.reset = trigger_music_reset;
+ this.use = trigger_music_use;
+ this.reset = trigger_music_reset;
- Net_LinkEntity(self, false, 0, trigger_music_SendEntity);
+ Net_LinkEntity(this, false, 0, trigger_music_SendEntity);
}
#elif defined(CSQC)
+entity TargetMusic_list;
+STATIC_INIT(TargetMusic_list)
+{
+ TargetMusic_list = LL_NEW();
+}
+
void TargetMusic_Advance()
{
// run AFTER all the thinks!
- entity best, e;
- float vol, vol0;
- best = music_default;
- if(music_target && time < music_target.lifetime)
- best = music_target;
- if(music_trigger)
- best = music_trigger;
- for(e = world; (e = findfloat(e, enttype, NET_ENT_CLIENT_TRIGGER_MUSIC.m_id)); ) if(e.noise)
- {
- vol0 = e.lastvol;
- if(getsoundtime(e, CH_BGM_SINGLE) < 0)
- {
- vol0 = -1;
- }
- if(e == best)
+ entity best = music_default;
+ if (music_target && time < music_target.lifetime) best = music_target;
+ if (music_trigger) best = music_trigger;
+ LL_EACH(TargetMusic_list, it.noise, LAMBDA(
+ const float vol0 = (getsoundtime(it, CH_BGM_SINGLE) >= 0) ? it.lastvol : -1;
+ if (it == best)
{
// increase volume
- if(e.fade_time > 0)
- e.state = bound(0, e.state + frametime / e.fade_time, 1);
- else
- e.state = 1;
+ it.state = (it.fade_time > 0) ? bound(0, it.state + frametime / it.fade_time, 1) : 1;
}
else
{
// decrease volume
- if(e.fade_rate > 0)
- e.state = bound(0, e.state - frametime / e.fade_rate, 1);
- else
- e.state = 0;
+ it.state = (it.fade_rate > 0) ? bound(0, it.state - frametime / it.fade_rate, 1) : 0;
}
- vol = e.state * e.volume * autocvar_bgmvolume;
- if(vol != vol0)
+ const float vol = it.state * it.volume * autocvar_bgmvolume;
+ if (vol != vol0)
{
if(vol0 < 0)
- _sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
+ _sound(it, CH_BGM_SINGLE, it.noise, vol, ATTEN_NONE); // restart
else
- _sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
- e.lastvol = vol;
+ _sound(it, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+ it.lastvol = vol;
}
- }
+ ));
music_trigger = world;
-
- if(best)
- bgmtime = getsoundtime(best, CH_BGM_SINGLE);
- else
- bgmtime = gettime(GETTIME_CDTRACK);
+ bgmtime = (best) ? getsoundtime(best, CH_BGM_SINGLE) : gettime(GETTIME_CDTRACK);
}
NET_HANDLE(TE_CSQC_TARGET_MUSIC, bool isNew)
void Net_TargetMusic()
{
- int id = ReadShort();
- float vol = ReadByte() / 255.0;
- float fai = ReadByte() / 16.0;
- float fao = ReadByte() / 16.0;
- float tim = ReadByte();
- string noi = ReadString();
+ const int id = ReadShort();
+ const float vol = ReadByte() / 255.0;
+ const float fai = ReadByte() / 16.0;
+ const float fao = ReadByte() / 16.0;
+ const float tim = ReadByte();
+ const string noi = ReadString();
- entity e;
- for(e = world; (e = findfloat(e, enttype, NET_ENT_CLIENT_TRIGGER_MUSIC.m_id)); )
- {
- if(e.count == id)
- break;
- }
- if(!e)
+ entity e = NULL;
+ LL_EACH(TargetMusic_list, it.count == id, LAMBDA(e = it; break));
+ if (!e)
{
- e = spawn();
- e.enttype = NET_ENT_CLIENT_TRIGGER_MUSIC.m_id;
+ LL_PUSH(TargetMusic_list, e = new(TargetMusic));
+ make_pure(e);
e.count = id;
}
if(e.noise != noi)
sound(self, CH_TRIGGER_SINGLE, SND_Null, VOL_BASE * self.volume, self.atten);
self.use = target_speaker_use_on;
}
-void target_speaker_reset()
-{SELFPARAM();
- if(self.spawnflags & 1) // LOOPED_ON
+void target_speaker_reset(entity this)
+{
+ if(this.spawnflags & 1) // LOOPED_ON
{
- if(self.use == target_speaker_use_on)
+ if(this.use == target_speaker_use_on)
target_speaker_use_on();
}
- else if(self.spawnflags & 2)
+ else if(this.spawnflags & 2)
{
- if(self.use == target_speaker_use_off)
+ if(this.use == target_speaker_use_off)
target_speaker_use_off();
}
}
#include "../../server/anticheat.qh"
#endif
-#ifdef SVQC
-
float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
{
- if (IS_PLAYER(player) && player.health >= 1)
+ if (IS_PLAYER(player) && !PHYS_DEAD(player))
{
TDEATHLOOP(org)
{
+ #ifdef SVQC
if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+ #endif
if(IS_PLAYER(head))
- if(head.health >= 1)
+ if(!PHYS_DEAD(head))
return 1;
}
}
return 0;
}
+#ifdef SVQC
+
+void trigger_teleport_link(entity this);
+
void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
{
TDEATHLOOP(player.origin)
tdeath(e, e, e, '0 0 0', '0 0 0');
}
+#endif
+
void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
{SELFPARAM();
entity telefragger;
makevectors (to_angles);
+#ifdef SVQC
if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
{
if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
self.pushltime = time + 0.2;
}
}
+#endif
// Relocate the player
// assuming to allows PL_MIN to PL_MAX box and some more
+#ifdef SVQC
from = player.origin;
setorigin (player, to);
player.oldorigin = to; // don't undo the teleport by unsticking
makevectors(player.angles);
Reset_ArcBeam(player, v_forward);
UpdateCSQCProjectileAfterTeleport(player);
+#elif defined(CSQC)
+ from = player.move_origin;
+ player.move_origin = to;
+ player.move_angles = to_angles;
+ player.move_velocity = to_velocity;
+ player.move_flags &= ~FL_ONGROUND;
+ player.iflags |= IFLAG_TELEPORTED | IFLAG_V_ANGLE | IFLAG_ANGLES;
+ player.csqcmodel_teleported = 1;
+ player.v_angle = to_angles;
+ setproperty(VF_ANGLES, player.move_angles);
+ setproperty(VF_CL_VIEWANGLES, player.move_angles);
+
+ makevectors(player.move_angles);
+#endif
+#ifdef SVQC
if(IS_PLAYER(player))
{
if(tflags & TELEPORT_FLAG_TDEATH)
player.lastteleporttime = time;
}
+#endif
}
entity Simple_TeleportPlayer(entity teleporter, entity player)
for(e = world; (e = find(e, targetname, teleporter.target)); )
{
p = 1;
- if(autocvar_g_telefrags_avoid)
+ if(STAT(TELEPORT_TELEFRAG_AVOID, player))
{
+ #ifdef SVQC
locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+ #elif defined(CSQC)
+ locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+ #endif
if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
p = 0;
}
e = RandomSelection_chosen_ent;
}
+#ifdef SVQC
if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
+#elif defined(CSQC)
+ if(!e) { LOG_INFO("Teleport destination could not be found from CSQC.\n"); }
+#endif
makevectors(e.mangle);
+#ifdef SVQC
if(e.speed)
if(vlen(player.velocity) > e.speed)
player.velocity = normalize(player.velocity) * max(0, e.speed);
+#elif defined(CSQC)
+ if(e.speed)
+ if(vlen(player.move_velocity) > e.speed)
+ player.move_velocity = normalize(player.move_velocity) * max(0, e.speed);
+#endif
- if(autocvar_g_teleport_maxspeed)
- if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
- player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
+#ifdef SVQC
+ if(STAT(TELEPORT_MAXSPEED, player))
+ if(vlen(player.velocity) > STAT(TELEPORT_MAXSPEED, player))
+ player.velocity = normalize(player.velocity) * max(0, STAT(TELEPORT_MAXSPEED, player));
+#elif defined(CSQC)
+ if(STAT(TELEPORT_MAXSPEED, player))
+ if(vlen(player.move_velocity) > STAT(TELEPORT_MAXSPEED, player))
+ player.move_velocity = normalize(player.move_velocity) * max(0, STAT(TELEPORT_MAXSPEED, player));
+#endif
+#ifdef SVQC
locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+
TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+#elif defined(CSQC)
+ locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+
+ TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.move_velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+#endif
return e;
}
-void teleport_findtarget ()
-{SELFPARAM();
+void teleport_findtarget()
+{
+ int n = 0;
entity e;
- float n;
-
- n = 0;
for(e = world; (e = find(e, targetname, self.target)); )
{
++n;
+#ifdef SVQC
if(e.movetype == MOVETYPE_NONE)
waypoint_spawnforteleporter(self, e.origin, 0);
if(e.classname != "info_teleport_destination")
LOG_INFO("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
+#endif
}
if(n == 0)
}
// now enable touch
+#ifdef SVQC
self.touch = Teleport_Touch;
+
+ trigger_teleport_link(self);
+#elif defined(CSQC)
+ self.move_touch = Teleport_Touch;
+#endif
}
entity Teleport_Find(vector mi, vector ma)
return world;
}
+#ifdef SVQC
void WarpZone_PostTeleportPlayer_Callback(entity pl)
{SELFPARAM();
makevectors(pl.angles);
#ifndef T_TELEPORTERS_H
#define T_TELEPORTERS_H
+.entity pusher;
+const float TELEPORT_FLAG_SOUND = 1;
+const float TELEPORT_FLAG_PARTICLES = 2;
+const float TELEPORT_FLAG_TDEATH = 4;
+const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+#define TELEPORT_FLAGS_WARPZONE 0
+#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
+#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+
+// types for .teleportable entity setting
+const float TELEPORT_NORMAL = 1; // play sounds/effects etc
+const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+
+entity Simple_TeleportPlayer(entity teleporter, entity player);
+
+void Teleport_Touch ();
+
+void teleport_findtarget();
+
+entity Teleport_Find(vector mi, vector ma);
+
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
+
+entity teleport_first;
+.entity teleport_next;
+
#ifdef SVQC
void trigger_teleport_use();
if(head.takedamage) \
if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
-
float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
float tdeath_hit;
void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
void spawn_tdeath(vector v0, entity e, vector v);
-.entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
-
-#define TELEPORT_FLAGS_WARPZONE 0
-#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
-#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
-
-// types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
-
void Reset_ArcBeam(entity player, vector forward);
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
-
-entity Simple_TeleportPlayer(entity teleporter, entity player);
-
-void Teleport_Touch ();
-
-void teleport_findtarget ();
-
-entity Teleport_Find(vector mi, vector ma);
-
-entity teleport_first;
-.entity teleport_next;
void WarpZone_PostTeleportPlayer_Callback(entity pl);
#endif
+#ifdef CSQC
+#define TDEATHLOOP(o) \
+ entity head; \
+ vector deathmin; \
+ vector deathmax; \
+ float deathradius; \
+ deathmin = (o) + player.mins; \
+ deathmax = (o) + player.maxs; \
+ if(telefragmin != telefragmax) \
+ { \
+ if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
+ if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
+ if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
+ if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
+ if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
+ if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
+ } \
+ deathradius = max(vlen(deathmin), vlen(deathmax)); \
+ for(head = findradius(o, deathradius); head; head = head.chain) \
+ if(head != player) \
+ if(head.isplayermodel) \
+ if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
+#endif
+
#endif
}
}
-void counter_reset()
-{SELFPARAM();
- self.count = self.cnt;
- multi_reset();
+void counter_reset(entity this)
+{
+ this.count = this.cnt;
+ multi_reset(this);
}
/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
self.nextthink = self.wait;
}
-void delay_reset()
-{SELFPARAM();
- self.think = func_null;
- self.nextthink = 0;
+void delay_reset(entity this)
+{
+ this.think = func_null;
+ this.nextthink = 0;
}
spawnfunc(trigger_delay)
SUB_UseTargets();
}
-void _spawnfunc_trigger_flipflop();
spawnfunc(trigger_flipflop)
{
- if(self.spawnflags & 1)
- self.state = 1;
- self.use = flipflop_use;
- self.reset = _spawnfunc_trigger_flipflop; // perfect resetter
+ if(this.spawnflags & 1)
+ this.state = 1;
+ this.use = flipflop_use;
+ this.reset = spawnfunc_trigger_flipflop; // perfect resetter
}
-void _spawnfunc_trigger_flipflop() { SELFPARAM(); spawnfunc_trigger_flipflop(this); }
#endif
remove(self);
}
-void _spawnfunc_trigger_gamestart();
+void self_spawnfunc_trigger_gamestart();
spawnfunc(trigger_gamestart)
{
- self.use = gamestart_use;
- self.reset2 = _spawnfunc_trigger_gamestart;
+ this.use = gamestart_use;
+ this.reset2 = self_spawnfunc_trigger_gamestart;
- if(self.wait)
+ if(this.wait)
{
- self.think = self.use;
- self.nextthink = game_starttime + self.wait;
+ this.think = this.use;
+ this.nextthink = game_starttime + this.wait;
}
else
- InitializeEntity(self, gamestart_use, INITPRIO_FINDTARGET);
+ InitializeEntity(this, gamestart_use, INITPRIO_FINDTARGET);
}
-void _spawnfunc_trigger_gamestart() { SELFPARAM(); spawnfunc_trigger_gamestart(this); }
+void self_spawnfunc_trigger_gamestart() { SELFPARAM(); spawnfunc_trigger_gamestart(this); }
#endif
torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
- grav = PHYS_GRAVITY;
+ grav = PHYS_GRAVITY(other);
if(PHYS_ENTGRAVITY(other))
grav *= PHYS_ENTGRAVITY(other);
void trigger_push_touch()
{SELFPARAM();
- if (self.active == ACTIVE_NOT)
+ if (this.active == ACTIVE_NOT)
return;
#ifdef SVQC
return;
#endif
- if(self.team)
- if(((self.spawnflags & 4) == 0) == (DIFF_TEAM(self, other)))
+ if(this.team)
+ if(((this.spawnflags & 4) == 0) == (DIFF_TEAM(this, other)))
return;
EXACTTRIGGER_TOUCH;
- if(self.enemy)
+ if(this.enemy)
{
- other.velocity = trigger_push_calculatevelocity(other.origin, self.enemy, self.height);
+ other.velocity = trigger_push_calculatevelocity(other.origin, this.enemy, this.height);
other.move_velocity = other.velocity;
}
- else if(self.target)
+ else if(this.target)
{
entity e;
RandomSelection_Init();
- for(e = world; (e = find(e, targetname, self.target)); )
+ for(e = world; (e = find(e, targetname, this.target)); )
{
if(e.cnt)
RandomSelection_Add(e, 0, string_null, e.cnt, 1);
else
RandomSelection_Add(e, 0, string_null, 1, 1);
}
- other.velocity = trigger_push_calculatevelocity(other.origin, RandomSelection_chosen_ent, self.height);
+ other.velocity = trigger_push_calculatevelocity(other.origin, RandomSelection_chosen_ent, this.height);
other.move_velocity = other.velocity;
}
else
{
- other.velocity = self.movedir;
+ other.velocity = this.movedir;
other.move_velocity = other.velocity;
}
+#ifdef SVQC
UNSET_ONGROUND(other);
-
+#elif defined(CSQC)
other.move_flags &= ~FL_ONGROUND;
+#endif
#ifdef SVQC
if (IS_PLAYER(other))
// reset tracking of oldvelocity for impact damage (sudden velocity changes)
other.oldvelocity = other.velocity;
- if(self.pushltime < time) // prevent "snorring" sound when a player hits the jumppad more than once
+ if(this.pushltime < time) // prevent "snorring" sound when a player hits the jumppad more than once
{
// flash when activated
Send_Effect(EFFECT_JUMPPAD, other.origin, other.velocity, 1);
- _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
- self.pushltime = time + 0.2;
+ _sound (other, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+ this.pushltime = time + 0.2;
}
if(IS_REAL_CLIENT(other) || IS_BOT_CLIENT(other))
{
bool found = false;
for(int i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i)
- if(other.(jumppadsused[i]) == self)
+ if(other.(jumppadsused[i]) == this)
found = true;
if(!found)
{
- other.(jumppadsused[other.jumppadcount % NUM_JUMPPADSUSED]) = self;
+ other.(jumppadsused[other.jumppadcount % NUM_JUMPPADSUSED]) = this;
other.jumppadcount = other.jumppadcount + 1;
}
if(IS_REAL_CLIENT(other))
{
- if(self.message)
- centerprint(other, self.message);
+ if(this.message)
+ centerprint(other, this.message);
}
else
other.lastteleporttime = time;
other.istypefrag = 0;
}
- if(self.enemy.target)
+ if(this.enemy.target)
{
activator = other;
- WITH(entity, self, self.enemy, SUB_UseTargets());
+ WITH(entity, self, this.enemy, SUB_UseTargets());
}
if (other.flags & FL_PROJECTILE)
UpdateCSQCProjectile(other);
}
- if (self.spawnflags & PUSH_ONCE)
+ if (this.spawnflags & PUSH_ONCE)
{
- self.touch = func_null;
- self.think = SUB_Remove;
- self.nextthink = time;
+ this.touch = func_null;
+ this.think = SUB_Remove_self;
+ this.nextthink = time;
}
#endif
}
}
trigger_push_link();
- defer(0.1, trigger_push_updatelink);
+ defer(self, 0.1, trigger_push_updatelink);
#endif
}
#ifdef SVQC
-float trigger_push_send(entity to, float sf)
-{SELFPARAM();
+float trigger_push_send(entity this, entity to, float sf)
+{
WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
WriteByte(MSG_ENTITY, sf);
void trigger_push_link()
{
- //Net_LinkEntity(self, false, 0, trigger_push_send);
+ Net_LinkEntity(self, false, 0, trigger_push_send);
}
#endif
#ifdef SVQC
void target_push_link()
{SELFPARAM();
- //Net_LinkEntity(self, false, 0, target_push_send);
+ Net_LinkEntity(self, false, 0, target_push_send);
//self.SendFlags |= 1; // update
}
self.entremove = trigger_remove_generic;
self.solid = SOLID_TRIGGER;
- self.draw = trigger_draw_generic;
- self.trigger_touch = trigger_push_touch;
+ //self.draw = trigger_draw_generic;
+ self.move_touch = trigger_push_touch;
self.drawmask = MASK_NORMAL;
self.move_time = time;
trigger_push_findtarget();
SUB_UseTargets();
}
-void monoflop_reset()
-{SELFPARAM();
- self.state = 0;
- self.nextthink = 0;
+void monoflop_reset(entity this)
+{
+ this.state = 0;
+ this.nextthink = 0;
}
spawnfunc(trigger_monoflop)
}
}
-void multi_reset()
-{SELFPARAM();
- if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
- self.touch = multi_touch;
- if (self.max_health)
+void multi_reset(entity this)
+{
+ if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
+ this.touch = multi_touch;
+ if (this.max_health)
{
- self.health = self.max_health;
- self.takedamage = DAMAGE_YES;
- self.solid = SOLID_BBOX;
+ this.health = this.max_health;
+ this.takedamage = DAMAGE_YES;
+ this.solid = SOLID_BBOX;
}
- self.think = func_null;
- self.nextthink = 0;
- self.team = self.team_saved;
+ this.think = func_null;
+ this.nextthink = 0;
+ this.team = this.team_saved;
}
/*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
#ifdef SVQC
void multi_trigger();
-void multi_reset();
+void multi_reset(entity this);
spawnfunc(trigger_once);
#endif
#ifdef SVQC
-void _spawnfunc_trigger_relay();
/*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
This fixed size trigger cannot be touched, it can only be fired by other events. It can contain killtargets, targets, delays, and messages.
*/
spawnfunc(trigger_relay)
{
- self.use = SUB_UseTargets;
- self.reset = _spawnfunc_trigger_relay; // this spawnfunc resets fully
+ this.use = SUB_UseTargets;
+ this.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
}
-void _spawnfunc_trigger_relay() { SELFPARAM(); spawnfunc_trigger_relay(this); }
#endif
}
}
-void trigger_relay_teamcheck_reset()
-{SELFPARAM();
- self.team = self.team_saved;
+void trigger_relay_teamcheck_reset(entity this)
+{
+ this.team = this.team_saved;
}
spawnfunc(trigger_relay_teamcheck)
{
- self.team_saved = self.team;
- self.use = trigger_relay_teamcheck_use;
- self.reset = trigger_relay_teamcheck_reset;
+ this.team_saved = this.team;
+ this.use = trigger_relay_teamcheck_use;
+ this.reset = trigger_relay_teamcheck_reset;
}
#endif
float secrets_found;
-.float stat_secrets_total;
-.float stat_secrets_found;
+.float stat_secrets_total = _STAT(SECRETS_TOTAL);
+.float stat_secrets_found = _STAT(SECRETS_FOUND);
/**
* update secrets status.
self.classname = "trigger_swamp";
self.solid = SOLID_TRIGGER;
- self.draw = trigger_draw_generic;
- self.trigger_touch = swamp_touch;
+ self.move_touch = swamp_touch;
self.drawmask = MASK_NORMAL;
self.move_time = time;
self.entremove = trigger_remove_generic;
+REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_TELEPORT)
+
#ifdef SVQC
void trigger_teleport_use()
{SELFPARAM();
self.SendFlags |= SF_TRIGGER_UPDATE;
#endif
}
+#endif
void Teleport_Touch ()
{SELFPARAM();
- string s;
-
if (self.active != ACTIVE_ACTIVE)
return;
+#ifdef SVQC
if (!other.teleportable)
return;
if(IS_TURRET(other))
return;
+#endif
- if(other.deadflag != DEAD_NO)
+ if(PHYS_DEAD(other))
return;
if(self.team)
- if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+ if(((self.spawnflags & 4) == 0) == (DIFF_TEAM(this, other)))
return;
EXACTTRIGGER_TOUCH;
+#ifdef SVQC
if(IS_PLAYER(other))
RemoveGrapplingHook(other);
+#endif
- entity e = Simple_TeleportPlayer(self, other);
+ entity e;
+ e = Simple_TeleportPlayer(self, other);
+#ifdef SVQC
activator = other;
- s = self.target; self.target = string_null;
+ string s = self.target; self.target = string_null;
SUB_UseTargets();
if (!self.target) self.target = s;
WITH(entity, self, e, SUB_UseTargets());
+#endif
+}
+
+#ifdef SVQC
+float trigger_teleport_send(entity this, entity to, float sf)
+{
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_TELEPORT);
+ WriteByte(MSG_ENTITY, sf);
+
+ if(sf & 1)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+ WriteInt24_t(MSG_ENTITY, self.spawnflags);
+ WriteByte(MSG_ENTITY, self.active);
+ WriteCoord(MSG_ENTITY, self.speed);
+
+ trigger_common_write(true);
+ }
+
+ if(sf & 2)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+ WriteByte(MSG_ENTITY, self.active);
+ }
+
+ return true;
+}
+
+void trigger_teleport_link(entity this)
+{
+ Net_LinkEntity(this, false, 0, trigger_teleport_send);
}
spawnfunc(trigger_teleport)
self.teleport_next = teleport_first;
teleport_first = self;
}
+#elif defined(CSQC)
+NET_HANDLE(ENT_CLIENT_TRIGGER_TELEPORT, bool isnew)
+{
+ int sf = ReadByte();
+
+ if(sf & 1)
+ {
+ self.classname = "trigger_teleport";
+ int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+ self.spawnflags = ReadInt24_t();
+ self.active = ReadByte();
+ self.speed = ReadCoord();
+
+ trigger_common_read(true);
+
+ self.entremove = trigger_remove_generic;
+ self.solid = SOLID_TRIGGER;
+ //self.draw = trigger_draw_generic;
+ //self.move_touch = trigger_push_touch;
+ self.drawmask = MASK_NORMAL;
+ self.move_time = time;
+ teleport_findtarget();
+
+ self.teleport_next = teleport_first;
+ teleport_first = self;
+ }
+
+ if(sf & 2)
+ {
+ self.team = ReadByte();
+ self.active = ReadByte();
+ }
+ return true;
+}
+
#endif
if(withtarget)
{
+ if(self.target) { strunzone(self.target); }
self.target = strzone(ReadString());
+ if(self.target2) { strunzone(self.target2); }
self.target2 = strzone(ReadString());
+ if(self.target3) { strunzone(self.target3); }
self.target3 = strzone(ReadString());
+ if(self.target4) { strunzone(self.target4); }
self.target4 = strzone(ReadString());
+ if(self.targetname) { strunzone(self.targetname); }
self.targetname = strzone(ReadString());
+ if(self.killtarget) { strunzone(self.killtarget); }
self.killtarget = strzone(ReadString());
}
REGISTRY(Turrets, BITS(5))
#define Turrets_from(i) _Turrets_from(i, TUR_Null)
#define get_turretinfo(i) Turrets_from(i)
-REGISTER_REGISTRY(RegisterTurrets)
+REGISTER_REGISTRY(Turrets)
REGISTRY_CHECK(Turrets)
const int TUR_FIRST = 1;
#define TUR_LAST (Turrets_COUNT - 1)
-#define REGISTER_TURRET(id, inst) REGISTER(RegisterTurrets, TUR, Turrets, id, m_id, inst)
+#define REGISTER_TURRET(id, inst) REGISTER(Turrets, TUR, id, m_id, inst)
REGISTER_TURRET(Null, NEW(Turret));
void turret_gibboom();
void turret_gib_draw(entity this)
{
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
self.drawmask = MASK_NORMAL;
return true;
}
-void load_unit_settings(entity ent, float is_reload)
+void load_unit_settings(entity ent, bool is_reload)
{SELFPARAM();
string unitname = ent.netname;
string sbase;
}
void turrets_manager_think()
-{SELFPARAM();
- self.nextthink = time + 1;
+{
+ SELFPARAM();
+ this.nextthink = time + 1;
- entity e;
if (autocvar_g_turrets_reloadcvars == 1)
{
- e = nextent(world);
- while (e)
- {
- if (IS_TURRET(e))
- {
- load_unit_settings(e,1);
- Turret tur = get_turretinfo(self.m_id);
- tur.tr_think(tur);
- }
-
- e = nextent(e);
- }
- cvar_set("g_turrets_reloadcvars","0");
+ FOREACH_ENTITY(IS_TURRET(it), LAMBDA(
+ load_unit_settings(it, true);
+ Turret tur = get_turretinfo(it.m_id);
+ tur.tr_think(tur);
+ ));
+ cvar_set("g_turrets_reloadcvars", "0");
}
}
/* mins */ ATTRIB(EWheel, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(EWheel, maxs, vector, '32 32 48');
/* modelname */ ATTRIB(EWheel, mdl, string, "ewheel-base2.md3");
-/* model */ ATTRIB(EWheel, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(EWheel, head_model, string, strzone(strcat("models/turrets/", "ewheel-gun1.md3")));
+/* model */ ATTRIB_STRZONE(EWheel, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(EWheel, head_model, string, strcat("models/turrets/", "ewheel-gun1.md3"));
/* netname */ ATTRIB(EWheel, netname, string, "ewheel");
/* fullname */ ATTRIB(EWheel, turret_name, string, _("eWheel Turret"));
ATTRIB(EWheel, m_weapon, Weapon, WEP_EWHEEL);
/* mins */ ATTRIB(Flac, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(Flac, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(Flac, mdl, string, "base.md3");
-/* model */ ATTRIB(Flac, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(Flac, head_model, string, strzone(strcat("models/turrets/", "flac.md3")));
+/* model */ ATTRIB_STRZONE(Flac, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(Flac, head_model, string, strcat("models/turrets/", "flac.md3"));
/* netname */ ATTRIB(Flac, netname, string, "flac");
/* fullname */ ATTRIB(Flac, turret_name, string, _("FLAC Cannon"));
ATTRIB(Flac, m_weapon, Weapon, WEP_FLAC);
/* mins */ ATTRIB(FusionReactor, mins, vector, '-34 -34 0');
/* maxs */ ATTRIB(FusionReactor, maxs, vector, '34 34 90');
/* modelname */ ATTRIB(FusionReactor, mdl, string, "base.md3");
-/* model */ ATTRIB(FusionReactor, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(FusionReactor, head_model, string, strzone(strcat("models/turrets/", "reactor.md3")));
+/* model */ ATTRIB_STRZONE(FusionReactor, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(FusionReactor, head_model, string, strcat("models/turrets/", "reactor.md3"));
/* netname */ ATTRIB(FusionReactor, netname, string, "fusionreactor");
/* fullname */ ATTRIB(FusionReactor, turret_name, string, _("Fusion Reactor"));
ENDCLASS(FusionReactor)
/* mins */ ATTRIB(Hellion, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(Hellion, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(Hellion, mdl, string, "base.md3");
-/* model */ ATTRIB(Hellion, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(Hellion, head_model, string, strzone(strcat("models/turrets/", "hellion.md3")));
+/* model */ ATTRIB_STRZONE(Hellion, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(Hellion, head_model, string, strcat("models/turrets/", "hellion.md3"));
/* netname */ ATTRIB(Hellion, netname, string, "hellion");
/* fullname */ ATTRIB(Hellion, turret_name, string, _("Hellion Missile Turret"));
ATTRIB(Hellion, m_weapon, Weapon, WEP_HELLION);
/* mins */ ATTRIB(HunterKiller, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(HunterKiller, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(HunterKiller, mdl, string, "base.md3");
-/* model */ ATTRIB(HunterKiller, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(HunterKiller, head_model, string, strzone(strcat("models/turrets/", "hk.md3")));
+/* model */ ATTRIB_STRZONE(HunterKiller, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(HunterKiller, head_model, string, strcat("models/turrets/", "hk.md3"));
/* netname */ ATTRIB(HunterKiller, netname, string, "hk");
/* fullname */ ATTRIB(HunterKiller, turret_name, string, _("Hunter-Killer Turret"));
ATTRIB(HunterKiller, m_weapon, Weapon, WEP_HK);
/* mins */ ATTRIB(MachineGunTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(MachineGunTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(MachineGunTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(MachineGunTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(MachineGunTurret, head_model, string, strzone(strcat("models/turrets/", "machinegun.md3")));
+/* model */ ATTRIB_STRZONE(MachineGunTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(MachineGunTurret, head_model, string, strcat("models/turrets/", "machinegun.md3"));
/* netname */ ATTRIB(MachineGunTurret, netname, string, "machinegun");
/* fullname */ ATTRIB(MachineGunTurret, turret_name, string, _("Machinegun Turret"));
ATTRIB(MachineGunTurret, m_weapon, Weapon, WEP_TUR_MACHINEGUN);
/* mins */ ATTRIB(MLRSTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(MLRSTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(MLRSTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(MLRSTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(MLRSTurret, head_model, string, strzone(strcat("models/turrets/", "mlrs.md3")));
+/* model */ ATTRIB_STRZONE(MLRSTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(MLRSTurret, head_model, string, strcat("models/turrets/", "mlrs.md3"));
/* netname */ ATTRIB(MLRSTurret, netname, string, "mlrs");
/* fullname */ ATTRIB(MLRSTurret, turret_name, string, _("MLRS Turret"));
ATTRIB(MLRSTurret, m_weapon, Weapon, WEP_TUR_MLRS);
/* mins */ ATTRIB(PhaserTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(PhaserTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(PhaserTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(PhaserTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(PhaserTurret, head_model, string, strzone(strcat("models/turrets/", "phaser.md3")));
+/* model */ ATTRIB_STRZONE(PhaserTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(PhaserTurret, head_model, string, strcat("models/turrets/", "phaser.md3"));
/* netname */ ATTRIB(PhaserTurret, netname, string, "phaser");
/* fullname */ ATTRIB(PhaserTurret, turret_name, string, _("Phaser Cannon"));
ATTRIB(PhaserTurret, m_weapon, Weapon, WEP_PHASER);
/* mins */ ATTRIB(PlasmaTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(PlasmaTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(PlasmaTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(PlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(PlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasma.md3")));
+/* model */ ATTRIB_STRZONE(PlasmaTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(PlasmaTurret, head_model, string, strcat("models/turrets/", "plasma.md3"));
/* netname */ ATTRIB(PlasmaTurret, netname, string, "plasma");
/* fullname */ ATTRIB(PlasmaTurret, turret_name, string, _("Plasma Cannon"));
ATTRIB(PlasmaTurret, m_weapon, Weapon, WEP_PLASMA);
/* mins */ ATTRIB(DualPlasmaTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(DualPlasmaTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(DualPlasmaTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(DualPlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(DualPlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasmad.md3")));
+/* model */ ATTRIB_STRZONE(DualPlasmaTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(DualPlasmaTurret, head_model, string, strcat("models/turrets/", "plasmad.md3"));
/* netname */ ATTRIB(DualPlasmaTurret, netname, string, "plasma_dual");
/* fullname */ ATTRIB(DualPlasmaTurret, turret_name, string, _("Dual Plasma Cannon"));
ATTRIB(DualPlasmaTurret, m_weapon, Weapon, WEP_PLASMA_DUAL);
/* mins */ ATTRIB(TeslaCoil, mins, vector, '-60 -60 0');
/* maxs */ ATTRIB(TeslaCoil, maxs, vector, '60 60 128');
/* modelname */ ATTRIB(TeslaCoil, mdl, string, "tesla_base.md3");
-/* model */ ATTRIB(TeslaCoil, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(TeslaCoil, head_model, string, strzone(strcat("models/turrets/", "tesla_head.md3")));
+/* model */ ATTRIB_STRZONE(TeslaCoil, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(TeslaCoil, head_model, string, strcat("models/turrets/", "tesla_head.md3"));
/* netname */ ATTRIB(TeslaCoil, netname, string, "tesla");
/* fullname */ ATTRIB(TeslaCoil, turret_name, string, _("Tesla Coil"));
ATTRIB(TeslaCoil, m_weapon, Weapon, WEP_TESLA);
/* mins */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0');
/* maxs */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95');
/* modelname */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3");
-/* model */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3")));
+/* model */ ATTRIB_STRZONE(WalkerTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(WalkerTurret, head_model, string, strcat("models/turrets/", "walker_head_minigun.md3"));
/* netname */ ATTRIB(WalkerTurret, netname, string, "walker");
/* fullname */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret"));
ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER);
case ANIM_PAIN:
if(self.frame != ANIM_PAIN)
- defer(0.25, walker_setnoanim);
+ defer(self, 0.25, walker_setnoanim);
break;
case ANIM_MELEE:
if(self.frame != ANIM_MELEE)
{
- defer(0.41, walker_setnoanim);
- defer(0.21, walker_melee_do_dmg);
+ defer(self, 0.41, walker_setnoanim);
+ defer(self, 0.21, walker_melee_do_dmg);
}
movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
}
#ifdef TURRET_DEBUG
-void SUB_Remove();
void marker_think()
{SELFPARAM();
if(self.cnt)
if(cvar_type(e.netname))
{
cvar_set(e.netname, e.message);
+ strunzone(e.netname);
+ strunzone(e.message);
remove(e);
++i;
}
{
shutdown_running = 1;
Shutdown();
+ shutdownhooks();
}
cvar_settemp_restore(); // this must be done LAST, but in any case
}
string get_model_parameters_desc;
float get_model_parameters(string mod, float skn); // call with string_null to clear; skin -1 means mod is the filename of the txt file and is to be split
-vector vec2(vector v);
-
#ifndef MENUQC
vector NearestPointOnBox(entity box, vector org);
#endif
#define normal_or_gentle(normal, gentle) (GENTLE ? ((gentle != "") ? gentle : normal) : normal)
#endif
-vector vec3(float x, float y, float z);
-
#ifndef MENUQC
vector animfixfps(entity e, vector a, vector b);
#endif
#include "all.qh"
-#ifndef MENUQC
-STATIC_INIT(vehicles_common_initialize)
-{
-#ifdef SVQC
- addstat(STAT_HUD, AS_INT, hud);
- addstat(STAT_VEHICLESTAT_HEALTH, AS_INT, vehicle_health);
- addstat(STAT_VEHICLESTAT_SHIELD, AS_INT, vehicle_shield);
- addstat(STAT_VEHICLESTAT_ENERGY, AS_INT, vehicle_energy);
-
- addstat(STAT_VEHICLESTAT_W2MODE, AS_INT, vehicle_weapon2mode);
-
- addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1);
- addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
-
- addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2);
- addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
-#endif // SVQC
-}
-#endif
-
REGISTER_NET_LINKED(ENT_CLIENT_AUXILIARYXHAIR)
#if defined(SVQC)
REGISTRY(Vehicles, BITS(3))
#define Vehicles_from(i) _Vehicles_from(i, VEH_Null)
#define get_vehicleinfo(i) Vehicles_from(i)
-REGISTER_REGISTRY(RegisterVehicles)
+REGISTER_REGISTRY(Vehicles)
REGISTRY_CHECK(Vehicles)
const int VEH_FIRST = 1;
#define VEH_LAST (Vehicles_COUNT - 1)
/** If you register a new vehicle, make sure to add it to all.inc */
-#define REGISTER_VEHICLE(id, inst) REGISTER(RegisterVehicles, VEH, Vehicles, id, vehicleid, inst)
+#define REGISTER_VEHICLE(id, inst) REGISTER(Vehicles, VEH, id, vehicleid, inst)
#if defined(SVQC)
#include "sv_vehicles.qh"
float barAlpha = autocvar_hud_progressbar_alpha * hudAlpha;
float blinkValue = 0.55 + sin(time * 7) * 0.45;
- float health = getstati(STAT_VEHICLESTAT_HEALTH) * 0.01;
- float shield = getstati(STAT_VEHICLESTAT_SHIELD) * 0.01;
- float energy = getstati(STAT_VEHICLESTAT_ENERGY) * 0.01;
- float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1) * 0.01;
- float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1) * 0.01;
- float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2) * 0.01;
- float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
+ float health = STAT(VEHICLESTAT_HEALTH) * 0.01;
+ float shield = STAT(VEHICLESTAT_SHIELD) * 0.01;
+ float energy = STAT(VEHICLESTAT_ENERGY) * 0.01;
+ float ammo1 = STAT(VEHICLESTAT_AMMO1) * 0.01;
+ float reload1 = STAT(VEHICLESTAT_RELOAD1) * 0.01;
+ float ammo2 = STAT(VEHICLESTAT_AMMO2) * 0.01;
+ float reload2 = STAT(VEHICLESTAT_RELOAD2) * 0.01;
// HACK to deal with the inconsistent use of the vehicle stats
ammo1 = (ammo1) ? ammo1 : energy;
void RaptorCBShellfragDraw(entity this);
void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
-#define weapon2mode getstati(STAT_VEHICLESTAT_W2MODE)
+#define weapon2mode STAT(VEHICLESTAT_W2MODE)
#endif
proj.use = vehicles_projectile_explode;
proj.owner = self;
proj.realowner = _owner;
- proj.think = SUB_Remove;
+ proj.think = SUB_Remove_self;
proj.nextthink = time + 30;
if(_health)
if(ret.wp00 == veh)
{
ret.classname = "";
- ret.think = SUB_Remove;
+ ret.think = SUB_Remove_self;
ret.nextthink = time + 0.1;
if(ret.waypointsprite_attached)
.entity gunner1;
.entity gunner2;
-.float vehicle_health; /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
-.float vehicle_energy; /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
-.float vehicle_shield; /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
+.float vehicle_health = _STAT(VEHICLESTAT_HEALTH); /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
+.float vehicle_energy = _STAT(VEHICLESTAT_ENERGY); /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
+.float vehicle_shield = _STAT(VEHICLESTAT_SHIELD); /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
-.float vehicle_ammo1; /// If self is player this is 0..100 indicating percentage of primary ammo left UNLESS value is already stored in vehicle_energy. If self is vehile, this is the real ammo1 value.
-.float vehicle_reload1; /// If self is player this is 0..100 indicating percentage of primary reload status. If self is vehile, this is the real reload1 value.
-.float vehicle_ammo2; /// If self is player this is 0..100 indicating percentage of secondary ammo left. If self is vehile, this is the real ammo2 value.
-.float vehicle_reload2; /// If self is player this is 0..100 indicating percentage of secondary reload status. If self is vehile, this is the real reload2 value.
+.float vehicle_ammo1 = _STAT(VEHICLESTAT_AMMO1); /// If self is player this is 0..100 indicating percentage of primary ammo left UNLESS value is already stored in vehicle_energy. If self is vehile, this is the real ammo1 value.
+.float vehicle_reload1 = _STAT(VEHICLESTAT_RELOAD1); /// If self is player this is 0..100 indicating percentage of primary reload status. If self is vehile, this is the real reload1 value.
+.float vehicle_ammo2 = _STAT(VEHICLESTAT_AMMO2); /// If self is player this is 0..100 indicating percentage of secondary ammo left. If self is vehile, this is the real ammo2 value.
+.float vehicle_reload2 = _STAT(VEHICLESTAT_RELOAD2); /// If self is player this is 0..100 indicating percentage of secondary reload status. If self is vehile, this is the real reload2 value.
.float sound_nexttime;
const float VOL_VEHICLEENGINE = 1;
const float VHSF_NORMAL = 0;
const float VHSF_FACTORY = 2;
-.int hud;
+.int hud = _STAT(HUD);
.float dmg_time;
.int volly_counter;
// vehicle functions
.void(int _spawnflag) vehicle_spawn; /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
.bool(int _imp) vehicles_impulse;
-.int vehicle_weapon2mode;
+.int vehicle_weapon2mode = _STAT(VEHICLESTAT_W2MODE);
.void(int exit_flags) vehicle_exit;
.bool() vehicle_enter;
const int VHEF_NORMAL = 0; /// User pressed exit key
dropmark.gravity = 1;
}
- float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
+ float reload2 = STAT(VEHICLESTAT_RELOAD2) * 0.01;
if(reload2 == 1)
{
setorigin(dropmark, pmove_org);
if(wasfreed(self))
return;
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
self.move_avelocity += randomvec() * 15;
self.renderflags = 0;
#endif
// client movement
-void viewloc_PlayerPhysics()
-{SELFPARAM();
- if(self.viewloc)
+void viewloc_PlayerPhysics(entity this)
+{
+ if(this.viewloc)
{
- vector oldmovement = self.movement;
- self.movement_x = oldmovement_y;
- self.movement_y = 0;
+ vector oldmovement = this.movement;
+ this.movement_x = oldmovement_y;
+ this.movement_y = 0;
- if(self.movement_x < 0)
- self.movement_x = -self.movement_x;
+ if(this.movement_x < 0)
+ this.movement_x = -this.movement_x;
vector level_start, level_end;
- level_start = self.viewloc.enemy.origin;
- level_end = self.viewloc.goalentity.origin;
+ level_start = this.viewloc.enemy.origin;
+ level_end = this.viewloc.goalentity.origin;
vector forward, backward;
forward = vectoangles(normalize(level_end - level_start));
backward = vectoangles(normalize(level_start - level_end));
- if(self.movement_x < 0) // left
- self.angles_y = backward_y;
- if(self.movement_x > 0) // right
- self.angles_y = forward_y;
+ if(this.movement_x < 0) // left
+ this.angles_y = backward_y;
+ if(this.movement_x > 0) // right
+ this.angles_y = forward_y;
if(oldmovement_x > 0)
#ifdef CSQC
input_angles_x =
#endif
- self.v_angle_x = self.angles_x = -50;
+ this.v_angle_x = this.angles_x = -50;
else if(oldmovement_x < 0)
#ifdef CSQC
input_angles_x =
#endif
- self.v_angle_x = self.angles_x = 50;
+ this.v_angle_x = this.angles_x = 50;
- //if(!PHYS_INPUT_BUTTON_CROUCH(self) && !IS_DUCKED(self))
+ //if(!PHYS_INPUT_BUTTON_CROUCH(this) && !IS_DUCKED(this))
#ifdef SVQC
- //self.BUTTON_CROUCH = (oldmovement_x < 0);
- if(oldmovement_x < 0)
- self.BUTTON_CROUCH = true;
+ //this.BUTTON_CROUCH = (oldmovement_x < 0);
+ if (oldmovement.x < 0)
+ this.BUTTON_CROUCH = true;
#elif defined(CSQC)
- if(oldmovement_x < 0) { input_buttons |= 16; self.flags |= FL_DUCKED; } //else { input_buttons &= ~16; self.flags &= ~FL_DUCKED; }
+ if (oldmovement.x < 0)
+ {
+ input_buttons |= BIT(4);
+ this.flags |= FL_DUCKED;
+ }
+ //else { input_buttons &= ~16; this.flags &= ~FL_DUCKED; }
#endif
}
}
vector old_camera_angle = '0 0 0';
void viewloc_SetViewLocation()
{
- entity view = CSQCModel_server2csqc(player_localentnum);
- if(!view) { return; }
+ entity view = CSQCModel_server2csqc(player_localentnum - 1);
+ if (!view) return;
//NOTE: the "cam_" cvars sould probably be changed out with a spawnflag or an entity key. I have it like this for my testing -- Player_2
if(view.viewloc && !wasfreed(view.viewloc) && view.viewloc.enemy && view.viewloc.goalentity)
{
.entity viewloc;
-void viewloc_PlayerPhysics();
+void viewloc_PlayerPhysics(entity this);
#ifdef CSQC
#include "../../lib/warpzone/common.qh"
#include "../../lib/warpzone/client.qh"
#include "../util.qh"
- #include "../buffs/all.qh"
#include "../../client/autocvars.qh"
#include "../deathtypes/all.qh"
#include "../../lib/csqcmodel/interpolate.qh"
#include "../../lib/csqcmodel/cl_model.qh"
#elif defined(MENUQC)
#elif defined(SVQC)
- #include "../../lib/warpzone/anglestransform.qh"
- #include "../../lib/warpzone/common.qh"
- #include "../../lib/warpzone/util_server.qh"
- #include "../../lib/warpzone/server.qh"
- #include "../constants.qh"
- #include "../stats.qh"
- #include "../teams.qh"
- #include "../util.qh"
- #include "../buffs/all.qh"
- #include "../monsters/all.qh"
- #include "config.qh"
- #include "../../server/weapons/csqcprojectile.qh"
- #include "../../server/weapons/tracing.qh"
- #include "../../server/t_items.qh"
- #include "../../server/autocvars.qh"
- #include "../../server/constants.qh"
- #include "../../server/defs.qh"
- #include "../notifications.qh"
- #include "../deathtypes/all.qh"
- #include "../../server/mutators/all.qh"
- #include "../mapinfo.qh"
- #include "../../server/command/common.qh"
- #include "../../lib/csqcmodel/sv_model.qh"
- #include "../../server/portals.qh"
- #include "../../server/g_hook.qh"
+ #include "../../lib/warpzone/anglestransform.qh"
+ #include "../../lib/warpzone/common.qh"
+ #include "../../lib/warpzone/util_server.qh"
+ #include "../../lib/warpzone/server.qh"
+ #include "../constants.qh"
+ #include "../stats.qh"
+ #include "../teams.qh"
+ #include "../util.qh"
+ #include "../monsters/all.qh"
+ #include "config.qh"
+ #include "../../server/weapons/csqcprojectile.qh"
+ #include "../../server/weapons/tracing.qh"
+ #include "../../server/t_items.qh"
+ #include "../../server/autocvars.qh"
+ #include "../../server/constants.qh"
+ #include "../../server/defs.qh"
+ #include "../notifications.qh"
+ #include "../deathtypes/all.qh"
+ #include "../../server/mutators/all.qh"
+ #include "../mapinfo.qh"
+ #include "../../server/command/common.qh"
+ #include "../../lib/csqcmodel/sv_model.qh"
+ #include "../../server/portals.qh"
+ #include "../../server/g_hook.qh"
#endif
#ifndef MENUQC
#include "calculations.qc"
// WEAPON PLUGIN SYSTEM
-WepSet WepSet_FromWeapon(int a)
+WepSet _WepSet_FromWeapon(int a)
{
a -= WEP_FIRST;
if (Weapons_MAX > 24)
return '1 0 0' * power2of(a);
}
#ifdef SVQC
- void WepSet_AddStat()
- {
- addstat(STAT_WEAPONS, AS_INT, weapons_x);
- if (Weapons_MAX > 24) addstat(STAT_WEAPONS2, AS_INT, weapons_y);
- if (Weapons_MAX > 48) addstat(STAT_WEAPONS3, AS_INT, weapons_z);
- }
- void WepSet_AddStat_InMap()
- {
- addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
- if (Weapons_MAX > 24) addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
- if (Weapons_MAX > 48) addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
- }
void WriteWepSet(float dst, WepSet w)
{
if (Weapons_MAX > 48) WriteInt72_t(dst, w);
#ifdef CSQC
WepSet WepSet_GetFromStat()
{
- WepSet w = '0 0 0';
- w.x = getstati(STAT_WEAPONS);
- if (Weapons_MAX > 24) w.y = getstati(STAT_WEAPONS2);
- if (Weapons_MAX > 48) w.z = getstati(STAT_WEAPONS3);
- return w;
+ return STAT(WEAPONS);
}
WepSet WepSet_GetFromStat_InMap()
{
- WepSet w = '0 0 0';
- w_x = getstati(STAT_WEAPONSINMAP);
- if (Weapons_MAX > 24) w_y = getstati(STAT_WEAPONSINMAP2);
- if (Weapons_MAX > 48) w_z = getstati(STAT_WEAPONSINMAP3);
- return w;
+ return STAT(WEAPONSINMAP);
}
WepSet ReadWepSet()
{
case ammo_nails: return STAT_NAILS;
case ammo_rockets: return STAT_ROCKETS;
case ammo_cells: return STAT_CELLS;
- case ammo_plasma: return STAT_PLASMA;
- case ammo_fuel: return STAT_FUEL;
+ case ammo_plasma: return STAT_PLASMA.m_id;
+ case ammo_fuel: return STAT_FUEL.m_id;
default: return -1;
}
}
#define WEAPONS_ALL_H
#include "../command/all.qh"
+#include "../stats.qh"
#include "config.qh"
// weapon sets
typedef vector WepSet;
-#define WEPSET(id) WepSet_FromWeapon(WEP_##id.m_id)
-WepSet WepSet_FromWeapon(int a);
#ifdef SVQC
-void WepSet_AddStat();
-void WepSet_AddStat_InMap();
void WriteWepSet(float dest, WepSet w);
#endif
REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
#define Weapons_from(i) _Weapons_from(i, WEP_Null)
#define get_weaponinfo(i) Weapons_from(i)
-REGISTER_REGISTRY(RegisterWeapons)
+REGISTER_REGISTRY(Weapons)
STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, LAMBDA(it.m_pickup = NEW(WeaponPickup, it))); }
+.WepSet m_wepset;
+#define WEPSET(id) (WEP_##id.m_wepset)
+#define WepSet_FromWeapon(i) (Weapons_from(i).m_wepset)
+WepSet _WepSet_FromWeapon(int i);
+STATIC_INIT(WepSets)
+{
+ FOREACH(Weapons, true, LAMBDA(it.m_wepset = _WepSet_FromWeapon(it.m_id)));
+}
GENERIC_COMMAND(dumpweapons, "Dump all weapons into weapons_dump.txt") // WEAPONTODO: make this work with other progs than just server
{
#define REGISTER_WEAPON(id, inst) \
/* WepSet WEPSET_##id; */ \
- REGISTER(RegisterWeapons, WEP, Weapons, id, m_id, inst)
+ REGISTER(Weapons, WEP, id, m_id, inst)
// create cvars for weapon settings
#define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
{
FOREACH(Weapons, true, LAMBDA(
it.m_id = i;
- WepSet set = WepSet_FromWeapon(it.m_id);
+ WepSet set = it.m_wepset;
WEPSET_ALL |= set;
if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
it.weapon = it.m_id;
.vector weaponentity_glowmod;
//.int weapon; // current weapon
-.int switchweapon; // weapon requested to switch to
-.int switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible)
+#ifdef SVQC
+.int switchweapon = _STAT(SWITCHWEAPON);
+.int switchingweapon = _STAT(SWITCHINGWEAPON);
+#endif
.string weaponname; // name of .weapon
.vector spawnorigin; // for casings
#ifndef WEAPON_H
#define WEAPON_H
#include "../items/item/pickup.qh"
+#include "../stats.qh"
const int MAX_WEAPONSLOTS = 2;
.entity weaponentities[MAX_WEAPONSLOTS];
/** idle frame */
const int WS_READY = 4;
+#ifdef SVQC
+.int ammo_shells;
+.int ammo_nails;
+.int ammo_rockets;
+.int ammo_cells;
+.int ammo_plasma = _STAT(PLASMA);
+.int ammo_fuel = _STAT(FUEL);
+.int ammo_none;
+#else
.int ammo_shells;
.int ammo_nails;
.int ammo_rockets;
.int ammo_plasma;
.int ammo_fuel;
.int ammo_none;
+#endif
/** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
CLASS(Weapon, Object)
.float beam_heat; // (beam) amount of heat produced
.float arc_overheat; // (dropped arc/player) time during which it's too hot
.float arc_cooldown; // (dropped arc/player) cooling speed
-.float arc_heat_percent; // (player) arc heat in [0,1] (stat)
+.float arc_heat_percent = _STAT(ARC_HEAT);
.float arc_smoke_sound;
#endif
#ifdef CSQC
if(!self.beam_usevieworigin)
{
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(self);
}
// origin = beam starting origin
// self.iflags = IFLAG_ORIGIN | IFLAG_ANGLES | IFLAG_V_ANGLE; // why doesn't this work?
self.iflags = IFLAG_ORIGIN;
- InterpolateOrigin_Undo();
+ InterpolateOrigin_Undo(self);
}
if(sf & ARC_SF_START) // starting location
else
{
// use player origin so that third person display still works
- self.origin = getplayerorigin(player_localnum) + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
+ self.origin = entcs_receiver(player_localnum).origin + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
}
}
if(!self.beam_usevieworigin)
{
- InterpolateOrigin_Note();
+ InterpolateOrigin_Note(this);
}
return true;
}
void W_Blaster_Think()
{SELFPARAM();
- self.movetype = MOVETYPE_FLY;
- self.think = SUB_Remove;
- self.nextthink = time + self.blaster_lifetime;
- CSQCProjectile(self, true, PROJECTILE_BLASTER, true);
+ this.movetype = MOVETYPE_FLY;
+ this.think = SUB_Remove_self;
+ this.nextthink = time + this.blaster_lifetime;
+ CSQCProjectile(this, true, PROJECTILE_BLASTER, true);
}
void W_Blaster_Attack(
W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext);
}
-void W_Crylink_Reset()
-{SELFPARAM();
- W_Crylink_Dequeue(self);
- remove(self);
+void W_Crylink_Reset(entity this)
+{
+ W_Crylink_Dequeue(this);
+ remove(this);
}
// force projectile to explode
//missile.angles = vectoangles(missile.velocity); // csqc
missile.touch = W_HLAC_Touch;
- missile.think = SUB_Remove;
+ missile.think = SUB_Remove_self;
missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime);
//missile.angles = vectoangles(missile.velocity); // csqc
missile.touch = W_HLAC_Touch;
- missile.think = SUB_Remove;
+ missile.think = SUB_Remove_self;
missile.nextthink = time + WEP_CVAR_SEC(hlac, lifetime);
void W_MachineGun_MuzzleFlash_Think()
{SELFPARAM();
- self.frame = self.frame + 2;
- self.scale = self.scale * 0.5;
- self.alpha = self.alpha - 0.25;
- self.nextthink = time + 0.05;
+ this.frame += 2;
+ this.scale *= 0.5;
+ this.alpha -= 0.25;
+ this.nextthink = time + 0.05;
- if(self.alpha <= 0)
+ if(this.alpha <= 0)
{
- self.think = SUB_Remove;
- self.nextthink = time;
- self.realowner.muzzle_flash = world;
+ this.think = SUB_Remove_self;
+ this.nextthink = time;
+ this.realowner.muzzle_flash = world;
return;
}
missile.bot_dodge = true;
missile.bot_dodgerating = 50;
missile.touch = W_Seeker_Tag_Touch;
- missile.think = SUB_Remove;
+ missile.think = SUB_Remove_self;
missile.nextthink = time + WEP_CVAR(seeker, tag_lifetime);
missile.movetype = MOVETYPE_FLY;
missile.solid = SOLID_BBOX;
if(a < ALPHA_MIN_VISIBLE) { remove(self); }
// WEAPONTODO: save this only once when creating the entity
- vector sw_color = getcsqcplayercolor(self.sv_entnum); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
+ vector sw_color = getcsqcplayercolor(self.sv_entnum - 1); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
// WEAPONTODO: trace to find what we actually hit
vector endpos = (self.sw_shotorg + (self.sw_shotdir * self.sw_distance));
// muzzle flash for 1st person view
flash = spawn();
setmodel(flash, MDL_SHOTGUN_MUZZLEFLASH); // precision set below
- flash.think = SUB_Remove;
+ flash.think = SUB_Remove_self;
flash.nextthink = time + 0.06;
flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
W_AttachToShotorg(self, flash, '5 0 0');
#endif
#endif
#ifdef IMPLEMENTATION
+
+REGISTER_NET_TEMP(TE_CSQC_VAPORBEAMPARTICLE)
+
+#if defined(SVQC)
+void SendCSQCVaporizerBeamParticle(entity player, int hit) {
+ vector v;
+ v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WriteHeader(MSG_BROADCAST, TE_CSQC_VAPORBEAMPARTICLE);
+ WriteCoord(MSG_BROADCAST, w_shotorg.x);
+ WriteCoord(MSG_BROADCAST, w_shotorg.y);
+ WriteCoord(MSG_BROADCAST, w_shotorg.z);
+ WriteCoord(MSG_BROADCAST, v.x);
+ WriteCoord(MSG_BROADCAST, v.y);
+ WriteCoord(MSG_BROADCAST, v.z);
+ WriteByte(MSG_BROADCAST, hit);
+ WriteShort(MSG_BROADCAST, num_for_edict(player));
+ WriteByte(MSG_BROADCAST, player.team);
+}
+#elif defined(CSQC)
+bool autocvar_cl_vaporizerbeam_particle = false;
+float autocvar_cl_vaporizerbeam_lifetime = 0.8;
+float autocvar_cl_vaporizerbeam_colorboost = 0.7;
+
+string Draw_VaporizerBeam_trace_callback_tex;
+float Draw_VaporizerBeam_trace_callback_rnd;
+vector Draw_VaporizerBeam_trace_callback_rgb;
+float Draw_VaporizerBeam_trace_callback_a;
+void Draw_VaporizerBeam_trace_callback(vector start, vector hit, vector end)
+{
+ float i;
+ vector vorg;
+ vorg = WarpZone_TransformOrigin(WarpZone_trace_transform, view_origin);
+ for(i = 0; i < Draw_VaporizerBeam_trace_callback_a; ++i)
+ Draw_CylindricLine(hit, start, 8, Draw_VaporizerBeam_trace_callback_tex, 0.25, Draw_VaporizerBeam_trace_callback_rnd, Draw_VaporizerBeam_trace_callback_rgb, min(1, Draw_VaporizerBeam_trace_callback_a - i), DRAWFLAG_NORMAL, vorg);
+ Draw_VaporizerBeam_trace_callback_rnd += 0.25 * vlen(hit - start) / 8;
+}
+
+.vector vorg1, vorg2;
+.float spawn_time;
+void VaporizerBeam_Draw(entity this)
+{
+ //draw either the old v2.3 beam or the new beam
+ particles_alphamin = particles_alphamax = particles_fade = 1;
+
+ string tex = "particles/lgbeam";
+ if(this.cnt)
+ tex = "particles/gauntletbeam";
+ vector rgb = getcsqcplayercolor(this.sv_entnum - 1);
+ rgb *= (1 + autocvar_cl_vaporizerbeam_colorboost);
+
+ float fail = (self.nextthink - time);
+
+ Draw_VaporizerBeam_trace_callback_tex = tex;
+ Draw_VaporizerBeam_trace_callback_rnd = 0;
+ Draw_VaporizerBeam_trace_callback_rgb = rgb;
+ Draw_VaporizerBeam_trace_callback_a = bound(0, fail, 1);
+ WarpZone_TraceBox_ThroughZone(this.vorg1, '0 0 0', '0 0 0', this.vorg2, MOVE_NOTHING, world, world, Draw_VaporizerBeam_trace_callback);
+ Draw_VaporizerBeam_trace_callback_tex = string_null;
+
+ /*if(!MUTATOR_CALLHOOK(Particles_VaporizerBeam, this.vorg1, this.vorg2))
+ if(autocvar_cl_particles_oldvortexbeam && (getstati(STAT_ALLOW_OLDVORTEXBEAM) || isdemo()))
+ WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), this.vorg1, this.vorg2, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
+ else
+ WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM), this.vorg1, this.vorg2, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);*/
+}
+
+NET_HANDLE(TE_CSQC_VAPORBEAMPARTICLE, bool isNew)
+{
+ Net_Accept(vortex_beam);
+ this.think = SUB_Remove_self;
+ this.nextthink = time + bound(0, autocvar_cl_vaporizerbeam_lifetime, 10);
+ this.draw = VaporizerBeam_Draw;
+ this.drawmask = MASK_NORMAL;
+
+ this.vorg1_x = ReadCoord(); this.vorg1_y = ReadCoord(); this.vorg1_z = ReadCoord();
+ this.vorg2_x = ReadCoord(); this.vorg2_y = ReadCoord(); this.vorg2_z = ReadCoord();
+ this.cnt = ReadByte();
+ this.sv_entnum = ReadShort();
+ this.team = ReadByte() - 1;
+
+ if(autocvar_cl_vaporizerbeam_particle)
+ {
+ WarpZone_TrailParticles(world, particleeffectnum(((this.cnt) ? EFFECT_VAPORIZER_HIT(this.team) : EFFECT_VAPORIZER(this.team))), this.vorg1, this.vorg2);
+ this.draw = func_null;
+ this.drawmask = MASK_NORMAL;
+ remove(this);
+ }
+
+ pointparticles(EFFECT_VORTEX_MUZZLEFLASH, this.vorg1, normalize(this.vorg2 - this.vorg1) * 1000, 1);
+ return true;
+}
+#endif
+
#ifdef SVQC
spawnfunc(weapon_vaporizer) { weapon_defaultspawnfunc(this, WEP_VAPORIZER); }
spawnfunc(weapon_minstanex) { spawnfunc_weapon_vaporizer(this); }
damage_goodhits = 0;
FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, vaporizer_damage, 800, 0, 0, 0, 0, WEP_VAPORIZER.m_id);
+ // do this now, as goodhits is disabled below
+ SendCSQCVaporizerBeamParticle(self, damage_goodhits);
+
if(yoda && flying)
Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
if(damage_goodhits && self.vaporizer_lasthit)
self.vaporizer_lasthit = damage_goodhits;
- Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
-
- // teamcolor / hit beam effect
- vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- Send_Effect((damage_goodhits ? EFFECT_VAPORIZER_HIT(self.team) : EFFECT_VAPORIZER(self.team)), w_shotorg, v, 1);
-
if(autocvar_g_rm)
if(!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
W_RocketMinsta_Explosion(trace_endpos);
charge = sqrt(charge); // divide evenly among trail spacing and alpha
particles_alphamin = particles_alphamax = particles_fade = charge;
- if (autocvar_cl_particles_oldvortexbeam && (getstati(STAT_ALLOW_OLDVORTEXBEAM) || isdemo()))
+ if(!MUTATOR_CALLHOOK(Particles_VortexBeam, shotorg, endpos))
+ if(autocvar_cl_particles_oldvortexbeam && (STAT(ALLOW_OLDVORTEXBEAM) || isdemo()))
WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
else
WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
spawnfunc(weapon_vortex) { weapon_defaultspawnfunc(this, WEP_VORTEX); }
spawnfunc(weapon_nex) { spawnfunc_weapon_vortex(this); }
+REGISTER_MUTATOR(vortex_charge, true);
+
+MUTATOR_HOOKFUNCTION(vortex_charge, GetPressedKeys)
+{SELFPARAM();
+ // WEAPONTODO
+ float xyspeed = vlen(vec2(self.velocity));
+ if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+ {
+ // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
+ xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
+ float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
+ // add the extra charge
+ self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
+ }
+}
+
void W_Vortex_Attack(Weapon thiswep, float issecondary)
{SELFPARAM();
float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
#define pointparticles __pointparticles
#define setmodel _setmodel
+#define STAT_FRAGLIMIT _STAT_FRAGLIMIT
+#define STAT_TIMELIMIT _STAT_TIMELIMIT
+#define STAT_MOVEVARS_TICRATE _STAT_MOVEVARS_TICRATE
+#define STAT_MOVEVARS_TIMESCALE _STAT_MOVEVARS_TIMESCALE
+#define STAT_MOVEVARS_GRAVITY _STAT_MOVEVARS_GRAVITY
+
#include "upstream/csprogsdefs.qc"
#undef true
#undef pointparticles
#undef setmodel
-#pragma noref 0
+#undef STAT_FRAGLIMIT
+#undef STAT_TIMELIMIT
+#undef STAT_MOVEVARS_TICRATE
+#undef STAT_MOVEVARS_TIMESCALE
+#undef STAT_MOVEVARS_GRAVITY
-#define ReadFloat() ReadCoord()
+#pragma noref 0
#endif
#pragma noref 0
-#define WriteFloat(to, f) WriteCoord(to, f)
-
#endif
#include "warpzone/mathlib.qc"
#include "accumulate.qh"
+#include "arraylist.qh"
#include "bits.qh"
#include "bool.qh"
#include "color.qh"
#include "noise.qc"
#include "oo.qh"
#include "p2mathlib.qc"
-#include "player.qh"
#include "progname.qh"
#include "random.qc"
#include "registry.qh"
#include "sort.qh"
#include "spawnfunc.qh"
#include "static.qh"
+#include "stats.qh"
#include "string.qh"
#include "struct.qh"
#include "test.qc"
--- /dev/null
+#ifndef ARRAYLIST_H
+#define ARRAYLIST_H
+
+typedef int ArrayList;
+
+#define AL_declare(this) ArrayList this; int this##_len = (0)
+#define AL_init(this, n, default, T) \
+ do \
+ { \
+ this = buf_create(); \
+ this##_len = n; \
+ for (int i = 0; i < this##_len; ++i) \
+ { \
+ const _AL_type__##T() it = default; \
+ AL_set##T(this, i, it); \
+ } \
+ } \
+ while (0)
+#define AL_delete(this) buf_del(this)
+
+#define _AL_type__s() string
+#define AL_gets(this, idx) bufstr_get(this, idx)
+#define AL_sets(this, idx, val) bufstr_set(this, idx, val)
+
+#define _AL_type__f() float
+#define AL_getf(this, idx) stof(AL_gets(this, idx))
+#define AL_setf(this, idx, val) AL_sets(this, idx, ftos(val))
+
+#define _AL_type__e() entity
+#define AL_gete(this, idx) ftoe(AL_getf(this, idx))
+#define AL_sete(this, idx, val) AL_setf(this, idx, etof(val))
+
+#define AL_EACH(this, T, cond, body) \
+ do \
+ { \
+ const noref ArrayList _al = this; \
+ for (int i = 0, n = this##_len; i < n; ++i) \
+ { \
+ const noref _AL_type__##T() it = AL_get##T(_al, i); \
+ if (cond) { body } \
+ } \
+ } \
+ while (0)
+
+#endif
// Time processing and counting functions/macros
// ===============================================
-#define count_years_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
+#define count_years_decs(time, decs) sprintf(CTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
#define count_years(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d year")), /* first */ \
- ZCTX(_("CI_SEC^%d years")), /* year */ \
- ZCTX(_("CI_THI^%d years")), /* third */ \
- ZCTX(_("CI_MUL^%d years"))) /* multi */
+ CTX(_("CI_ZER^%d years")), /* zeroth */ \
+ CTX(_("CI_FIR^%d year")), /* first */ \
+ CTX(_("CI_SEC^%d years")), /* year */ \
+ CTX(_("CI_THI^%d years")), /* third */ \
+ CTX(_("CI_MUL^%d years"))) /* multi */
-#define count_weeks_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
+#define count_weeks_decs(time, decs) sprintf(CTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
#define count_weeks(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d week")), /* first */ \
- ZCTX(_("CI_SEC^%d weeks")), /* week */ \
- ZCTX(_("CI_THI^%d weeks")), /* third */ \
- ZCTX(_("CI_MUL^%d weeks"))) /* multi */
+ CTX(_("CI_ZER^%d weeks")), /* zeroth */ \
+ CTX(_("CI_FIR^%d week")), /* first */ \
+ CTX(_("CI_SEC^%d weeks")), /* week */ \
+ CTX(_("CI_THI^%d weeks")), /* third */ \
+ CTX(_("CI_MUL^%d weeks"))) /* multi */
-#define count_days_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
+#define count_days_decs(time, decs) sprintf(CTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
#define count_days(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d day")), /* first */ \
- ZCTX(_("CI_SEC^%d days")), /* day */ \
- ZCTX(_("CI_THI^%d days")), /* third */ \
- ZCTX(_("CI_MUL^%d days"))) /* multi */
+ CTX(_("CI_ZER^%d days")), /* zeroth */ \
+ CTX(_("CI_FIR^%d day")), /* first */ \
+ CTX(_("CI_SEC^%d days")), /* day */ \
+ CTX(_("CI_THI^%d days")), /* third */ \
+ CTX(_("CI_MUL^%d days"))) /* multi */
-#define count_hours_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
+#define count_hours_decs(time, decs) sprintf(CTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
#define count_hours(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d hour")), /* first */ \
- ZCTX(_("CI_SEC^%d hours")), /* hour */ \
- ZCTX(_("CI_THI^%d hours")), /* third */ \
- ZCTX(_("CI_MUL^%d hours"))) /* multi */
+ CTX(_("CI_ZER^%d hours")), /* zeroth */ \
+ CTX(_("CI_FIR^%d hour")), /* first */ \
+ CTX(_("CI_SEC^%d hours")), /* hour */ \
+ CTX(_("CI_THI^%d hours")), /* third */ \
+ CTX(_("CI_MUL^%d hours"))) /* multi */
-#define count_minutes_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
+#define count_minutes_decs(time, decs) sprintf(CTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
#define count_minutes(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d minute")), /* first */ \
- ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
- ZCTX(_("CI_THI^%d minutes")), /* third */ \
- ZCTX(_("CI_MUL^%d minutes"))) /* multi */
+ CTX(_("CI_ZER^%d minutes")), /* zeroth */ \
+ CTX(_("CI_FIR^%d minute")), /* first */ \
+ CTX(_("CI_SEC^%d minutes")), /* minute */ \
+ CTX(_("CI_THI^%d minutes")), /* third */ \
+ CTX(_("CI_MUL^%d minutes"))) /* multi */
-#define count_seconds_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
+#define count_seconds_decs(time, decs) sprintf(CTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
#define count_seconds(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d second")), /* first */ \
- ZCTX(_("CI_SEC^%d seconds")), /* second */ \
- ZCTX(_("CI_THI^%d seconds")), /* third */ \
- ZCTX(_("CI_MUL^%d seconds"))) /* multi */
+ CTX(_("CI_ZER^%d seconds")), /* zeroth */ \
+ CTX(_("CI_FIR^%d second")), /* first */ \
+ CTX(_("CI_SEC^%d seconds")), /* second */ \
+ CTX(_("CI_THI^%d seconds")), /* third */ \
+ CTX(_("CI_MUL^%d seconds"))) /* multi */
string count_ordinal(int interval)
{
// we don't do this for the local player as that one is already handled
// by CSQCPlayer_SetCamera()
- if(!CSQCPlayer_IsLocalPlayer())
- InterpolateOrigin_Do();
+ if (!CSQCPlayer_IsLocalPlayer(this)) InterpolateOrigin_Do(this);
CSQCModel_InterpolateAnimation_Do();
self.csqcmodel_teleported = 0;
}
+entity CSQCModel_players[255]; // 255 is engine limit on maxclients
+
+void CSQCModel_remove()
+{
+ SELFPARAM();
+ CSQCModel_players[this.entnum - 1] = NULL;
+}
+
NET_HANDLE(ENT_CLIENT_MODEL, bool isnew)
{
int sf = ReadInt24_t();
// some nice flags for CSQCMODEL_IF and the hooks
- bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
- bool islocalplayer = (self.entnum == player_localnum + 1);
- noref bool isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+ bool isplayer = (this.entnum >= 1 && this.entnum <= maxclients);
+ if (isnew && isplayer)
+ {
+ CSQCModel_players[this.entnum - 1] = this;
+ this.entremove = CSQCModel_remove;
+ }
+ bool islocalplayer = (this.entnum == player_localnum + 1);
+ noref bool isnolocalplayer = (isplayer && (this.entnum != player_localnum + 1));
- self.classname = "csqcmodel";
- self.iflags |= IFLAG_ORIGIN; // interpolate origin too
- self.iflags |= IFLAG_ANGLES; // interpolate angles too
- self.iflags |= IFLAG_VELOCITY | IFLAG_AUTOVELOCITY; // let's calculate velocity automatically
+ this.classname = "csqcmodel";
+ this.iflags |= IFLAG_ORIGIN; // interpolate origin too
+ this.iflags |= IFLAG_ANGLES; // interpolate angles too
+ this.iflags |= IFLAG_VELOCITY | IFLAG_AUTOVELOCITY; // let's calculate velocity automatically
{ CSQCMODEL_HOOK_PREUPDATE }
- CSQCPlayer_PreUpdate();
- InterpolateOrigin_Undo();
+ CSQCPlayer_PreUpdate(this);
+ InterpolateOrigin_Undo(this);
CSQCModel_InterpolateAnimation_PreNote(sf);
#define CSQCMODEL_IF(cond) if(cond) {
#define CSQCMODEL_ENDIF }
#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
if(sf & flag) \
- self.f = r();
+ this.f = r();
#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
if(sf & flag) \
- self.f = (r() + mi) / s;
+ this.f = (r() + mi) / s;
ALLPROPERTIES
#undef CSQCMODEL_PROPERTY_SCALED
#undef CSQCMODEL_PROPERTY
if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
{
- vector pmin = self.mins, pmax = self.maxs;
- setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
- setsize(self, pmin, pmax);
+ vector pmin = this.mins, pmax = this.maxs;
+ setmodelindex(this, this.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
+ setsize(this, pmin, pmax);
}
if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
{
- self.iflags |= IFLAG_TELEPORTED;
- self.csqcmodel_teleported = 1;
+ this.iflags |= IFLAG_TELEPORTED;
+ this.csqcmodel_teleported = 1;
}
CSQCModel_InterpolateAnimation_Note(sf);
- InterpolateOrigin_Note();
- CSQCPlayer_PostUpdate();
+ InterpolateOrigin_Note(this);
+ CSQCPlayer_PostUpdate(this);
{ CSQCMODEL_HOOK_POSTUPDATE }
#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
- InterpolateOrigin_Do();
+ InterpolateOrigin_Do(this);
CSQCModel_InterpolateAnimation_Do();
#endif
// relink
- setorigin(self, self.origin);
+ setorigin(this, this.origin);
// set obvious render flags
- if(self.entnum == player_localentnum)
- self.renderflags |= RF_EXTERNALMODEL;
+ if(this.entnum == player_localentnum)
+ this.renderflags |= RF_EXTERNALMODEL;
else
- self.renderflags &= ~RF_EXTERNALMODEL;
+ this.renderflags &= ~RF_EXTERNALMODEL;
// draw it
- self.drawmask = MASK_NORMAL;
- self.predraw = CSQCModel_Draw;
+ this.drawmask = MASK_NORMAL;
+ this.predraw = CSQCModel_Draw;
return true;
}
-entity CSQCModel_server2csqc(float pl)
+/**
+ * @param i zero indexed player
+ */
+entity CSQCModel_server2csqc(int i)
{
- return findfloat(world, entnum, pl); // FIXME optimize this using an array
+ if (i < maxclients) return CSQCModel_players[i];
+ ++i;
+ LOG_WARNINGF("player out of bounds: %d\n", i);
+ return findfloat(NULL, entnum, i);
}
#undef CSQCMODEL_ENDIF
#undef CSQCMODEL_IF
-entity CSQCModel_server2csqc(float pl);
+entity CSQCModel_server2csqc(int i);
.float csqcmodel_teleported;
// this is exported for custom frame animation code. Use with care.
#include "../../common/viewloc.qh"
float autocvar_cl_movement_errorcompensation = 0;
-int autocvar_cl_movement = 1;
// engine stuff
float pmove_onground; // weird engine flag we shouldn't really use but have to for now
vector CSQCPlayer_GetPredictionErrorO()
{
- if(time >= csqcplayer_predictionerrortime)
- return '0 0 0';
+ if (time >= csqcplayer_predictionerrortime) return '0 0 0';
return csqcplayer_predictionerroro * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor;
}
vector CSQCPlayer_GetPredictionErrorV()
{
- if(time >= csqcplayer_predictionerrortime)
- return '0 0 0';
+ if (time >= csqcplayer_predictionerrortime) return '0 0 0';
return csqcplayer_predictionerrorv * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor;
}
csqcplayer_predictionerrortime = time + 1.0 / csqcplayer_predictionerrorfactor;
}
-void CSQCPlayer_Unpredict()
-{SELFPARAM();
- if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
- return;
- if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
- error("Cannot unpredict in current status");
- self.origin = csqcplayer_origin;
- self.velocity = csqcplayer_velocity;
- csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
- self.flags = player_pmflags;
+void CSQCPlayer_Unpredict(entity this)
+{
+ if (csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED) return;
+ if (csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED) LOG_FATALF("Cannot unpredict in current status (%d)\n", csqcplayer_status);
+ this.origin = csqcplayer_origin;
+ this.velocity = csqcplayer_velocity;
+ csqcplayer_moveframe = csqcplayer_sequence + 1; // + 1 because the recieved frame has the move already done (server side)
+ this.flags = player_pmflags;
}
-void CSQCPlayer_SetMinsMaxs()
-{SELFPARAM();
- if(self.flags & FL_DUCKED)
+void CSQCPlayer_SetMinsMaxs(entity this)
+{
+ if (this.flags & FL_DUCKED)
{
- self.mins = PL_CROUCH_MIN;
- self.maxs = PL_CROUCH_MAX;
- self.view_ofs = PL_CROUCH_VIEW_OFS;
+ this.mins = PL_CROUCH_MIN;
+ this.maxs = PL_CROUCH_MAX;
+ this.view_ofs = PL_CROUCH_VIEW_OFS;
}
else
{
- self.mins = PL_MIN;
- self.maxs = PL_MAX;
- self.view_ofs = PL_VIEW_OFS;
+ this.mins = PL_MIN;
+ this.maxs = PL_MAX;
+ this.view_ofs = PL_VIEW_OFS;
}
}
-void CSQCPlayer_SavePrediction()
-{SELFPARAM();
- player_pmflags = self.flags;
- csqcplayer_origin = self.origin;
- csqcplayer_velocity = self.velocity;
+void CSQCPlayer_SavePrediction(entity this)
+{
+ player_pmflags = this.flags;
+ csqcplayer_origin = this.origin;
+ csqcplayer_velocity = this.velocity;
csqcplayer_sequence = servercommandframe;
csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
}
-void CSQC_ClientMovement_PlayerMove_Frame();
+void CSQC_ClientMovement_PlayerMove_Frame(entity this);
+void _Movetype_Physics_ClientFrame(entity this, float movedt);
-void PM_Movement_Move()
-{SELFPARAM();
- runstandardplayerphysics(self);
-#ifdef CSQC
- self.flags =
- ((self.pmove_flags & PMF_DUCKED) ? FL_DUCKED : 0) |
- (!(self.pmove_flags & PMF_JUMP_HELD) ? FL_JUMPRELEASED : 0) |
- ((self.pmove_flags & PMF_ONGROUND) ? FL_ONGROUND : 0);
-#endif
+void Movetype_Physics_Spam(entity this) // optimized
+{
+ _Movetype_Physics_ClientFrame(this, PHYS_INPUT_TIMELENGTH);
+ if(wasfreed(this))
+ return;
+
+ this.avelocity = this.move_avelocity;
+ this.velocity = this.move_velocity;
+ this.angles = this.move_angles;
+ this.flags = BITSET(this.flags, FL_ONGROUND, boolean(this.move_flags & FL_ONGROUND));
+ setorigin(this, this.move_origin);
}
-void CSQCPlayer_Physics()
+void CSQCPlayer_Physics(entity this)
{
- switch(autocvar_cl_movement)
+ if(autocvar_cl_movement)
{
- case 1: CSQC_ClientMovement_PlayerMove_Frame(); break;
- case 2: PM_Movement_Move(); break;
+ CSQC_ClientMovement_PlayerMove_Frame(this);
+
+ if(autocvar_cl_movement == 3)
+ {
+ this.move_origin = this.origin;
+ this.move_angles = this.angles;
+ //this.move_movetype = MOVETYPE_WALK; // temp
+ this.move_velocity = this.velocity;
+ this.move_avelocity = this.avelocity;
+ this.move_flags = BITSET(this.move_flags, FL_ONGROUND, boolean(this.flags & FL_ONGROUND));
+ Movetype_Physics_Spam(this);
+ }
}
}
-void CSQCPlayer_PredictTo(float endframe, float apply_error)
-{SELFPARAM();
- CSQCPlayer_Unpredict();
- if(apply_error)
+void CSQCPlayer_PredictTo(entity this, float endframe, bool apply_error)
+{
+ CSQCPlayer_Unpredict(this);
+ if (apply_error)
{
- self.origin += CSQCPlayer_GetPredictionErrorO();
- self.velocity += CSQCPlayer_GetPredictionErrorV();
+ this.origin += CSQCPlayer_GetPredictionErrorO();
+ this.velocity += CSQCPlayer_GetPredictionErrorV();
}
- CSQCPlayer_SetMinsMaxs();
+ CSQCPlayer_SetMinsMaxs(this);
csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
}
#endif
- if(csqcplayer_moveframe >= endframe)
+ if (csqcplayer_moveframe >= endframe)
{
getinputstate(csqcplayer_moveframe - 1);
}
{
do
{
- if (!getinputstate(csqcplayer_moveframe))
- break;
- CSQCPlayer_Physics();
- CSQCPlayer_SetMinsMaxs();
- csqcplayer_moveframe++;
+ if (!getinputstate(csqcplayer_moveframe)) break;
+ CSQCPlayer_Physics(this);
+ CSQCPlayer_SetMinsMaxs(this);
+ ++csqcplayer_moveframe;
}
- while(csqcplayer_moveframe < endframe);
+ while (csqcplayer_moveframe < endframe);
}
- //add in anything that was applied after (for low packet rate protocols)
+ // add in anything that was applied after (for low packet rate protocols)
input_angles = view_angles;
}
-bool CSQCPlayer_IsLocalPlayer()
-{SELFPARAM();
- return (self == csqcplayer);
+bool CSQCPlayer_IsLocalPlayer(entity this)
+{
+ return (this == csqcplayer);
}
void CSQCPlayer_SetViewLocation()
viewloc_SetViewLocation();
}
+/** Called once per CSQC_UpdateView() */
void CSQCPlayer_SetCamera()
-{SELFPARAM();
- vector v0;
- v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
-
- if(csqcplayer)
+{
+ const vector v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+ const float vh = getstati(STAT_VIEWHEIGHT);
+ const vector pl_viewofs = PL_VIEW_OFS;
+ const vector pl_viewofs_crouch = PL_CROUCH_VIEW_OFS;
+ const entity e = csqcplayer;
+ if (e)
{
- setself(csqcplayer);
-
- if(servercommandframe == 0 || clientcommandframe == 0)
+ if (servercommandframe == 0 || clientcommandframe == 0)
{
- InterpolateOrigin_Do();
- self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+ InterpolateOrigin_Do(e);
+ e.view_ofs = '0 0 1' * vh;
// get crouch state from the server
- if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
- self.flags &= ~FL_DUCKED;
- else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
- self.flags |= FL_DUCKED;
+ if (vh == pl_viewofs.z) e.flags &= ~FL_DUCKED;
+ else if (vh == pl_viewofs_crouch.z) e.flags |= FL_DUCKED;
// get onground state from the server
- if(pmove_onground)
- self.flags |= FL_ONGROUND;
- else
- self.flags &= ~FL_ONGROUND;
+ e.flags = BITSET(e.flags, FL_ONGROUND, pmove_onground);
- CSQCPlayer_SetMinsMaxs();
+ CSQCPlayer_SetMinsMaxs(e);
// override it back just in case
- self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+ e.view_ofs = '0 0 1' * vh;
// set velocity
- self.velocity = v0;
+ e.velocity = v0;
}
else
{
- float flg = self.iflags;
- self.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
- InterpolateOrigin_Do();
- self.iflags = flg;
+ const int flg = e.iflags; e.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
+ InterpolateOrigin_Do(e);
+ e.iflags = flg;
- if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
+ if (csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
{
- vector o, v;
- o = self.origin;
- v = v0;
+ const vector o = e.origin;
csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
- CSQCPlayer_PredictTo(servercommandframe + 1, false);
- CSQCPlayer_SetPredictionError(self.origin - o, self.velocity - v, pmove_onground - !!(self.flags & FL_ONGROUND));
- self.origin = o;
- self.velocity = v;
+ CSQCPlayer_PredictTo(e, servercommandframe + 1, false);
+ CSQCPlayer_SetPredictionError(e.origin - o, e.velocity - v0, pmove_onground - boolean(e.flags & FL_ONGROUND));
+ e.origin = o;
+ e.velocity = v0;
// get crouch state from the server
- if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
- self.flags &= ~FL_DUCKED;
- else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
- self.flags |= FL_DUCKED;
+ if (vh == pl_viewofs.z) e.flags &= ~FL_DUCKED;
+ else if(vh == pl_viewofs_crouch.z) e.flags |= FL_DUCKED;
// get onground state from the server
- if(pmove_onground)
- self.flags |= FL_ONGROUND;
- else
- self.flags &= ~FL_ONGROUND;
+ e.flags = BITSET(e.flags, FL_ONGROUND, pmove_onground);
- CSQCPlayer_SavePrediction();
+ CSQCPlayer_SavePrediction(e);
}
- CSQCPlayer_PredictTo(clientcommandframe + 1, true);
+ CSQCPlayer_PredictTo(e, clientcommandframe + 1, true);
#ifdef CSQCMODEL_SERVERSIDE_CROUCH
// get crouch state from the server (LAG)
- if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
- self.flags &= ~FL_DUCKED;
- else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
- self.flags |= FL_DUCKED;
+ if (vh == pl_viewofs.z) e.flags &= ~FL_DUCKED;
+ else if (vh == pl_viewofs_crouch.z) e.flags |= FL_DUCKED;
#endif
+ CSQCPlayer_SetMinsMaxs(e);
- CSQCPlayer_SetMinsMaxs();
-
- self.angles_y = input_angles.y;
+ e.angles_y = input_angles.y;
}
// relink
- setorigin(self, self.origin);
-
- setself(this);
- }
-
- entity view = CSQCModel_server2csqc(player_localentnum);
-
- if(view && view != csqcplayer)
- {
- WITH(entity, self, view, InterpolateOrigin_Do());
- view.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+ setorigin(e, e.origin);
}
- if(view)
+ const entity view = CSQCModel_server2csqc(player_localentnum - 1);
+ if (view)
{
+ if (view != csqcplayer)
+ {
+ InterpolateOrigin_Do(view);
+ view.view_ofs = '0 0 1' * vh;
+ }
int refdefflags = 0;
-
- if(view.csqcmodel_teleported)
- refdefflags |= REFDEFFLAG_TELEPORTED;
-
- if(input_buttons & 4)
- refdefflags |= REFDEFFLAG_JUMPING;
-
+ if (view.csqcmodel_teleported) refdefflags |= REFDEFFLAG_TELEPORTED;
+ if (input_buttons & BIT(1)) refdefflags |= REFDEFFLAG_JUMPING;
// note: these two only work in WIP2, but are harmless in WIP1
- if(getstati(STAT_HEALTH) <= 0)
- refdefflags |= REFDEFFLAG_DEAD;
-
- if(intermission)
- refdefflags |= REFDEFFLAG_INTERMISSION;
-
+ if (getstati(STAT_HEALTH) <= 0) refdefflags |= REFDEFFLAG_DEAD;
+ if (intermission) refdefflags |= REFDEFFLAG_INTERMISSION;
V_CalcRefdef(view, refdefflags);
}
else
// FIXME by CSQC spec we have to do this:
// but it breaks chase cam
/*
- setproperty(VF_ORIGIN, pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT));
+ setproperty(VF_ORIGIN, pmove_org + '0 0 1' * vh);
setproperty(VF_ANGLES, view_angles);
*/
}
-
- { CSQCPLAYER_HOOK_POSTCAMERASETUP }
+ CSQCPLAYER_HOOK_POSTCAMERASETUP();
}
void CSQCPlayer_Remove()
{
- csqcplayer = world;
+ csqcplayer = NULL;
cvar_settemp("cl_movement_replay", "1");
}
-float CSQCPlayer_PreUpdate()
-{SELFPARAM();
- if(self != csqcplayer)
- return 0;
- if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
- CSQCPlayer_Unpredict();
- return 1;
+bool CSQCPlayer_PreUpdate(entity this)
+{
+ if (this != csqcplayer) return false;
+ if (csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER) CSQCPlayer_Unpredict(this);
+ return true;
}
-float CSQCPlayer_PostUpdate()
-{SELFPARAM();
- if(self.entnum != player_localnum + 1)
- return 0;
- csqcplayer = self;
+bool CSQCPlayer_PostUpdate(entity this)
+{
+ if (this.entnum != player_localnum + 1) return false;
+ csqcplayer = this;
csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
cvar_settemp("cl_movement_replay", "0");
- self.entremove = CSQCPlayer_Remove;
- return 1;
+ this.entremove = CSQCPlayer_Remove;
+ return true;
}
#ifndef LIB_CSQCMODEL_CL_PLAYER_H
#define LIB_CSQCMODEL_CL_PLAYER_H
+int autocvar_cl_movement = 1;
+
entity csqcplayer;
float csqcplayer_status;
const int CSQCPLAYERSTATUS_UNPREDICTED = 0;
const int FL_DUCKED = 524288;
void CSQCPlayer_SetCamera();
-float CSQCPlayer_PreUpdate();
-float CSQCPlayer_PostUpdate();
-float CSQCPlayer_IsLocalPlayer();
+float CSQCPlayer_PreUpdate(entity this);
+float CSQCPlayer_PostUpdate(entity this);
+float CSQCPlayer_IsLocalPlayer(entity this);
#endif
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\
IN THE SOFTWARE.\
-";
+"; // "
.vector glowmod;
.vector view_ofs;
*/
#include "interpolate.qh"
-#if defined(CSQC)
-// #include "../../client/defs.qh"
-// #include "../warpzone/anglestransform.qh"
-// #include "../../client/autocvars.qh"
-// #include "cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
+// 1 = old, 2 = new
.vector iorigin1, iorigin2;
.vector ivelocity1, ivelocity2;
.vector iforward1, iforward2;
.vector ivup1, ivup2;
.float itime1, itime2;
void InterpolateOrigin_Reset()
-{SELFPARAM();
+{
+ SELFPARAM();
self.iflags &= ~IFLAG_INTERNALMASK;
self.itime1 = self.itime2 = 0;
}
-void InterpolateOrigin_Note()
-{SELFPARAM();
- float dt;
- int f0;
-
- dt = time - self.itime2;
+void InterpolateOrigin_Note(entity this)
+{
+ float dt = time - this.itime2;
- f0 = self.iflags;
- if(self.iflags & IFLAG_PREVALID)
- self.iflags |= IFLAG_VALID;
- else
- self.iflags |= IFLAG_PREVALID;
+ int f0 = this.iflags;
+ if (this.iflags & IFLAG_PREVALID) this.iflags |= IFLAG_VALID;
+ else this.iflags |= IFLAG_PREVALID;
- if(self.iflags & IFLAG_ORIGIN)
+ if (this.iflags & IFLAG_ORIGIN)
{
- self.iorigin1 = self.iorigin2;
- self.iorigin2 = self.origin;
+ this.iorigin1 = this.iorigin2;
+ this.iorigin2 = this.origin;
}
- if(self.iflags & IFLAG_AUTOANGLES)
- if(self.iorigin2 != self.iorigin1)
- self.angles = vectoangles(self.iorigin2 - self.iorigin1);
+ if (this.iflags & IFLAG_AUTOANGLES
+ && this.iorigin2
+ != this.iorigin1) this.angles = vectoangles(this.iorigin2 - this.iorigin1);
- if(self.iflags & IFLAG_AUTOVELOCITY)
- if(self.itime2 != self.itime1)
- self.velocity = (self.iorigin2 - self.iorigin1) * (1.0 / (self.itime2 - self.itime1));
+ if (this.iflags & IFLAG_AUTOVELOCITY
+ && this.itime2
+ != this.itime1) this.velocity = (this.iorigin2 - this.iorigin1) * (1.0 / (this.itime2 - this.itime1));
- if(self.iflags & IFLAG_ANGLES)
+ if (this.iflags & IFLAG_ANGLES)
{
- fixedmakevectors(self.angles);
- if(f0 & IFLAG_VALID)
+ fixedmakevectors(this.angles);
+ if (f0 & IFLAG_VALID)
{
- self.iforward1 = self.iforward2;
- self.iup1 = self.iup2;
+ this.iforward1 = this.iforward2;
+ this.iup1 = this.iup2;
}
else
{
- self.iforward1 = v_forward;
- self.iup1 = v_up;
+ this.iforward1 = v_forward;
+ this.iup1 = v_up;
}
- self.iforward2 = v_forward;
- self.iup2 = v_up;
+ this.iforward2 = v_forward;
+ this.iup2 = v_up;
}
- if(self.iflags & IFLAG_V_ANGLE)
+ if (this.iflags & IFLAG_V_ANGLE)
{
- fixedmakevectors(self.v_angle);
- if(f0 & IFLAG_VALID)
+ fixedmakevectors(this.v_angle);
+ if (f0 & IFLAG_VALID)
{
- self.ivforward1 = self.ivforward2;
- self.ivup1 = self.ivup2;
+ this.ivforward1 = this.ivforward2;
+ this.ivup1 = this.ivup2;
}
else
{
- self.ivforward1 = v_forward;
- self.ivup1 = v_up;
+ this.ivforward1 = v_forward;
+ this.ivup1 = v_up;
}
- self.ivforward2 = v_forward;
- self.ivup2 = v_up;
+ this.ivforward2 = v_forward;
+ this.ivup2 = v_up;
}
- else if(self.iflags & IFLAG_V_ANGLE_X)
+ else if (this.iflags & IFLAG_V_ANGLE_X)
{
- self.ivforward1_x = self.ivforward2_x;
- self.ivforward2_x = self.v_angle.x;
+ this.ivforward1_x = this.ivforward2_x;
+ this.ivforward2_x = this.v_angle.x;
}
- if(self.iflags & IFLAG_VELOCITY)
+ if (this.iflags & IFLAG_VELOCITY)
{
- self.ivelocity1 = self.ivelocity2;
- self.ivelocity2 = self.velocity;
+ this.ivelocity1 = this.ivelocity2;
+ this.ivelocity2 = this.velocity;
}
- if(self.iflags & IFLAG_TELEPORTED)
+ if (this.iflags & IFLAG_TELEPORTED)
{
- self.iflags &= ~IFLAG_TELEPORTED;
- self.itime1 = self.itime2 = time; // don't lerp
+ this.iflags &= ~IFLAG_TELEPORTED;
+ this.itime1 = this.itime2 = time; // don't lerp
}
- else if(vlen(self.iorigin2 - self.iorigin1) > 1000)
+ else if (vdist(this.iorigin2 - this.iorigin1, >, 1000))
{
- self.itime1 = self.itime2 = time; // don't lerp
+ this.itime1 = this.itime2 = time; // don't lerp
}
- else if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000))
+ else if ((this.iflags & IFLAG_VELOCITY) && vdist(this.ivelocity2 - this.ivelocity1, >, 1000))
{
- self.itime1 = self.itime2 = time; // don't lerp
+ this.itime1 = this.itime2 = time; // don't lerp
}
- else if(dt >= 0.2)
+ else if (dt >= 0.2)
{
- self.itime1 = self.itime2 = time;
+ this.itime1 = this.itime2 = time;
}
else
{
- self.itime1 = serverprevtime;
- self.itime2 = time;
+ this.itime1 = serverprevtime;
+ this.itime2 = time;
}
}
-void InterpolateOrigin_Do()
-{SELFPARAM();
- vector forward, up;
- if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
+
+/** set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time */
+void InterpolateOrigin_Do(entity this)
+{
+ if (this.itime1 && this.itime2 && this.itime1 != this.itime2)
{
- float f;
- f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess);
- if(self.iflags & IFLAG_ORIGIN)
- setorigin(self, (1 - f) * self.iorigin1 + f * self.iorigin2);
- if(self.iflags & IFLAG_ANGLES)
+ float f = bound(0, (time - this.itime1) / (this.itime2 - this.itime1), 1 + autocvar_cl_lerpexcess);
+ float f_1 = 1 - f;
+ if (this.iflags & IFLAG_ORIGIN) setorigin(this, f_1 * this.iorigin1 + f * this.iorigin2);
+ if (this.iflags & IFLAG_ANGLES)
{
- forward = (1 - f) * self.iforward1 + f * self.iforward2;
- up = (1 - f) * self.iup1 + f * self.iup2;
- self.angles = fixedvectoangles2(forward, up);
+ vector forward = f_1 * this.iforward1 + f * this.iforward2;
+ vector up = f_1 * this.iup1 + f * this.iup2;
+ this.angles = fixedvectoangles2(forward, up);
}
- if(self.iflags & IFLAG_V_ANGLE)
+ if (this.iflags & IFLAG_V_ANGLE)
{
- forward = (1 - f) * self.ivforward1 + f * self.ivforward2;
- up = (1 - f) * self.ivup1 + f * self.ivup2;
- self.v_angle = fixedvectoangles2(forward, up);
+ vector forward = f_1 * this.ivforward1 + f * this.ivforward2;
+ vector up = f_1 * this.ivup1 + f * this.ivup2;
+ this.v_angle = fixedvectoangles2(forward, up);
}
- else if(self.iflags & IFLAG_V_ANGLE_X)
- self.v_angle_x = (1 - f) * self.ivforward1_x + f * self.ivforward2_x;
- if(self.iflags & IFLAG_VELOCITY)
- self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
+ else if (this.iflags & IFLAG_V_ANGLE_X)
+ {
+ this.v_angle_x = f_1 * this.ivforward1.x + f * this.ivforward2.x;
+ }
+ if (this.iflags & IFLAG_VELOCITY) this.velocity = f_1 * this.ivelocity1 + f * this.ivelocity2;
}
}
-void InterpolateOrigin_Undo()
-{SELFPARAM();
- if(self.iflags & IFLAG_ORIGIN)
- setorigin(self, self.iorigin2);
- if(self.iflags & IFLAG_ANGLES)
- self.angles = fixedvectoangles2(self.iforward2, self.iup2);
- if(self.iflags & IFLAG_V_ANGLE)
- self.v_angle = fixedvectoangles2(self.ivforward2, self.ivup2);
- else if(self.iflags & IFLAG_V_ANGLE_X)
- self.v_angle_x = self.ivforward2_x;
- if(self.iflags & IFLAG_VELOCITY)
- self.velocity = self.ivelocity2;
-}
+/** snap origin to iorigin2 (actual origin) */
+void InterpolateOrigin_Undo(entity this)
+{
+ if (this.iflags & IFLAG_ORIGIN) setorigin(this, this.iorigin2);
+ if (this.iflags & IFLAG_ANGLES) this.angles = fixedvectoangles2(this.iforward2, this.iup2);
+ if (this.iflags & IFLAG_V_ANGLE) this.v_angle = fixedvectoangles2(this.ivforward2, this.ivup2);
+ else if (this.iflags & IFLAG_V_ANGLE_X) this.v_angle_x = this.ivforward2_x;
+ if (this.iflags & IFLAG_VELOCITY) this.velocity = this.ivelocity2;
+}
const int IFLAG_INTERNALMASK = IFLAG_VALID | IFLAG_PREVALID;
// call this BEFORE reading an entity update
-void InterpolateOrigin_Undo();
+void InterpolateOrigin_Undo(entity this);
// call this AFTER receiving an entity update
-void InterpolateOrigin_Note();
+void InterpolateOrigin_Note(entity this);
// call this when the entity got teleported, before InterpolateOrigin_Note
void InterpolateOrigin_Reset();
// call this BEFORE drawing
-void InterpolateOrigin_Do();
+void InterpolateOrigin_Do(entity this);
// in case we interpolate that:
.vector v_angle;
class(Defer).void() think;
class(Defer).float nextthink;
-/*
-==================
-SUB_Remove
+ /** Remove self */
+ void SUB_Remove(entity this)
+ {
+ remove(this);
+ }
-Remove self
-==================
-*/
- void SUB_Remove()
+ /** Remove self */
+ void SUB_Remove_self()
{
SELFPARAM();
- remove(self);
+ remove(this);
}
void defer_think()
{
SELFPARAM();
- self.think = SUB_Remove;
- self.nextthink = time;
- WITH(entity, self, self.owner, self.use());
+ this.think = SUB_Remove_self;
+ this.nextthink = time;
+ WITH(entity, self, this.owner, this.use());
}
/*
Execute func() after time + fdelay.
self when func is executed = self when defer is called
*/
- void defer(float fdelay, void() func)
+ void defer(entity this, float fdelay, void() func)
{
- SELFPARAM();
-
entity e = new(deferred);
make_pure(e);
e.owner = this;
do \
{ \
for (int i = start; i < end; ++i) \
- { \
- const noref entity it = arr[i]; \
- if (cond) { body } \
- } \
+ { \
+ const noref entity it = arr[i]; \
+ if (cond) { body } \
+ } \
} \
while (0)
#define FOREACH_LIST(list, next, cond, body) \
do \
- { \
- noref int i = 0; \
+ { \
+ int i = 0; \
for (entity it = list##_first; it; (it = it.next, ++i)) \
- { \
- if (cond) { body } \
- } \
+ { \
+ if (cond) { body } \
+ } \
+ } \
+ while (0)
+
+#define FOREACH_WORD(words, cond, body) \
+ do \
+ { \
+ string _words = words; \
+ int i = 0; \
+ for (string _it; (_it = car(_words)); (_words = cdr(_words), ++i)) \
+ { \
+ const noref string it = _it; \
+ if (cond) { body } \
+ } \
+ } \
+ while (0)
+
+#if defined(CSQC)
+ entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403;
+#elif defined(SVQC)
+ entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403;
+#elif defined(MENUQC)
+ entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #27;
+#endif
+
+.entity _FOREACH_ENTITY_fld;
+.entity _FOREACH_ENTITY_next;
+
+#define FOREACH_ENTITY_UNORDERED(cond, body) \
+ do { \
+ int i = 0; \
+ for (entity it = findchainentity_tofield(_FOREACH_ENTITY_fld, NULL, _FOREACH_ENTITY_next); it; (it = it._FOREACH_ENTITY_next, ++i)) \
+ { \
+ if (cond) { body } \
+ } \
} \
while (0)
+#define FOREACH_ENTITY_ORDERED(cond, body) \
+ do { \
+ int i = 0; \
+ for (entity it = NULL; (it = nextent(it)); ++i) \
+ { \
+ if (cond) { body } \
+ } \
+ } \
+ while (0)
+
+#define FOREACH_ENTITY(cond, body) FOREACH_ENTITY_UNORDERED(cond, body)
+
#define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
#endif
#define LL_NEW() NEW(LinkedList)
+#define LL_EMPTY(ll) (ll.ll_head == NULL)
+
/**
* Push to tail
*/
} \
while (0)
+#define ASSERT_LESS(name, var, const) noref int name[(const - var + 1)];
+
#endif
#define MAP_H
// Databases (hash tables)
-const float DB_BUCKETS = 8192;
-void db_save(float db, string pFilename)
+const int DB_BUCKETS = 8192;
+void db_save(int db, string filename)
{
- int fh = fopen(pFilename, FILE_WRITE);
+ int fh = fopen(filename, FILE_WRITE);
if (fh < 0)
{
- LOG_INFO(strcat("^1Can't write DB to ", pFilename));
+ LOG_WARNINGF("^1Can't write DB to %s\n", filename);
return;
}
- int n = buf_getsize(db);
fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
- for (int i = 0; i < n; ++i)
+ for (int i = 0, n = buf_getsize(db); i < n; ++i)
fputs(fh, strcat(bufstr_get(db, i), "\n"));
fclose(fh);
}
return buf_create();
}
-void db_put(float db, string pKey, string pValue);
+void db_put(int db, string key, string value);
-int db_load(string pFilename)
+int db_load(string filename)
{
int db = buf_create();
if (db < 0) return -1;
- int fh = fopen(pFilename, FILE_READ);
+ int fh = fopen(filename, FILE_READ);
if (fh < 0) return db;
string l = fgets(fh);
- if (stof(l) == DB_BUCKETS)
+ if (stoi(l) == DB_BUCKETS)
{
for (int i = 0; (l = fgets(fh)); ++i)
{
return db;
}
-void db_dump(float db, string pFilename)
+void db_dump(int db, string filename)
{
- int fh = fopen(pFilename, FILE_WRITE);
- if (fh < 0) error(strcat("Can't dump DB to ", pFilename));
- int n = buf_getsize(db);
+ int fh = fopen(filename, FILE_WRITE);
+ if (fh < 0) LOG_FATALF("Can't dump DB to %s\n");
fputs(fh, "0\n");
- for (int i = 0; i < n; ++i)
+ for (int i = 0, n = buf_getsize(db); i < n; ++i)
{
int m = tokenizebyseparator(bufstr_get(db, i), "\\");
for (int j = 2; j < m; j += 2)
fclose(fh);
}
-void db_close(float db)
+void db_close(int db)
{
buf_del(db);
}
-string db_get(float db, string pKey)
+string db_get(int db, string key)
{
- int h = crc16(false, pKey) % DB_BUCKETS;
- return uri_unescape(infoget(bufstr_get(db, h), pKey));
+ int h = crc16(false, key) % DB_BUCKETS;
+ return uri_unescape(infoget(bufstr_get(db, h), key));
}
-void db_put(float db, string pKey, string pValue)
+#define db_remove(db, key) db_put(db, key, "")
+
+void db_put(int db, string key, string value)
{
- int h = crc16(false, pKey) % DB_BUCKETS;
- bufstr_set(db, h, infoadd(bufstr_get(db, h), pKey, uri_escape(pValue)));
+ int h = crc16(false, key) % DB_BUCKETS;
+ bufstr_set(db, h, infoadd(bufstr_get(db, h), key, uri_escape(value)));
}
void db_test()
else return pow(e.(a) / e.(c), 1.0 / mean);
}
-#define MEAN_ACCUMULATE(prefix, v, w) mean_accumulate(self, prefix##_accumulator, prefix##_count, prefix##_mean, v, w)
-#define MEAN_EVALUATE(prefix) mean_evaluate(self, prefix##_accumulator, prefix##_count, prefix##_mean)
+#define MEAN_ACCUMULATE(s, prefix, v, w) mean_accumulate(s, prefix##_accumulator, prefix##_count, prefix##_mean, v, w)
+#define MEAN_EVALUATE(s, prefix) mean_evaluate(s, prefix##_accumulator, prefix##_count, prefix##_mean)
#define MEAN_DECLARE(prefix, m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
/** Returns a random number between -1.0 and 1.0 */
.int Version; // deprecated, use SendFlags
.int SendFlags;
.bool(entity to, int sendflags) SendEntity;
+ /** return false to remove from the client */
.bool(entity this, entity to, int sendflags) SendEntity3;
bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, to, sendflags); }
if (dt)
{
e.nextthink = time + dt;
- e.think = SUB_Remove;
+ e.think = SUB_Remove_self;
}
}
#ifdef CSQC
#define REGISTER_NET_LINKED(id) \
- [[accumulate]] NET_HANDLE(id, bool) \
+ [[accumulate]] NET_HANDLE(id, bool isnew) \
{ \
this = self; \
this.sourceLocFile = __FILE__; \
this.sourceLocLine = __LINE__; \
+ if (!this) isnew = true; \
} \
- REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, new(net_linked_packet)) \
+ REGISTER(LinkedEntities, NET, id, m_id, new(net_linked_packet)) \
{ \
make_pure(this); \
this.netname = #id; \
#else
#define REGISTER_NET_LINKED(id) \
const bool NET_##id##_istemp = false; \
- REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, new(net_linked_packet)) \
+ REGISTER(LinkedEntities, NET, id, m_id, new(net_linked_packet)) \
{ \
make_pure(this); \
this.netname = #id; \
REGISTRY(LinkedEntities, BITS(8) - 1)
#define LinkedEntities_from(i) _LinkedEntities_from(i, NULL)
-REGISTER_REGISTRY(RegisterLinkedEntities)
-REGISTRY_SORT(LinkedEntities, 0)
+REGISTER_REGISTRY(LinkedEntities)
+REGISTRY_SORT(LinkedEntities)
REGISTRY_CHECK(LinkedEntities)
STATIC_INIT(RegisterLinkedEntities_renumber)
{
#ifdef CSQC
#define REGISTER_NET_TEMP(id) \
NET_HANDLE(id, bool); \
- REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, new(net_temp_packet)) \
+ REGISTER(TempEntities, NET, id, m_id, new(net_temp_packet)) \
{ \
make_pure(this); \
this.netname = #id; \
#else
#define REGISTER_NET_TEMP(id) \
const bool NET_##id##_istemp = true; \
- REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, new(net_temp_packet)) \
+ REGISTER(TempEntities, NET, id, m_id, new(net_temp_packet)) \
{ \
make_pure(this); \
this.netname = #id; \
REGISTRY(TempEntities, BITS(8) - 80)
#define TempEntities_from(i) _TempEntities_from(i, NULL)
-REGISTER_REGISTRY(RegisterTempEntities)
-REGISTRY_SORT(TempEntities, 0)
+REGISTER_REGISTRY(TempEntities)
+REGISTRY_SORT(TempEntities)
REGISTRY_CHECK(TempEntities)
STATIC_INIT(RegisterTempEntities_renumber)
{
return v;
}
+ #define ReadFloat() ReadCoord()
+ vector ReadVector() { vector v; v.x = ReadFloat(); v_y = ReadFloat(); v.z = ReadFloat(); return v; }
+ vector ReadVector2D() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = 0; return v; }
+
float ReadApproxPastTime()
{
float dt = ReadByte();
WriteInt24_t(dst, val.z);
}
+ #define WriteFloat(to, f) WriteCoord(to, f)
+ #define WriteVector(to, v) do { WriteFloat(to, v.x); WriteFloat(to, v.y); WriteFloat(to, v.z); } while (0)
+ #define WriteVector2D(to, v) do { WriteFloat(to, v.x); WriteFloat(to, v.y); } while (0)
+
// this will use the value:
// 128
// accuracy near zero is APPROXPASTTIME_MAX/(256*255)
class(cname).type name; \
INIT(cname) \
{ \
+ noref bool strzone; /* Error on strzone() calls. */ \
this.name = val; \
}
+#define ATTRIB_STRZONE(cname, name, type, val) \
+ class(cname).type name; \
+ INIT(cname) \
+ { \
+ if (this.name) \
+ strunzone(this.name); \
+ this.name = strzone(val); \
+ }
+
#define ATTRIBARRAY(cname, name, type, cnt) \
class(cname).type name[cnt];
+++ /dev/null
-#ifdef CSQC
-#ifndef PLAYER_H
- #define PLAYER_H
-
- #include "string.qh"
-
- #include "../client/main.qh"
- #include "../common/teams.qh"
-
- int GetPlayerColorForce(int i)
- {
- if (!teamplay) return 0;
- else return stof(getplayerkeyvalue(i, "colors")) & 15;
- }
-
- int GetPlayerColor(int i)
- {
- if (!playerslots[i].gotscores) // unconnected
- return NUM_SPECTATOR;
- else if (stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR) return NUM_SPECTATOR;
- else return GetPlayerColorForce(i);
- }
-
- string GetPlayerName(int i)
- {
- return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
- }
-
-#endif
-#endif
#include "oo.qh"
-#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init, func)
-
-#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this)
-#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this)
+#if 1
+ #define _R_MAP(r, max) AL_declare(r); STATIC_INIT(r) { AL_init(r, max, NULL, e); }
+ #define _R_GET(r, i) AL_gete(r, i)
+ #define _R_SET(r, i, e) AL_sete(r, i, e)
+ #define _R_DEL(r) AL_delete(r)
+#else
+ #define _R_MAP(r, max) entity r[max]
+ #define _R_GET(r, i) r[i]
+ #define _R_SET(r, i, e) r[i] = e
+ #define _R_DEL(r)
+#endif
+/**
+ * Declare a new registry.
+ *
+ * Don't forget to call `REGISTER_REGISTRY`:
+ * REGISTER_REGISTRY(Foos)
+ */
#define REGISTRY(id, max) \
void Register##id() {} \
const int id##_MAX = max; \
- noref entity _##id[id##_MAX], id##_first, id##_last; \
+ noref entity id##_first, id##_last; \
+ _R_MAP(_##id, id##_MAX); \
+ SHUTDOWN(id) { _R_DEL(_##id); } \
int id##_COUNT; \
- entity _##id##_from(int i, entity null) { if (i >= 0 && i < id##_COUNT) { entity e = _##id[i]; if (e) return e; } return null; }
+ entity _##id##_from(int i, entity null) { if (i >= 0 && i < id##_COUNT) { entity e = _R_GET(_##id, i); if (e) return e; } return null; }
+
+REGISTRY(Registries, BITS(8))
/** registered item identifier */
.string registered_id;
/**
- * Register a new entity with a global constructor.
+ * Register a new entity with a registry.
* Must be followed by a semicolon or a function body with a `this` parameter.
* Wrapper macros may perform actions after user initialization like so:
* #define REGISTER_FOO(id) \
- * REGISTER(RegisterFoos, FOO, FOOS, id, m_id, NEW(Foo)); \
+ * REGISTER(Foos, FOO, id, m_id, NEW(Foo)); \
* REGISTER_INIT_POST(FOO, id) { \
* print("Registering foo #", this.m_id + 1, "\n"); \
* } \
* REGISTER_INIT(FOO, id)
*
- * Don't forget to forward declare `initfunc` and call `REGISTER_REGISTRY`:
- * void RegisterFoos();
- * REGISTER_REGISTRY(RegisterFoos)
*
- * @param initfunc The global constructor to accumulate into
+ * @param registry The registry to add each entity to.
* @param ns Short for namespace, prefix for each global (ns##_##id)
- * @param array The array to add each entity to. Also requires `array##_first` and `array##_last` to be defined
* @param id The identifier of the current entity being registered
- * @param fld The field to store the current count into
+ * @param fld The field to store the locally unique unique entity id
* @param inst An expression to create a new instance, invoked for every registration
*/
-#define REGISTER(initfunc, ns, array, id, fld, inst) \
- entity ns##_##id; \
- REGISTER_INIT(ns, id) {} \
- REGISTER_INIT_POST(ns, id) {} \
- void Register_##ns##_##id() \
+#define REGISTER(...) EVAL(OVERLOAD(REGISTER, __VA_ARGS__))
+#define REGISTER_5(registry, ns, id, fld, inst) REGISTER_4(registry, ns##_##id, fld, inst)
+#define REGISTER_4(registry, id, fld, inst) \
+ entity id; \
+ REGISTER_INIT(id) {} \
+ REGISTER_INIT_POST(id) {} \
+ void Register_##id() \
{ \
- if (array##_COUNT >= array##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(array##_MAX)); \
- entity this = inst; \
- ns##_##id = this; \
+ if (registry##_COUNT >= registry##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(registry##_MAX)); \
+ entity this = id = inst; \
this.registered_id = #id; \
- this.fld = array##_COUNT; \
- _##array[array##_COUNT++] = this; \
- if (!array##_first) array##_first = this; \
- if (array##_last) array##_last.REGISTRY_NEXT = this; \
- array##_last = this; \
- Register_##ns##_##id##_init(this); \
- Register_##ns##_##id##_init_post(this); \
+ REGISTRY_PUSH(registry, fld, this); \
+ Register_##id##_init(this); \
+ Register_##id##_init_post(this); \
} \
- ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \
- REGISTER_INIT(ns, id)
+ ACCUMULATE_FUNCTION(Register##registry, Register_##id) \
+ REGISTER_INIT(id)
+
+#define REGISTRY_PUSH(registry, fld, it) do { \
+ it.fld = registry##_COUNT; \
+ _R_SET(_##registry, registry##_COUNT, it); \
+ ++registry##_COUNT; \
+ if (!registry##_first) registry##_first = it; \
+ if (registry##_last) registry##_last.REGISTRY_NEXT = it; \
+ registry##_last = it; \
+} while (0)
+
+#define REGISTRY_RESERVE(registry, fld, id, suffix) do { \
+ entity e = new(registry_reserved); \
+ e.registered_id = #id "/" #suffix; \
+ REGISTRY_PUSH(registry, fld, e); \
+} while (0)
+
+#define REGISTER_INIT(id) [[accumulate]] void Register_##id##_init(entity this)
+#define REGISTER_INIT_POST(id) [[accumulate]] void Register_##id##_init_post(entity this)
/** internal next pointer */
#define REGISTRY_NEXT enemy
.entity REGISTRY_NEXT;
-#define REGISTRY_SORT(id, skip) \
+#define REGISTRY_SORT(...) EVAL(OVERLOAD(REGISTRY_SORT, __VA_ARGS__))
+#define REGISTRY_SORT_1(id) REGISTRY_SORT_2(id, 0)
+#define REGISTRY_SORT_2(id, skip) \
void _REGISTRY_SWAP_##id(int i, int j, entity pass) \
{ \
i += skip; j += skip; \
\
- entity a = _##id[i], b = _##id[j]; \
- _##id[i] = b; \
- _##id[j] = a; \
+ entity a = _R_GET(_##id, i), b = _R_GET(_##id, j); \
+ _R_SET(_##id, i, b); \
+ _R_SET(_##id, j, a); \
\
entity a_next = a.REGISTRY_NEXT, b_next = b.REGISTRY_NEXT; \
a.REGISTRY_NEXT = b_next; \
b.REGISTRY_NEXT = a_next; \
\
if (i == 0) id##_first = b; \
- else _##id[i - 1].REGISTRY_NEXT = b; \
+ else _R_GET(_##id, i - 1).REGISTRY_NEXT = b; \
\
if (j == 0) id##_first = a; \
- else _##id[j - 1].REGISTRY_NEXT = a; \
+ else _R_GET(_##id, j - 1).REGISTRY_NEXT = a; \
} \
int _REGISTRY_CMP_##id(int i, int j, entity pass) \
{ \
i += skip; j += skip; \
- string a = _##id[i].registered_id; \
- string b = _##id[j].registered_id; \
+ string a = _R_GET(_##id, i).registered_id; \
+ string b = _R_GET(_##id, j).registered_id; \
return strcmp(a, b); \
} \
STATIC_INIT(Registry_sort_##id) \
string h = REGISTRY_HASH(id) = strzone(digest_hex(algo, s)); \
LOG_TRACEF(#id ": %s\n[%s]\n", h, s); \
} \
- [[accumulate]] void Registry_check(string r, string sv) \
+ void Registry_check(string r, string sv) \
{ \
if (r == #id) \
{ \
} \
} \
} \
- [[accumulate]] void Registry_send_all() { Registry_send(#id, REGISTRY_HASH(id)); } \
+ void Registry_send_all() { Registry_send(#id, REGISTRY_HASH(id)); } \
+
+#define REGISTER_REGISTRY(...) EVAL(OVERLOAD(REGISTER_REGISTRY, __VA_ARGS__))
+#define REGISTER_REGISTRY_1(id) REGISTER_REGISTRY_2(id, #id)
+#define REGISTER_REGISTRY_2(id, str) \
+ ACCUMULATE_FUNCTION(__static_init, Register##id) \
+ CLASS(id##Registry, Object) \
+ ATTRIB(id##Registry, m_name, string, str) \
+ ATTRIB(id##Registry, REGISTRY_NEXT, entity, id##_first) \
+ ENDCLASS(id##Registry) \
+ REGISTER(Registries, REGISTRY, id, m_id, NEW(id##Registry));
+
#endif
#define _spawnfunc_check(fld) \
if (fieldname == #fld) continue;
- #define spawnfunc_1(id, whitelist) spawnfunc_2(id, whitelist)
+ bool __spawnfunc_unreachable_workaround = true;
+
+ #define spawnfunc_1(id) spawnfunc_2(id, FIELDS_UNION)
#define spawnfunc_2(id, whitelist) \
- void spawnfunc_##id(entity this) \
+ void __spawnfunc_##id(entity this); \
+ [[accumulate]] void spawnfunc_##id(entity this) \
{ \
this = self; \
if (!this.sourceLocFile) \
} \
this.spawnfunc_checked = true; \
} \
+ __spawnfunc_##id(this); \
+ if (__spawnfunc_unreachable_workaround) return; \
} \
- [[accumulate]] void spawnfunc_##id(entity this)
+ void __spawnfunc_##id(entity this)
#define FIELD_SCALAR(fld, n) \
fld(n)
FIELD_VEC(fld, velocity) \
/**/
- #define spawnfunc(...) EVAL(OVERLOAD(spawnfunc, __VA_ARGS__, FIELDS_UNION))
+ #define spawnfunc(...) EVAL(OVERLOAD(spawnfunc, __VA_ARGS__))
#endif
#define static_init_late() CALL_ACCUMULATED_FUNCTION(__static_init_late)
void __static_init_precache() {}
#define static_init_precache() CALL_ACCUMULATED_FUNCTION(__static_init_precache)
+void __shutdown() {}
+#define shutdownhooks() CALL_ACCUMULATED_FUNCTION(__shutdown)
#define _STATIC_INIT(where, func) \
void _static_##func(); \
#define STATIC_INIT(func) _STATIC_INIT(__static_init, func)
#define STATIC_INIT_LATE(func) _STATIC_INIT(__static_init_late, func##_late)
#define PRECACHE(func) _STATIC_INIT(__static_init_precache, func##_precache)
+#define SHUTDOWN(func) _STATIC_INIT(__shutdown, func##_shutdown)
#endif
--- /dev/null
+#ifndef LIB_STATS_H
+#define LIB_STATS_H
+
+// TODO: rename to 'netvars'
+
+#include "registry.qh"
+#include "sort.qh"
+
+.int m_id;
+typedef vector vectori;
+
+#define REGISTER_STAT(...) EVAL(OVERLOAD(REGISTER_STAT, __VA_ARGS__))
+#if defined(CSQC)
+ /** Get all stats and store them as globals, access with `STAT(ID)` */
+ void stats_get() {}
+ #define STAT(...) EVAL(OVERLOAD(STAT, __VA_ARGS__))
+ #define STAT_1(id) STAT_2(id, NULL)
+ #define STAT_2(id, cl) (0, _STAT(id))
+
+ #define getstat_int(id) getstati(id, 0, 24)
+ #define getstat_bool(id) boolean(getstati(id))
+ #define getstat_float(id) getstatf(id)
+ #define getstat_vector(id) vec3(getstat_float(id + 0), getstat_float(id + 1), getstat_float(id + 2))
+ #define getstat_vectori(id) vec3(getstat_int(id + 0), getstat_int(id + 1), getstat_int(id + 2))
+
+ #define _STAT(id) g_stat_##id
+ #define REGISTER_STAT_2(id, T) \
+ T _STAT(id); \
+ REGISTER(Stats, STAT_##id, m_id, new(stat)) \
+ { \
+ make_pure(this); \
+ if (#T == "vector" || #T == "vectori") { \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+ } \
+ } \
+ [[accumulate]] void stats_get() \
+ { \
+ _STAT(id) = getstat_##T(STAT_##id.m_id); \
+ }
+ #define REGISTER_STAT_3(x, T, expr) REGISTER_STAT(x, T)
+#elif defined(SVQC)
+ /** Add all registered stats, access with `STAT(ID, player)` or `.type stat = _STAT(ID); player.stat` */
+ void stats_add() {}
+ #define STAT(id, cl) (cl._STAT(id))
+
+ #define addstat_int(id, fld) addstat(id, AS_INT, fld)
+ #define addstat_bool(id, fld) addstat(id, AS_INT, fld)
+ #define addstat_float(id, fld) addstat(id, AS_FLOAT, fld)
+ #define addstat_vector(id, fld) do { \
+ addstat_float(id + 0, fld##_x); \
+ addstat_float(id + 1, fld##_y); \
+ addstat_float(id + 2, fld##_z); \
+ } while (0)
+ #define addstat_vectori(id, fld) do { \
+ addstat_int(id + 0, fld##_x); \
+ addstat_int(id + 1, fld##_y); \
+ addstat_int(id + 2, fld##_z); \
+ } while (0)
+ const int AS_STRING = 1;
+ const int AS_INT = 2;
+ const int AS_FLOAT = 8;
+
+ .int __stat_null;
+ /** Prevent engine stats being sent */
+ STATIC_INIT(stats_clear)
+ {
+ int r = 32;
+ for (int i = 0, n = 256 - r; i < n; ++i) {
+ addstat(r + i, AS_INT, __stat_null);
+ }
+ }
+
+ #define _STAT(id) stat_##id
+ #define REGISTER_STAT_2(id, T) \
+ .T _STAT(id); \
+ REGISTER(Stats, STAT_##id, m_id, new(stat)) \
+ { \
+ make_pure(this); \
+ if (#T == "vector" || #T == "vectori") { \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+ } \
+ } \
+ [[accumulate]] void stats_add() \
+ { \
+ addstat_##T(STAT_##id.m_id, _STAT(id)); \
+ }
+ void GlobalStats_update(entity this) {}
+ #define REGISTER_STAT_3(x, T, expr) \
+ REGISTER_STAT(x, T); \
+ [[accumulate]] void GlobalStats_update(entity this) { STAT(x, this) = (expr); } \
+ STATIC_INIT(worldstat_##x) { entity this = world; STAT(x, this) = (expr); }
+#else
+ #define REGISTER_STAT_2(id, type)
+ #define REGISTER_STAT_3(x, T, expr)
+#endif
+
+const int STATS_ENGINE_RESERVE = 32;
+
+REGISTRY(Stats, 256 - STATS_ENGINE_RESERVE)
+REGISTER_REGISTRY(Stats)
+REGISTRY_SORT(Stats)
+REGISTRY_CHECK(Stats)
+STATIC_INIT(RegisterStats_renumber)
+{
+ FOREACH(Stats, true, LAMBDA(it.m_id = STATS_ENGINE_RESERVE + i));
+}
+#ifdef SVQC
+STATIC_INIT(stats_add) { stats_add(); }
+#endif
+
+#endif
#ifndef VECTOR_H
#define VECTOR_H
+noref vector _vlen2;
+#define vlen2(v) \
+ (_vlen2 = (v), \
+ _vlen2.x * _vlen2.x \
+ + _vlen2.y * _vlen2.y \
+ + _vlen2.z * _vlen2.z)
+
+noref float _vdist_f;
+/** Vector distance comparison, avoids sqrt() */
+#define vdist(v, cmp, f) (vlen2(v) cmp (_vdist_f = (f), _vdist_f * _vdist_f))
+/*
+#define vdist(v, cmp, f) (vlen(v) cmp (f))
+*/
+
+#define cross(a, b) ((a) >< (b))
+/*
+vector cross(vector a, vector b)
+{
+ return
+ '1 0 0' * (a.y * b.z - a.z * b.y)
+ + '0 1 0' * (a.z * b.x - a.x * b.z)
+ + '0 0 1' * (a.x * b.y - a.y * b.x);
+}
+*/
+
const vector eX = '1 0 0';
const vector eY = '0 1 0';
const vector eZ = '0 0 1';
return v;
}
-float vlen2d(vector v)
-{
- return sqrt(v.x * v.x + v.y * v.y);
-}
-
float vlen_maxnorm2d(vector v)
{
return max(v.x, v.y, -v.x, -v.y);
up = v_up; \
} while (0)
-vector vec2(vector v)
-{
- v.z = 0;
- return v;
-}
+noref vector _vec2;
+#define vec2(v) (_vec2 = (v), _vec2.z = 0, _vec2)
-vector vec3(float x, float y, float z)
-{
- vector v;
- v.x = x;
- v.y = y;
- v.z = z;
- return v;
-}
+noref vector _vec3;
+#define vec3(x, y, z) (_vec3_x = (x), _vec3_y = (y), _vec3_z = (z), _vec3)
vector rotate(vector v, float a)
{
return r;
}
-vector yinvert(vector v)
-{
- v.y = 1 - v.y;
- return v;
-}
+noref vector _yinvert;
+#define yinvert(v) (_yinvert = (v), _yinvert.y = 1 - _yinvert.y, _yinvert)
#ifndef MENUQC
vector get_corner_position(entity box, int corner)
#include "anglestransform.qh"
-#ifdef POSITIVE_PITCH_IS_DOWN
-vector fixedvectoangles(vector a)
-{
- vector ang;
- ang = vectoangles(a);
- ang.x = -ang.x;
- return ang;
-}
-vector fixedvectoangles2(vector a, vector b)
-{
- vector ang;
- ang = vectoangles2(a, b);
- ang.x = -ang.x;
- return ang;
-}
-#else
-void fixedmakevectors(vector a)
-{
- // a makevectors that actually inverts vectoangles
- a.x = -a.x;
- makevectors(a);
-}
-#endif
-
// angles transforms
// angles in fixedmakevectors/fixedvectoangles space
vector AnglesTransform_Apply(vector transform, vector v)
return t;
}
-#ifdef POSITIVE_PITCH_IS_DOWN
+#if POSITIVE_PITCH_IS_DOWN
vector AnglesTransform_ApplyToAngles(vector transform, vector v)
{
v.x = -v.x;
#ifndef LIB_WARPZONE_ANGLETRANSFORM_H
#define LIB_WARPZONE_ANGLETRANSFORM_H
-#define POSITIVE_PITCH_IS_DOWN
+#ifndef POSITIVE_PITCH_IS_DOWN
+#define POSITIVE_PITCH_IS_DOWN 1
+#endif
-#ifdef POSITIVE_PITCH_IS_DOWN
-#define fixedmakevectors makevectors
-vector fixedvectoangles(vector a);
-vector fixedvectoangles2(vector a, vector b);
+#if POSITIVE_PITCH_IS_DOWN
+ #define fixedmakevectors makevectors
+ noref vector _fixedvectoangles;
+ #define fixedvectoangles(a) (_fixedvectoangles = vectoangles(a), _fixedvectoangles.x *= -1, _fixedvectoangles)
+ noref vector _fixedvectoangles2;
+ #define fixedvectoangles2(a, b) (_fixedvectoangles2 = vectoangles2(a, b), _fixedvectoangles2.x *= -1, _fixedvectoangles2)
#else
-void fixedmakevectors(vector a);
-#define fixedvectoangles2 vectoangles2
-#define fixedvectoangles vectoangles
+ void fixedmakevectors(vector a)
+ {
+ // a makevectors that actually inverts vectoangles
+ a.x = -a.x;
+ makevectors(a);
+ }
+ #define fixedvectoangles2 vectoangles2
+ #define fixedvectoangles vectoangles
#endif
vector AnglesTransform_Apply(vector transform, vector v);
if (is_pure(e)) return true;
switch (s)
{
- case "entcs_sender":
- case "entcs_receiver":
// case "net_linked": // actually some real entities are linked without classname, fail
case "":
return true;
{
return !(x < y || x == y || x > y);
}
-
-vector cross(vector a, vector b)
-{
- return
- '1 0 0' * (a.y * b.z - a.z * b.y)
- + '0 1 0' * (a.z * b.x - a.x * b.z)
- + '0 0 1' * (a.x * b.y - a.y * b.x);
-}
const float M_SQRT2 = 1.41421356237309504880; /* sqrt(2) */
const float M_SQRT1_2 = 0.70710678118654752440; /* 1/sqrt(2) */
-// Non-<math.h> stuff follows here.
-vector cross(vector a, vector b);
-
#endif
ts.SendEntity = WarpZone_Teleported_Send;
ts.SendFlags = 0xFFFFFF;
ts.drawonlytoclient = player;
- ts.think = SUB_Remove;
+ ts.think = SUB_Remove_self;
ts.nextthink = time + 1;
ts.owner = player;
ts.enemy = wz;
}
void WarpZone_StartFrame()
-{SELFPARAM();
- entity e;
- if(warpzone_initialized == 0)
+{
+ SELFPARAM();
+ if (!warpzone_initialized)
{
- warpzone_initialized = 1;
- for(setself(warpzone_first); self; setself(self.warpzone_next))
+ warpzone_initialized = true;
+ for (setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_FindOriginTarget();
- for(setself(warpzone_position_first); self; setself(self.warpzone_next))
+ for (setself(warpzone_position_first); self; setself(self.warpzone_next))
WarpZonePosition_InitStep_FindTarget();
- for(setself(warpzone_first); self; setself(self.warpzone_next))
+ for (setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_UpdateTransform();
setself(this);
WarpZones_Reconnect();
WarpZone_PostInitialize_Callback();
}
- entity oldother;
- oldother = other;
- for(e = world; (e = nextent(e)); )
+ entity oldother = other;
+ for (entity e = world; (e = nextent(e)); )
{
- if(warpzone_warpzones_exist) { WarpZone_StoreProjectileData(e); }
-
- if(IS_REAL_CLIENT(e))
+ if (warpzone_warpzones_exist) WarpZone_StoreProjectileData(e);
+ if (IS_REAL_CLIENT(e))
{
- if(e.solid == SOLID_NOT) // not spectating?
- if(e.movetype == MOVETYPE_NOCLIP || e.movetype == MOVETYPE_FLY || e.movetype == MOVETYPE_FLY_WORLDONLY) // not spectating? (this is to catch observers)
+ if (e.solid == SOLID_NOT) // not spectating?
+ if (e.movetype == MOVETYPE_NOCLIP || e.movetype == MOVETYPE_FLY || e.movetype == MOVETYPE_FLY_WORLDONLY) // not spectating? (this is to catch observers)
{
other = e; // player
// warpzones
- if(warpzone_warpzones_exist) {
- setself(WarpZone_Find(e.origin + e.mins, e.origin + e.maxs));
- if(self)
- if(!WarpZoneLib_ExactTrigger_Touch())
- if(WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0)
- WarpZone_Teleport(self, e, -1, 0); } // NOT triggering targets by this!
+ if (warpzone_warpzones_exist) {
+ setself(WarpZone_Find(e.origin + e.mins, e.origin + e.maxs));
+ if (self)
+ if (!WarpZoneLib_ExactTrigger_Touch())
+ if (WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0)
+ WarpZone_Teleport(self, e, -1, 0); // NOT triggering targets by this!
+ }
// teleporters
setself(Teleport_Find(e.origin + e.mins, e.origin + e.maxs));
- if(self)
- if(!WarpZoneLib_ExactTrigger_Touch())
+ if (self)
+ if (!WarpZoneLib_ExactTrigger_Touch())
Simple_TeleportPlayer(self, other); // NOT triggering targets by this!
}
}
-
- if(IS_NOT_A_CLIENT(e))
+ else if (IS_NOT_A_CLIENT(e))
{
- if(warpzone_warpzones_exist)
- for (; (e = nextent(e)); )
+ if (warpzone_warpzones_exist)
+ while ((e = nextent(e)))
WarpZone_StoreProjectileData(e);
break;
}
}
.float warpzone_reconnecting;
-float visible_to_some_client(entity ent)
+bool visible_to_some_client(entity ent)
{
- entity e;
- for(e = nextent(world); !IS_NOT_A_CLIENT(e); e = nextent(e))
- if(IS_PLAYER(e) && IS_REAL_CLIENT(e))
- if(checkpvs(e.origin + e.view_ofs, ent))
- return 1;
- return 0;
+ FOREACH_ENTITY(!IS_NOT_A_CLIENT(it), LAMBDA(
+ if (IS_PLAYER(it) && IS_REAL_CLIENT(it) && checkpvs(it.origin + it.view_ofs, ent)) return true;
+ ));
+ return false;
}
void trigger_warpzone_reconnect_use()
{SELFPARAM();
if (argc == 1)
{
LOG_INFO(_("Available options:\n"));
- float i;
- entity e;
- string s;
- for (i = 0, e = NULL; (e = nextent(e)); )
- if (e.classname != "vtbl" && e.name != "")
+ FOREACH_ENTITY_ORDERED(it.name != "", LAMBDA(
+ if (it.classname == "vtbl") continue;
+ string s = it.name;
+ if (filter)
{
- s = e.name;
- if (filter)
- {
- if (substring(s, 0, strlen(filter)) != filter) continue;
- s = substring(s, strlen(filter), strlen(s) - strlen(filter));
- }
- LOG_INFO(strcat(" ", s, "\n"));
- ++i;
+ if (!startsWith(s, filter)) continue;
+ s = substring(s, strlen(filter), strlen(s) - strlen(filter));
}
+ LOG_INFOF(" %s\n", s);
+ ));
}
else if (argc == 2 && !isdemo()) // don't allow this command in demos
{
REGISTRY(Settings, BITS(3))
#define Settings_from(i) _Settings_from(i, NULL)
-REGISTER_REGISTRY(RegisterSettings)
+REGISTER_REGISTRY(Settings)
#define REGISTER_SETTINGS(id, impl) \
LAZY_NEW(id, impl) \
- REGISTER(RegisterSettings, MENU, Settings, id, m_id, NEW(Lazy, LAZY(id)))
+ REGISTER(Settings, MENU, id, m_id, NEW(Lazy, LAZY(id)))
#endif
#endif
#define ITEM_H
#include "skin.qh"
CLASS(Item, Object)
- METHOD(Item, draw, void(entity));
- METHOD(Item, keyDown, float(entity, float, float, float));
- METHOD(Item, keyUp, float(entity, float, float, float));
- METHOD(Item, mouseMove, float(entity, vector));
- METHOD(Item, mousePress, float(entity, vector));
- METHOD(Item, mouseDrag, float(entity, vector));
- METHOD(Item, mouseRelease, float(entity, vector));
- METHOD(Item, focusEnter, void(entity));
- METHOD(Item, focusLeave, void(entity));
- METHOD(Item, resizeNotify, void(entity, vector, vector, vector, vector));
- METHOD(Item, relinquishFocus, void(entity));
- METHOD(Item, showNotify, void(entity));
- METHOD(Item, hideNotify, void(entity));
- METHOD(Item, toString, string(entity));
- METHOD(Item, destroy, void(entity));
+ METHOD(Item, draw, void(Item));
+ METHOD(Item, keyDown, float(Item, float, float, float));
+ METHOD(Item, keyUp, float(Item, float, float, float));
+ METHOD(Item, mouseMove, float(Item, vector));
+ METHOD(Item, mousePress, float(Item, vector));
+ METHOD(Item, mouseDrag, float(Item, vector));
+ METHOD(Item, mouseRelease, float(Item, vector));
+ METHOD(Item, focusEnter, void(Item));
+ METHOD(Item, focusLeave, void(Item));
+ METHOD(Item, resizeNotify, void(Item, vector, vector, vector, vector));
+ METHOD(Item, relinquishFocus, void(Item));
+ METHOD(Item, showNotify, void(Item));
+ METHOD(Item, hideNotify, void(Item));
+ METHOD(Item, toString, string(Item));
+ METHOD(Item, destroy, void(Item));
ATTRIB(Item, focused, float, 0)
ATTRIB(Item, focusable, float, 0)
ATTRIB(Item, allowFocusSound, float, 0)
#endif
#ifdef IMPLEMENTATION
-void Item_destroy(entity me)
-{
- // free memory associated with me
-}
-
-void Item_relinquishFocus(entity me)
-{
- if(me.parent)
- if(me.parent.instanceOfContainer)
- me.parent.setFocus(me.parent, NULL);
-}
-
-void Item_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- me.origin = absOrigin;
- me.size = absSize;
-}
-
-float autocvar_menu_showboxes;
-void Item_draw(entity me)
-{
- if(autocvar_menu_showboxes)
+ METHOD(Item, destroy, void(Item this))
{
+ // free memory associated with this
+ }
+
+ METHOD(Item, relinquishFocus, void(Item this))
+ {
+ entity par = this.parent;
+ if (!par) return;
+ if (par.instanceOfContainer) par.setFocus(par, NULL);
+ }
+
+ METHOD(Item, resizeNotify, void(Item this, vector relOrigin, vector relSize, vector absOrigin, vector absSize))
+ {
+ this.origin = absOrigin;
+ this.size = absSize;
+ }
+
+ int autocvar_menu_showboxes;
+ METHOD(Item, draw, void(Item this))
+ {
+ if (!autocvar_menu_showboxes) return;
vector rgb = '1 0 1';
float a = fabs(autocvar_menu_showboxes);
// don't draw containers and border images
- if(me.instanceOfContainer || me.instanceOfBorderImage)
+ if (this.instanceOfContainer || this.instanceOfBorderImage)
{
rgb = '0 0 0';
a = 0;
}
-#if 0
- // hack to detect multi drawing
- float r = random() * 3;
- if(r >= 2)
- rgb = '1 0 0';
- else if(r >= 1)
- rgb = '0 1 0';
- else
- rgb = '0 0 1';
-#endif
- if(autocvar_menu_showboxes < 0)
+ #if 0
+ // hack to detect multi drawing
+ float r = random() * 3;
+ if (r >= 2) rgb = '1 0 0';
+ else if (r >= 1) rgb = '0 1 0';
+ else rgb = '0 0 1';
+ #endif
+ if (autocvar_menu_showboxes < 0)
{
draw_Fill('0 0 0', '0.5 0.5 0', rgb, a);
draw_Fill('0.5 0.5 0', '0.5 0.5 0', rgb, a);
}
- if(autocvar_menu_showboxes > 0)
+ else if (autocvar_menu_showboxes > 0)
{
draw_Fill('0 0 0', '1 1 0', rgb, a);
}
}
-}
-
-void Item_showNotify(entity me)
-{
-}
-
-void Item_hideNotify(entity me)
-{
-}
-
-float Item_keyDown(entity me, float scan, float ascii, float shift)
-{
- return 0; // unhandled
-}
-
-float Item_keyUp(entity me, float scan, float ascii, float shift)
-{
- return 0; // unhandled
-}
-
-float Item_mouseMove(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-float Item_mousePress(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-float Item_mouseDrag(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-float Item_mouseRelease(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-void Item_focusEnter(entity me)
-{
- if(me.allowFocusSound)
- m_play_focus_sound();
-}
-
-void Item_focusLeave(entity me)
-{
-}
-
-string Item_toString(entity me)
-{
- return string_null;
-}
+
+ METHOD(Item, showNotify, void(Item this))
+ {}
+
+ METHOD(Item, hideNotify, void(Item this))
+ {}
+
+ METHOD(Item, keyDown, float(Item this, float scan, float ascii, float shift))
+ {
+ return 0; // unhandled
+ }
+
+ METHOD(Item, keyUp, float(Item this, float scan, float ascii, float shift))
+ {
+ return 0; // unhandled
+ }
+
+ METHOD(Item, mouseMove, float(Item this, vector pos))
+ {
+ return 0; // unhandled
+ }
+
+ METHOD(Item, mousePress, float(Item this, vector pos))
+ {
+ return 0; // unhandled
+ }
+
+ METHOD(Item, mouseDrag, float(Item this, vector pos))
+ {
+ return 0; // unhandled
+ }
+
+ METHOD(Item, mouseRelease, float(Item this, vector pos))
+ {
+ return 0; // unhandled
+ }
+
+ METHOD(Item, focusEnter, void(Item this))
+ {
+ if (this.allowFocusSound) m_play_focus_sound();
+ }
+
+ METHOD(Item, focusLeave, void(Item this))
+ {}
+
+ METHOD(Item, toString, string(Item this))
+ {
+ return string_null;
+ }
#endif
save = draw_alpha;
if (me.disabled) draw_alpha *= me.disabledAlpha;
draw_ButtonPicture('0 0 0', strcat(me.src, "_s"), eX * (1 - me.textSpace) + eY, me.color2, 1);
+ if (me.valueMax > me.valueMin) // valid?
if (almost_in_bounds(me.valueMin, me.sliderValue, me.valueMax))
{
controlLeft = (me.sliderValue - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth);
me.sliderAnim = NULL;
}
- me.setText(me, me.valueToText(me, me.value));
+ if (me.valueMax > me.valueMin) // valid?
+ me.setText(me, me.valueToText(me, me.value));
draw_alpha = save;
SUPER(Slider).draw(me);
me.text = string_null; // TEMPSTRING!
#include "../common/mapinfo.qh"
#include "../common/mutators/base.qh"
-///////////////////////////////////////////////
-// Menu Source File
-///////////////////////
-// This file belongs to dpmod/darkplaces
-// AK contains all menu functions (especially the required ones)
-///////////////////////////////////////////////
-
-float mouseButtonsPressed;
+int mouseButtonsPressed;
vector menuMousePos;
int menuShiftState;
float menuPrevTime;
float menuAlpha;
float menuLogoAlpha;
float prevMenuAlpha;
-float menuInitialized;
-float menuNotTheFirstFrame;
-float menuMouseMode;
+bool menuInitialized;
+bool menuNotTheFirstFrame;
+int menuMouseMode;
-float conwidth_s, conheight_s, vidwidth_s, vidheight_s, vidpixelheight_s,
- realconwidth, realconheight;
+float conwidth_s, conheight_s;
+float vidwidth_s, vidheight_s, vidpixelheight_s;
+float realconwidth, realconheight;
void m_sync()
{
updateCompression();
- vidwidth_s = vidheight_s = vidpixelheight_s = 0; // Force updateConwidths on next draw.
+ vidwidth_s = vidheight_s = vidpixelheight_s = 0; // Force updateConwidths on next draw
loadAllCvars(main);
}
void m_gamestatus()
{
gamestatus = 0;
- if(isserver())
- gamestatus = gamestatus | GAME_ISSERVER;
- if(clientstate() == CS_CONNECTED || isdemo())
- gamestatus = gamestatus | GAME_CONNECTED;
- if(cvar("developer"))
- gamestatus = gamestatus | GAME_DEVELOPER;
+ if (isserver()) gamestatus |= GAME_ISSERVER;
+ if (clientstate() == CS_CONNECTED || isdemo()) gamestatus |= GAME_CONNECTED;
+ if (cvar("developer")) gamestatus |= GAME_DEVELOPER;
}
void m_init()
{
- float restarting = 0;
+ bool restarting = false;
cvar_set("_menu_alpha", "0");
prvm_language = cvar_string("prvm_language");
- if(prvm_language == "")
+ if (prvm_language == "")
{
prvm_language = "en";
cvar_set("prvm_language", prvm_language);
localcmd("\nmenu_restart\n");
- restarting = 1;
+ restarting = true;
}
prvm_language = strzone(prvm_language);
cvar_set("_menu_prvm_language", prvm_language);
#ifdef WATERMARK
- LOG_TRACEF("^4MQC Build information: ^1%s\n", WATERMARK);
+ LOG_INFOF("^4MQC Build information: ^1%s\n", WATERMARK);
#endif
// list all game dirs (TEST)
- if(cvar("developer"))
+ if (cvar("developer"))
{
- float i;
- string s;
- for(i = 0; ; ++i)
+ for (int i = 0; ; ++i)
{
- s = getgamedirinfo(i, GETGAMEDIRINFO_NAME);
- if (!s)
- break;
+ string s = getgamedirinfo(i, GETGAMEDIRINFO_NAME);
+ if (!s) break;
LOG_TRACE(s, ": ", getgamedirinfo(i, GETGAMEDIRINFO_DESCRIPTION));
}
}
float ddsload = cvar("r_texture_dds_load");
float texcomp = cvar("gl_texturecompression");
updateCompression();
- if(ddsload != cvar("r_texture_dds_load") || texcomp != cvar("gl_texturecompression"))
- localcmd("\nr_restart\n");
+ if (ddsload != cvar("r_texture_dds_load") || texcomp != cvar("gl_texturecompression")) localcmd("\nr_restart\n");
- if(!restarting)
+ if (!restarting)
{
- if(cvar("_menu_initialized")) // always show menu after menu_restart
+ if (cvar("_menu_initialized")) // always show menu after menu_restart
m_display();
- else
- m_hide();
+ else m_hide();
cvar_set("_menu_initialized", "1");
}
-
}
-const float MENU_ASPECT = 1.25; // 1280x1024
+const float MENU_ASPECT = 1280 / 1024;
void draw_reset_cropped()
{
{
if (w != vidwidth_s || h != vidheight_s || p != vidpixelheight_s)
{
- if (updateConwidths(w, h, p))
- localcmd(sprintf("\nexec %s\n", cvar_string("menu_font_cfg")));
+ if (updateConwidths(w, h, p)) localcmd(sprintf("\nexec %s\n", cvar_string("menu_font_cfg")));
vidwidth_s = w;
vidheight_s = h;
vidpixelheight_s = p;
conheight_s = conheight;
realconwidth = cvar("vid_conwidth");
realconheight = cvar("vid_conheight");
- if(realconwidth / realconheight > MENU_ASPECT)
+ if (realconwidth / realconheight > MENU_ASPECT)
{
// widescreen
conwidth = realconheight * MENU_ASPECT;
conwidth = realconwidth;
conheight = realconwidth / MENU_ASPECT;
}
- if(main)
+ if (main)
{
- if(conwidth_s != conwidth || conheight_s != conheight)
+ if (conwidth_s != conwidth || conheight_s != conheight)
{
draw_reset_cropped();
main.resizeNotify(main, '0 0 0', eX * conwidth + eY * conheight, '0 0 0', eX * conwidth + eY * conheight);
}
else
{
- vidwidth_s = vidheight_s = vidpixelheight_s = 0; // retry next frame
+ vidwidth_s = vidheight_s = vidpixelheight_s = 0; // retry next frame
}
}
string m_goto_buffer;
void m_init_delayed()
{
- float fh, glob, n, i;
- string s;
-
draw_reset_cropped();
- menuInitialized = 0;
- if(!preMenuInit())
- return;
- menuInitialized = 1;
+ menuInitialized = false;
+ if (!preMenuInit()) return;
+ menuInitialized = true;
- fh = -1;
- if(cvar_string("menu_skin") != "")
+ int fh = -1;
+ if (cvar_string("menu_skin") != "")
{
draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
fh = fopen(language_filename(strcat(draw_currentSkin, "/skinvalues.txt")), FILE_READ);
}
- if(fh < 0)
- if(cvar_defstring("menu_skin") != "")
+ if (fh < 0 && cvar_defstring("menu_skin") != "")
{
cvar_set("menu_skin", cvar_defstring("menu_skin"));
draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
fh = fopen(language_filename(strcat(draw_currentSkin, "/skinvalues.txt")), FILE_READ);
}
- if(fh < 0)
+ if (fh < 0)
{
draw_currentSkin = "gfx/menu/default";
fh = fopen(language_filename(strcat(draw_currentSkin, "/skinvalues.txt")), FILE_READ);
}
- if(fh < 0)
- {
- error("cannot load any menu skin\n");
- }
+ if (fh < 0) error("cannot load any menu skin\n");
draw_currentSkin = strzone(draw_currentSkin);
- while((s = fgets(fh)))
+ for (string s; (s = fgets(fh)); )
{
// these two are handled by skinlist.qc
- if(substring(s, 0, 6) == "title ")
- continue;
- if(substring(s, 0, 7) == "author ")
- continue;
- n = tokenize_console(s);
- if(n >= 2)
- Skin_ApplySetting(argv(0), substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
+ if (substring(s, 0, 6) == "title ") continue;
+ if (substring(s, 0, 7) == "author ") continue;
+ int n = tokenize_console(s);
+ if (n < 2) continue;
+ Skin_ApplySetting(argv(0), substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
}
fclose(fh);
- glob = search_begin(strcat(draw_currentSkin, "/*.tga"), true, true);
- if(glob >= 0)
+ int glob = search_begin(strcat(draw_currentSkin, "/*.tga"), true, true);
+ if (glob >= 0)
{
- n = search_getsize(glob);
- for(i = 0; i < n; ++i)
+ for (int i = 0, n = search_getsize(glob); i < n; ++i)
precache_pic(search_getfilename(glob, i));
search_end(glob);
}
draw_setMousePointer(SKINGFX_CURSOR, SKINSIZE_CURSOR, SKINOFFSET_CURSOR);
anim = NEW(AnimHost);
- main = NEW(MainWindow); main.configureMainWindow(main);
+ main = NEW(MainWindow);
+ main.configureMainWindow(main);
main.resizeNotify(main, '0 0 0', eX * conwidth + eY * conheight, '0 0 0', eX * conwidth + eY * conheight);
- main.focused = 1;
+ main.focused = true;
menuShiftState = 0;
menuMousePos = '0.5 0.5 0';
m_sync();
- if(m_goto_buffer)
+ if (m_goto_buffer)
{
m_goto(m_goto_buffer);
strunzone(m_goto_buffer);
m_goto_buffer = string_null;
}
- if(Menu_Active)
- m_display(); // delayed menu display
+ if (Menu_Active) m_display(); // delayed menu display
}
-void m_keyup (float key, float ascii)
+void m_keyup(float key, float ascii)
{
- if(!menuInitialized)
- return;
- if(!Menu_Active)
- return;
+ if (!menuInitialized) return;
+ if (!Menu_Active) return;
draw_reset_cropped();
main.keyUp(main, key, ascii, menuShiftState);
- if(key >= K_MOUSE1 && key <= K_MOUSE3)
+ if (key >= K_MOUSE1 && key <= K_MOUSE3)
{
--mouseButtonsPressed;
- if(!mouseButtonsPressed)
- main.mouseRelease(main, menuMousePos);
- if(mouseButtonsPressed < 0)
+ if (!mouseButtonsPressed) main.mouseRelease(main, menuMousePos);
+ if (mouseButtonsPressed < 0)
{
mouseButtonsPressed = 0;
LOG_TRACE("Warning: released an already released button\n");
}
}
- if(key == K_ALT) menuShiftState -= (menuShiftState & S_ALT);
- if(key == K_CTRL) menuShiftState -= (menuShiftState & S_CTRL);
- if(key == K_SHIFT) menuShiftState -= (menuShiftState & S_SHIFT);
+ if (key == K_ALT) menuShiftState &= ~S_ALT;
+ if (key == K_CTRL) menuShiftState &= ~S_CTRL;
+ if (key == K_SHIFT) menuShiftState &= ~S_SHIFT;
}
void m_keydown(float key, float ascii)
{
- if(!menuInitialized)
- return;
- if(!Menu_Active)
- return;
+ if (!menuInitialized) return;
+ if (!Menu_Active) return;
- if(menuMouseMode)
- if(key >= K_MOUSE1 && key <= K_MOUSE3)
+ if (menuMouseMode && key >= K_MOUSE1 && key <= K_MOUSE3)
{
// detect a click outside of the game window
vector p = getmousepos();
- if(p.x < 0 || p.x > realconwidth || p.y < 0 || p.y > realconheight)
+ if (p.x < 0 || p.x > realconwidth || p.y < 0 || p.y > realconheight)
{
++mouseButtonsPressed;
return;
}
}
- if(keyGrabber)
+ if (keyGrabber)
{
- entity e;
- e = keyGrabber;
+ entity e = keyGrabber;
keyGrabber = NULL;
e.keyGrabbed(e, key, ascii);
}
else
{
draw_reset_cropped();
- if(key >= K_MOUSE1 && key <= K_MOUSE3)
- if(!mouseButtonsPressed)
- main.mousePress(main, menuMousePos);
- if(!main.keyDown(main, key, ascii, menuShiftState))
- if(key == K_ESCAPE)
- if(gamestatus & (GAME_ISSERVER | GAME_CONNECTED)) // don't back out to console only
- m_hide(); // disable menu on unhandled ESC
+ if (!mouseButtonsPressed && key >= K_MOUSE1 && key <= K_MOUSE3) main.mousePress(main, menuMousePos);
+ if (!main.keyDown(main, key, ascii, menuShiftState))
+ {
+ // disable menu on unhandled ESC
+ if (key == K_ESCAPE)
+ if (gamestatus & (GAME_ISSERVER | GAME_CONNECTED)) // don't back out to console only
+ m_hide();
+ }
}
- if(key >= K_MOUSE1 && key <= K_MOUSE3)
+ if (key >= K_MOUSE1 && key <= K_MOUSE3)
{
++mouseButtonsPressed;
- if(mouseButtonsPressed > 10)
+ if (mouseButtonsPressed > 10)
{
mouseButtonsPressed = 10;
LOG_TRACE("Warning: pressed an already pressed button\n");
}
}
- if(key == K_ALT) menuShiftState |= S_ALT;
- if(key == K_CTRL) menuShiftState |= S_CTRL;
- if(key == K_SHIFT) menuShiftState |= S_SHIFT;
+ if (key == K_ALT) menuShiftState |= S_ALT;
+ if (key == K_CTRL) menuShiftState |= S_CTRL;
+ if (key == K_SHIFT) menuShiftState |= S_SHIFT;
}
-const float SCALEMODE_CROP = 0;
-const float SCALEMODE_LETTERBOX = 1;
-const float SCALEMODE_WIDTH = 2;
-const float SCALEMODE_HEIGHT = 3;
-const float SCALEMODE_STRETCH = 4;
+enum {
+ SCALEMODE_CROP,
+ SCALEMODE_LETTERBOX,
+ SCALEMODE_WIDTH,
+ SCALEMODE_HEIGHT,
+ SCALEMODE_STRETCH,
+};
void draw_Picture_Aligned(vector algn, float scalemode, string img, float a)
{
- vector sz, org, isz, isz_w, isz_h;
- float width_is_larger;
-
- sz = draw_PictureSize(img);
- width_is_larger = (sz.x * draw_scale.y >= sz.y * draw_scale.x);
- isz_w = '1 0 0' + '0 1 0' * ((sz.y / sz.x) * (draw_scale.x / draw_scale.y));
- isz_h = '0 1 0' + '1 0 0' * ((sz.x / sz.y) * (draw_scale.y / draw_scale.x));
-
- switch(scalemode)
+ vector sz = draw_PictureSize(img);
+ bool width_is_larger = (sz.x * draw_scale.y >= sz.y * draw_scale.x);
+ vector isz_w = '1 0 0' + '0 1 0' * ((sz.y / sz.x) * (draw_scale.x / draw_scale.y));
+ vector isz_h = '0 1 0' + '1 0 0' * ((sz.x / sz.y) * (draw_scale.y / draw_scale.x));
+ vector isz;
+ switch (scalemode)
{
default:
case SCALEMODE_CROP:
isz = '1 1 0';
break;
}
-
- org = eX * (algn.x * (1 - isz.x)) + eY * (algn.y * (1 - isz.y));
+ vector org = eX * (algn.x * (1 - isz.x)) + eY * (algn.y * (1 - isz.y));
draw_Picture(org, img, isz, '1 1 1', a);
}
void drawBackground(string img, float a, string algn, float force1)
{
- if(main.mainNexposee.ModalController_state == 0)
- return;
-
- vector v;
- float i, l;
- string c;
- float scalemode;
-
- v.z = 0;
-
- scalemode = SCALEMODE_CROP;
-
- l = 0;
- for(i = 0; i < strlen(algn); ++i)
+ if (main.mainNexposee.ModalController_state == 0) return;
+ vector v = '0 0 0';
+ int scalemode = SCALEMODE_CROP;
+ for (int i = 0, l = 0; i < strlen(algn); ++i)
{
- c = substring(algn, i, 1);
- switch(c)
+ string c = substring(algn, i, 1);
+ switch (c)
{
- case "c": scalemode = SCALEMODE_CROP; goto nopic;
- case "l": scalemode = SCALEMODE_LETTERBOX; goto nopic;
- case "h": scalemode = SCALEMODE_HEIGHT; goto nopic;
- case "w": scalemode = SCALEMODE_WIDTH; goto nopic;
- case "s": scalemode = SCALEMODE_STRETCH; goto nopic;
- case "1": case "4": case "7": v.x = 0.0; break;
- case "2": case "5": case "8": v.x = 0.5; break;
- case "3": case "6": case "9": v.x = 1.0; break;
- default: v.x = random(); break;
+ case "c":
+ scalemode = SCALEMODE_CROP;
+ goto nopic;
+ case "l":
+ scalemode = SCALEMODE_LETTERBOX;
+ goto nopic;
+ case "h":
+ scalemode = SCALEMODE_HEIGHT;
+ goto nopic;
+ case "w":
+ scalemode = SCALEMODE_WIDTH;
+ goto nopic;
+ case "s":
+ scalemode = SCALEMODE_STRETCH;
+ goto nopic;
+ case "1": case "4": case "7":
+ v.x = 0.0;
+ break;
+ case "2": case "5": case "8":
+ v.x = 0.5;
+ break;
+ case "3": case "6": case "9":
+ v.x = 1.0;
+ break;
+ default:
+ v.x = random();
+ break;
}
- switch(c)
+ switch (c)
{
- case "7": case "8": case "9": v.y = 0.0; break;
- case "4": case "5": case "6": v.y = 0.5; break;
- case "1": case "2": case "3": v.y = 1.0; break;
- default: v.y = random(); break;
+ case "7": case "8": case "9":
+ v.y = 0.0;
+ break;
+ case "4": case "5": case "6":
+ v.y = 0.5;
+ break;
+ case "1": case "2": case "3":
+ v.y = 1.0;
+ break;
+ default:
+ v.y = random();
+ break;
}
- if(l == 0)
+ if (l == 0)
+ {
draw_Picture_Aligned(v, scalemode, img, a);
- else if(force1)
+ }
+ else if (force1)
+ {
// force all secondary layers to use alpha 1. Prevents ugly issues
// with overlap. It's a flag because it cannot be used for the
// ingame background
- draw_Picture_Aligned(v, scalemode, strcat(img, "_l", ftos(l+1)), 1);
+ draw_Picture_Aligned(v, scalemode, strcat(img, "_l", ftos(l + 1)), 1);
+ }
else
- draw_Picture_Aligned(v, scalemode, strcat(img, "_l", ftos(l+1)), a);
+ {
+ draw_Picture_Aligned(v, scalemode, strcat(img, "_l", ftos(l + 1)), a);
+ }
++l;
-:nopic
+ : nopic
}
}
-float menu_tooltips;
-float menu_tooltips_old;
+int menu_tooltips;
+int menu_tooltips_old;
vector menuTooltipAveragedMousePos;
entity menuTooltipItem;
vector menuTooltipOrigin;
vector menuTooltipSize;
float menuTooltipAlpha;
string menuTooltipText;
-float menuTooltipState; // 0: static, 1: fading in, 2: fading out, 3: forced fading out
-float m_testmousetooltipbox(vector pos)
+int menuTooltipState; // 0: static, 1: fading in, 2: fading out, 3: forced fading out
+bool m_testmousetooltipbox(vector pos)
{
- if(pos.x >= menuTooltipOrigin.x && pos.x < menuTooltipOrigin.x + menuTooltipSize.x)
- if(pos.y >= menuTooltipOrigin.y && pos.y < menuTooltipOrigin.y + menuTooltipSize.y)
- return false;
- return true;
+ return !(
+ (pos.x >= menuTooltipOrigin.x && pos.x < menuTooltipOrigin.x + menuTooltipSize.x)
+ && (pos.y >= menuTooltipOrigin.y && pos.y < menuTooltipOrigin.y + menuTooltipSize.y)
+ );
}
-float m_testtooltipbox(vector tooltippos)
+bool m_testtooltipbox(vector tooltippos)
{
- if(tooltippos.x < 0)
- return false;
- if(tooltippos.y < 0)
- return false;
- if(tooltippos.x + menuTooltipSize.x > 1)
- return false;
- if(tooltippos.y + menuTooltipSize.y > 1)
- return false;
+ if (tooltippos.x < 0) return false;
+ if (tooltippos.y < 0) return false;
+ if (tooltippos.x + menuTooltipSize.x > 1) return false;
+ if (tooltippos.y + menuTooltipSize.y > 1) return false;
menuTooltipOrigin = tooltippos;
return true;
}
-float m_allocatetooltipbox(vector pos)
+bool m_allocatetooltipbox(vector pos)
{
- vector avoidplus, avoidminus;
- vector v;
-
+ vector avoidplus;
avoidplus.x = (SKINAVOID_TOOLTIP_x + SKINSIZE_CURSOR_x - SKINOFFSET_CURSOR_x * SKINSIZE_CURSOR_x) / conwidth;
avoidplus.y = (SKINAVOID_TOOLTIP_y + SKINSIZE_CURSOR_y - SKINOFFSET_CURSOR_y * SKINSIZE_CURSOR_y) / conheight;
avoidplus.z = 0;
+ vector avoidminus;
avoidminus.x = (SKINAVOID_TOOLTIP_x + SKINOFFSET_CURSOR_x * SKINSIZE_CURSOR_x) / conwidth + menuTooltipSize.x;
avoidminus.y = (SKINAVOID_TOOLTIP_y + SKINOFFSET_CURSOR_y * SKINSIZE_CURSOR_y) / conheight + menuTooltipSize.y;
avoidminus.z = 0;
// bottom right
- v = pos + avoidplus;
- if(m_testtooltipbox(v))
- return true;
+ vector v = pos + avoidplus;
+ if (m_testtooltipbox(v)) return true;
// bottom center
v.x = pos.x - menuTooltipSize.x * 0.5;
- if(m_testtooltipbox(v))
- return true;
+ if (m_testtooltipbox(v)) return true;
// bottom left
v.x = pos.x - avoidminus.x;
- if(m_testtooltipbox(v))
- return true;
+ if (m_testtooltipbox(v)) return true;
// top left
v.y = pos.y - avoidminus.y;
- if(m_testtooltipbox(v))
- return true;
+ if (m_testtooltipbox(v)) return true;
// top center
v.x = pos.x - menuTooltipSize.x * 0.5;
- if(m_testtooltipbox(v))
- return true;
+ if (m_testtooltipbox(v)) return true;
// top right
v.x = pos.x + avoidplus.x;
- if(m_testtooltipbox(v))
- return true;
+ if (m_testtooltipbox(v)) return true;
return false;
}
entity m_findtooltipitem(entity root, vector pos)
{
- entity it;
- entity best;
-
- best = NULL;
- it = root;
-
- while(it.instanceOfContainer)
+ entity best = NULL;
+ for (entity it = root; it.instanceOfContainer; )
{
- while(it.instanceOfNexposee && it.focusedChild)
+ while (it.instanceOfNexposee && it.focusedChild)
{
it = it.focusedChild;
pos = globalToBox(pos, it.Container_origin, it.Container_size);
}
- if(it.instanceOfNexposee)
+ if (it.instanceOfNexposee)
{
it = it.itemFromPoint(it, pos);
- if(it.tooltip)
- best = it;
- else if(menu_tooltips == 2 && (it.cvarName || it.onClickCommand))
- best = it;
+ if (it.tooltip) best = it;
+ else if (menu_tooltips == 2 && (it.cvarName || it.onClickCommand)) best = it;
it = NULL;
}
- else if(it.instanceOfModalController)
+ else if (it.instanceOfModalController)
+ {
it = it.focusedChild;
+ }
else
+ {
it = it.itemFromPoint(it, pos);
- if(!it)
- break;
- if(it.tooltip)
- best = it;
- else if(menu_tooltips == 2 && (it.cvarName || it.onClickCommand))
- best = it;
+ }
+ if (!it) break;
+ if (it.tooltip) best = it;
+ else if (menu_tooltips == 2 && (it.cvarName || it.onClickCommand)) best = it;
pos = globalToBox(pos, it.Container_origin, it.Container_size);
}
string s;
if (menuTooltipItem.cvarName)
{
- if (getCvarsMulti(menuTooltipItem))
- s = strcat("[", menuTooltipItem.cvarName, " ", getCvarsMulti(menuTooltipItem), "]");
- else
- s = strcat("[", menuTooltipItem.cvarName, "]");
+ if (getCvarsMulti(menuTooltipItem)) s =
+ strcat("[", menuTooltipItem.cvarName, " ", getCvarsMulti(menuTooltipItem), "]");
+ else s = strcat("[", menuTooltipItem.cvarName, "]");
}
else if (menuTooltipItem.onClickCommand)
+ {
s = strcat("<", menuTooltipItem.onClickCommand, ">");
+ }
else
+ {
return menuTooltipItem.tooltip;
- if (menuTooltipItem.tooltip)
- return strcat(menuTooltipItem.tooltip, " ", s);
+ }
+ if (menuTooltipItem.tooltip) return strcat(menuTooltipItem.tooltip, " ", s);
return s;
}
return menuTooltipItem.tooltip;
}
-string prev_tooltip;
void m_tooltip(vector pos)
{
- float f, i, w;
+ static string prev_tooltip;
entity it;
- vector fontsize, p;
- string s;
-
menu_tooltips = cvar("menu_tooltips");
if (!menu_tooltips)
{
// don't return immediately, fade out the active tooltip first
- if (menuTooltipItem == NULL)
- return;
+ if (menuTooltipItem == NULL) return;
it = NULL;
menu_tooltips_old = menu_tooltips;
}
else
{
- f = bound(0, frametime * 2, 1);
+ float f = bound(0, frametime * 2, 1);
menuTooltipAveragedMousePos = menuTooltipAveragedMousePos * (1 - f) + pos * f;
f = vlen(pos - menuTooltipAveragedMousePos);
- if(f < 0.01)
+ if (f < 0.01)
{
it = m_findtooltipitem(main, pos);
- if(it.instanceOfListBox && it.isScrolling(it))
- it = world;
+ if (it.instanceOfListBox && it.isScrolling(it)) it = world;
- if(it && prev_tooltip != it.tooltip)
+ if (it && prev_tooltip != it.tooltip)
{
// fade out if tooltip of a certain item has changed
menuTooltipState = 3;
- if(prev_tooltip)
- strunzone(prev_tooltip);
+ if (prev_tooltip) strunzone(prev_tooltip);
prev_tooltip = strzone(it.tooltip);
}
- else if(menuTooltipItem && !m_testmousetooltipbox(pos))
- menuTooltipState = 3; // fade out if mouse touches it
-
+ else if (menuTooltipItem && !m_testmousetooltipbox(pos))
+ {
+ menuTooltipState = 3; // fade out if mouse touches it
+ }
}
else
+ {
it = NULL;
+ }
}
- fontsize = '1 0 0' * (SKINFONTSIZE_TOOLTIP / conwidth) + '0 1 0' * (SKINFONTSIZE_TOOLTIP / conheight);
+ vector fontsize = '1 0 0' * (SKINFONTSIZE_TOOLTIP / conwidth) + '0 1 0' * (SKINFONTSIZE_TOOLTIP / conheight);
// float menuTooltipState; // 0: static, 1: fading in, 2: fading out, 3: forced fading out
- if(it != menuTooltipItem)
+ if (it != menuTooltipItem)
{
- switch(menuTooltipState)
+ switch (menuTooltipState)
{
case 0:
- if(menuTooltipItem)
+ if (menuTooltipItem)
{
// another item: fade out first
menuTooltipState = 2;
menuTooltipState = 1;
menuTooltipItem = it;
- menuTooltipOrigin.x = -1; // unallocated
+ menuTooltipOrigin.x = -1; // unallocated
- if (menuTooltipText)
- strunzone(menuTooltipText);
+ if (menuTooltipText) strunzone(menuTooltipText);
menuTooltipText = strzone(gettooltip());
- i = 0;
- w = 0;
- getWrappedLine_remaining = menuTooltipText;
- while(getWrappedLine_remaining)
+ int i = 0;
+ float w = 0;
+ for (getWrappedLine_remaining = menuTooltipText; getWrappedLine_remaining; ++i)
{
- s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors);
- ++i;
- f = draw_TextWidth(s, false, fontsize);
- if(f > w)
- w = f;
+ string s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors);
+ float f = draw_TextWidth(s, false, fontsize);
+ if (f > w) w = f;
}
menuTooltipSize.x = w + 2 * (SKINMARGIN_TOOLTIP_x / conwidth);
menuTooltipSize.y = i * fontsize.y + 2 * (SKINMARGIN_TOOLTIP_y / conheight);
break;
}
}
- else if(menuTooltipState == 2) // re-fade in?
+ else if (menuTooltipState == 2) // re-fade in?
+ {
menuTooltipState = 1;
+ }
- switch(menuTooltipState)
+ switch (menuTooltipState)
{
- case 1: // fade in
+ case 1: // fade in
menuTooltipAlpha = bound(0, menuTooltipAlpha + 5 * frametime, 1);
- if(menuTooltipAlpha == 1)
- menuTooltipState = 0;
+ if (menuTooltipAlpha == 1) menuTooltipState = 0;
break;
- case 2: // fade out
- case 3: // forced fade out
+ case 2: // fade out
+ case 3: // forced fade out
menuTooltipAlpha = bound(0, menuTooltipAlpha - 2 * frametime, 1);
- if(menuTooltipAlpha == 0)
+ if (menuTooltipAlpha == 0)
{
menuTooltipState = 0;
menuTooltipItem = NULL;
break;
}
- if(menuTooltipItem == NULL)
+ if (menuTooltipItem == NULL)
{
if (menuTooltipText)
{
}
else
{
- if(menu_tooltips != menu_tooltips_old)
+ if (menu_tooltips != menu_tooltips_old)
{
- if (menu_tooltips != 0 && menu_tooltips_old != 0)
- menuTooltipItem = NULL; // reload tooltip next frame
+ if (menu_tooltips != 0 && menu_tooltips_old != 0) menuTooltipItem = NULL; // reload tooltip next frame
menu_tooltips_old = menu_tooltips;
}
- else if(menuTooltipOrigin.x < 0) // unallocated?
+ else if (menuTooltipOrigin.x < 0) // unallocated?
+ {
m_allocatetooltipbox(pos);
-
- if(menuTooltipOrigin.x >= 0)
+ }
+ if (menuTooltipOrigin.x >= 0)
{
// draw the tooltip!
- p = SKINBORDER_TOOLTIP;
+ vector p = SKINBORDER_TOOLTIP;
p.x *= 1 / conwidth;
p.y *= 1 / conheight;
draw_BorderPicture(menuTooltipOrigin, SKINGFX_TOOLTIP, menuTooltipSize, '1 1 1', menuTooltipAlpha, p);
p = menuTooltipOrigin;
p.x += SKINMARGIN_TOOLTIP_x / conwidth;
p.y += SKINMARGIN_TOOLTIP_y / conheight;
- getWrappedLine_remaining = menuTooltipText;
- while(getWrappedLine_remaining)
+ for (getWrappedLine_remaining = menuTooltipText; getWrappedLine_remaining; p.y += fontsize.y)
{
- s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors);
+ string s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors);
draw_Text(p, s, fontsize, SKINCOLOR_TOOLTIP, SKINALPHA_TOOLTIP * menuTooltipAlpha, false);
- p.y += fontsize.y;
}
}
}
void m_draw(float width, float height)
{
- float t;
- float realFrametime;
-
m_gamestatus();
execute_next_frame();
menuMouseMode = cvar("menu_mouse_absolute");
- if (anim)
- anim.tickAll(anim);
+ if (anim) anim.tickAll(anim);
UpdateConWidthHeight(width, height, cvar("vid_pixelheight"));
- if(!menuInitialized)
+ if (!menuInitialized)
{
// TODO draw an info image about this situation
m_init_delayed();
return;
}
- if(!menuNotTheFirstFrame)
+ if (!menuNotTheFirstFrame)
{
- menuNotTheFirstFrame = 1;
- if(Menu_Active)
- if(!cvar("menu_video_played"))
- {
- localcmd("cd loop $menu_cdtrack; play sound/announcer/default/welcome.wav\n");
- menuLogoAlpha = -0.8; // no idea why, but when I start this at zero, it jumps instead of fading FIXME
- }
+ menuNotTheFirstFrame = true;
+ if (Menu_Active && !cvar("menu_video_played"))
+ {
+ localcmd("cd loop $menu_cdtrack; play sound/announcer/default/welcome.wav\n");
+ menuLogoAlpha = -0.8; // no idea why, but when I start this at zero, it jumps instead of fading FIXME
+ }
// ALWAYS set this cvar; if we start but menu is not active, this means we want no background music!
localcmd("set menu_video_played 1\n");
}
- t = gettime();
- realFrametime = frametime = min(0.2, t - menuPrevTime);
+ float t = gettime();
+ float realFrametime = frametime = min(0.2, t - menuPrevTime);
menuPrevTime = t;
time += frametime;
t = cvar("menu_slowmo");
- if(t)
+ if (t)
{
frametime *= t;
realFrametime *= t;
}
else
+ {
t = 1;
+ }
- if(Menu_Active)
+ if (Menu_Active)
{
- if(getmousetarget() == (menuMouseMode ? MT_CLIENT : MT_MENU) && (getkeydest() == KEY_MENU || getkeydest() == KEY_MENU_GRABBED))
- setkeydest(keyGrabber ? KEY_MENU_GRABBED : KEY_MENU);
- else
- m_hide();
+ if (getmousetarget() == (menuMouseMode ? MT_CLIENT : MT_MENU)
+ && (getkeydest() == KEY_MENU || getkeydest() == KEY_MENU_GRABBED))
+ setkeydest(keyGrabber ? KEY_MENU_GRABBED : KEY_MENU);
+ else m_hide();
}
- if(cvar("cl_capturevideo"))
- frametime = t / cvar("cl_capturevideo_fps"); // make capturevideo work smoothly
+ if (cvar("cl_capturevideo")) frametime = t / cvar("cl_capturevideo_fps"); // make capturevideo work smoothly
prevMenuAlpha = menuAlpha;
- if(Menu_Active)
+ if (Menu_Active)
{
- if(menuAlpha == 0 && menuLogoAlpha < 2)
+ if (menuAlpha == 0 && menuLogoAlpha < 2)
{
- menuLogoAlpha = menuLogoAlpha + frametime * 2;
+ menuLogoAlpha += 2 * frametime;
}
else
{
- menuAlpha = min(1, menuAlpha + frametime * 5);
+ menuAlpha = min(1, menuAlpha + 5 * frametime);
menuLogoAlpha = 2;
}
}
else
{
- menuAlpha = max(0, menuAlpha - frametime * 5);
+ menuAlpha = max(0, menuAlpha - 5 * frametime);
menuLogoAlpha = 2;
}
draw_reset_cropped();
- if(!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)))
+ if (!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)))
{
- if(menuLogoAlpha > 0)
+ if (menuLogoAlpha > 0)
{
draw_reset_full();
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_BACKGROUND, 1);
drawBackground(SKINGFX_BACKGROUND, bound(0, menuLogoAlpha, 1), SKINALIGN_BACKGROUND, true);
draw_reset_cropped();
- if(menuAlpha <= 0 && SKINALPHA_CURSOR_INTRO > 0)
+ if (menuAlpha <= 0 && SKINALPHA_CURSOR_INTRO > 0)
{
draw_alpha = SKINALPHA_CURSOR_INTRO * bound(0, menuLogoAlpha, 1);
draw_drawMousePointer(menuMousePos);
}
}
}
- else if(SKINALPHA_BACKGROUND_INGAME)
+ else if (SKINALPHA_BACKGROUND_INGAME)
{
- if(menuAlpha > 0)
+ if (menuAlpha > 0)
{
draw_reset_full();
- drawBackground(SKINGFX_BACKGROUND_INGAME, menuAlpha * SKINALPHA_BACKGROUND_INGAME, SKINALIGN_BACKGROUND_INGAME, false);
+ drawBackground(SKINGFX_BACKGROUND_INGAME, menuAlpha * SKINALPHA_BACKGROUND_INGAME,
+ SKINALIGN_BACKGROUND_INGAME, false);
draw_reset_cropped();
}
}
- if(menuAlpha != prevMenuAlpha)
- cvar_set("_menu_alpha", ftos(menuAlpha));
+ if (menuAlpha != prevMenuAlpha) cvar_set("_menu_alpha", ftos(menuAlpha));
draw_reset_cropped();
preMenuDraw();
draw_reset_cropped();
- if(menuAlpha <= 0)
+ if (menuAlpha <= 0)
{
- if(prevMenuAlpha > 0)
- main.initializeDialog(main, main.firstChild);
+ if (prevMenuAlpha > 0) main.initializeDialog(main, main.firstChild);
draw_reset_cropped();
postMenuDraw();
return;
draw_alpha *= menuAlpha;
- if(!Menu_Active)
+ if (!Menu_Active)
{
// do not update mouse position
// it prevents mouse jumping to '0 0 0' when menu is fading out
}
- else if(menuMouseMode)
+ else if (menuMouseMode)
{
- vector newMouse;
- newMouse = globalToBox(getmousepos(), draw_shift, draw_scale);
- if(newMouse != '0 0 0')
- if(newMouse != menuMousePos)
- {
- menuMousePos = newMouse;
- if(mouseButtonsPressed)
- main.mouseDrag(main, menuMousePos);
- else
- main.mouseMove(main, menuMousePos);
- }
+ vector newMouse = globalToBox(getmousepos(), draw_shift, draw_scale);
+ if (newMouse != '0 0 0' && newMouse != menuMousePos)
+ {
+ menuMousePos = newMouse;
+ if (mouseButtonsPressed) main.mouseDrag(main, menuMousePos);
+ else main.mouseMove(main, menuMousePos);
+ }
}
- else
+ else if (frametime > 0)
{
- if(frametime > 0)
+ vector dMouse = getmousepos() * (frametime / realFrametime); // for capturevideo
+ if (dMouse != '0 0 0')
{
- vector dMouse, minpos, maxpos;
- dMouse = getmousepos() * (frametime / realFrametime); // for capturevideo
- if(dMouse != '0 0 0')
- {
- minpos = globalToBox('0 0 0', draw_shift, draw_scale);
- maxpos = globalToBox(eX * (realconwidth - 1) + eY * (realconheight - 1), draw_shift, draw_scale);
- dMouse = globalToBoxSize(dMouse, draw_scale);
- menuMousePos += dMouse * cvar("menu_mouse_speed");
- menuMousePos.x = bound(minpos.x, menuMousePos.x, maxpos.x);
- menuMousePos.y = bound(minpos.y, menuMousePos.y, maxpos.y);
- if(mouseButtonsPressed)
- main.mouseDrag(main, menuMousePos);
- else
- main.mouseMove(main, menuMousePos);
- }
+ vector minpos = globalToBox('0 0 0', draw_shift, draw_scale);
+ vector maxpos = globalToBox(eX * (realconwidth - 1) + eY * (realconheight - 1), draw_shift, draw_scale);
+ dMouse = globalToBoxSize(dMouse, draw_scale);
+ menuMousePos += dMouse * cvar("menu_mouse_speed");
+ menuMousePos.x = bound(minpos.x, menuMousePos.x, maxpos.x);
+ menuMousePos.y = bound(minpos.y, menuMousePos.y, maxpos.y);
+ if (mouseButtonsPressed) main.mouseDrag(main, menuMousePos);
+ else main.mouseMove(main, menuMousePos);
}
}
main.draw(main);
setkeydest(KEY_MENU);
setmousetarget((menuMouseMode ? MT_CLIENT : MT_MENU));
- if(!menuInitialized)
- return;
+ if (!menuInitialized) return;
- if(mouseButtonsPressed)
- main.mouseRelease(main, menuMousePos);
+ if (mouseButtonsPressed) main.mouseRelease(main, menuMousePos);
mouseButtonsPressed = 0;
main.focusEnter(main);
setkeydest(KEY_GAME);
setmousetarget(MT_CLIENT);
- if(!menuInitialized)
- return;
+ if (!menuInitialized) return;
main.focusLeave(main);
main.hideNotify(main);
}
-void m_toggle(float mode)
+void m_toggle(int mode)
{
- if(Menu_Active)
+ if (Menu_Active)
{
- if (mode == 1)
- return;
+ if (mode == 1) return;
m_hide();
}
else
{
- if (mode == 0)
- return;
+ if (mode == 0) return;
m_display();
}
}
void Shutdown()
{
- entity e;
-
m_hide();
- for(e = NULL; (e = nextent(e)) != NULL; )
- {
- if(e.classname != "vtbl")
- if(e.destroy)
- e.destroy(e);
- }
+ FOREACH_ENTITY_ORDERED(it.destroy, LAMBDA(
+ if (it.classname == "vtbl") continue;
+ it.destroy(it);
+ ));
}
void m_focus_item_chain(entity outermost, entity innermost)
{
- if(innermost.parent != outermost)
- m_focus_item_chain(outermost, innermost.parent);
+ if (innermost.parent != outermost) m_focus_item_chain(outermost, innermost.parent);
innermost.parent.setFocus(innermost.parent, innermost);
}
void m_activate_window(entity wnd)
{
- entity par;
- par = wnd.parent;
- if(par)
- m_activate_window(par);
+ entity par = wnd.parent;
+ if (par) m_activate_window(par);
- if(par.instanceOfModalController)
+ if (par.instanceOfModalController)
{
- if(wnd.tabSelectingButton)
+ if (wnd.tabSelectingButton)
// tabs
TabButton_Click(wnd.tabSelectingButton, wnd);
else
// root
par.initializeDialog(par, wnd);
}
- else if(par.instanceOfNexposee)
+ else if (par.instanceOfNexposee)
{
// nexposee (sorry for violating abstraction here)
par.selectedChild = wnd;
par.animationState = 1;
Container_setFocus(par, NULL);
}
- else if(par.instanceOfContainer)
+ else if (par.instanceOfContainer)
{
// other containers
- if(par.focused)
- par.setFocus(par, wnd);
+ if (par.focused) par.setFocus(par, wnd);
}
}
void m_setpointerfocus(entity wnd)
{
- if(wnd.instanceOfContainer)
- {
- entity focus = wnd.preferredFocusedGrandChild(wnd);
- if(focus)
- {
- menuMousePos = focus.origin + 0.5 * focus.size;
- menuMousePos.x *= 1 / conwidth;
- menuMousePos.y *= 1 / conheight;
- entity par = wnd.parent;
- if(par.focused)
- par.setFocus(par, wnd);
- if(wnd.focused)
- m_focus_item_chain(wnd, focus);
- }
- }
+ if (!wnd.instanceOfContainer) return;
+ entity focus = wnd.preferredFocusedGrandChild(wnd);
+ if (!focus) return;
+ menuMousePos = focus.origin + 0.5 * focus.size;
+ menuMousePos.x *= 1 / conwidth;
+ menuMousePos.y *= 1 / conheight;
+ entity par = wnd.parent;
+ if (par.focused) par.setFocus(par, wnd);
+ if (wnd.focused) m_focus_item_chain(wnd, focus);
}
void m_goto(string itemname)
{
- entity e;
- if(!menuInitialized)
+ if (!menuInitialized)
{
- if(m_goto_buffer)
- strunzone(m_goto_buffer);
+ if (m_goto_buffer) strunzone(m_goto_buffer);
m_goto_buffer = strzone(itemname);
return;
}
- if(itemname == "") // this can be called by GameCommand
+ if (itemname == "") // this can be called by GameCommand
{
- if(gamestatus & (GAME_ISSERVER | GAME_CONNECTED))
+ if (gamestatus & (GAME_ISSERVER | GAME_CONNECTED))
{
m_hide();
}
}
else
{
- for(e = NULL; (e = find(e, name, itemname)); )
- if(e.classname != "vtbl")
- break;
+ entity e;
+ for (e = NULL; (e = find(e, name, itemname)); )
+ if (e.classname != "vtbl") break;
- if((e) && (!e.requiresConnection || (gamestatus & (GAME_ISSERVER | GAME_CONNECTED))))
+ if ((e) && (!e.requiresConnection || (gamestatus & (GAME_ISSERVER | GAME_CONNECTED))))
{
m_hide();
m_activate_window(e);
}
}
-float menuLastFocusSoundTime;
void m_play_focus_sound()
{
- if(cvar("menu_sounds") > 1)
- if(time - menuLastFocusSoundTime > 0.25)
- {
- localsound(MENU_SOUND_FOCUS);
- menuLastFocusSoundTime = time;
- }
+ static float menuLastFocusSoundTime;
+ if (cvar("menu_sounds") < 2) return;
+ if (time - menuLastFocusSoundTime <= 0.25) return;
+ localsound(MENU_SOUND_FOCUS);
+ menuLastFocusSoundTime = time;
}
void m_play_click_sound(string soundfile)
{
- if(cvar("menu_sounds"))
- localsound(soundfile);
+ if (!cvar("menu_sounds")) return;
+ localsound(soundfile);
}
#include "../common/constants.qh"
#include "../common/util.qh"
-// constants
+const int GAME_ISSERVER = BIT(0);
+const int GAME_CONNECTED = BIT(1);
+const int GAME_DEVELOPER = BIT(2);
-const int GAME_ISSERVER = 1;
-const int GAME_CONNECTED = 2;
-const int GAME_DEVELOPER = 4;
-
-// prototypes
-
-float Menu_Active;
+bool Menu_Active;
int gamestatus;
const int S_SHIFT = 1;
.string name;
entity keyGrabber;
-.void(entity me, float key, float ascii) keyGrabbed;
+.void(entity this, float key, float ascii) keyGrabbed;
-float conwidth, conheight; // "virtual" conwidth/height values for other stuff to assume for scaling
+// "virtual" conwidth/height values for other stuff to assume for scaling
+float conwidth, conheight;
-float preMenuInit(); // you have to define this for pre-menu initialization. Return 0 if initialization needs to be retried a frame later, 1 if it succeeded.
-void preMenuDraw(); // this is run before the menu is drawn. You may put some stuff there that has to be done every frame.
-void postMenuDraw(); // this is run just after the menu is drawn (or not). Useful to draw something over everything else.
+/** you have to define this for pre-menu initialization. Return 0 if initialization needs to be retried a frame later, 1 if it succeeded. */
+float preMenuInit();
+/** this is run before the menu is drawn. You may put some stuff there that has to be done every frame. */
+void preMenuDraw();
+/** this is run just after the menu is drawn (or not). Useful to draw something over everything else. */
+void postMenuDraw();
void m_sync();
void draw_reset_cropped();
-// sounds
-
const string MENU_SOUND_CLEAR = "sound/menu/clear.wav";
const string MENU_SOUND_CLOSE = "sound/menu/close.wav";
const string MENU_SOUND_EXECUTE = "sound/menu/execute.wav";
+++ /dev/null
-#ifndef SYS_POST_H
-#define SYS_POST_H
-
-#pragma noref 0
-#endif
+++ /dev/null
-#ifndef SYS_PRE_H
-#define SYS_PRE_H
-
-#pragma noref 1
-#endif
void XonoticCrosshairPicker_cellDraw(entity me, vector cell, vector cellPos)
{
- vector sz;
- string cross = strcat("/gfx/crosshair", crosshairpicker_cellToCrosshair(me, cell));
- sz = draw_PictureSize(cross);
+ string s = strcat("/gfx/crosshair", crosshairpicker_cellToCrosshair(me, cell));
+ vector sz = draw_PictureSize(s);
sz = globalToBoxSize(sz, me.size);
float ar = sz.x / sz.y;
sz.x = me.realCellSize.x;
sz.y = sz.x / ar;
- sz = sz * 0.95;
+ sz *= 0.95;
vector crosshairPos = cellPos + 0.5 * me.realCellSize;
- draw_Picture(crosshairPos - 0.5 * sz, cross, sz, SKINCOLOR_CROSSHAIRPICKER_CROSSHAIR, SKINALPHA_CROSSHAIRPICKER_CROSSHAIR);
+ draw_Picture(crosshairPos - 0.5 * sz, s, sz, SKINCOLOR_CROSSHAIRPICKER_CROSSHAIR, SKINALPHA_CROSSHAIRPICKER_CROSSHAIR);
if(cvar("crosshair_dot"))
draw_Picture(crosshairPos - 0.5 * sz * cvar("crosshair_dot_size"), "/gfx/crosshairdot", sz * cvar("crosshair_dot_size"), SKINCOLOR_CROSSHAIRPICKER_CROSSHAIR, SKINALPHA_CROSSHAIRPICKER_CROSSHAIR);
#ifdef IMPLEMENTATION
-void GameType_ConfigureSliders(entity e, entity l, string pLabel, float pMin, float pMax, float pStep, string pCvar, string theTooltip)
+void GameType_ConfigureSliders(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip)
{
- if(pCvar == "")
+ int i;
+ entity e = me.sliderFraglimit;
+ entity l = me.labelFraglimit;
+ e.configureXonoticTextSlider(e, pCvar, pTooltip);
+ e.disabled = l.disabled = !pCvar;
+ l.setText(l, pLabel);
+
+ // clear old values
+ for(i = 0; i < e.nValues; ++i);
{
- e.configureXonoticTextSlider(e, string_null, string_null);
- l.setText(l, pLabel);
- e.disabled = l.disabled = true;
- }
- else
- {
- e.configureXonoticTextSlider(e, pCvar, theTooltip);
-
- // clear old values
- int i;
- for(i = 0; i <= e.nValues; ++i);
+ if(e.(valueStrings[i]))
+ {
+ strunzone(e.(valueStrings[i]));
+ e.(valueStrings[i]) = string_null;
+ }
+ if(e.(valueIdentifiers[i]))
{
- if(e.(valueStrings[i])) { strunzone(e.(valueStrings[i])); }
- if(e.(valueIdentifiers[i])) { strunzone(e.(valueIdentifiers[i])); }
+ strunzone(e.(valueIdentifiers[i]));
+ e.(valueIdentifiers[i]) = string_null;
}
- e.clearValues(e);
+ }
+ e.clearValues(e);
+ if(pCvar != "")
+ {
// set new values
e.addValue(e, strzone(_("Default")), strzone("-1"));
for(i = pMin; i <= pMax; i += pStep) { e.addValue(e, strzone(ftos(i)), strzone(ftos(i))); }
e.addValue(e, strzone(_("Unlimited")), strzone("0"));
- e.configureXonoticTextSliderValues(e);
-
- // set text field
- l.setText(l, pLabel);
- e.disabled = l.disabled = false;
}
+ e.configureXonoticTextSliderValues(e);
+
+
+ entity t = me.sliderTeams;
+ entity tl = me.labelTeams;
+ t.configureXonoticTextSlider(t, tCvar, string_null);
+ tl.disabled = t.disabled = !tCvar;
+ t.nValues = (tCvar == "") ? 0 : 4; // instead of clearing / readding the very same values
+ t.configureXonoticTextSliderValues(t);
}
entity makeXonoticServerCreateTab()
void XonoticServerCreateTab_gameTypeChangeNotify(entity me)
{
- // tell the map list to update
- float gt;
- entity e, l;
- gt = MapInfo_CurrentGametype();
- e = me.sliderFraglimit;
- l = me.labelFraglimit;
-
- switch(gt)
+ switch(MapInfo_CurrentGametype())
{
- case MAPINFO_TYPE_CTF: GameType_ConfigureSliders(e, l, _("Capture limit:"), 1, 20, 1, "capturelimit_override", string_null); break;
- case MAPINFO_TYPE_DOMINATION: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, "g_domination_point_limit", string_null); break;
- case MAPINFO_TYPE_KEYHUNT: GameType_ConfigureSliders(e, l, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit", string_null); break;
- case MAPINFO_TYPE_LMS: GameType_ConfigureSliders(e, l, _("Lives:"), 3, 50, 1, "g_lms_lives_override", string_null); break;
- case MAPINFO_TYPE_RACE: GameType_ConfigureSliders(e, l, _("Laps:"), 1, 25, 1, "g_race_laps_limit", string_null); break;
- case MAPINFO_TYPE_NEXBALL: GameType_ConfigureSliders(e, l, _("Goals:"), 1, 50, 1, "g_nexball_goallimit", string_null); break;
- case MAPINFO_TYPE_ASSAULT: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, "", string_null); break;
- case MAPINFO_TYPE_ONSLAUGHT: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, "", string_null); break;
- case MAPINFO_TYPE_CTS: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, "", string_null); break;
- case MAPINFO_TYPE_INVASION: GameType_ConfigureSliders(e, l, _("Point limit:"), 5, 0, 5, "", string_null); break;
- case MAPINFO_TYPE_TEAM_DEATHMATCH:GameType_ConfigureSliders(e, l, _("Point limit:"), 5, 100, 5, "g_tdm_point_limit", string_null); break;
- default: GameType_ConfigureSliders(e, l, _("Frag limit:"), 5, 100, 5, "fraglimit_override", _("The amount of frags needed before the match will end")); break;
+ case MAPINFO_TYPE_CA: GameType_ConfigureSliders(me, _("Frag limit:"), 5, 100, 5, "fraglimit_override", "g_ca_teams_override", _("The amount of frags needed before the match will end")); break;
+ case MAPINFO_TYPE_FREEZETAG: GameType_ConfigureSliders(me, _("Frag limit:"), 5, 100, 5, "fraglimit_override", "g_freezetag_teams_override", _("The amount of frags needed before the match will end")); break;
+ case MAPINFO_TYPE_CTF: GameType_ConfigureSliders(me, _("Capture limit:"), 1, 20, 1, "capturelimit_override", string_null, _("The amount of captures needed before the match will end")); break;
+ case MAPINFO_TYPE_DOMINATION: GameType_ConfigureSliders(me, _("Point limit:"), 50, 500, 10, "g_domination_point_limit", "g_domination_teams_override", _("The amount of points needed before the match will end")); break;
+ case MAPINFO_TYPE_KEYHUNT: GameType_ConfigureSliders(me, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit", "g_keyhunt_teams_override", _("The amount of points needed before the match will end")); break;
+ case MAPINFO_TYPE_LMS: GameType_ConfigureSliders(me, _("Lives:"), 3, 50, 1, "g_lms_lives_override", string_null, string_null); break;
+ case MAPINFO_TYPE_RACE: GameType_ConfigureSliders(me, _("Laps:"), 1, 25, 1, "g_race_laps_limit", string_null, string_null); break;
+ case MAPINFO_TYPE_NEXBALL: GameType_ConfigureSliders(me, _("Goals:"), 1, 50, 1, "g_nexball_goallimit", string_null, _("The amount of goals needed before the match will end")); break;
+ case MAPINFO_TYPE_ASSAULT: GameType_ConfigureSliders(me, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); break;
+ case MAPINFO_TYPE_ONSLAUGHT: GameType_ConfigureSliders(me, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); break;
+ case MAPINFO_TYPE_CTS: GameType_ConfigureSliders(me, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); break;
+ case MAPINFO_TYPE_INVASION: GameType_ConfigureSliders(me, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); break;
+ case MAPINFO_TYPE_TEAM_DEATHMATCH: GameType_ConfigureSliders(me, _("Point limit:"), 5, 100, 5, "g_tdm_point_limit", "g_tdm_teams_override", _("The amount of points needed before the match will end")); break;
+ default: GameType_ConfigureSliders(me, _("Frag limit:"), 5, 100, 5, "fraglimit_override", string_null, _("The amount of frags needed before the match will end")); break;
}
- string x = string_null;
- string theTooltip = string_null;
- e = me.sliderTeams;
- switch(gt)
- {
- // old tooltip: _("Override the default amount of teams in teamgames")
- case MAPINFO_TYPE_CA: x = "g_ca_teams_override"; break;
- case MAPINFO_TYPE_DOMINATION: x = "g_domination_teams_override"; break;
- case MAPINFO_TYPE_FREEZETAG: x = "g_freezetag_teams_override"; break;
- case MAPINFO_TYPE_KEYHUNT: x = "g_keyhunt_teams_override"; break;
- case MAPINFO_TYPE_TEAM_DEATHMATCH: x = "g_tdm_teams_override"; break;
- }
- e.configureXonoticTextSlider(e, x, theTooltip);
- e.configureXonoticTextSliderValues(e);
- me.sliderTeams.disabled = me.labelTeams.disabled = !x;
-
me.mapListBox.refilter(me.mapListBox);
}
me.currentServerNumFreeSlots = strzone(s);
me.numFreeSlotsLabel.setText(me.numFreeSlotsLabel, me.currentServerNumFreeSlots);
- me.currentServerMod = ((modname == "Xonotic") ? _("Default") : modname);
+ me.currentServerMod = ((modname == "Xonotic") ? ZCTX(_("MOD^Default")) : modname);
me.currentServerMod = strzone(me.currentServerMod);
me.modLabel.setText(me.modLabel, me.currentServerMod);
#endif
me.gotoRC(me, me.rows - 1, 0);
- me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "color -1 -1;name \"$_cl_name\";sendcvar cl_weaponpriority;sendcvar cl_autoswitch;sendcvar cl_forceplayermodels;sendcvar cl_forceplayermodelsfromxonotic;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY));
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "color -1 -1;name \"$_cl_name\";sendcvar cl_autoswitch;sendcvar cl_forceplayermodels;sendcvar cl_forceplayermodelsfromxonotic;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY));
}
#endif
float n;
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Quality preset:")));
- n = 5 + 2 * !!cvar("developer");
+ n = 5 + 2 * boolean(cvar("developer"));
if(cvar("developer"))
me.TD(me, 1, 5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^OMG!")), '1 0 1', "exec effects-omg.cfg", 0));
me.TD(me, 1, 5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Low")), '0 0 0', "exec effects-low.cfg", 0));
topics.onChangeEntity = this;
int
- col = 0, width = 1.5;
+ col = 0, width = 1;
this.gotoRC(this, 0, col);
this.TD(this, this.rows, width, topics);
float teams, nTeams;
teams = cvar("_teams_available");
nTeams = 0;
- me.team1.disabled = !(teams & 1); nTeams += !!(teams & 1);
- me.team2.disabled = !(teams & 2); nTeams += !!(teams & 2);
- me.team3.disabled = !(teams & 4); nTeams += !!(teams & 4);
- me.team4.disabled = !(teams & 8); nTeams += !!(teams & 8);
+ me.team1.disabled = !(teams & 1); nTeams += boolean(teams & 1);
+ me.team2.disabled = !(teams & 2); nTeams += boolean(teams & 2);
+ me.team3.disabled = !(teams & 4); nTeams += boolean(teams & 4);
+ me.team4.disabled = !(teams & 8); nTeams += boolean(teams & 8);
}
void XonoticTeamSelectDialog_fill(entity me)
continue;
bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_ID, argv(0));
bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_NAME, argv(1));
- float k = strstrofs(argv(2), "(", 0);
- if(k > 0)
- if(substring(argv(2), strlen(argv(2)) - 1, 1) == ")")
- {
- string percent = substring(argv(2), k + 1, -2);
- if(percent != "100%")
- bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_PERCENTAGE, percent);
- }
- bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_NAME_LOCALIZED, (k < 0) ? argv(2) : substring(argv(2), 0, k - 1));
+ bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_NAME_LOCALIZED, argv(2));
+ string percent = argv(3);
+ if(percent && percent != "100%")
+ bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_PERCENTAGE, percent);
++i;
}
fclose(fh);
void XonoticPlayerModelSelector_showNotify(entity me)
{
+ // Reinitialize self.
+ me.destroy(me);
me.configureXonoticPlayerModelSelector(me);
}
#endif
{
if(me.cvarName)
{
- me.checked = !!cvar(me.cvarName);
+ me.checked = boolean(cvar(me.cvarName));
}
else
{
METHOD(XonoticServerList, toggleFavorite, void(entity, string));
ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85)
+ METHOD(XonoticServerList, mouseMove, float(entity, vector));
+ ATTRIB(XonoticServerList, mouseOverIcons, bool, false)
+ METHOD(XonoticServerList, focusedItemChangeNotify, void(entity));
ATTRIB(XonoticServerList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticServerList, realUpperMargin, float, 0)
int category_draw_count;
#define SLIST_CATEGORIES \
- SLIST_CATEGORY(CAT_FAVORITED, "", "", ZCTX(_("SLCAT^Favorites"))) \
- SLIST_CATEGORY(CAT_RECOMMENDED, "", "", ZCTX(_("SLCAT^Recommended"))) \
- SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Normal Servers"))) \
- SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Servers"))) \
- SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Competitive Mode"))) \
- SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", ZCTX(_("SLCAT^Modified Servers"))) \
- SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Overkill Mode"))) \
- SLIST_CATEGORY(CAT_INSTAGIB, "", "CAT_SERVERS", ZCTX(_("SLCAT^InstaGib Mode"))) \
- SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", ZCTX(_("SLCAT^Defrag Mode")))
+ SLIST_CATEGORY(CAT_FAVORITED, "", "", CTX(_("SLCAT^Favorites"))) \
+ SLIST_CATEGORY(CAT_RECOMMENDED, "", "", CTX(_("SLCAT^Recommended"))) \
+ SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", CTX(_("SLCAT^Normal Servers"))) \
+ SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", CTX(_("SLCAT^Servers"))) \
+ SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", CTX(_("SLCAT^Competitive Mode"))) \
+ SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", CTX(_("SLCAT^Modified Servers"))) \
+ SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", CTX(_("SLCAT^Overkill Mode"))) \
+ SLIST_CATEGORY(CAT_INSTAGIB, "", "CAT_SERVERS", CTX(_("SLCAT^InstaGib Mode"))) \
+ SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", CTX(_("SLCAT^Defrag Mode")))
#define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
#define SLIST_CATEGORY(name,enoverride,dioverride,str) \
#ifdef COMPAT_NO_MOD_IS_XONOTIC
if(modname == "")
- modname = "xonotic";
+ modname = "Xonotic";
#endif
+ string original_modname = modname;
modname = strtolower(modname);
/*
if(modname != "cts")
if(modname != "nix")
if(modname != "newtoys")
- pure = false;
+ pure_available = false;
if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
theAlpha = SKINALPHA_SERVERLIST_FULL;
if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
+ if(isFocused && me.mouseOverIcons && !me.tooltip)
+ {
+ string t = "";
+ if(me.seenIPv4 && me.seenIPv6)
+ t = strcat(t, (isv6) ? "IPv6, " : "IPv4, ");
+ t = strcat(t, _("encryption:"), " ", (q ? sprintf(_("AES level %d"), q) : ZCTX(_("ENC^none"))), ", ");
+ t = strcat(t, sprintf(_("mod: %s"), ((modname == "xonotic") ? ZCTX(_("MOD^Default")) : original_modname)));
+ if(pure_available)
+ t = strcat(t, sprintf(_(" (%s)"), (pure) ? _("official settings") : _("modified settings")));
+ t = strcat(t, ", ");
+ t = strcat(t, ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? _("stats enabled") : _("stats disabled")));
+ setZonedTooltip(me, t, string_null);
+ }
// --------------
// RENDER TEXT
// --------------
draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
}
+void XonoticServerList_focusedItemChangeNotify(entity me)
+{
+ clearTooltip(me);
+}
+
+float XonoticServerList_mouseMove(entity me, vector pos)
+{
+ if(!SUPER(XonoticServerList).mouseMove(me, pos))
+ {
+ me.mouseOverIcons = false;
+ clearTooltip(me);
+ return 1;
+ }
+
+ me.mouseOverIcons = (pos_x <= me.columnIconsSize);
+ if(!me.mouseOverIcons)
+ clearTooltip(me);
+ return 1;
+}
+
bool XonoticServerList_keyDown(entity me, int scan, bool ascii, bool shift)
{
vector org, sz;
void saveCvarsMulti(entity me)
{
float n, i;
- string s;
+ string s, cvarname;
me.saveCvars_Multi(me);
s = cvar_string(me.cvarName);
n = tokenize_console(me.cvarNames_Multi);
for(i = 0; i < n; ++i)
{
+ // cvars prefixed with ! get saved with the inverted value
if(substring(argv(i), 0, 1) == "!")
- cvar_set(substring(argv(i), 1, strlen(argv(i))), ((s == "0") ? "1" : "0"));
+ {
+ cvarname = substring(argv(i), 1, strlen(argv(i)));
+ cvar_set(cvarname, ((s == "0") ? "1" : "0"));
+ }
else
- cvar_set(argv(i), s);
+ {
+ cvarname = argv(i);
+ cvar_set(cvarname, s);
+ }
- CheckSendCvars(me, argv(i));
+ CheckSendCvars(me, cvarname);
}
}
void makeMulti(entity e, string otherCvars)
#ifndef SERVER_ALL_H
#define SERVER_ALL_H
+int maxclients;
+
+const string STR_PLAYER = "player";
+const string STR_SPECTATOR = "spectator";
+const string STR_OBSERVER = "observer";
+
+#define IS_PLAYER(v) ((v).classname == STR_PLAYER)
+#define IS_SPEC(v) ((v).classname == STR_SPECTATOR)
+#define IS_OBSERVER(v) ((v).classname == STR_OBSERVER)
+
+#define IS_CLIENT(v) (v.flags & FL_CLIENT)
+#define IS_BOT_CLIENT(v) (clienttype(v) == CLIENTTYPE_BOT)
+#define IS_REAL_CLIENT(v) (clienttype(v) == CLIENTTYPE_REAL)
+#define IS_NOT_A_CLIENT(v) (clienttype(v) == CLIENTTYPE_NOTACLIENT)
+
+#define IS_MONSTER(v) (v.flags & FL_MONSTER)
+#define IS_VEHICLE(v) (v.vehicle_flags & VHF_ISVEHICLE)
+#define IS_TURRET(v) (v.turret_flags & TUR_FLAG_ISTURRET)
+
+#define FOR_EACH_CLIENTSLOT(v) for (v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
+#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if (IS_CLIENT(v))
+#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if (IS_REAL_CLIENT(v))
+
+#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if (IS_PLAYER(v))
+#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if (IS_SPEC(v))
+#define FOR_EACH_OBSERVER(v) FOR_EACH_CLIENT(v) if (IS_OBSERVER(v))
+#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if (IS_PLAYER(v))
+
+#define FOR_EACH_MONSTER(v) for (v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
+
#include "../common/effects/all.qh"
#include "../common/models/all.qh"
#include "../common/sounds/all.qh"
// returns 0 for: -1, -sqrt(0.5), 0 (angles that commonly happen with kbd)
}
-void anticheat_physics()
-{SELFPARAM();
+void anticheat_physics(entity this)
+{
float f;
// div0_evade -> SPECTATORS
- makevectors(self.v_angle);
- if(self.anticheat_div0_evade_offset == 0)
+ makevectors(this.v_angle);
+ if(this.anticheat_div0_evade_offset == 0)
{
f = fabs(anticheat_div0_evade_evasion_delta - floor(anticheat_div0_evade_evasion_delta) - 0.5) * 2; // triangle function
- self.anticheat_div0_evade_offset = servertime + sys_frametime * (3 * f - 1);
- self.anticheat_div0_evade_v_angle = self.v_angle;
- self.anticheat_div0_evade_forward_initial = v_forward;
- MEAN_ACCUMULATE(anticheat_div0_evade, 0, 1);
+ this.anticheat_div0_evade_offset = servertime + sys_frametime * (3 * f - 1);
+ this.anticheat_div0_evade_v_angle = this.v_angle;
+ this.anticheat_div0_evade_forward_initial = v_forward;
+ MEAN_ACCUMULATE(this, anticheat_div0_evade, 0, 1);
}
else
{
- if(time < self.anticheat_div0_evade_offset)
- self.anticheat_div0_evade_v_angle = self.v_angle;
- MEAN_ACCUMULATE(anticheat_div0_evade, 0.5 - 0.5 * (self.anticheat_div0_evade_forward_initial * v_forward), 1);
+ if(time < this.anticheat_div0_evade_offset)
+ this.anticheat_div0_evade_v_angle = this.v_angle;
+ MEAN_ACCUMULATE(this, anticheat_div0_evade, 0.5 - 0.5 * (this.anticheat_div0_evade_forward_initial * v_forward), 1);
}
- MEAN_ACCUMULATE(anticheat_div0_strafebot_old, movement_oddity(self.movement, self.anticheat_div0_strafebot_movement_prev), 1);
- self.anticheat_div0_strafebot_movement_prev = self.movement;
+ MEAN_ACCUMULATE(this, anticheat_div0_strafebot_old, movement_oddity(this.movement, this.anticheat_div0_strafebot_movement_prev), 1);
+ this.anticheat_div0_strafebot_movement_prev = this.movement;
// Note: this actually tries to detect snap-aim.
- if(vlen(self.anticheat_div0_strafebot_forward_prev) && time > self.anticheat_fixangle_endtime) {
- float cosangle = self.anticheat_div0_strafebot_forward_prev * v_forward;
+ if(vlen(this.anticheat_div0_strafebot_forward_prev) && time > this.anticheat_fixangle_endtime) {
+ float cosangle = this.anticheat_div0_strafebot_forward_prev * v_forward;
float angle = cosangle < -1 ? M_PI : cosangle > 1 ? 0 : acos(cosangle);
/*
if (angle >= 10 * M_PI / 180)
- printf("SNAP %s: %f for %f, %f since fixangle\n", self.netname, angle * 180 / M_PI, cosangle, time - self.anticheat_fixangle_endtime);
+ printf("SNAP %s: %f for %f, %f since fixangle\n", this.netname, angle * 180 / M_PI, cosangle, time - this.anticheat_fixangle_endtime);
*/
- MEAN_ACCUMULATE(anticheat_div0_strafebot_new, angle / M_PI, 1);
+ MEAN_ACCUMULATE(this, anticheat_div0_strafebot_new, angle / M_PI, 1);
if (autocvar_slowmo > 0) {
// Technically this is a NOP, as the engine should be ensuring
float dt = max(0.001, frametime) / autocvar_slowmo;
float anglespeed = angle / dt;
- MEAN_ACCUMULATE(anticheat_idle_snapaim_signal, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_noise, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m2, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m3, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m4, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m7, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m10, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_signal, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_noise, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m2, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m3, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m4, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m7, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m10, anglespeed, dt);
}
}
- self.anticheat_div0_strafebot_forward_prev = v_forward;
+ this.anticheat_div0_strafebot_forward_prev = v_forward;
// generic speedhack detection: correlate anticheat_speedhack_movetime (UPDATED BEFORE THIS) and server time
- self.anticheat_speedhack_movetime_frac += frametime;
- f = floor(self.anticheat_speedhack_movetime_frac);
- self.anticheat_speedhack_movetime_frac -= f;
- self.anticheat_speedhack_movetime_count += f;
- self.anticheat_speedhack_movetime = self.anticheat_speedhack_movetime_frac + self.anticheat_speedhack_movetime_count;
- f = self.anticheat_speedhack_movetime - servertime;
- if(self.anticheat_speedhack_offset == 0)
- self.anticheat_speedhack_offset = f;
+ this.anticheat_speedhack_movetime_frac += frametime;
+ f = floor(this.anticheat_speedhack_movetime_frac);
+ this.anticheat_speedhack_movetime_frac -= f;
+ this.anticheat_speedhack_movetime_count += f;
+ this.anticheat_speedhack_movetime = this.anticheat_speedhack_movetime_frac + this.anticheat_speedhack_movetime_count;
+ f = this.anticheat_speedhack_movetime - servertime;
+ if(this.anticheat_speedhack_offset == 0)
+ this.anticheat_speedhack_offset = f;
else
{
- MEAN_ACCUMULATE(anticheat_speedhack, max(0, f - self.anticheat_speedhack_offset), 1);
- self.anticheat_speedhack_offset += (f - self.anticheat_speedhack_offset) * frametime * 0.1;
+ MEAN_ACCUMULATE(this, anticheat_speedhack, max(0, f - this.anticheat_speedhack_offset), 1);
+ this.anticheat_speedhack_offset += (f - this.anticheat_speedhack_offset) * frametime * 0.1;
}
// new generic speedhack detection
- if (self.anticheat_speedhack_lasttime > 0) {
- float dt = servertime - self.anticheat_speedhack_lasttime;
+ if (this.anticheat_speedhack_lasttime > 0) {
+ float dt = servertime - this.anticheat_speedhack_lasttime;
const float falloff = 0.2;
- self.anticheat_speedhack_accu *= exp(-dt * falloff);
- self.anticheat_speedhack_accu += frametime * falloff;
+ this.anticheat_speedhack_accu *= exp(-dt * falloff);
+ this.anticheat_speedhack_accu += frametime * falloff;
// NOTE: at cl_netfps x, this actually averages not to 1, but to 1/x * falloff / (1 - exp(-1/x * falloff))
// For 15 netfps (absolute minimum bearable), and 0.2 falloff, this is: 1.0067
- self.anticheat_speedhack_lasttime = servertime;
- MEAN_ACCUMULATE(anticheat_speedhack_m1, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m2, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m3, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m4, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m5, self.anticheat_speedhack_accu, frametime);
+ this.anticheat_speedhack_lasttime = servertime;
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m1, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m2, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m3, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m4, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m5, this.anticheat_speedhack_accu, frametime);
} else {
- self.anticheat_speedhack_accu = 1;
- self.anticheat_speedhack_lasttime = servertime;
+ this.anticheat_speedhack_accu = 1;
+ this.anticheat_speedhack_lasttime = servertime;
}
}
return;
// TODO(divVerent): Use xonstat to acquire good thresholds.
GameLogEcho(strcat(":anticheat:_time:", ftos(self.playerid), ":", ftos(servertime - self.anticheat_jointime)));
- GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack), 240, 0, 9999))); // Actually this one seems broken.
- GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m1), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m2), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m3), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m4), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m5), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_old), 120, 0.15, 0.4)));
- GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_new), 120, 0.25, 0.8)));
- GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_evade), 120, 0.2, 0.5)));
- GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal) - MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m2), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m3), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m4), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m7), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m10), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack), 240, 0, 9999))); // Actually this one seems broken.
+ GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m1), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m2), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m3), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m4), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m5), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_div0_strafebot_old), 120, 0.15, 0.4)));
+ GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_div0_strafebot_new), 120, 0.25, 0.8)));
+ GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_div0_evade), 120, 0.2, 0.5)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_signal) - MEAN_EVALUATE(self, anticheat_idle_snapaim_noise), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_signal), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_noise), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m2), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m3), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m4), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m7), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m10), 120, 0, 9999)));
}
float anticheat_getvalue(string id)
{SELFPARAM();
switch(id) {
case "_time": return servertime - self.anticheat_jointime;
- case "speedhack": return MEAN_EVALUATE(anticheat_speedhack);
- case "speedhack_m1": return MEAN_EVALUATE(anticheat_speedhack_m1);
- case "speedhack_m2": return MEAN_EVALUATE(anticheat_speedhack_m2);
- case "speedhack_m3": return MEAN_EVALUATE(anticheat_speedhack_m3);
- case "speedhack_m4": return MEAN_EVALUATE(anticheat_speedhack_m4);
- case "speedhack_m5": return MEAN_EVALUATE(anticheat_speedhack_m5);
- case "div0_strafebot_old": return MEAN_EVALUATE(anticheat_div0_strafebot_old);
- case "div0_strafebot_new": return MEAN_EVALUATE(anticheat_div0_strafebot_new);
- case "div0_evade": return MEAN_EVALUATE(anticheat_div0_evade);
- case "idle_snapaim": return MEAN_EVALUATE(anticheat_idle_snapaim_signal) - MEAN_EVALUATE(anticheat_idle_snapaim_noise);
- case "idle_snapaim_signal": return MEAN_EVALUATE(anticheat_idle_snapaim_signal);
- case "idle_snapaim_noise": return MEAN_EVALUATE(anticheat_idle_snapaim_noise);
- case "idle_snapaim_m2": return MEAN_EVALUATE(anticheat_idle_snapaim_m2);
- case "idle_snapaim_m3": return MEAN_EVALUATE(anticheat_idle_snapaim_m3);
- case "idle_snapaim_m4": return MEAN_EVALUATE(anticheat_idle_snapaim_m4);
- case "idle_snapaim_m7": return MEAN_EVALUATE(anticheat_idle_snapaim_m7);
- case "idle_snapaim_m10": return MEAN_EVALUATE(anticheat_idle_snapaim_m10);
+ case "speedhack": return MEAN_EVALUATE(self, anticheat_speedhack);
+ case "speedhack_m1": return MEAN_EVALUATE(self, anticheat_speedhack_m1);
+ case "speedhack_m2": return MEAN_EVALUATE(self, anticheat_speedhack_m2);
+ case "speedhack_m3": return MEAN_EVALUATE(self, anticheat_speedhack_m3);
+ case "speedhack_m4": return MEAN_EVALUATE(self, anticheat_speedhack_m4);
+ case "speedhack_m5": return MEAN_EVALUATE(self, anticheat_speedhack_m5);
+ case "div0_strafebot_old": return MEAN_EVALUATE(self, anticheat_div0_strafebot_old);
+ case "div0_strafebot_new": return MEAN_EVALUATE(self, anticheat_div0_strafebot_new);
+ case "div0_evade": return MEAN_EVALUATE(self, anticheat_div0_evade);
+ case "idle_snapaim": return MEAN_EVALUATE(self, anticheat_idle_snapaim_signal) - MEAN_EVALUATE(self, anticheat_idle_snapaim_noise);
+ case "idle_snapaim_signal": return MEAN_EVALUATE(self, anticheat_idle_snapaim_signal);
+ case "idle_snapaim_noise": return MEAN_EVALUATE(self, anticheat_idle_snapaim_noise);
+ case "idle_snapaim_m2": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m2);
+ case "idle_snapaim_m3": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m3);
+ case "idle_snapaim_m4": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m4);
+ case "idle_snapaim_m7": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m7);
+ case "idle_snapaim_m10": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m10);
}
return -1;
}
void anticheat_report();
void anticheat_shutdown();
-void anticheat_physics();
+void anticheat_physics(entity this);
void anticheat_spectatecopy(entity spectatee);
void anticheat_prethink();
bool autocvar_bot_nofire;
#define autocvar_bot_number cvar("bot_number")
#define autocvar_bot_prefix cvar_string("bot_prefix")
-bool autocvar_bot_sound_monopoly;
#define autocvar_bot_suffix cvar_string("bot_suffix")
bool autocvar_bot_usemodelnames;
int autocvar_bot_vs_human;
float autocvar_g_balance_contents_drowndelay;
int autocvar_g_balance_contents_playerdamage_drowning;
int autocvar_g_balance_contents_playerdamage_lava;
+int autocvar_g_balance_contents_playerdamage_lava_burn; // 10 is a nice value
+float autocvar_g_balance_contents_playerdamage_lava_burn_time = 2.5; // note: damage is total across this time (not by dps)
int autocvar_g_balance_contents_playerdamage_slime;
int autocvar_g_balance_contents_projectiledamage;
float autocvar_g_balance_damagepush_speedfactor;
string autocvar_g_banned_list;
bool autocvar_g_banned_list_idmode;
bool autocvar_g_botclip_collisions;
-bool autocvar_g_bugrigs;
bool autocvar_g_campaign;
#define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
int autocvar_g_campaign_skill;
string autocvar_sv_defaultplayermodel_red;
string autocvar_sv_defaultplayermodel_yellow;
int autocvar_sv_defaultplayerskin;
-bool autocvar_sv_dodging_frozen;
bool autocvar_sv_doublejump;
bool autocvar_sv_eventlog;
bool autocvar_sv_eventlog_console;
float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag;
float autocvar_g_trueaim_minrange;
-bool autocvar_g_debug_defaultsounds;
float autocvar_g_grab_range;
int autocvar_g_max_info_autoscreenshot;
bool autocvar_physics_ode;
for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
{
entity e = get_weaponinfo(i);
- if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
+ if ((self.weapons & (e.m_wepset)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
self.switchweapon = i;
}
}
}
// Keep pressing keys raised by the "presskey" command
- ispressingkey = !!bot_presskeys();
+ ispressingkey = boolean(bot_presskeys());
// Handle conditions
if (!(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE))
#include "anticheat.qh"
#include "cl_impulse.qh"
#include "cl_player.qh"
-#include "ent_cs.qh"
#include "ipban.qh"
#include "miscfunctions.qh"
#include "portals.qh"
#include "bot/bot.qh"
#include "bot/navigation.qh"
+#include "../common/ent_cs.qh"
#include "../common/vehicles/all.qh"
#include "../common/triggers/teleporters.qh"
precache_model(modelname);
_setmodel(e, modelname);
player_setupanimsformodel();
- UpdatePlayerSounds();
}
/*
self.event_damage = func_null;
}
+int player_getspecies(entity this)
+{
+ get_model_parameters(this.model, this.skin);
+ int s = get_model_parameters_species;
+ get_model_parameters(string_null, 0);
+ if (s < 0) return SPECIES_HUMAN;
+ return s;
+}
+
.float model_randomizer;
void FixPlayermodel(entity player)
{
if(chmdl || oldskin != player.skin) // model or skin has changed
{
- player.species = player_getspecies(); // update species
- UpdatePlayerSounds(); // update skin sounds
+ player.species = player_getspecies(player); // update species
}
if(!teamplay)
this.bot_attack = true;
this.monster_attack = true;
- this.spider_slowness = 0;
-
this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = false;
if (this.killcount == FRAGS_SPECTATOR) {
else
stuffcmd(self, "set _teams_available 0\n");
- attach_entcs(self);
+ entcs_attach(self);
bot_relinkplayerlist();
Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
- if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
+ if(g_weaponarena_weapons == WEPSET(TUBA))
stuffcmd(self, "cl_cmd settemp chase_active 1\n");
}
self.model_randomizer = random();
if(IS_REAL_CLIENT(self))
- sv_notice_join();
+ sv_notice_join(self);
for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
WITH(entity, self, e, e.init_for_player(this));
bot_clientdisconnect();
- detach_entcs(self);
+ entcs_detach(self);
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":part:", ftos(self.playerid)));
if(self.weaponorder_byimpulse)
strunzone(self.weaponorder_byimpulse);
- ClearPlayerSounds();
-
if(self.personal)
remove(self.personal);
if (!self.crouch)
{
self.crouch = true;
- self.view_ofs = self.stat_pl_crouch_view_ofs;
- setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max);
+ self.view_ofs = STAT(PL_CROUCH_VIEW_OFS, self);
+ setsize (self, STAT(PL_CROUCH_MIN, self), STAT(PL_CROUCH_MAX, self));
// setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
}
}
{
if (self.crouch)
{
- tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self);
+ tracebox(self.origin, STAT(PL_MIN, self), STAT(PL_MAX, self), self.origin, false, self);
if (!trace_startsolid)
{
self.crouch = false;
- self.view_ofs = self.stat_pl_view_ofs;
- setsize (self, self.stat_pl_min, self.stat_pl_max);
+ self.view_ofs = STAT(PL_VIEW_OFS, self);
+ setsize (self, STAT(PL_MIN, self), STAT(PL_MAX, self));
}
}
}
// weapon switching impulses
if(self.deadflag == DEAD_NO)
W_NextWeaponOnImpulse(imp);
- //else
+ //else // don't retry, as this can break weaplast bind
// self.impulse = imp; // retry in next frame
}
else if(imp >= 10 && imp <= 20)
break;
}
}
- //else
+ //else // don't retry, as this can break weaplast bind
//self.impulse = imp; // retry in next frame
}
else if(imp == 21)
m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
}
- //else
+ //else // don't retry, as this can break weaplast bind
//self.impulse = imp; // retry in next frame
}
else if(imp >= WEP_IMPULSE_BEGIN && imp <= WEP_IMPULSE_END)
if(!self.vehicle)
if(self.deadflag == DEAD_NO)
W_SwitchWeapon (imp - WEP_IMPULSE_BEGIN + WEP_FIRST);
- //else
+ //else // don't retry, as this can break weaplast bind
//self.impulse = imp; // retry in next frame
}
// deploy waypoints
setself(this);
}
-float player_getspecies()
-{SELFPARAM();
- float s;
- get_model_parameters(self.model, self.skin);
- s = get_model_parameters_species;
- get_model_parameters(string_null, 0);
- if(s < 0)
- return SPECIES_HUMAN;
- return s;
-}
-
void player_setupanimsformodel()
{SELFPARAM();
// load animation info
PlayerScore_Add(self, SP_DMGTAKEN, realdmg);
}
}
-
+
bool abot = (IS_BOT_CLIENT(attacker));
bool vbot = (IS_BOT_CLIENT(self));
}
}
-float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
-// message "": do not say, just test flood control
-// return value:
-// 1 = accept
-// 0 = reject
-// -1 = fake accept
+void MoveToTeam(entity client, int team_colour, int type)
+{
+ int lockteams_backup = lockteams; // backup any team lock
+ lockteams = 0; // disable locked teams
+ TeamchangeFrags(client); // move the players frags
+ SetPlayerColors(client, team_colour - 1); // set the players colour
+ Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE.m_id, client.origin, '0 0 0'); // kill the player
+ lockteams = lockteams_backup; // restore the team lock
+ LogTeamchange(client.playerid, client.team, type);
+}
+
+/**
+ * message "": do not say, just test flood control
+ * return value:
+ * 1 = accept
+ * 0 = reject
+ * -1 = fake accept
+ */
+int Say(entity source, float teamsay, entity privatesay, string msgin, bool floodcontrol)
{
string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, colorprefix;
float flood;
return ret;
}
-
-float GetVoiceMessageVoiceType(string type)
-{
- if(type == "taunt")
- return VOICETYPE_TAUNT;
- if(type == "teamshoot")
- return VOICETYPE_LASTATTACKER;
- return VOICETYPE_TEAMRADIO;
-}
-
-.string GetVoiceMessageSampleField(string type)
-{
- GetPlayerSoundSampleField_notFound = 0;
- switch(type)
- {
-#define _VOICEMSG(m) case #m: return playersound_##m;
- ALLVOICEMSGS
-#undef _VOICEMSG
- }
- GetPlayerSoundSampleField_notFound = 1;
- return playersound_taunt;
-}
-
-.string GetPlayerSoundSampleField(string type)
-{
- GetPlayerSoundSampleField_notFound = 0;
- switch(type)
- {
-#define _VOICEMSG(m) case #m: return playersound_##m;
- ALLPLAYERSOUNDS
-#undef _VOICEMSG
- }
- GetPlayerSoundSampleField_notFound = 1;
- return playersound_taunt;
-}
-
-void PrecacheGlobalSound(string samplestring)
-{
- float n, i;
- tokenize_console(samplestring);
- n = stof(argv(1));
- if(n > 0)
- {
- for(i = 1; i <= n; ++i)
- precache_sound(strcat(argv(0), ftos(i), ".wav"));
- }
- else
- {
- precache_sound(strcat(argv(0), ".wav"));
- }
-}
-
-void PrecachePlayerSounds(string f)
-{
- int fh = fopen(f, FILE_READ);
- if (fh < 0)
- return;
- for (string s; (s = fgets(fh)); )
- {
- int n = tokenize_console(s);
- if (n != 3)
- {
- if (n != 0) LOG_TRACEF("Invalid sound info line: %s\n", s);
- continue;
- }
- PrecacheGlobalSound(strcat(argv(1), " ", argv(2)));
- }
- fclose(fh);
-
- if (!allvoicesamples)
- {
-#define _VOICEMSG(m) allvoicesamples = strcat(allvoicesamples, " ", #m);
- ALLVOICEMSGS
-#undef _VOICEMSG
- allvoicesamples = strzone(substring(allvoicesamples, 1, strlen(allvoicesamples) - 1));
- }
-}
-
-void ClearPlayerSounds()
-{SELFPARAM();
-#define _VOICEMSG(m) if(self.playersound_##m) { strunzone(self.playersound_##m); self.playersound_##m = string_null; }
- ALLPLAYERSOUNDS
- ALLVOICEMSGS
-#undef _VOICEMSG
-}
-
-float LoadPlayerSounds(string f, float first)
-{SELFPARAM();
- float fh;
- string s;
- var .string field;
- fh = fopen(f, FILE_READ);
- if(fh < 0)
- {
- LOG_TRACE("Player sound file not found: ", f, "\n");
- return 0;
- }
- while((s = fgets(fh)))
- {
- if(tokenize_console(s) != 3)
- continue;
- field = GetPlayerSoundSampleField(argv(0));
- if(GetPlayerSoundSampleField_notFound)
- field = GetVoiceMessageSampleField(argv(0));
- if(GetPlayerSoundSampleField_notFound)
- continue;
- if (self.(field))
- strunzone(self.(field));
- self.(field) = strzone(strcat(argv(1), " ", argv(2)));
- }
- fclose(fh);
- return 1;
-}
-
-void UpdatePlayerSounds()
-{SELFPARAM();
- if(self.modelindex == self.modelindex_for_playersound)
- if(self.skin == self.skin_for_playersound)
- return;
- self.modelindex_for_playersound = self.modelindex;
- self.skin_for_playersound = self.skin;
- ClearPlayerSounds();
- LoadPlayerSounds("sound/player/default.sounds", 1);
- if(!autocvar_g_debug_defaultsounds)
- if(!LoadPlayerSounds(get_model_datafilename(self.model, self.skin, "sounds"), 0))
- LoadPlayerSounds(get_model_datafilename(self.model, 0, "sounds"), 0);
-}
-
-void FakeGlobalSound(string sample, float chan, float voicetype)
-{SELFPARAM();
- float n;
- float tauntrand;
-
- if(sample == "")
- return;
-
- tokenize_console(sample);
- n = stof(argv(1));
- if(n > 0)
- sample = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
- else
- sample = strcat(argv(0), ".wav"); // randomization
-
- switch(voicetype)
- {
- case VOICETYPE_LASTATTACKER_ONLY:
- break;
- case VOICETYPE_LASTATTACKER:
- if(self.pusher)
- {
- msg_entity = self;
- if(IS_REAL_CLIENT(msg_entity))
- soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTEN_NONE);
- }
- break;
- case VOICETYPE_TEAMRADIO:
- msg_entity = self;
- if(msg_entity.cvar_cl_voice_directional == 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- break;
- case VOICETYPE_AUTOTAUNT:
- if(!sv_autotaunt)
- break;
- if(!sv_taunt)
- break;
- if(autocvar_sv_gentle)
- break;
- tauntrand = random();
- msg_entity = self;
- if (tauntrand < msg_entity.cvar_cl_autotaunt)
- {
- if (msg_entity.cvar_cl_voice_directional >= 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- }
- break;
- case VOICETYPE_TAUNT:
- if(IS_PLAYER(self))
- if(self.deadflag == DEAD_NO)
- animdecide_setaction(self, ANIMACTION_TAUNT, true);
- if(!sv_taunt)
- break;
- if(autocvar_sv_gentle)
- break;
- msg_entity = self;
- if (msg_entity.cvar_cl_voice_directional >= 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- break;
- case VOICETYPE_PLAYERSOUND:
- msg_entity = self;
- soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTEN_NORM);
- break;
- default:
- backtrace("Invalid voice type!");
- break;
- }
-}
-
-void GlobalSound(string sample, float chan, float voicetype)
-{SELFPARAM();
- float n;
- float tauntrand;
-
- if(sample == "")
- return;
-
- tokenize_console(sample);
- n = stof(argv(1));
- if(n > 0)
- sample = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
- else
- sample = strcat(argv(0), ".wav"); // randomization
-
- switch(voicetype)
- {
- case VOICETYPE_LASTATTACKER_ONLY:
- if(self.pusher)
- {
- msg_entity = self.pusher;
- if(IS_REAL_CLIENT(msg_entity))
- {
- if(msg_entity.cvar_cl_voice_directional == 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- }
- }
- break;
- case VOICETYPE_LASTATTACKER:
- if(self.pusher)
- {
- msg_entity = self.pusher;
- if(IS_REAL_CLIENT(msg_entity))
- {
- if(msg_entity.cvar_cl_voice_directional == 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- }
- msg_entity = self;
- if(IS_REAL_CLIENT(msg_entity))
- soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTEN_NONE);
- }
- break;
- case VOICETYPE_TEAMRADIO:
- FOR_EACH_REALCLIENT(msg_entity)
- if(!teamplay || msg_entity.team == self.team)
- {
- if(msg_entity.cvar_cl_voice_directional == 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- }
- break;
- case VOICETYPE_AUTOTAUNT:
- if(!sv_autotaunt)
- break;
- if(!sv_taunt)
- break;
- if(autocvar_sv_gentle)
- break;
- tauntrand = random();
- FOR_EACH_REALCLIENT(msg_entity)
- if (tauntrand < msg_entity.cvar_cl_autotaunt)
- {
- if (msg_entity.cvar_cl_voice_directional >= 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- }
- break;
- case VOICETYPE_TAUNT:
- if(IS_PLAYER(self))
- if(self.deadflag == DEAD_NO)
- animdecide_setaction(self, ANIMACTION_TAUNT, true);
- if(!sv_taunt)
- break;
- if(autocvar_sv_gentle)
- break;
- FOR_EACH_REALCLIENT(msg_entity)
- {
- if (msg_entity.cvar_cl_voice_directional >= 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
- }
- break;
- case VOICETYPE_PLAYERSOUND:
- _sound(self, chan, sample, VOL_BASE, ATTEN_NORM);
- break;
- default:
- backtrace("Invalid voice type!");
- break;
- }
-}
-
-void PlayerSound(.string samplefield, float chan, float voicetype)
-{SELFPARAM();
- GlobalSound(self.(samplefield), chan, voicetype);
-}
-
-void VoiceMessage(string type, string msg)
-{SELFPARAM();
- float voicetype, ownteam;
- float flood;
- var .string sample = GetVoiceMessageSampleField(type);
-
- if(GetPlayerSoundSampleField_notFound)
- {
- sprint(self, strcat("Invalid voice. Use one of: ", allvoicesamples, "\n"));
- return;
- }
-
- voicetype = GetVoiceMessageVoiceType(type);
- ownteam = (voicetype == VOICETYPE_TEAMRADIO);
-
- flood = Say(self, ownteam, world, msg, 1);
-
- if (IS_SPEC(self) || IS_OBSERVER(self) || flood < 0)
- FakeGlobalSound(self.(sample), CH_VOICE, voicetype);
- else if (flood > 0)
- GlobalSound(self.(sample), CH_VOICE, voicetype);
-}
-
-void MoveToTeam(entity client, float team_colour, float type)
-{
- float lockteams_backup;
-
- lockteams_backup = lockteams; // backup any team lock
-
- lockteams = 0; // disable locked teams
-
- TeamchangeFrags(client); // move the players frags
- SetPlayerColors(client, team_colour - 1); // set the players colour
- Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE.m_id, client.origin, '0 0 0'); // kill the player
-
- lockteams = lockteams_backup; // restore the team lock
-
- LogTeamchange(client.playerid, client.team, type);
-}
void CopyBody_Think();
void CopyBody(float keepvelocity);
-float player_getspecies();
-
void player_setupanimsformodel();
-void player_anim ();
+void player_anim();
-void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+void PlayerCorpseDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
// g_<gametype>_str:
// If 0, default is used.
// For consistency, negative values there are mapped to zero too.
#define GAMETYPE_DEFAULTED_SETTING(str) \
((gametype_setting_tmp = cvar(strcat("g_", GetGametype(), "_" #str))), \
- (gametype_setting_tmp < 0) ? 0 : \
- (gametype_setting_tmp == 0 || autocvar_g_respawn_delay_forced) ? max(0, autocvar_g_##str) : \
- gametype_setting_tmp)
-
+ (gametype_setting_tmp < 0) ? 0 \
+ : (gametype_setting_tmp == 0 || autocvar_g_respawn_delay_forced) ? max(0, autocvar_g_##str) \
+ : gametype_setting_tmp)
void calculate_player_respawn_time();
void ClientKill_Now_TeamChange();
-void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
-
-.float muted; // to be used by prvm_edictset server playernumber muted 1
-float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol);
-// message "": do not say, just test flood control
-// return value:
-// 1 = accept
-// 0 = reject
-// -1 = fake accept
-
-float GetVoiceMessageVoiceType(string type);
-
-string allvoicesamples;
-.string GetVoiceMessageSampleField(string type);
-
-.string GetPlayerSoundSampleField(string type);
-
-void PrecacheGlobalSound(string samplestring);
-
-void PrecachePlayerSounds(string f);
-
-void ClearPlayerSounds();
-
-float LoadPlayerSounds(string f, float first);
-
-.int modelindex_for_playersound;
-.int skin_for_playersound;
-void UpdatePlayerSounds();
-
-void FakeGlobalSound(string sample, float chan, float voicetype);
-
-void GlobalSound(string sample, float chan, float voicetype);
+void MoveToTeam(entity client, float team_colour, float type);
-void PlayerSound(.string samplefield, float chan, float voicetype);
+void PlayerDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
-void VoiceMessage(string type, string msg);
+/** to be used by `prvm_edictset server playernumber muted 1` */
+.float muted;
+int Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol);
-void MoveToTeam(entity client, float team_colour, float type);
#endif
{
if (argv(1) != "")
{
- if (argc >= 3) VoiceMessage(argv(1), substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
- else VoiceMessage(argv(1), "");
+ entity e = GetVoiceMessage(argv(1));
+ if (!e)
+ {
+ sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
+ return;
+ }
+ if (argc >= 3) VoiceMessage(e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+ else VoiceMessage(e, "");
return;
}
// =======================
// Resets the state of all clients, items, weapons, waypoints, ... of the map.
-void reset_map(float dorespawn)
+void reset_map(bool dorespawn)
{
SELFPARAM();
MUTATOR_CALLHOOK(reset_map_global);
- for (entity e = world; (e = nextent(e)); )
- {
- setself(e);
- if (IS_NOT_A_CLIENT(self))
+ FOREACH_ENTITY_ORDERED(IS_NOT_A_CLIENT(it), LAMBDA(
+ if (it.reset)
{
- if (self.reset)
- {
- self.reset();
- continue;
- }
-
- if (self.team_saved) self.team = self.team_saved;
-
- if (self.flags & FL_PROJECTILE) // remove any projectiles left
- remove(self);
+ WITH(entity, self, it, it.reset(it));
+ continue;
}
- }
+ if (it.team_saved) it.team = it.team_saved;
+ if (it.flags & FL_PROJECTILE) remove(it); // remove any projectiles left
+ ));
// Waypoints and assault start come LAST
- for (entity e = world; (e = nextent(e)); )
- {
- setself(e);
- if (IS_NOT_A_CLIENT(self))
- {
- if (self.reset2)
- {
- self.reset2();
- continue;
- }
- }
- }
+ FOREACH_ENTITY_ORDERED(IS_NOT_A_CLIENT(it), LAMBDA(
+ if (it.reset2) WITH(entity, self, it, it.reset2());
+ ));
entity e;
FOR_EACH_PLAYER(e)
- if (e.frozen) WITH(entity, self, e, Unfreeze(self));
+ if (e.frozen) WITH(entity, self, e, Unfreeze(e));
// Moving the player reset code here since the player-reset depends
// on spawnpoint entities which have to be reset first --blub
void ReadyRestart_think()
{
SELFPARAM();
- restart_mapalreadyrestarted = 1;
+ restart_mapalreadyrestarted = true;
reset_map(true);
Score_ClearAll();
- remove(self);
+ remove(this);
}
// Forces a restart of the game without actually reloading the map // this is a mess...
void ReadyRestart_force()
{
- entity tmp_player, restart_timer;
-
bprint("^1Server is restarting...\n");
VoteReset();
// clear overtime, we have to decrease timelimit to its original value again.
- if (checkrules_overtimesadded > 0 && g_race_qualifying != 2) cvar_set("timelimit", ftos(autocvar_timelimit - (checkrules_overtimesadded * autocvar_timelimit_overtime)));
+ if (checkrules_overtimesadded > 0 && g_race_qualifying != 2)
+ cvar_set("timelimit", ftos(autocvar_timelimit - (checkrules_overtimesadded * autocvar_timelimit_overtime)));
checkrules_suddendeathend = checkrules_overtimesadded = checkrules_suddendeathwarning = 0;
- readyrestart_happened = 1;
+ readyrestart_happened = true;
game_starttime = time + RESTART_COUNTDOWN;
+ entity tmp_player;
+
// clear player attributes
FOR_EACH_CLIENT(tmp_player)
{
PS_GR_P_ADDVAL(tmp_player, PLAYERSTATS_ALIVETIME, -PS_GR_P_ADDVAL(tmp_player, PLAYERSTATS_ALIVETIME, 0));
}
- restart_mapalreadyrestarted = 0; // reset this var, needed when cvar sv_ready_restart_repeatable is in use
+ restart_mapalreadyrestarted = false; // reset this var, needed when cvar sv_ready_restart_repeatable is in use
// disable the warmup global for the server
warmup_stage = 0; // once the game is restarted the game is in match stage
// reset the .ready status of all players (also spectators)
FOR_EACH_REALCLIENT(tmp_player)
{
- tmp_player.ready = 0;
+ tmp_player.ready = false;
}
readycount = 0;
Nagger_ReadyCounted(); // NOTE: this causes a resend of that entity, and will also turn off warmup state on the client
// lock teams with lockonrestart
if (autocvar_teamplay_lockonrestart && teamplay)
{
- lockteams = 1;
+ lockteams = true;
bprint("^1The teams are now locked.\n");
}
// initiate the restart-countdown-announcer entity
if (autocvar_sv_ready_restart_after_countdown)
{
- restart_timer = spawn();
+ entity restart_timer = new(restart_timer);
+ make_pure(restart_timer);
restart_timer.think = ReadyRestart_think;
restart_timer.nextthink = game_starttime;
}
{
tmp_player.allowed_timeouts = autocvar_sv_timeout_number;
}
- // reset map immediately if this cvar is not set
- if (!autocvar_sv_ready_restart_after_countdown) reset_map(true); }
- if (autocvar_sv_eventlog) GameLogEcho(":restart"); }
+ }
+ // reset map immediately if this cvar is not set
+ if (!autocvar_sv_ready_restart_after_countdown) reset_map(true);
+ if (autocvar_sv_eventlog) GameLogEcho(":restart");
+}
void ReadyRestart()
{
// Reset ALL scores, but only do that at the beginning of the countdown if sv_ready_restart_after_countdown is off!
// Otherwise scores could be manipulated during the countdown.
- if (!autocvar_sv_ready_restart_after_countdown) Score_ClearAll();
+ if (!autocvar_sv_ready_restart_after_countdown) Score_ClearAll();
ReadyRestart_force();
}
const int FL_SPAWNING = BIT(18);
const int FL_PICKUPITEMS = BIT(19);
-const int SVC_SOUND = 6;
-const int SVC_STOPSOUND = 16;
const int SVC_SETVIEW = 5;
const int RESPAWN_FORCE = 1;
#define SERVER_DEFS_H
#include "../common/weapons/all.qh"
+#include "../common/stats.qh"
#define INDEPENDENT_ATTACK_FINISHED 1
float team1_score, team2_score, team3_score, team4_score;
-float maxclients;
-
// flag set on worldspawn so that the code knows if it is dedicated or not
float server_is_dedicated;
.float pain_frame; //"
.float crouch; // Crouching or not?
-.float strength_finished;
-.float invincible_finished;
-.float superweapons_finished;
+.float strength_finished = _STAT(STRENGTH_FINISHED);
+.float invincible_finished = _STAT(INVINCIBLE_FINISHED);
+.float superweapons_finished = _STAT(SUPERWEAPONS_FINISHED);
.float cnt; // used in too many places
.float count;
void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire);
void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
// VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
-.float weapon_nextthink;
+.float weapon_nextthink = _STAT(WEAPON_NEXTTHINK);
.void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think;
.float cvar_cl_clippedspectating;
.float cvar_cl_autoscreenshot;
.float cvar_cl_jetpack_jump;
-.float cvar_cl_movement_track_canjump;
+.float cvar_cl_movement_track_canjump = _STAT(MOVEVARS_CL_TRACK_CANJUMP);
.float cvar_cl_newusekeysupported;
.string cvar_g_xonoticversion;
// WEAPONTODO: remove this
WepSet weaponsInMap;
-.WepSet weaponsinmap;
+#define weapons _STAT(WEAPONS)
+#define weaponsinmap _STAT(WEAPONSINMAP)
.float respawn_countdown; // next number to count
float next_pingtime;
-// player sounds, voice messages
-// TODO implemented fall and falling
-#define ALLPLAYERSOUNDS \
- _VOICEMSG(death) \
- _VOICEMSG(drown) \
- _VOICEMSG(fall) \
- _VOICEMSG(falling) \
- _VOICEMSG(gasp) \
- _VOICEMSG(jump) \
- _VOICEMSG(pain100) \
- _VOICEMSG(pain25) \
- _VOICEMSG(pain50) \
- _VOICEMSG(pain75)
-
-#define ALLVOICEMSGS \
- _VOICEMSG(attack) \
- _VOICEMSG(attackinfive) \
- _VOICEMSG(coverme) \
- _VOICEMSG(defend) \
- _VOICEMSG(freelance) \
- _VOICEMSG(incoming) \
- _VOICEMSG(meet) \
- _VOICEMSG(needhelp) \
- _VOICEMSG(seenflag) \
- _VOICEMSG(taunt) \
- _VOICEMSG(teamshoot)
-
-#define _VOICEMSG(m) .string playersound_##m;
-ALLPLAYERSOUNDS
-ALLVOICEMSGS
-#undef _VOICEMSG
-
-// reserved sound names for the future (some models lack sounds for them):
-// _VOICEMSG(flagcarriertakingdamage) \
-// _VOICEMSG(getflag) \
-// reserved sound names for the future (ALL models lack sounds for them):
-// _VOICEMSG(affirmative) \
-// _VOICEMSG(attacking) \
-// _VOICEMSG(defending) \
-// _VOICEMSG(roaming) \
-// _VOICEMSG(onmyway) \
-// _VOICEMSG(droppedflag) \
-// _VOICEMSG(negative) \
-// _VOICEMSG(seenenemy) \
-// /**/
-
-string globalsound_fall;
-string globalsound_metalfall;
-string globalsound_step;
-string globalsound_metalstep;
-
-const float VOICETYPE_PLAYERSOUND = 10;
-const float VOICETYPE_TEAMRADIO = 11;
-const float VOICETYPE_LASTATTACKER = 12;
-const float VOICETYPE_LASTATTACKER_ONLY = 13;
-const float VOICETYPE_AUTOTAUNT = 14;
-const float VOICETYPE_TAUNT = 15;
-
-void PrecachePlayerSounds(string f);
-void PrecacheGlobalSound(string samplestring);
-void UpdatePlayerSounds();
-void ClearPlayerSounds();
-void PlayerSound(.string samplefield, float channel, float voicetype);
-void GlobalSound(string samplestring, float channel, float voicetype);
-void FakeGlobalSound(string samplestring, float channel, float voicetype);
-void VoiceMessage(string type, string message);
-float GetPlayerSoundSampleField_notFound;
-.string GetVoiceMessageSampleField(string type);
-
// autotaunt system
.float cvar_cl_autotaunt;
.float cvar_cl_voice_directional;
string clientstuff;
.float phase;
-.int pressedkeys;
+.int pressedkeys = _STAT(PRESSED_KEYS);
.string fog;
float game_starttime; //point in time when the countdown to game start is over
float round_starttime; //point in time when the countdown to round start is over
-.float stat_game_starttime;
-.float stat_round_starttime;
+.float stat_game_starttime = _STAT(GAMESTARTTIME);
+.float stat_round_starttime = _STAT(ROUNDSTARTTIME);
void W_Porto_Remove (entity p);
.string message2;
-.float stat_allow_oldvortexbeam;
+.bool stat_allow_oldvortexbeam = _STAT(ALLOW_OLDVORTEXBEAM);
// reset to 0 on weapon switch
// may be useful to all weapons
void SUB_DontUseTargets();
void SUB_UseTargets();
-.void() reset; // if set, an entity is reset using this
+.void(entity this) reset; // if set, an entity is reset using this
.void() reset2; // if set, an entity is reset using this (after calling ALL the reset functions for other entities)
void ClientData_Touch(entity e);
.float floodcontrol_voice;
.float floodcontrol_voiceteam;
-.float stat_shotorg; // networked stat for trueaim HUD
+.float stat_shotorg = _STAT(SHOTORG); // networked stat for trueaim HUD
string matchid;
-.float last_pickup;
+.float last_pickup = _STAT(LAST_PICKUP);
-.float hit_time;
-.float typehit_time;
+.float hit_time = _STAT(HIT_TIME);
+.float typehit_time = _STAT(TYPEHIT_TIME);
-.float damage_dealt_total;
+.float damage_dealt_total = _STAT(DAMAGE_DEALT_TOTAL);
-.float stat_leadlimit;
+.float stat_leadlimit = _STAT(LEADLIMIT);
bool radar_showennemies;
.float weapon_load[Weapons_MAX];
.int ammo_none; // used by the reloading system, must always be 0
-.float clip_load;
+.float clip_load = _STAT(WEAPON_CLIPLOAD);
.float old_clip_load;
-.float clip_size;
+.float clip_size = _STAT(WEAPON_CLIPSIZE);
-.float minelayer_mines;
-.float vortex_charge;
+.float minelayer_mines = _STAT(LAYED_MINES);
+.float vortex_charge = _STAT(VORTEX_CHARGE);
.float vortex_charge_rottime;
-.float vortex_chargepool_ammo;
-.float hagar_load;
+.float vortex_chargepool_ammo = _STAT(VORTEX_CHARGEPOOL);
+.float hagar_load = _STAT(HAGAR_LOAD);
.int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
.float player_blocked;
.float weapon_blocked; // weapon use disabled
-.float frozen; // for freeze attacks
-.float revive_progress;
+.float frozen = _STAT(FROZEN); // for freeze attacks
+.float revive_progress = _STAT(REVIVE_PROGRESS);
.float revival_time; // time at which player was last revived
.float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
.entity iceblock;
.entity muzzle_flash;
.float misc_bulletcounter; // replaces uzi & hlac bullet counter.
-.float stat_respawn_time; // shows respawn time, and is negative when awaiting respawn
+.float stat_respawn_time = _STAT(RESPAWN_TIME); // shows respawn time, and is negative when awaiting respawn
void PlayerUseKey();
+++ /dev/null
-#include "ent_cs.qh"
-
-float entcs_customize()
-{
- SELFPARAM();
- entity o = self.owner;
- if(o.deadflag != DEAD_NO)
- return false;
- if (!IS_PLAYER(o))
- return false;
- if(other == o)
- return false;
- if((IS_PLAYER(other)) || other.caplayer)
- if(!teamplay || o.team != other.team)
- if (!radar_showennemies)
- return false;
- return true;
-}
-
-bool entcs_send(entity this, entity to, int sf)
-{
- WriteHeader(MSG_ENTITY, ENT_CLIENT_ENTCS);
- WriteByte(MSG_ENTITY, sf);
- if(sf & BIT(0))
- WriteByte(MSG_ENTITY, num_for_edict(self.owner) - 1);
- if(sf & BIT(1))
- {
- WriteShort(MSG_ENTITY, self.origin.x);
- WriteShort(MSG_ENTITY, self.origin.y);
- WriteShort(MSG_ENTITY, self.origin.z);
- }
- if(sf & BIT(2))
- WriteByte(MSG_ENTITY, self.angles.y * 256.0 / 360);
- if(sf & BIT(3))
- WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale?
- if(sf & BIT(4))
- WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
- return true;
-}
-
-void entcs_think()
-{
- SELFPARAM();
- self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing
- entity o = self.owner;
- if (o.origin != self.origin)
- {
- setorigin(self, o.origin);
- self.SendFlags |= BIT(1);
- }
- if (o.angles.y != self.angles.y)
- {
- self.angles = o.angles;
- self.SendFlags |= BIT(2);
- }
- if (o.health != self.health)
- {
- self.health = o.health;
- self.SendFlags |= BIT(3);
- }
- if (o.armorvalue != self.armorvalue)
- {
- self.armorvalue = o.armorvalue;
- self.SendFlags |= BIT(4);
- }
-}
-
-entity attach_entcs(entity e)
-{
- entity ent = e.entcs = new(entcs_sender);
- make_pure(ent);
- ent.owner = e;
- ent.think = entcs_think;
- ent.nextthink = time;
-
- Net_LinkEntity(ent, false, 0, entcs_send);
- ent.customizeentityforclient = entcs_customize;
-
- return ent;
-}
-
-void detach_entcs(entity e)
-{
- if (!e.entcs) return;
- remove(e.entcs);
- e.entcs = NULL;
-}
+++ /dev/null
-#ifndef ENT_CS_H
-#define ENT_CS_H
-
-/**
- * The point of these entities is to avoid the problems
- * with clientprediction.
- * If you add SendEntity to players, the engine will not
- * do any prediction anymore, and you'd have to write the whole
- * prediction code in CSQC, you want that? :P
- * Data can depend on gamemode. For now, it serves as GPS entities
- * in onslaught... YAY ;)
- */
-
-.entity entcs;
-
-float entcs_customize();
-
-bool entcs_send(entity this, entity to, int sf);
-
-void entcs_think();
-
-entity attach_entcs(entity e);
-
-void detach_entcs(entity e);
-
-#endif
#include "weapons/accuracy.qh"
#include "weapons/csqcprojectile.qh"
#include "weapons/selection.qh"
-#include "../common/buffs/all.qh"
#include "../common/constants.qh"
#include "../common/deathtypes/all.qh"
#include "../common/notifications.qh"
{
// after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
Weapon culprit = DEATH_WEAPONOF(deathtype);
- if(!culprit)
- culprit = get_weaponinfo(attacker.weapon);
- else if(!(attacker.weapons & WepSet_FromWeapon(culprit.m_id)))
- culprit = get_weaponinfo(attacker.weapon);
+ if(!culprit) culprit = get_weaponinfo(attacker.weapon);
+ else if(!(attacker.weapons & (culprit.m_wepset))) culprit = get_weaponinfo(attacker.weapon);
if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
{
// all others (including the culprit): remove
GiveFrags_randomweapons.weapons &= ~attacker.weapons;
- GiveFrags_randomweapons.weapons &= ~WepSet_FromWeapon(culprit.m_id);
+ GiveFrags_randomweapons.weapons &= ~(culprit.m_wepset);
// among the remaining ones, choose one by random
W_RandomWeapons(GiveFrags_randomweapons, 1);
if(GiveFrags_randomweapons.weapons)
{
attacker.weapons |= GiveFrags_randomweapons.weapons;
- attacker.weapons &= ~WepSet_FromWeapon(culprit.m_id);
+ attacker.weapons &= ~(culprit.m_wepset);
}
}
return false;
}
+.int buffs = _STAT(BUFFS); // TODO: remove
+
void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
{
// Sanity check
farcent.origin = hitloc;
farcent.forcetype = FORCETYPE_FORCEATPOS;
farcent.nextthink = time + 0.1;
- farcent.think = SUB_Remove;
+ farcent.think = SUB_Remove_self;
}
else
{
//pl.disableclientprediction = false;
}
-void GrapplingHookReset()
-{SELFPARAM();
- if(self.realowner.hook == self)
- RemoveGrapplingHook(self.owner);
+void GrapplingHookReset(entity this)
+{
+ if(this.realowner.hook == this)
+ RemoveGrapplingHook(this.owner);
else // in any case:
- remove(self);
+ remove(this);
}
void GrapplingHookThink();
void() SUB_CalcMoveDone;
void() SUB_CalcAngleMoveDone;
//void() SUB_UseTargets;
-void() SUB_Remove;
spawnfunc(info_null);
-/*
-==================
-SUB_Remove
-
-Remove self
-==================
-*/
-void SUB_Remove ();
-
/*
==================
SUB_Friction
#include "scores.qh"
#include "teamplay.qh"
#include "weapons/weaponstats.qh"
-#include "../common/buffs/all.qh"
#include "../common/constants.qh"
#include "../common/deathtypes/all.qh"
#include "../common/mapinfo.qh"
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
}
+void __init_dedicated_server_shutdown() {
+ MapInfo_Shutdown();
+}
+
void Map_MarkAsRecent(string m);
float world_already_spawned;
void Nagger_Init();
void ClientInit_Spawn();
void WeaponStats_Init();
void WeaponStats_Shutdown();
-void Physics_AddStats();
spawnfunc(worldspawn)
{
float fd, l, j, n;
compressShortVector_init();
- entity head;
- head = nextent(world);
maxclients = 0;
- while(head)
+ for (entity head = nextent(world); head; head = nextent(head))
{
++maxclients;
- head = nextent(head);
}
server_is_dedicated = (stof(cvar_defstring("is_dedicated")) ? true : false);
WeaponStats_Init();
- WepSet_AddStat();
- WepSet_AddStat_InMap();
- addstat(STAT_SWITCHWEAPON, AS_INT, switchweapon);
- addstat(STAT_SWITCHINGWEAPON, AS_INT, switchingweapon);
- addstat(STAT_WEAPON_NEXTTHINK, AS_FLOAT, weapon_nextthink);
- addstat(STAT_GAMESTARTTIME, AS_FLOAT, stat_game_starttime);
- addstat(STAT_ROUNDSTARTTIME, AS_FLOAT, stat_round_starttime);
- addstat(STAT_ALLOW_OLDVORTEXBEAM, AS_INT, stat_allow_oldvortexbeam);
Nagger_Init();
- addstat(STAT_STRENGTH_FINISHED, AS_FLOAT, strength_finished);
- addstat(STAT_INVINCIBLE_FINISHED, AS_FLOAT, invincible_finished);
- addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
- addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
- addstat(STAT_FUEL, AS_INT, ammo_fuel);
- addstat(STAT_PLASMA, AS_INT, ammo_plasma);
- addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
- addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
- addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
- addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size);
- addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);
- addstat(STAT_HIT_TIME, AS_FLOAT, hit_time);
- addstat(STAT_DAMAGE_DEALT_TOTAL, AS_INT, damage_dealt_total);
- addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time);
- addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines);
-
- addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge);
- addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo);
-
- addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
-
- addstat(STAT_ARC_HEAT, AS_FLOAT, arc_heat_percent);
-
- // freeze attacks
- addstat(STAT_FROZEN, AS_INT, frozen);
- addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
-
- // physics
- Physics_AddStats();
-
- // new properties
- addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
- addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
- addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
- addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
- addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
- addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
- addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
- addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
- addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
- addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
- addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
- addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
- addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
- addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-
- // secrets
- addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
- addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
-
- // monsters
- addstat(STAT_MONSTERS_TOTAL, AS_FLOAT, stat_monsters_total);
- addstat(STAT_MONSTERS_KILLED, AS_FLOAT, stat_monsters_killed);
-
- // misc
- addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
-
next_pingtime = time + 5;
detect_maptype();
void FixIntermissionClient(entity e)
{
- string s;
if(!e.autoscreenshot) // initial call
{
e.autoscreenshot = time + 0.8; // used for autoscreenshot
if(IS_REAL_CLIENT(e))
{
stuffcmd(e, "\nscr_printspeed 1000000\n");
- s = autocvar_sv_intermission_cdtrack;
- if(s != "")
- stuffcmd(e, strcat("\ncd loop ", s, "\n"));
+ string list = autocvar_sv_intermission_cdtrack;
+ for(string it; (it = car(list)); list = cdr(list))
+ RandomSelection_Add(world, 0, it, 1, 1);
+ if(RandomSelection_chosen_string && RandomSelection_chosen_string != "")
+ stuffcmd(e, strcat("\ncd loop ", RandomSelection_chosen_string, "\n"));
msg_entity = e;
WriteByte(MSG_ONE, SVC_INTERMISSION);
}
);
}
-float WinningCondition_Race(float fraglimit)
-{
- float wc;
- entity p;
- float n, c;
-
- n = 0;
- c = 0;
- FOR_EACH_PLAYER(p)
- {
- ++n;
- if(p.race_completed)
- ++c;
- }
- if(n && (n == c))
- return WINNING_YES;
- wc = WinningCondition_Scores(fraglimit, 0);
-
- // ALWAYS initiate overtime, unless EVERYONE has finished the race!
- if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
- // do NOT support equality when the laps are all raced!
- return WINNING_STARTSUDDENDEATHOVERTIME;
- else
- return WINNING_NEVER;
-}
-
-float WinningCondition_QualifyingThenRace(float limit)
-{
- float wc;
- wc = WinningCondition_Scores(limit, 0);
-
- // NEVER initiate overtime
- if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
- {
- return WINNING_YES;
- }
-
- return wc;
-}
-
float WinningCondition_RanOutOfSpawns()
{
entity head;
{
LOG_INFO("NOTE: crashed before even initializing the world, not saving persistent data\n");
}
+ else
+ {
+ __init_dedicated_server_shutdown();
+ }
}
{
e = get_weaponinfo(j);
if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
- g_weaponarena_weapons |= WepSet_FromWeapon(j);
+ g_weaponarena_weapons |= (e.m_wepset);
}
}
else if (s == "most")
e = get_weaponinfo(j);
if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
if (e.spawnflags & WEP_FLAG_NORMAL)
- g_weaponarena_weapons |= WepSet_FromWeapon(j);
+ g_weaponarena_weapons |= (e.m_wepset);
}
}
else if (s == "none")
e = get_weaponinfo(j);
if (e.netname == s)
{
- g_weaponarena_weapons |= WepSet_FromWeapon(j);
+ g_weaponarena_weapons |= (e.m_wepset);
g_weaponarena_list = strcat(g_weaponarena_list, e.m_name, " & ");
break;
}
{
e = get_weaponinfo(i);
int w = want_weapon(e, false);
+ WepSet s = e.m_wepset;
if(w & 1)
- start_weapons |= WepSet_FromWeapon(i);
+ start_weapons |= s;
if(w & 2)
- start_weapons_default |= WepSet_FromWeapon(i);
+ start_weapons_default |= s;
if(w & 4)
- start_weapons_defaultmask |= WepSet_FromWeapon(i);
+ start_weapons_defaultmask |= s;
}
}
{
e = get_weaponinfo(i);
int w = want_weapon(e, g_warmup_allguns);
+ WepSet s = (e.m_wepset);
if(w & 1)
- warmup_start_weapons |= WepSet_FromWeapon(i);
+ warmup_start_weapons |= s;
if(w & 2)
- warmup_start_weapons_default |= WepSet_FromWeapon(i);
+ warmup_start_weapons_default |= s;
if(w & 4)
- warmup_start_weapons_defaultmask |= WepSet_FromWeapon(i);
+ warmup_start_weapons_defaultmask |= s;
}
}
}
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- if(precache_weapons & WepSet_FromWeapon(i)) {
- Weapon w = get_weaponinfo(i);
- w.wr_init(w);
+ if(precache_weapons & (e.m_wepset)) {
+ e.wr_init(e);
}
}
warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
}
-float sound_allowed(float destin, entity e)
-{
- // sounds from world may always pass
- for (;;)
- {
- if (e.classname == "body")
- e = e.enemy;
- else if (e.realowner && e.realowner != e)
- e = e.realowner;
- else if (e.owner && e.owner != e)
- e = e.owner;
- else
- break;
- }
- // sounds to self may always pass
- if (destin == MSG_ONE)
- if (e == msg_entity)
- return true;
- // sounds by players can be removed
- if (autocvar_bot_sound_monopoly)
- if (IS_REAL_CLIENT(e))
- return false;
- // anything else may pass
- return true;
-}
-
-void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float attenu)
-{
- float entno, idx;
-
- if (!sound_allowed(_dest, e))
- return;
-
- entno = num_for_edict(e);
- idx = precache_sound_index(samp);
-
- int sflags;
- sflags = 0;
-
- attenu = floor(attenu * 64);
- vol = floor(vol * 255);
-
- if (vol != 255)
- sflags |= SND_VOLUME;
- if (attenu != 64)
- sflags |= SND_ATTENUATION;
- if (entno >= 8192 || chan < 0 || chan > 7)
- sflags |= SND_LARGEENTITY;
- if (idx >= 256)
- sflags |= SND_LARGESOUND;
-
- WriteByte(_dest, SVC_SOUND);
- WriteByte(_dest, sflags);
- if (sflags & SND_VOLUME)
- WriteByte(_dest, vol);
- if (sflags & SND_ATTENUATION)
- WriteByte(_dest, attenu);
- if (sflags & SND_LARGEENTITY)
- {
- WriteShort(_dest, entno);
- WriteByte(_dest, chan);
- }
- else
- {
- WriteShort(_dest, entno * 8 + chan);
- }
- if (sflags & SND_LARGESOUND)
- WriteShort(_dest, idx);
- else
- WriteByte(_dest, idx);
-
- WriteCoord(_dest, o.x);
- WriteCoord(_dest, o.y);
- WriteCoord(_dest, o.z);
-}
-void soundto(float _dest, entity e, float chan, string samp, float vol, float _atten)
-{
- vector o;
-
- if (!sound_allowed(_dest, e))
- return;
-
- o = e.origin + 0.5 * (e.mins + e.maxs);
- soundtoat(_dest, e, o, chan, samp, vol, _atten);
-}
-void soundat(entity e, vector o, float chan, string samp, float vol, float _atten)
-{
- soundtoat(((chan & 8) ? MSG_ALL : MSG_BROADCAST), e, o, chan, samp, vol, _atten);
-}
-void stopsoundto(float _dest, entity e, float chan)
-{
- float entno;
-
- if (!sound_allowed(_dest, e))
- return;
-
- entno = num_for_edict(e);
-
- if (entno >= 8192 || chan < 0 || chan > 7)
- {
- float idx, sflags;
- idx = precache_sound_index(SND(Null));
- sflags = SND_LARGEENTITY;
- if (idx >= 256)
- sflags |= SND_LARGESOUND;
- WriteByte(_dest, SVC_SOUND);
- WriteByte(_dest, sflags);
- WriteShort(_dest, entno);
- WriteByte(_dest, chan);
- if (sflags & SND_LARGESOUND)
- WriteShort(_dest, idx);
- else
- WriteByte(_dest, idx);
- WriteCoord(_dest, e.origin.x);
- WriteCoord(_dest, e.origin.y);
- WriteCoord(_dest, e.origin.z);
- }
- else
- {
- WriteByte(_dest, SVC_STOPSOUND);
- WriteShort(_dest, entno * 8 + chan);
- }
-}
-void stopsound(entity e, float chan)
-{
- if (!sound_allowed(MSG_BROADCAST, e))
- return;
-
- stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
- stopsoundto(MSG_ALL, e, chan); // in case of packet loss
-}
-
-void play2(entity e, string filename)
-{
- //stuffcmd(e, strcat("play2 ", filename, "\n"));
- msg_entity = e;
- soundtoat(MSG_ONE, world, '0 0 0', CH_INFO, filename, VOL_BASE, ATTEN_NONE);
-}
-
-// use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
-.float spamtime;
-float spamsound(entity e, float chan, string samp, float vol, float _atten)
-{
- if (!sound_allowed(MSG_BROADCAST, e))
- return false;
-
- if (time > e.spamtime)
- {
- e.spamtime = time;
- _sound(e, chan, samp, vol, _atten);
- return true;
- }
- return false;
-}
-
-void play2team(float t, string filename)
-{
- entity head;
-
- if (autocvar_bot_sound_monopoly)
- return;
-
- FOR_EACH_REALPLAYER(head)
- {
- if (head.team == t)
- play2(head, filename);
- }
-}
-
-void play2all(string samp)
-{
- if (autocvar_bot_sound_monopoly)
- return;
-
- _sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
-}
-
-void PrecachePlayerSounds(string f);
void precache_playermodel(string m)
{
float globhandle, i, n;
precache_playermodels(autocvar_sv_defaultplayermodel);
}
- if (g_footsteps)
- {
- PrecacheGlobalSound((globalsound_step = "misc/footstep0 6"));
- PrecacheGlobalSound((globalsound_metalstep = "misc/metalfootstep0 6"));
- }
-
- // gore and miscellaneous sounds
- PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
- PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
-
#if 0
// Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
if(s != "")
{
db_put(ServerProgsDB, strcat("/uid2name/", myuid), s);
- db_put(ServerProgsDB, strcat("uid2name", myuid), "");
+ db_remove(ServerProgsDB, strcat("uid2name", myuid));
}
}
void objerror(string s);
void droptofloor();
-void() SUB_Remove;
void attach_sameorigin(entity e, entity to, string tag);
#define PROJECTILE_TOUCH if(WarpZone_Projectile_Touch()) return
-const string STR_PLAYER = "player";
-const string STR_SPECTATOR = "spectator";
-const string STR_OBSERVER = "observer";
-
-#define IS_PLAYER(v) ((v).classname == STR_PLAYER)
-#define IS_SPEC(v) ((v).classname == STR_SPECTATOR)
-#define IS_OBSERVER(v) ((v).classname == STR_OBSERVER)
-#define IS_CLIENT(v) (v.flags & FL_CLIENT)
-#define IS_BOT_CLIENT(v) (clienttype(v) == CLIENTTYPE_BOT)
-#define IS_REAL_CLIENT(v) (clienttype(v) == CLIENTTYPE_REAL)
-#define IS_NOT_A_CLIENT(v) (clienttype(v) == CLIENTTYPE_NOTACLIENT)
-
-#define IS_MONSTER(v) (v.flags & FL_MONSTER)
-#define IS_VEHICLE(v) (v.vehicle_flags & VHF_ISVEHICLE)
-#define IS_TURRET(v) (v.turret_flags & TUR_FLAG_ISTURRET)
-
-#define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
-#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v))
-#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v))
-
-#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(IS_PLAYER(v))
-#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if (!IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too
-#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(IS_PLAYER(v))
-
-#define FOR_EACH_MONSTER(v) for(v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
-
#define CENTER_OR_VIEWOFS(ent) (ent.origin + (IS_PLAYER(ent) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
// copies a string to a tempstring (so one can strunzone it)
float want_weapon(entity weaponinfo, float allguns); // WEAPONTODO: what still needs done?
void readplayerstartcvars();
-float g_bugrigs;
-float g_bugrigs_planar_movement;
-float g_bugrigs_planar_movement_car_jumping;
-float g_bugrigs_reverse_spinning;
-float g_bugrigs_reverse_speeding;
-float g_bugrigs_reverse_stopping;
-float g_bugrigs_air_steering;
-float g_bugrigs_angle_smoothing;
-float g_bugrigs_friction_floor;
-float g_bugrigs_friction_brake;
-float g_bugrigs_friction_air;
-float g_bugrigs_accel;
-float g_bugrigs_speed_ref;
-float g_bugrigs_speed_pow;
-float g_bugrigs_steer;
-
float sv_autotaunt;
float sv_taunt;
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
- g_bugrigs = cvar("g_bugrigs");
- g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
- g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
- g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
- g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
- g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
- g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
- g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
- g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
- g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
- g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
- g_bugrigs_accel = cvar("g_bugrigs_accel");
- g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
- g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
- g_bugrigs_steer = cvar("g_bugrigs_steer");
-
g_instagib = cvar("g_instagib");
sv_clones = cvar("sv_clones");
//#NO AUTOCVARS END
-
-// Sound functions
-//string precache_sound (string s) = #19;
-// hack
-float precache_sound_index (string s) = #19;
-
-const float SND_VOLUME = BIT(0);
-const float SND_ATTENUATION = BIT(1);
-const float SND_LARGEENTITY = BIT(3);
-const float SND_LARGESOUND = BIT(4);
-
const float INITPRIO_FIRST = 0;
const float INITPRIO_GAMETYPE = 0;
const float INITPRIO_GAMETYPE_FALLBACK = 1;
#include "../../common/stats.qh"
#include "../../common/teams.qh"
#include "../../common/util.qh"
- #include "../../common/nades/all.qh"
- #include "../../common/buffs/all.qh"
#include "../../common/command/markup.qh"
#include "../../common/command/rpn.qh"
#include "../../common/command/generic.qh"
string item_model_output;
MUTATOR_HOOKABLE(ItemModel, EV_ItemModel);
-/** called when a player presses the jump key */
-#define EV_PlayerJump(i, o) \
- /**/ i(float, player_multijump) \
- /**/ i(float, player_jumpheight) \
- /**/ o(float, player_multijump) \
- /**/ o(float, player_jumpheight) \
- /**/
-float player_multijump;
-float player_jumpheight;
-MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
-
/** called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill */
#define EV_GiveFragsForKill(i, o) \
/**/ i(entity, __self) \
/** TODO change this into a general PlayerPostThink hook? */
MUTATOR_HOOKABLE(GetPressedKeys, EV_NO_ARGS);
-/**
- * called before any player physics, may adjust variables for movement,
- * is run AFTER bot code and idle checking
- */
-MUTATOR_HOOKABLE(PlayerPhysics, EV_NO_ARGS);
-
/** is meant to call GetCvars_handle*(get_cvars_s, get_cvars_f, cvarfield, "cvarname") for cvars this mutator needs from the client */
#define EV_GetCvars(i, o) \
/**/ i(float, get_cvars_f) \
#define EV_SpectateSet(i, o) \
/**/ i(entity, __self) \
/**/ i(entity, spec_player) \
+ /**/ o(entity, spec_player) \
/**/
entity spec_player;
MUTATOR_HOOKABLE(SpectateSet, EV_SpectateSet);
#define EV_SpectateNext(i, o) \
/**/ i(entity, __self) \
/**/ i(entity, spec_player) \
+ /**/ o(entity, spec_player) \
/**/
MUTATOR_HOOKABLE(SpectateNext, EV_SpectateNext);
#define EV_SpectatePrev(i, o) \
/**/ i(entity, __self) \
/**/ i(entity, spec_player) \
+ /**/ o(entity, spec_player) \
/**/ i(entity, spec_first) \
/**/
entity spec_first;
string monster_model;
string monster_model_output;
MUTATOR_HOOKABLE(MonsterModel, EV_MonsterModel);
+
+/**/
+#define EV_Player_ChangeTeam(i, o) \
+ /**/ i(entity, __self) \
+ /**/ i(float, pct_curteam) \
+ /**/ i(float, pct_newteam) \
+ /**/
+float pct_curteam;
+float pct_newteam;
+MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
#endif
.float lastground;
float total_players;
float redalive, bluealive, yellowalive, pinkalive;
-.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat;
+.float redalive_stat = _STAT(REDALIVE);
+.float bluealive_stat = _STAT(BLUEALIVE);
+.float yellowalive_stat = _STAT(YELLOWALIVE);
+.float pinkalive_stat = _STAT(PINKALIVE);
#endif
// reset this objective. Used when spawning an objective
// and when a new round starts
-void assault_objective_reset()
-{SELFPARAM();
- self.health = ASSAULT_VALUE_INACTIVE;
+void assault_objective_reset(entity this)
+{
+ this.health = ASSAULT_VALUE_INACTIVE;
}
// decrease the health of targeted objectives
assault_setenemytoobjective();
}
-void target_assault_roundend_reset()
-{SELFPARAM();
+void target_assault_roundend_reset(entity this)
+{
//print("round end reset\n");
- self.cnt = self.cnt + 1; // up round counter
- self.winning = 0; // up round
+ ++this.cnt; // up round counter
+ this.winning = false; // up round
}
void target_assault_roundend_use()
else
assault_attacker_team = NUM_TEAM_1;
- entity ent;
- for(ent = world; (ent = nextent(ent)); )
- {
- if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)
- {
- if(ent.team_saved == NUM_TEAM_1)
- ent.team_saved = NUM_TEAM_2;
- else if(ent.team_saved == NUM_TEAM_2)
- ent.team_saved = NUM_TEAM_1;
- }
- }
+ FOREACH_ENTITY(clienttype(it) == CLIENTTYPE_NOTACLIENT, LAMBDA(
+ if (it.team_saved == NUM_TEAM_1) it.team_saved = NUM_TEAM_2;
+ else if (it.team_saved == NUM_TEAM_2) it.team_saved = NUM_TEAM_1;
+ ));
// reset the level with a countdown
cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60));
spawnfunc(target_objective)
{
- if (!g_assault) { remove(self); return; }
+ if (!g_assault) { remove(this); return; }
- self.classname = "target_objective";
- self.use = assault_objective_use;
- assault_objective_reset();
- self.reset = assault_objective_reset;
- self.spawn_evalfunc = target_objective_spawn_evalfunc;
+ this.classname = "target_objective";
+ this.use = assault_objective_use;
+ this.reset = assault_objective_reset;
+ this.reset(this);
+ this.spawn_evalfunc = target_objective_spawn_evalfunc;
}
spawnfunc(target_objective_decrease)
return false;
}
-// Returns next available player to spectate if g_ca_spectate_enemies == 0
+/** Returns next available player to spectate if g_ca_spectate_enemies == 0 */
entity CA_SpectateNext(entity player, entity start)
{
- if(SAME_TEAM(start, player))
- return start;
-
- entity spec_other = start;
+ if (SAME_TEAM(start, player)) return start;
// continue from current player
- while(spec_other && DIFF_TEAM(spec_other, player))
- spec_other = find(spec_other, classname, "player");
-
- if (!spec_other)
+ for (entity e = start; (e = find(e, classname, "player")); )
{
- // restart from begining
- spec_other = find(spec_other, classname, "player");
- while(spec_other && DIFF_TEAM(spec_other, player))
- spec_other = find(spec_other, classname, "player");
+ if (SAME_TEAM(player, e)) return e;
}
-
- return spec_other;
+ // restart from begining
+ for (entity e = NULL; (e = find(e, classname, "player")); )
+ {
+ if (SAME_TEAM(player, e)) return e;
+ }
+ return start;
}
+
MUTATOR_HOOKFUNCTION(ca, PlayerSpawn)
{SELFPARAM();
self.caplayer = 1;
round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart);
round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
- addstat(STAT_REDALIVE, AS_INT, redalive_stat);
- addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
- addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
- addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
-
EliminatedPlayers_Init(ca_isEliminated);
}
#define CTF_DIFFTEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? SAME_TEAM(a,b) : DIFF_TEAM(a,b))
// networked flag statuses
-.int ctf_flagstatus;
+.int ctf_flagstatus = _STAT(CTF_FLAGSTATUS);
#endif
const int CTF_RED_FLAG_TAKEN = 1;
bool autocvar_g_ctf_flag_glowtrails;
int autocvar_g_ctf_flag_health;
bool autocvar_g_ctf_flag_return;
+bool autocvar_g_ctf_flag_return_carrying;
float autocvar_g_ctf_flag_return_carried_radius;
float autocvar_g_ctf_flag_return_time;
bool autocvar_g_ctf_flag_return_when_unreachable;
}
else if(CTF_SAMETEAM(toucher, flag) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, flag) && is_not_monster)
ctf_Handle_Capture(flag, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to his base
+ else if(CTF_DIFFTEAM(toucher, flag) && (toucher.flagcarried) && CTF_SAMETEAM(toucher.flagcarried, toucher) && (!toucher.ctf_captureshielded) && autocvar_g_ctf_flag_return_carrying && (time > toucher.next_take_time) && is_not_monster)
+ {
+ ctf_Handle_Return(toucher.flagcarried, toucher); // return their current flag
+ ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // now pickup the flag
+ }
else if(CTF_DIFFTEAM(toucher, flag) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && is_not_monster)
ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // toucher just stole the enemies flag
break;
case FLAG_DROPPED:
{
- if(CTF_SAMETEAM(toucher, flag) && (autocvar_g_ctf_flag_return || num_perteam <= 1) && flag.team) // automatically return if there's only 1 player on the team
+ if(CTF_SAMETEAM(toucher, flag) && (autocvar_g_ctf_flag_return || num_perteam <= 1 || (autocvar_g_ctf_flag_return_carrying && toucher.flagcarried)) && flag.team) // automatically return if there's only 1 player on the team
ctf_Handle_Return(flag, toucher); // toucher just returned his own flag
else if(is_not_monster && (!toucher.flagcarried) && ((toucher != flag.ctf_dropper) || (time > flag.ctf_droptime + autocvar_g_ctf_flag_collect_delay)))
ctf_Handle_Pickup(flag, toucher, PICKUP_DROPPED); // toucher just picked up a dropped enemy flag
ctf_CheckStalemate();
}
-void ctf_Reset()
-{SELFPARAM();
- if(self.owner)
- if(IS_PLAYER(self.owner))
- ctf_Handle_Throw(self.owner, world, DROP_RESET);
+void ctf_Reset(entity this)
+{
+ if(this.owner && IS_PLAYER(this.owner))
+ ctf_Handle_Throw(this.owner, world, DROP_RESET);
- ctf_RespawnFlag(self);
+ ctf_RespawnFlag(this);
}
void ctf_DelayedFlagSetup() // called after a flag is placed on a map by ctf_FlagSetup()
// if no teams are found, spawn defaults
if(find(world, classname, "ctf_team") == world)
{
- LOG_INFO("No ""ctf_team"" entities found on this map, creating them anyway.\n");
+ LOG_INFO("No \"ctf_team\" entities found on this map, creating them anyway.\n");
ctf_SpawnTeam("Red", NUM_TEAM_1 - 1);
ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1);
if(ctf_teams >= 3)
ctf_captureshield_max_ratio = autocvar_g_ctf_shield_max_ratio;
ctf_captureshield_force = autocvar_g_ctf_shield_force;
- addstat(STAT_CTF_FLAGSTATUS, AS_INT, ctf_flagstatus);
-
InitializeEntity(world, ctf_DelayedInit, INITPRIO_GAMETYPE);
}
MUTATOR_HOOKFUNCTION(cts, Race_FinalCheckpoint)
{
if(autocvar_g_cts_finish_kill_delay)
- CTS_ClientKill(self);
+ CTS_ClientKill(race_player);
return false;
}
const float SP_DOM_CAPS = 4;
// pps: points per second
-.float dom_total_pps;
-.float dom_pps_red;
-.float dom_pps_blue;
-.float dom_pps_yellow;
-.float dom_pps_pink;
+.float dom_total_pps = _STAT(DOM_TOTAL_PPS);
+.float dom_pps_red = _STAT(DOM_PPS_RED);
+.float dom_pps_blue = _STAT(DOM_PPS_BLUE);
+.float dom_pps_yellow = _STAT(DOM_PPS_YELLOW);
+.float dom_pps_pink = _STAT(DOM_PPS_PINK);
float total_pps;
float pps_red;
float pps_blue;
dompoint_captured();
}
-void dom_controlpoint_setup()
-{SELFPARAM();
+void dom_controlpoint_setup(entity this);
+void dom_controlpoint_setup_self() { SELFPARAM(); dom_controlpoint_setup(this); }
+void dom_controlpoint_setup(entity this)
+{
entity head;
// find the spawnfunc_dom_team representing unclaimed points
head = find(world, classname, "dom_team");
remove(self);
return;
}
- self.think = dom_controlpoint_setup;
+ self.think = dom_controlpoint_setup_self;
self.nextthink = time + 0.1;
self.reset = dom_controlpoint_setup;
setself(this);
}
-void _spawnfunc_dom_controlpoint() { SELFPARAM(); spawnfunc_dom_controlpoint(self); }
+void self_spawnfunc_dom_controlpoint() { SELFPARAM(); spawnfunc_dom_controlpoint(self); }
void dom_spawnpoint(vector org)
{SELFPARAM();
setself(spawn());
self.classname = "dom_controlpoint";
- self.think = _spawnfunc_dom_controlpoint;
+ self.think = self_spawnfunc_dom_controlpoint;
self.nextthink = time;
setorigin(self, org);
spawnfunc_dom_controlpoint(this);
// if no teams are found, spawn defaults
if(find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
{
- LOG_INFO("No ""dom_team"" entities found on this map, creating them anyway.\n");
+ LOG_INFO("No \"dom_team\" entities found on this map, creating them anyway.\n");
domination_teams = bound(2, ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override), 4);
dom_spawnteams(domination_teams);
}
CheckAllowedTeams(world);
domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2);
- addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
- addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
- addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
- if(domination_teams >= 3) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
- if(domination_teams >= 4) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
-
domination_roundbased = autocvar_g_domination_roundbased;
ScoreRules_dom(domination_teams);
round_handler_Spawn(freezetag_CheckTeams, freezetag_CheckWinner, func_null);
round_handler_Init(5, autocvar_g_freezetag_warmup, autocvar_g_freezetag_round_timelimit);
- addstat(STAT_REDALIVE, AS_INT, redalive_stat);
- addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
- addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
- addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
-
EliminatedPlayers_Init(freezetag_isEliminated);
}
monster = spawnmonster("", mon, world, world, e.origin, false, false, 2);
else return;
- e.think = SUB_Remove;
+ e.think = SUB_Remove_self;
e.nextthink = time + 0.1;
}
else
WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
}
-void ka_Reset() // used to clear the ballcarrier whenever the match switches from warmup to normal
-{SELFPARAM();
- if((self.owner) && (IS_PLAYER(self.owner)))
- ka_DropEvent(self.owner);
+/** used to clear the ballcarrier whenever the match switches from warmup to normal */
+void ka_Reset(entity this)
+{
+ if((this.owner) && (IS_PLAYER(this.owner)))
+ ka_DropEvent(this.owner);
if(time < game_starttime)
{
- self.think = ka_RespawnBall;
- self.touch = func_null;
- self.nextthink = game_starttime;
+ this.think = ka_RespawnBall;
+ this.touch = func_null;
+ this.nextthink = game_starttime;
}
else
ka_RespawnBall();
// bits 5- 9: team of key 2, or 0 for no such key, or 30 for dropped, or 31 for self
// bits 10-14: team of key 3, or 0 for no such key, or 30 for dropped, or 31 for self
// bits 15-19: team of key 4, or 0 for no such key, or 30 for dropped, or 31 for self
-.float kh_state;
+.float kh_state = _STAT(KH_KEYS);
.float siren_time; // time delay the siren
//.float stuff_time; // time delay to stuffcmd a cvar
self.nextthink = time + 0.05;
}
-void key_reset()
-{SELFPARAM();
- kh_Key_AssignTo(self, world);
- kh_Key_Remove(self);
+void key_reset(entity this)
+{
+ kh_Key_AssignTo(this, world);
+ kh_Key_Remove(this);
}
const string STR_ITEM_KH_KEY = "item_kh_key";
}
else
{
- float missing_teams_mask = (!!p1) + (!!p2) * 2;
- if(kh_teams >= 3) missing_teams_mask += (!!p3) * 4;
- if(kh_teams >= 4) missing_teams_mask += (!!p4) * 8;
+ float missing_teams_mask = boolean(p1) + boolean(p2) * 2;
+ if(kh_teams >= 3) missing_teams_mask += boolean(p3) * 4;
+ if(kh_teams >= 4) missing_teams_mask += boolean(p4) * 8;
if(prev_missing_teams_mask != missing_teams_mask)
{
Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask);
kh_controller.model = "";
kh_controller.modelindex = 0;
- addstat(STAT_KH_KEYS, AS_INT, kh_state);
-
kh_ScoreRules(kh_teams);
}
MUTATOR_HOOKFUNCTION(lms, FilterItem)
{SELFPARAM();
if(autocvar_g_lms_extra_lives)
- if(self.itemdef == ITEM_HealthMega)
- {
- self.max_health = 1;
+ if(self.itemdef == ITEM_ExtraLife)
return false;
- }
+
+ return true;
+}
+
+void lms_extralife()
+{SELFPARAM();
+ StartItem(this, ITEM_ExtraLife);
+}
+
+MUTATOR_HOOKFUNCTION(lms, OnEntityPreSpawn)
+{SELFPARAM();
+ if (!autocvar_g_powerups) return false;
+ if (!autocvar_g_lms_extra_lives) return false;
+
+ // Can't use .itemdef here
+ if (self.classname != "item_health_mega") return false;
+
+ entity e = spawn();
+ e.think = lms_extralife;
+
+ e.nextthink = time + 0.1;
+ e.spawnflags = self.spawnflags;
+ e.noalign = self.noalign;
+ setorigin(e, self.origin);
return true;
}
MUTATOR_HOOKFUNCTION(lms, ItemTouch)
{SELFPARAM();
- // give extra lives for mega health
- if (self.items & ITEM_HealthMega.m_itemid)
+ if(self.itemdef == ITEM_ExtraLife)
{
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_EXTRALIVES);
PlayerScore_Add(other, SP_LMS_LIVES, autocvar_g_lms_extra_lives);
+ return MUT_ITEMTOUCH_PICKUP;
}
return MUT_ITEMTOUCH_CONTINUE;
GameLogEcho(strcat(":race:", mode, ":", ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
}
+float WinningCondition_Race(float fraglimit)
+{
+ float wc;
+ entity p;
+ float n, c;
+
+ n = 0;
+ c = 0;
+ FOR_EACH_PLAYER(p)
+ {
+ ++n;
+ if(p.race_completed)
+ ++c;
+ }
+ if(n && (n == c))
+ return WINNING_YES;
+ wc = WinningCondition_Scores(fraglimit, 0);
+
+ // ALWAYS initiate overtime, unless EVERYONE has finished the race!
+ if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
+ // do NOT support equality when the laps are all raced!
+ return WINNING_STARTSUDDENDEATHOVERTIME;
+ else
+ return WINNING_NEVER;
+}
+
+float WinningCondition_QualifyingThenRace(float limit)
+{
+ float wc;
+ wc = WinningCondition_Scores(limit, 0);
+
+ // NEVER initiate overtime
+ if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
+ {
+ return WINNING_YES;
+ }
+
+ return wc;
+}
+
MUTATOR_HOOKFUNCTION(rc, PlayerPhysics)
{SELFPARAM();
self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
MUTATOR_HOOKFUNCTION(rc, CheckRules_World)
{
- if(g_race_qualifying == 2 && checkrules_timelimit >= 0)
+ if(checkrules_timelimit >= 0)
{
- ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
- return true;
+ if(!g_race_qualifying)
+ {
+ ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
+ return true;
+ }
+ else if(g_race_qualifying == 2)
+ {
+ ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
+ return true;
+ }
}
return false;
// if no teams are found, spawn defaults
if(find(world, classname, "tdm_team") == world)
{
- LOG_INFO("No ""tdm_team"" entities found on this map, creating them anyway.\n");
+ LOG_INFO("No \"tdm_team\" entities found on this map, creating them anyway.\n");
int numteams = min(4, autocvar_g_tdm_teams_override);
}
}
-void SUB_Remove();
-
void pathlib_showsquare(vector where,float goodsquare,float _lifetime)
{
entity s;
s = spawn();
s.alpha = 0.25;
- s.think = SUB_Remove;
+ s.think = SUB_Remove_self;
s.nextthink = _lifetime;
s.scale = pathlib_gridsize / 512.001;
s.solid = SOLID_NOT;
e = spawn();
e.alpha = 0.25;
- e.think = SUB_Remove;
+ e.think = SUB_Remove_self;
e.nextthink = _lifetime;
e.scale = pathlib_gridsize / 512;
e.solid = SOLID_NOT;
e = findchainentity(owner, start);
while(e)
{
- e.think = SUB_Remove;
+ e.think = SUB_Remove_self;
e.nextthink = time;
e = e.chain;
}
void dumpnode(entity n)
{
n.is_path_node = false;
- n.think = SUB_Remove;
+ n.think = SUB_Remove_self;
n.nextthink = time;
}
node = spawn();
- node.think = SUB_Remove;
+ node.think = SUB_Remove_self;
node.nextthink = time + PATHLIB_NODEEXPIRE;
node.is_path_node = true;
node.owner = openlist;
{SELFPARAM();
self.(f) = stof(fgets(self.playerdemo_fh));
}
-float playerdemo_read()
-{SELFPARAM();
- if(self.playerdemo_mode != PLAYERDEMO_MODE_READING)
+float playerdemo_read(entity this)
+{
+ if(this.playerdemo_mode != PLAYERDEMO_MODE_READING)
return 0;
- if(self.playerdemo_time < 0)
+ if(this.playerdemo_time < 0)
return 1;
float t;
t = time;
- while(time >= self.playerdemo_time)
+ while(time >= this.playerdemo_time)
{
PLAYERDEMO_FIELDS(playerdemo_read_)
{
- time = self.playerdemo_time;
- PlayerPreThink();
+ time = this.playerdemo_time;
+ WITH(entity, this, this, PlayerPreThink());
// not running physics though... this is just so we can run weapon stuff
- PlayerPostThink();
+ WITH(entity, this, this, PlayerPostThink());
}
- self.playerdemo_time = stof(fgets(self.playerdemo_fh));
- if(self.playerdemo_time == 0)
+ this.playerdemo_time = stof(fgets(this.playerdemo_fh));
+ if(this.playerdemo_time == 0)
{
- self.playerdemo_time = -1;
+ this.playerdemo_time = -1;
return 1;
}
- self.playerdemo_time += self.playerdemo_starttime;
+ this.playerdemo_time += this.playerdemo_starttime;
}
- self.velocity = '0 0 0';
+ this.velocity = '0 0 0';
time = t;
return 1;
}
void playerdemo_init();
void playerdemo_shutdown();
void playerdemo_write();
-float playerdemo_read();
+float playerdemo_read(entity this);
void playerdemo_open_read(string f);
void playerdemo_open_write(string f);
*/
// PLAYERS use different math
-#ifndef POSITIVE_PITCH_IS_DOWN
+#if !(POSITIVE_PITCH_IS_DOWN)
ang.x = -ang.x;
#endif
//print("GOOD path: ", vtos(ang), "\n");
}
-#ifndef POSITIVE_PITCH_IS_DOWN
+#if !(POSITIVE_PITCH_IS_DOWN)
ang.x = -ang.x;
#endif
ang.z = vangle.z;
#include "cl_client.qc"
#include "cl_impulse.qc"
#include "cl_player.qc"
-#include "ent_cs.qc"
#include "g_damage.qc"
#include "g_hook.qc"
// #include "g_lights.qc" // TODO: was never used
#include "../common/campaign_file.qc"
#include "../common/campaign_setup.qc"
#include "../common/effects/effectinfo.qc"
+#include "../common/ent_cs.qc"
#include "../common/mapinfo.qc"
#include "../common/minigames/minigames.qc"
#include "../common/minigames/sv_minigames.qc"
#include "../common/viewloc.qc"
#include "../common/deathtypes/all.qc"
-#include "../common/buffs/all.qc"
#include "../common/effects/all.qc"
#include "../common/gamemodes/all.qc"
#include "../common/items/all.qc"
#include "../common/monsters/all.qc"
-#include "../common/nades/all.qc"
#include "../common/turrets/all.qc"
#include "../common/vehicles/all.qc"
#include "../common/weapons/all.qc"
{
if (i == RANKINGS_CNT)
{
- db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), string_null);
- db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), string_null);
+ db_remove(ServerProgsDB, strcat(map, rr, "time", ftos(i)));
+ db_remove(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)));
}
else
{
other.race_checkpoint = race_NextCheckpoint(self.race_checkpoint);
other.race_started = 1;
- race_SendTime(other, self.race_checkpoint, other.race_movetime, !!other.race_laptime);
+ race_SendTime(other, self.race_checkpoint, other.race_movetime, boolean(other.race_laptime));
if(!self.race_checkpoint) // start line
{
sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
}
Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
+ if(autocvar_g_balance_contents_playerdamage_lava_burn)
+ Fire_AddDamage(self, world, autocvar_g_balance_contents_playerdamage_lava_burn * self.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * self.waterlevel, DEATH_LAVA.m_id);
}
else if (self.watertype == CONTENT_SLIME)
{
if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
{
if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
- GlobalSound(globalsound_metalstep, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ GlobalSound(GS_STEP_METAL, CH_PLAYER, VOICETYPE_PLAYERSOUND);
else
- GlobalSound(globalsound_step, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ GlobalSound(GS_STEP, CH_PLAYER, VOICETYPE_PLAYERSOUND);
}
}
}
bot_serverframe();
anticheat_startframe();
MUTATOR_CALLHOOK(SV_StartFrame);
+ {
+ entity e;
+ FOR_EACH_CLIENT(e)
+ {
+ GlobalStats_update(e);
+ }
+ }
}
.vector originjitter;
{
if(self.gravity)
{
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
if(self.move_flags & FL_ONGROUND)
{ // For some reason move_avelocity gets set to '0 0 0' here ...
self.oldorigin = self.origin;
{
if(self.gravity)
{
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
if(self.move_flags & FL_ONGROUND)
self.gravity = 0;
self.drawmask = MASK_NORMAL;
}
+void ItemRemove()
+{SELFPARAM();
+ if (self.mdl)
+ strunzone(self.mdl);
+}
+
NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
{
int sf = ReadByte();
if(self.ItemStatus & ITS_ANIMATE2)
self.move_avelocity = '0 -90 0';
}
+
+ self.entremove = ItemRemove;
+
return true;
}
{
wi = get_weaponinfo(i);
- if (!(player.weapons & WepSet_FromWeapon(i)))
+ if (!(player.weapons & (wi.m_wepset)))
continue;
if(wi.items & ITEM_Shells.m_itemid)
if(this.angles != '0 0 0')
this.SendFlags |= ISF_ANGLES;
- this.reset = Item_Reset_self;
+ this.reset = Item_Reset;
// it's a level item
if(this.spawnflags & 1)
this.noalign = 1;
s = W_UndeprecateName(argv(i));
if(s == e.netname)
{
- self.weapons |= WepSet_FromWeapon(j);
+ self.weapons |= (e.m_wepset);
if(self.spawnflags == 0 || self.spawnflags == 2) {
Weapon w = get_weaponinfo(e.weapon);
w.wr_init(w);
}
self.netname = "";
- self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
- self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
- self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.strength_finished * !!(self.items & ITEM_Strength.m_itemid), "strength");
- self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.invincible_finished * !!(self.items & ITEM_Shield.m_itemid), "invincible");
- self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.superweapons_finished * !!(self.items & IT_SUPERWEAPON), "superweapons");
- self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & ITEM_Jetpack.m_itemid), "jetpack");
- self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
+ self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
+ self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
+ self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.strength_finished * boolean(self.items & ITEM_Strength.m_itemid), "strength");
+ self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.invincible_finished * boolean(self.items & ITEM_Shield.m_itemid), "invincible");
+ self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.superweapons_finished * boolean(self.items & IT_SUPERWEAPON), "superweapons");
+ self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & ITEM_Jetpack.m_itemid), "jetpack");
+ self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
if(self.ammo_shells != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_shells), "shells");
if(self.ammo_nails != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_nails), "nails");
if(self.ammo_rockets != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_rockets), "rockets");
{
e = get_weaponinfo(j);
if(e.weapon)
- self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.weapons & WepSet_FromWeapon(j)), e.netname);
+ self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.weapons & (e.m_wepset)), e.netname);
}
}
self.netname = strzone(self.netname);
float GiveWeapon(entity e, float wpn, float op, float val)
{
WepSet v0, v1;
- v0 = (e.weapons & WepSet_FromWeapon(wpn));
+ WepSet s = WepSet_FromWeapon(wpn);
+ v0 = (e.weapons & s);
switch(op)
{
case OP_SET:
if(val > 0)
- e.weapons |= WepSet_FromWeapon(wpn);
+ e.weapons |= s;
else
- e.weapons &= ~WepSet_FromWeapon(wpn);
+ e.weapons &= ~s;
break;
case OP_MIN:
case OP_PLUS:
if(val > 0)
- e.weapons |= WepSet_FromWeapon(wpn);
+ e.weapons |= s;
break;
case OP_MAX:
if(val <= 0)
- e.weapons &= ~WepSet_FromWeapon(wpn);
+ e.weapons &= ~s;
break;
case OP_MINUS:
if(val > 0)
- e.weapons &= ~WepSet_FromWeapon(wpn);
+ e.weapons &= ~s;
break;
}
- v1 = (e.weapons & WepSet_FromWeapon(wpn));
+ v1 = (e.weapons & s);
return (v0 != v1);
}
if(wi.weapon)
{
POSTGIVE_WEAPON(e, j, SND(WEAPONPICKUP), string_null);
- if (!(save_weapons & WepSet_FromWeapon(j)))
- if(e.weapons & WepSet_FromWeapon(j)) {
+ if (!(save_weapons & (wi.m_wepset)))
+ if(e.weapons & (wi.m_wepset)) {
Weapon w = get_weaponinfo(wi.weapon);
w.wr_init(w);
}
#include "../common/weapons/all.qh"
-#include "../common/buffs/all.qh"
spawnfunc(weapon_crylink);
spawnfunc(weapon_electro);
else if (targ.classname == "item_health_mega")
self.health = 200;
//remove(targ); // removing ents in init functions causes havoc, workaround:
- targ.think = SUB_Remove;
+ targ.think = SUB_Remove_self;
targ.nextthink = time;
}
self.spawnflags = 2;
spawnfunc(item_flight)
{
- if(!cvar("g_buffs") || !cvar("g_buffs_flight"))
- spawnfunc_item_jetpack(this);
- else
- buff_Init_Compat(self, BUFF_FLIGHT);
+ spawnfunc_item_jetpack(this);
}
.float notteam;
if(modifications != "")
s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
- if (cvar("g_nades"))
- s = strcat(s, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
-
if(cache_lastmutatormsg != autocvar_g_mutatormsg)
{
if(cache_lastmutatormsg)
// since this is an engine function, and gamecode doesn't have any calls earlier than this, do the connecting message here
if(!IS_CLIENT(self))
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_CONNECTING, self.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_CONNECTING, self.netname);
+
+ MUTATOR_CALLHOOK(Player_ChangeTeam, self, steam, dteam);
SetPlayerTeam(self, dteam, steam, !IS_CLIENT(self));
}
// update accuracy stats
-.float hit_time;
+//.float hit_time;
.float fired_time;
void accuracy_add(entity this, int w, int fired, int hit)
{
weaponwant = stof(car(rest)); rest = cdr(rest);
wep = get_weaponinfo(weaponwant);
- wepset = WepSet_FromWeapon(weaponwant);
+ wepset = wep.m_wepset;
if(imp >= 0)
if(wep.impulse != imp)
continue;
float i, have_other = false;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
+ Weapon e = get_weaponinfo(i);
if(i != weaponwant)
- if((get_weaponinfo(i)).impulse == imp || imp < 0)
- if((pl.weapons & WepSet_FromWeapon(i)) || (weaponsInMap & WepSet_FromWeapon(i)))
+ if(e.impulse == imp || imp < 0)
+ if((pl.weapons & (e.m_wepset)) || (weaponsInMap & (e.m_wepset)))
have_other = true;
}
{
weaponwant = stof(car(rest)); rest = cdr(rest);
wep = get_weaponinfo(weaponwant);
- wepset = WepSet_FromWeapon(weaponwant);
+ wepset = wep.m_wepset;
if(imp >= 0)
if(wep.impulse != imp)
continue;
float i, have_other = false;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
+ Weapon w = get_weaponinfo(i);
if(i != weaponwant)
- if((get_weaponinfo(i)).impulse == imp || imp < 0)
- if((pl.weapons & WepSet_FromWeapon(i)) || (weaponsInMap & WepSet_FromWeapon(i)))
+ if(w.impulse == imp || imp < 0)
+ if((pl.weapons & (w.m_wepset)) || (weaponsInMap & (w.m_wepset)))
have_other = true;
}
void W_SwitchToOtherWeapon(entity pl)
{
// hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
- float w, ww;
- w = pl.weapon;
- if(pl.weapons & WepSet_FromWeapon(w))
+ int ww;
+ WepSet set = WepSet_FromWeapon(pl.weapon);
+ if(pl.weapons & set)
{
- pl.weapons &= ~WepSet_FromWeapon(w);
+ pl.weapons &= ~set;
ww = w_getbestweapon(pl);
- pl.weapons |= WepSet_FromWeapon(w);
+ pl.weapons |= set;
}
else
ww = w_getbestweapon(pl);
{
float superweapons = 1;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- if(WepSet_FromWeapon(i) & WEPSET_SUPERWEAPONS)
- if(own.weapons & WepSet_FromWeapon(i))
- ++superweapons;
+ {
+ WepSet set = WepSet_FromWeapon(i);
+ if ((set & WEPSET_SUPERWEAPONS) && (own.weapons & set)) ++superweapons;
+ }
if(superweapons <= 1)
{
wep.superweapons_finished = own.superweapons_finished;
if(!W_IsWeaponThrowable(w))
return;
- if(!(self.weapons & WepSet_FromWeapon(w)))
- return;
- self.weapons &= ~WepSet_FromWeapon(w);
+ WepSet set = WepSet_FromWeapon(w);
+ if(!(self.weapons & set)) return;
+ self.weapons &= ~set;
W_SwitchWeapon_Force(self, w_getbestweapon(self));
string a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
--- /dev/null
+// This quickmenu example file can be loaded by setting
+// hud_panel_quickmenu_file quickmenu_example.txt
+// and executing "quickmenu file"
+// For more options see "quickmenu help"
+
+"Chat"
+ "nice one" "say :-) / nice one"
+ "good game" "say good game"
+ "hi / good luck" "say hi / good luck and have fun"
+"Chat"
+
+"Settings"
+ // nested submenu
+ "Sound settings"
+ "Hit sound" "toggle cl_hitsound"
+ "Chat sound" "toggle cl_chatsound"
+ "Sound settings"
+
+ // A toggle command displays a checkbox showing the current cvar's state
+ "enable 3rd person view" "toggle chase_active"
+ // it's possible to invert the meaning of the checkbox by inverting the
+ // parameters of toggle from the implicit 1 0 to 0 1
+ "disable 3rd person view" "toggle chase_active 0 1"
+"Settings"
+
+"screenshot" "wait; screenshot"
+
+// Commands that accept a player's name as parameter (%s), followed by one of
+// these special keywords:
+// ALLPLAYERS_BUT_ME
+// ALLPLAYERS
+// OWNTEAMPLAYERS_BUT_ME
+// OWNTEAMPLAYERS
+// ENEMYTEAMPLAYERS
+// lets you pick a player's name from a list:
+"private chat with:" "commandmode tell \"%s\"" ALLPLAYERS_BUT_ME