From: Martin Taibr Date: Sat, 18 Jan 2020 14:36:36 +0000 (+0000) Subject: Merge branch 'martin-t/electro-denoobing' into 'master' X-Git-Tag: xonotic-v0.8.5~1161^2~11 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=0257ecb2eed69a4d4e871a51f1ccb4afc1bcdf1a;hp=3a8534fb9a0bd460d360f0231014433a8b21cf1c Merge branch 'martin-t/electro-denoobing' into 'master' Electro: midair combos See merge request xonotic/xonotic-data.pk3dir!757 --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8724d06617..3e56730463 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,7 +29,7 @@ test_sv_game: - wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints - wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache - make - - EXPECT=892e447048e051e51f30cff2affc729a + - EXPECT=d5bda479d65190330f6ee23c6f9aa5e7 - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg | tee /dev/stderr | grep '^:' diff --git a/.tx/merge-base b/.tx/merge-base index df5f27c1ba..7a7217d257 100644 --- a/.tx/merge-base +++ b/.tx/merge-base @@ -1 +1 @@ -Sat Dec 28 07:24:50 CET 2019 +Wed Jan 15 07:24:54 CET 2020 diff --git a/bal-wep-testing.cfg b/bal-wep-testing.cfg index 3ee6d90197..abee0b6df7 100644 --- a/bal-wep-testing.cfg +++ b/bal-wep-testing.cfg @@ -293,7 +293,7 @@ set g_balance_crylink_weaponstartoverride -1 set g_balance_crylink_weaponthrowable 1 // }}} // {{{ #8: Vortex -set g_balance_vortex_charge 0 +set g_balance_vortex_charge 1 set g_balance_vortex_charge_always 0 set g_balance_vortex_charge_animlimit 0.5 set g_balance_vortex_charge_limit 1 @@ -309,7 +309,7 @@ set g_balance_vortex_charge_velocity_rate 0 set g_balance_vortex_primary_ammo 6 set g_balance_vortex_primary_animtime 0.4 set g_balance_vortex_primary_armorpierce 0 -set g_balance_vortex_primary_damage 65 +set g_balance_vortex_primary_damage 80 set g_balance_vortex_primary_damagefalloff_forcehalflife 0 set g_balance_vortex_primary_damagefalloff_halflife 0 set g_balance_vortex_primary_damagefalloff_maxdist 0 diff --git a/bal-wep-xonotic.cfg b/bal-wep-xonotic.cfg index 67cc55b8d9..c38ea832f3 100644 --- a/bal-wep-xonotic.cfg +++ b/bal-wep-xonotic.cfg @@ -247,7 +247,7 @@ set g_balance_crylink_primary_joinexplode_edgedamage 0 set g_balance_crylink_primary_joinexplode_force 0 set g_balance_crylink_primary_joinexplode_radius 0 set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_linkexplode 0 +set g_balance_crylink_primary_linkexplode 1 set g_balance_crylink_primary_middle_fadetime 5 set g_balance_crylink_primary_middle_lifetime 5 set g_balance_crylink_primary_other_fadetime 5 diff --git a/common.ru.po b/common.ru.po index d281638658..4c19cfd4e3 100644 --- a/common.ru.po +++ b/common.ru.po @@ -6,7 +6,7 @@ # adem4ik, 2014 # Alex Talker , 2014-2015 # Andrei Stepanov, 2014 -# Andrei Stepanov , 2014-2019 +# Andrei Stepanov , 2014-2020 # Andrey P , 2016 # Artem Vorotnikov , 2015 # Lord Canistra , 2011 @@ -19,7 +19,7 @@ msgstr "" "Project-Id-Version: Xonotic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-05-19 07:23+0200\n" -"PO-Revision-Date: 2019-11-21 19:30+0000\n" +"PO-Revision-Date: 2020-01-14 18:19+0000\n" "Last-Translator: Andrei Stepanov \n" "Language-Team: Russian (http://www.transifex.com/team-xonotic/xonotic/" "language/ru/)\n" @@ -1202,7 +1202,7 @@ msgstr "Голосование за карту" #: qcsrc/client/mapvoting.qc:392 #, c-format msgid "%d seconds left" -msgstr "Секунд осталось: %d" +msgstr "Осталось секунд: %d" #: qcsrc/client/mapvoting.qc:505 msgid "mv_mapdownload: ^3You're not supposed to use this command on your own!" diff --git a/gamemodes-server.cfg b/gamemodes-server.cfg index cd71ecec0e..28b434dc24 100644 --- a/gamemodes-server.cfg +++ b/gamemodes-server.cfg @@ -247,6 +247,8 @@ set g_ctf_flag_return_dropped 100 "automatically return the flag to base if drop set g_ctf_flag_return_damage 0 "allow the flag to be damaged, reducing time needed to automatically return to base" set g_ctf_flag_return_damage_delay 0 "how much time the flag takes to automatically return to base if it falls into lava/slime/trigger hurt" set g_ctf_flag_return_when_unreachable 1 "automatically return the flag if it falls into lava/slime/trigger hurt" +set g_ctf_flag_waypoint 1 "show a waypoint at the flag for easy discovery and directions" +set g_ctf_flag_waypoint_maxdistance 0 "maximum distance from a flag from which their waypoint is shown, a value of 0 means no limit" set g_ctf_flagcarrier_auto_helpme_damage 100 "automatically place a helpme notification on flag carrier waypointsprite if they get hit and their health dips below this value" set g_ctf_flagcarrier_auto_helpme_time 2 "antispam time for the helpme notification" set g_ctf_flagcarrier_selfdamagefactor 1 diff --git a/mutators.cfg b/mutators.cfg index 14289d8c85..b6ad3468e0 100644 --- a/mutators.cfg +++ b/mutators.cfg @@ -309,7 +309,8 @@ set g_buffs_effects 1 "show particle effects from carried buffs" set g_buffs_waypoint_distance 1024 "maximum distance at which buff waypoint can be seen from item" set g_buffs_pickup_anyway 0 "instantly respawn the buff when it is picked up, instead of waiting for the player to drop it" set g_buffs_pickup_delay 0.7 "cooldown before player can pick up another buff after dropping one" -set g_buffs_randomize 1 "randomize buff type when player drops buff" +set g_buffs_randomize 1 "randomize buff type when player drops the buff, only applies to teamplay gamemodes if g_buffs_randomize_teamplay is enabled" +set g_buffs_randomize_teamplay 1 "in teamplay gamemodes, randomize buff type when player drops the buff, requires g_buffs_randomize" set g_buffs_random_lifetime 30 "re-spawn the buff again if it hasn't been touched after this time in seconds" set g_buffs_random_location 0 "randomize buff location on start and when reset" set g_buffs_random_location_attempts 10 "number of random locations a single buff will attempt to respawn at before giving up" diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index 5793cd5a7b..1ed785f9fe 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -151,7 +151,7 @@ float autocvar_crosshair_ring_reload_alpha; float autocvar_crosshair_ring_reload_size; float autocvar_crosshair_size; bool autocvar_crosshair_chase = true; -float crosshair_chase_playeralpha = 0.25; +float autocvar_crosshair_chase_playeralpha = 0.25; int autocvar_ekg; float autocvar_fov; bool autocvar_hud_cursormode = true; diff --git a/qcsrc/client/hud/panel/quickmenu.qc b/qcsrc/client/hud/panel/quickmenu.qc index 3e61f9b5a6..c58fb2a675 100644 --- a/qcsrc/client/hud/panel/quickmenu.qc +++ b/qcsrc/client/hud/panel/quickmenu.qc @@ -854,6 +854,11 @@ void QuickMenu_Default(string target_submenu) QUICKMENU_ENTRY(CTX(_("QMCMD^Shuffle teams")), "vcall shuffleteams") QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote") + if(spectatee_status != 0) + { + QUICKMENU_SMENU_PL(CTX(_("QMCMD^Spectate a player")), "Spectate a player", "spectate \"%s^7\"", 0, 1) + } + if(target_submenu != "" && !target_submenu_found) { LOG_INFOF("Couldn't find submenu \"%s\"", target_submenu); diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index a2876e5f70..eb341d58cd 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -1120,12 +1120,12 @@ void HUD_Crosshair(entity this) else if(autocvar_chase_active > 0 && autocvar_crosshair_chase) { vector player_org = ((csqcplayer) ? csqcplayer.origin + csqcplayer.view_ofs : view_origin); - if(csqcplayer && crosshair_chase_playeralpha && crosshair_chase_playeralpha < 1) + if(csqcplayer && autocvar_crosshair_chase_playeralpha && autocvar_crosshair_chase_playeralpha < 1) { traceline(view_origin, view_origin + max_shot_distance * view_forward, MOVE_NORMAL, NULL); float myalpha = (!csqcplayer.m_alpha) ? 1 : csqcplayer.m_alpha; if(trace_ent == csqcplayer && STAT(HEALTH) > 0) - csqcplayer.alpha = min(crosshair_chase_playeralpha, myalpha); + csqcplayer.alpha = min(autocvar_crosshair_chase_playeralpha, myalpha); else csqcplayer.alpha = csqcplayer.m_alpha; } @@ -2329,6 +2329,8 @@ void CSQC_UpdateView(entity this, float w, float h) vid_width = vf_size.x; vid_height = vf_size.y; + ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE); + WaypointSprite_Load(); CSQCPlayer_SetCamera(); @@ -2339,8 +2341,6 @@ void CSQC_UpdateView(entity this, float w, float h) current_player = player_localnum; myteam = entcs_GetTeam(current_player); - ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE); - // abused multiple places below entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1)); if(!local_player) @@ -2445,10 +2445,7 @@ void CSQC_UpdateView(entity this, float w, float h) addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS); // TODO: .health is used in cl_deathfade (a feature we have turned off currently) renderscene(); - // now switch to 2D drawing mode by calling a 2D drawing function - // then polygon drawing will draw as 2D stuff, and NOT get queued until the - // next R_RenderScene call - drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0); + // Now the the scene has been rendered, begin with the 2D drawing functions View_NightVision(); DrawReticle(local_player); diff --git a/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc index aa05ea337b..11bbaea6fb 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc +++ b/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc @@ -48,6 +48,8 @@ bool autocvar_g_ctf_flag_return_when_unreachable; float autocvar_g_ctf_flag_return_damage; float autocvar_g_ctf_flag_return_damage_delay; float autocvar_g_ctf_flag_return_dropped; +bool autocvar_g_ctf_flag_waypoint = true; +float autocvar_g_ctf_flag_waypoint_maxdistance; float autocvar_g_ctf_flagcarrier_auto_helpme_damage; float autocvar_g_ctf_flagcarrier_auto_helpme_time; float autocvar_g_ctf_flagcarrier_selfdamagefactor; @@ -1224,10 +1226,14 @@ void ctf_DelayedFlagSetup(entity this) // called after a flag is placed on a map default: basename = WP_FlagBaseNeutral; break; } - entity wp = WaypointSprite_SpawnFixed(basename, this.origin + FLAG_WAYPOINT_OFFSET, this, wps_flagbase, RADARICON_FLAG); - wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 1 1'); - WaypointSprite_UpdateTeamRadar(this.wps_flagbase, RADARICON_FLAG, ((this.team) ? colormapPaletteColor(this.team - 1, false) : '1 1 1')); - setcefc(wp, ctf_FlagBase_Customize); + if(autocvar_g_ctf_flag_waypoint) + { + entity wp = WaypointSprite_SpawnFixed(basename, this.origin + FLAG_WAYPOINT_OFFSET, this, wps_flagbase, RADARICON_FLAG); + wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 1 1'); + wp.fade_rate = autocvar_g_ctf_flag_waypoint_maxdistance; + WaypointSprite_UpdateTeamRadar(this.wps_flagbase, RADARICON_FLAG, ((this.team) ? colormapPaletteColor(this.team - 1, false) : '1 1 1')); + setcefc(wp, ctf_FlagBase_Customize); + } // captureshield setup ctf_CaptureShield_Spawn(this); diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc index 3bb04b3695..257e5e40f1 100644 --- a/qcsrc/common/mapinfo.qc +++ b/qcsrc/common/mapinfo.qc @@ -843,9 +843,6 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet fputs(fh, sprintf("gametype %s // defaults: %s\n", MapInfo_Type_ToString(it), _MapInfo_GetDefaultEx(it))); }); - if(fexists(strcat("scripts/", pFilename, ".arena"))) - fputs(fh, "settemp_for_type all sv_q3acompat_machineshotgunswap 1\n"); - fputs(fh, "// optional: fog density red green blue alpha mindist maxdist\n"); fputs(fh, "// optional: settemp_for_type (all|gametypename) cvarname value\n"); fputs(fh, "// optional: clientsettemp_for_type (all|gametypename) cvarname value\n"); @@ -1144,7 +1141,9 @@ string MapInfo_FixName(string s) int MapInfo_CurrentFeatures() { int req = 0; - if(!(cvar("g_lms") || cvar("g_instagib") || cvar("g_overkill") || cvar("g_nix") || cvar("g_weaponarena") || !cvar("g_pickup_items") || cvar("g_race") || cvar("g_cts") || cvar("g_nexball"))) + // TODO: find a better way to check if weapons are required on the map + if(!(cvar("g_instagib") || cvar("g_overkill") || cvar("g_nix") || cvar("g_weaponarena") || !cvar("g_pickup_items") + || cvar("g_race") || cvar("g_cts") || cvar("g_nexball") || cvar("g_ca") || cvar("g_freezetag") || cvar("g_lms"))) req |= MAPINFO_FEATURE_WEAPONS; return req; } diff --git a/qcsrc/common/mapobjects/triggers.qc b/qcsrc/common/mapobjects/triggers.qc index 9a7181d3a2..27ffead9c7 100644 --- a/qcsrc/common/mapobjects/triggers.qc +++ b/qcsrc/common/mapobjects/triggers.qc @@ -235,7 +235,7 @@ match (string)this.target and call their .use function ============================== */ -void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse) +void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse, int skiptargets) { // // check for a delay @@ -249,10 +249,10 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe t.enemy = actor; t.message = this.message; t.killtarget = this.killtarget; - t.target = this.target; - t.target2 = this.target2; - t.target3 = this.target3; - t.target4 = this.target4; + if(!(skiptargets & BIT(1))) t.target = this.target; + if(!(skiptargets & BIT(2))) t.target2 = this.target2; + if(!(skiptargets & BIT(3))) t.target3 = this.target3; + if(!(skiptargets & BIT(4))) t.target4 = this.target4; t.antiwall_flag = this.antiwall_flag; return; } @@ -292,6 +292,8 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe for(int i = 0; i < 4; ++i) { + if(skiptargets & BIT(i + 1)) + continue; switch(i) { default: @@ -329,5 +331,6 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe } } -void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); } -void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); } +void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false, 0); } +void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true, 0); } +void SUB_UseTargets_SkipTargets(entity this, entity actor, entity trigger, int skiptargets) { SUB_UseTargets_Ex(this, actor, trigger, false, skiptargets); } diff --git a/qcsrc/common/mapobjects/triggers.qh b/qcsrc/common/mapobjects/triggers.qh index b9baf63f1c..797c9767f6 100644 --- a/qcsrc/common/mapobjects/triggers.qh +++ b/qcsrc/common/mapobjects/triggers.qh @@ -26,6 +26,10 @@ void SUB_UseTargets(entity this, entity actor, entity trigger); void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger); +// allow excluding certain .target* fields without needing to nullify them +// use BIT(1) through BIT(4) +void SUB_UseTargets_SkipTargets(entity this, entity actor, entity trigger, int skiptargets); + void generic_setactive(entity this, int act); // generic methods for netlinked entities void generic_netlinked_reset(entity this); diff --git a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc index 5789b6e4c4..f1a1491661 100644 --- a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc +++ b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc @@ -272,7 +272,7 @@ void buff_Think(entity this) { buff_SetCooldown(this, autocvar_g_buffs_cooldown_respawn + frametime); this.owner = NULL; - if(autocvar_g_buffs_randomize) + if(autocvar_g_buffs_randomize && (!teamplay || autocvar_g_buffs_randomize_teamplay)) buff_NewType(this); if(autocvar_g_buffs_random_location || (this.spawnflags & 64)) @@ -316,7 +316,7 @@ void buff_Waypoint_Reset(entity this) void buff_Reset(entity this) { - if(autocvar_g_buffs_randomize) + if(autocvar_g_buffs_randomize && (!teamplay || autocvar_g_buffs_randomize_teamplay)) buff_NewType(this); this.owner = NULL; buff_SetCooldown(this, autocvar_g_buffs_cooldown_activate); diff --git a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh index 671a524f9e..88efc94ebb 100644 --- a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh +++ b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh @@ -9,6 +9,7 @@ float autocvar_g_buffs_waypoint_distance; bool autocvar_g_buffs_pickup_anyway = false; float autocvar_g_buffs_pickup_delay = 0.7; bool autocvar_g_buffs_randomize; +bool autocvar_g_buffs_randomize_teamplay = true; float autocvar_g_buffs_random_lifetime; bool autocvar_g_buffs_random_location; int autocvar_g_buffs_random_location_attempts; diff --git a/qcsrc/common/mutators/mutator/overkill/okhmg.qc b/qcsrc/common/mutators/mutator/overkill/okhmg.qc index df55fb88c4..a0a8962a7d 100644 --- a/qcsrc/common/mutators/mutator/overkill/okhmg.qc +++ b/qcsrc/common/mutators/mutator/overkill/okhmg.qc @@ -74,14 +74,11 @@ METHOD(OverkillHeavyMachineGun, wr_think, void(entity thiswep, entity actor, .en (actor.(weaponentity).wframe == WFRAME_FIRE2)) { // Set secondary fire animation. - vector a = '0 0 0'; actor.(weaponentity).wframe = WFRAME_FIRE2; - a = actor.(weaponentity).anim_fire2; - a.z *= g_weaponratefactor; FOREACH_CLIENT(true, LAMBDA( if (it == actor || (IS_SPEC(it) && it.enemy == actor)) { - wframe_send(it, actor.(weaponentity), a, true); + wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true); } )); animdecide_setaction(actor, ANIMACTION_SHOOT, true); diff --git a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc index 768e364a78..17e71f06f8 100644 --- a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc +++ b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc @@ -68,14 +68,11 @@ METHOD(OverkillMachineGun, wr_think, void(entity thiswep, entity actor, .entity (actor.(weaponentity).wframe == WFRAME_FIRE2)) { // Set secondary fire animation. - vector a = '0 0 0'; actor.(weaponentity).wframe = WFRAME_FIRE2; - a = actor.(weaponentity).anim_fire2; - a.z *= g_weaponratefactor; FOREACH_CLIENT(true, LAMBDA( if (it == actor || (IS_SPEC(it) && it.enemy == actor)) { - wframe_send(it, actor.(weaponentity), a, true); + wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true); } )); animdecide_setaction(actor, ANIMACTION_SHOOT, true); diff --git a/qcsrc/common/mutators/mutator/overkill/oknex.qc b/qcsrc/common/mutators/mutator/overkill/oknex.qc index 83a3a3cc05..ca44a070a0 100644 --- a/qcsrc/common/mutators/mutator/overkill/oknex.qc +++ b/qcsrc/common/mutators/mutator/overkill/oknex.qc @@ -150,14 +150,11 @@ METHOD(OverkillNex, wr_think, void(entity thiswep, entity actor, .entity weapone (actor.(weaponentity).wframe == WFRAME_FIRE2)) { // Set secondary fire animation. - vector a = '0 0 0'; actor.(weaponentity).wframe = WFRAME_FIRE2; - a = actor.(weaponentity).anim_fire2; - a.z *= g_weaponratefactor; FOREACH_CLIENT(true, LAMBDA( if (it == actor || (IS_SPEC(it) && it.enemy == actor)) { - wframe_send(it, actor.(weaponentity), a, true); + wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true); } )); animdecide_setaction(actor, ANIMACTION_SHOOT, true); diff --git a/qcsrc/common/mutators/mutator/overkill/okrpc.qc b/qcsrc/common/mutators/mutator/overkill/okrpc.qc index fa4ffc4b5e..362f14846f 100644 --- a/qcsrc/common/mutators/mutator/overkill/okrpc.qc +++ b/qcsrc/common/mutators/mutator/overkill/okrpc.qc @@ -149,14 +149,11 @@ METHOD(OverkillRocketPropelledChainsaw, wr_think, void(entity thiswep, entity ac (actor.(weaponentity).wframe == WFRAME_FIRE2)) { // Set secondary fire animation. - vector a = '0 0 0'; actor.(weaponentity).wframe = WFRAME_FIRE2; - a = actor.(weaponentity).anim_fire2; - a.z *= g_weaponratefactor; FOREACH_CLIENT(true, LAMBDA( if (it == actor || (IS_SPEC(it) && it.enemy == actor)) { - wframe_send(it, actor.(weaponentity), a, true); + wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true); } )); animdecide_setaction(actor, ANIMACTION_SHOOT, true); diff --git a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc index 784d1c37b7..da4c4749d0 100644 --- a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc +++ b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc @@ -24,14 +24,11 @@ METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity wea (actor.(weaponentity).wframe == WFRAME_FIRE2)) { // Set secondary fire animation. - vector a = '0 0 0'; actor.(weaponentity).wframe = WFRAME_FIRE2; - a = actor.(weaponentity).anim_fire2; - a.z *= g_weaponratefactor; FOREACH_CLIENT(true, LAMBDA( if (it == actor || (IS_SPEC(it) && it.enemy == actor)) { - wframe_send(it, actor.(weaponentity), a, true); + wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true); } )); animdecide_setaction(actor, ANIMACTION_SHOOT, true); diff --git a/qcsrc/common/physics/movetypes/movetypes.qc b/qcsrc/common/physics/movetypes/movetypes.qc index bbd86d62e3..9d32cf3d5b 100644 --- a/qcsrc/common/physics/movetypes/movetypes.qc +++ b/qcsrc/common/physics/movetypes/movetypes.qc @@ -701,11 +701,11 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy) // SV_Ph { Movetype_Physics_NoMatchServer(this); - this.tic_saved_flags = this.flags; - this.tic_saved_velocity = this.velocity; - this.tic_saved_origin = this.origin; - this.tic_saved_avelocity = this.avelocity; - this.tic_saved_angles = this.angles; + this.tic_saved_flags = this.tic_flags = this.flags; + this.tic_saved_velocity = this.tic_velocity = this.velocity; + this.tic_saved_origin = this.tic_origin = this.origin; + this.tic_saved_avelocity = this.tic_avelocity = this.avelocity; + this.tic_saved_angles = this.tic_angles = this.angles; return; } diff --git a/qcsrc/common/physics/player.qc b/qcsrc/common/physics/player.qc index 82dca53520..16cb27aeca 100644 --- a/qcsrc/common/physics/player.qc +++ b/qcsrc/common/physics/player.qc @@ -54,11 +54,11 @@ void Physics_UpdateStats(entity this) STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod; } bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox; // NOTE: these hitboxes are off by 1 due to engine differences - STAT(PL_MIN, this) = (q3dfcompat) ? '-15 -15 -24' : autocvar_sv_player_mins; - STAT(PL_MAX, this) = (q3dfcompat) ? '15 15 32' : autocvar_sv_player_maxs; + STAT(PL_MIN, this) = (q3dfcompat) ? '-15 -15 -20' : autocvar_sv_player_mins; + STAT(PL_MAX, this) = (q3dfcompat) ? '15 15 36' : autocvar_sv_player_maxs; STAT(PL_VIEW_OFS, this) = (q3dfcompat) ? '0 0 26' : autocvar_sv_player_viewoffset; - STAT(PL_CROUCH_MIN, this) = (q3dfcompat) ? '-15 -15 -24' : autocvar_sv_player_crouch_mins; - STAT(PL_CROUCH_MAX, this) = (q3dfcompat) ? '15 15 16' : autocvar_sv_player_crouch_maxs; + STAT(PL_CROUCH_MIN, this) = (q3dfcompat) ? '-15 -15 -20' : autocvar_sv_player_crouch_mins; + STAT(PL_CROUCH_MAX, this) = (q3dfcompat) ? '15 15 20' : autocvar_sv_player_crouch_maxs; STAT(PL_CROUCH_VIEW_OFS, this) = (q3dfcompat) ? '0 0 12' : autocvar_sv_player_crouch_viewoffset; // old stats diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 6785a9f215..111c7e7956 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -245,7 +245,7 @@ void vehicles_projectile_explode_use(entity this, entity actor, entity trigger) vehicles_projectile_explode(this, trigger); } -entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, +entity vehicles_projectile(entity this, entity _mzlfx, Sound _mzlsound, vector _org, vector _vel, float _dmg, float _radi, float _force, float _size, int _deahtype, float _projtype, float _health, @@ -290,8 +290,8 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, if(_mzlsound != SND_Null) sound (this, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM); - if(_mzlfx) - Send_Effect_(_mzlfx, proj.origin, proj.velocity, 1); + if(_mzlfx != EFFECT_Null) + Send_Effect(_mzlfx, proj.origin, proj.velocity, 1); setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size); diff --git a/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc b/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc index 9299e938d0..81fd93aa02 100644 --- a/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc @@ -9,7 +9,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_BUMBLE_RAYGUN) void bumblebee_fire_cannon(entity this, entity _gun, string _tagname, entity _owner) { vector v = gettaginfo(_gun, gettagindex(_gun, _tagname)); - vehicles_projectile(this, EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, SND_VEH_BUMBLEBEE_FIRE, + vehicles_projectile(this, EFFECT_BIGPLASMA_MUZZLEFLASH, SND_VEH_BUMBLEBEE_FIRE, v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed, autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force, 0, DEATH_VH_BUMB_GUN.m_id, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner); diff --git a/qcsrc/common/vehicles/vehicle/racer.qc b/qcsrc/common/vehicles/vehicle/racer.qc index e2a2593948..87804586a2 100644 --- a/qcsrc/common/vehicles/vehicle/racer.qc +++ b/qcsrc/common/vehicles/vehicle/racer.qc @@ -291,15 +291,6 @@ bool racer_frame(entity this, float dt) if (PHYS_INPUT_BUTTON_ATCK(player)) if (wep1.wr_checkammo1(wep1, vehic, weaponentity)) { - string tagname = (vehic.cnt) - ? (vehic.cnt = 0, "tag_fire1") - : (vehic.cnt = 1, "tag_fire2"); - vector org = gettaginfo(vehic, gettagindex(vehic, tagname)); - w_shotorg = org; - w_shotdir = v_forward; - // Fix z-aim (for chase mode) - crosshair_trace(player); - w_shotdir.z = normalize(trace_endpos - org).z * 0.5; wep1.wr_think(wep1, vehic, weaponentity, 1); } diff --git a/qcsrc/common/vehicles/vehicle/racer_weapon.qc b/qcsrc/common/vehicles/vehicle/racer_weapon.qc index 0e7222eb24..f7253d8d8e 100644 --- a/qcsrc/common/vehicles/vehicle/racer_weapon.qc +++ b/qcsrc/common/vehicles/vehicle/racer_weapon.qc @@ -14,10 +14,20 @@ METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weapone veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost; veh.wait = time; } + string tagname = (veh.cnt) + ? (veh.cnt = 0, "tag_fire1") + : (veh.cnt = 1, "tag_fire2"); + vector shotorg = gettaginfo(veh, gettagindex(veh, tagname)); + w_shotorg = shotorg; + w_shotdir = v_forward; + // Fix z-aim (for chase mode) + crosshair_trace(player); + w_shotdir.z = normalize(trace_endpos - shotorg).z * 0.5; + if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_WAKI_GUN.m_id); vector org = w_shotorg; vector dir = w_shotdir; - entity bolt = vehicles_projectile(veh, EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND_LASERGUN_FIRE, + entity bolt = vehicles_projectile(veh, EFFECT_RACER_MUZZLEFLASH, SND_LASERGUN_FIRE, org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed, autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0, DEATH_VH_WAKI_GUN.m_id, PROJECTILE_WAKICANNON, 0, true, true, player); @@ -45,7 +55,7 @@ void racer_rocket_groundhugger(entity this); void racer_fire_rocket(entity player, vector org, vector dir, entity trg) { - entity rocket = vehicles_projectile(player.vehicle, EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE, + entity rocket = vehicles_projectile(player.vehicle, EFFECT_RACER_ROCKETLAUNCH, SND_ROCKET_FIRE, org, dir * autocvar_g_vehicle_racer_rocket_speed, autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3, DEATH_VH_WAKI_ROCKET.m_id, PROJECTILE_WAKIROCKET, 20, false, false, player); diff --git a/qcsrc/common/vehicles/vehicle/raptor.qc b/qcsrc/common/vehicles/vehicle/raptor.qc index e9f7f7333d..f0c4dc1ec7 100644 --- a/qcsrc/common/vehicles/vehicle/raptor.qc +++ b/qcsrc/common/vehicles/vehicle/raptor.qc @@ -453,7 +453,7 @@ bool raptor_takeoff(entity this, float dt) // Takeoff sequense if(vehic.frame < 25) { - vehic.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / PHYS_INPUT_FRAMETIME); + vehic.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / dt); vehic.velocity_z = min(vehic.velocity_z * 1.5, 256); vehic.bomb1.gun1.avelocity_y = 90 + ((vehic.frame / 25) * 25000); vehic.bomb1.gun2.avelocity_y = -vehic.bomb1.gun1.avelocity_y; diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc index 66b5bec883..7d4a250f41 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc @@ -7,7 +7,7 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weapon entity player = isPlayer ? actor : actor.owner; entity veh = player.vehicle; // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait] - float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4); + float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + ((veh.misc_bulletcounter + 1) >= 4)); if (fire & 1) if (weapon_prepareattack(thiswep, player, weaponentity, false, t)) { if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_RAPT_CANNON.m_id); @@ -16,12 +16,12 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weapon if (veh) { veh.misc_bulletcounter += 1; org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1")) - : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1"))); + : (((veh.misc_bulletcounter >= 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1"))); dir = v_forward; veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost; actor.cnt = time; } - vehicles_projectile(veh, EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND_LASERGUN_FIRE, + vehicles_projectile(veh, EFFECT_RAPTOR_MUZZLEFLASH, SND_LASERGUN_FIRE, org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed, autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0, DEATH_VH_RAPT_CANNON.m_id, PROJECTILE_RAPTORCANNON, 0, true, true, player); @@ -59,6 +59,8 @@ METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, .entity weapone entity veh = player.vehicle; if (fire & 2) if (!isPlayer || weapon_prepareattack(thiswep, player, weaponentity, true, autocvar_g_vehicle_raptor_flare_refire)) { + vector forward, right, up; + MAKE_VECTORS(player.v_angle, forward, right, up); for(int i = 0; i < 3; ++i) { entity _flare = spawn(); setmodel(_flare, MDL_VEH_RAPTOR_FLARE); @@ -67,7 +69,7 @@ METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, .entity weapone setorigin(_flare, actor.origin - '0 0 16'); set_movetype(_flare, MOVETYPE_TOSS); _flare.gravity = 0.15; - _flare.velocity = 0.25 * actor.velocity + (v_forward + randomvec() * 0.25)* -500; + _flare.velocity = 0.25 * actor.velocity + (forward + randomvec() * 0.25)* -500; setthink(_flare, raptor_flare_think); _flare.nextthink = time; _flare.owner = veh ? veh : player; diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qh b/qcsrc/common/vehicles/vehicle/raptor_weapons.qh index 37b87bbada..c762acfa23 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qh +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qh @@ -30,7 +30,7 @@ REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare)); float autocvar_g_vehicle_raptor_cannon_cost = 1; float autocvar_g_vehicle_raptor_cannon_damage = 10; float autocvar_g_vehicle_raptor_cannon_radius = 60; -float autocvar_g_vehicle_raptor_cannon_refire = 0.03; +float autocvar_g_vehicle_raptor_cannon_refire = 0.033333; float autocvar_g_vehicle_raptor_cannon_speed = 24000; float autocvar_g_vehicle_raptor_cannon_spread = 0.01; float autocvar_g_vehicle_raptor_cannon_force = 25; diff --git a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc index 308a92fd87..fdeddc47bf 100644 --- a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc @@ -183,7 +183,7 @@ void spiderbot_rocket_do(entity this) switch(STAT(VEHICLESTAT_W2MODE, this)) { case SBRM_VOLLY: - rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE, + rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE, v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner); @@ -197,7 +197,7 @@ void spiderbot_rocket_do(entity this) this.wait = -10; break; case SBRM_GUIDE: - rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE, + rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE, v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, this.owner); @@ -209,7 +209,7 @@ void spiderbot_rocket_do(entity this) break; case SBRM_ARTILLERY: - rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE, + rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE, v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner); diff --git a/qcsrc/common/weapons/all.qc b/qcsrc/common/weapons/all.qc index f2fdf4407f..b8d2428f3f 100644 --- a/qcsrc/common/weapons/all.qc +++ b/qcsrc/common/weapons/all.qc @@ -225,6 +225,20 @@ string GetAmmoPicture(int ammotype) } } +string GetAmmoName(int ammotype) +{ + switch (ammotype) + { + case RES_SHELLS: return ITEM_Shells.m_name; + case RES_BULLETS: return ITEM_Bullets.m_name; + case RES_ROCKETS: return ITEM_Rockets.m_name; + case RES_CELLS: return ITEM_Cells.m_name; + case RES_PLASMA: return ITEM_Plasma.m_name; + case RES_FUEL: return ITEM_JetpackFuel.m_name; + default: return "batteries"; + } +} + #ifdef CSQC int GetAmmoTypeFromNum(int i) { @@ -551,14 +565,27 @@ REGISTER_NET_TEMP(wframe) #ifdef CSQC NET_HANDLE(wframe, bool isNew) { - vector a = ReadVector(); + int fr = ReadByte(); + float t = ReadFloat(); int slot = ReadByte(); bool restartanim = ReadByte(); entity wepent = viewmodels[slot]; - if(a.x == wepent.anim_idle_x) // we don't need to enforce idle animation - wepent.animstate_looping = false; + if(fr == WFRAME_IDLE) + wepent.animstate_looping = false; // we don't need to enforce idle animation else + { + vector a = '0 0 0'; + switch(fr) + { + case WFRAME_IDLE: a = wepent.anim_idle; break; + case WFRAME_FIRE1: a = wepent.anim_fire1; break; + case WFRAME_FIRE2: a = wepent.anim_fire2; break; + default: + case WFRAME_RELOAD: a = wepent.anim_reload; break; + } + a.z *= t; anim_set(wepent, a, !restartanim, restartanim, restartanim); + } wepent.state = ReadByte(); wepent.weapon_nextthink = ReadFloat(); switch (wepent.state) @@ -578,13 +605,14 @@ NET_HANDLE(wframe, bool isNew) #endif #ifdef SVQC -void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim) +void wframe_send(entity actor, entity weaponentity, int wepframe, float attackrate, bool restartanim) { if (!IS_REAL_CLIENT(actor)) return; int channel = MSG_ONE; msg_entity = actor; WriteHeader(channel, wframe); - WriteVector(channel, a); + WriteByte(channel, wepframe); + WriteFloat(channel, attackrate); WriteByte(channel, weaponslot(weaponentity.weaponentity_fld)); WriteByte(channel, restartanim); WriteByte(channel, weaponentity.state); diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index 131e7b49ef..26b40084bf 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -392,6 +392,6 @@ REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive"); #endif #ifdef SVQC -void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim); +void wframe_send(entity actor, entity weaponentity, int wepframe, float attackrate, bool restartanim); #endif #endif diff --git a/qcsrc/common/weapons/weapon.qh b/qcsrc/common/weapons/weapon.qh index 3dd2a8048a..02fbdb536c 100644 --- a/qcsrc/common/weapons/weapon.qh +++ b/qcsrc/common/weapons/weapon.qh @@ -216,6 +216,8 @@ WepSet W_RandomWeapons(entity e, WepSet remaining, int n); string GetAmmoPicture(int ammotype); +string GetAmmoName(int ammotype); + #ifdef CSQC int GetAmmoTypeFromNum(int i); int GetAmmoStat(int ammotype); diff --git a/qcsrc/lib/csqcmodel/cl_player.qc b/qcsrc/lib/csqcmodel/cl_player.qc index 2af309c02e..a7937c317f 100644 --- a/qcsrc/lib/csqcmodel/cl_player.qc +++ b/qcsrc/lib/csqcmodel/cl_player.qc @@ -82,7 +82,7 @@ void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff) csqcplayer_predictionerroro = CSQCPlayer_GetPredictionErrorO() + o; csqcplayer_predictionerrorv = CSQCPlayer_GetPredictionErrorV() + v; - csqcplayer_predictionerrorfactor = autocvar_cl_movement_errorcompensation / ticrate; + csqcplayer_predictionerrorfactor = autocvar_cl_movement_errorcompensation / ((ticrate) ? ticrate : 1); csqcplayer_predictionerrortime = time + 1.0 / csqcplayer_predictionerrorfactor; } diff --git a/qcsrc/lib/warpzone/server.qc b/qcsrc/lib/warpzone/server.qc index 0244b40a9d..66ee6b133c 100644 --- a/qcsrc/lib/warpzone/server.qc +++ b/qcsrc/lib/warpzone/server.qc @@ -13,6 +13,10 @@ #include #endif +#ifdef SVQC +bool autocvar_sv_warpzone_allow_selftarget; +#endif + #ifdef WARPZONELIB_KEEPDEBUG #define WARPZONELIB_REMOVEHACK #endif @@ -213,19 +217,8 @@ void WarpZone_Touch(entity this, entity toucher) if(WarpZone_Teleport(this, toucher, f, 0)) { #ifdef SVQC - string save1, save2; - - save1 = this.target; this.target = string_null; - save2 = this.target3; this.target3 = string_null; - SUB_UseTargets(this, toucher, toucher); // use toucher too? - if (!this.target) this.target = save1; - if (!this.target3) this.target3 = save2; - - save1 = this.target; this.target = string_null; - save2 = this.target2; this.target2 = string_null; - SUB_UseTargets(this.enemy, toucher, toucher); // use toucher too? - if (!this.target) this.target = save1; - if (!this.target2) this.target2 = save2; + SUB_UseTargets_SkipTargets(this, toucher, toucher, BIT(1) | BIT(3)); // use toucher too? + SUB_UseTargets_SkipTargets(this.enemy, toucher, toucher, BIT(1) | BIT(2)); // use toucher too? #endif } else @@ -369,19 +362,8 @@ float WarpZone_CheckProjectileImpact(entity player) player.velocity = player.warpzone_oldvelocity; if(WarpZone_Teleport(wz, player, 0, 1)) { - string save1, save2; - - save1 = wz.target; wz.target = string_null; - save2 = wz.target3; wz.target3 = string_null; - SUB_UseTargets(wz, player, player); - if (!wz.target) wz.target = save1; - if (!wz.target3) wz.target3 = save2; - - save1 = wz.enemy.target; wz.enemy.target = string_null; - save2 = wz.enemy.target2; wz.enemy.target2 = string_null; - SUB_UseTargets(wz.enemy, player, player); - if (!wz.enemy.target) wz.enemy.target = save1; - if (!wz.enemy.target2) wz.enemy.target2 = save2; + SUB_UseTargets_SkipTargets(wz, player, player, BIT(1) | BIT(3)); + SUB_UseTargets_SkipTargets(wz.enemy, player, player, BIT(1) | BIT(2)); } else { @@ -648,7 +630,8 @@ void WarpZone_InitStep_FindTarget(entity this) // this way only one of the two ents needs to target if(this.target != "") { - this.enemy = this; // so the if(!e.enemy) check also skips this, saves one IF + if(!autocvar_sv_warpzone_allow_selftarget) + this.enemy = this; // so the if(!e.enemy) check also skips this, saves one IF e2 = NULL; for(e = NULL, i = 0; (e = find(e, targetname, this.target)); ) diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index a8195451f4..8213aaddec 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -93,7 +93,7 @@ float autocvar_g_ballistics_density_corpse; float autocvar_g_ballistics_density_player; float autocvar_g_ballistics_mindistance; bool autocvar_g_ballistics_penetrate_clips = true; -float autocvar_g_ballistics_solidpenetration_exponent = 0.25; +float autocvar_g_ballistics_solidpenetration_exponent = 1; float autocvar_g_ban_default_bantime; float autocvar_g_ban_default_masksize; float autocvar_g_ban_sync_interval; diff --git a/qcsrc/server/campaign.qc b/qcsrc/server/campaign.qc index ea5af04382..f0fcea6abf 100644 --- a/qcsrc/server/campaign.qc +++ b/qcsrc/server/campaign.qc @@ -129,9 +129,6 @@ void CampaignPreInit() cvar_set("skill", ftos(baseskill)); cvar_set("bot_number", ftos(campaign_bots[0])); #else - // since g_campaign is already set to 1 by the menu when starting a campaign level, we first need - // to set it back to 0 before settemping it to 1 so it'll be correctly restored to 0 on disconnection - cvar_set("g_campaign", "0"); cvar_settemp("g_campaign", "1"); cvar_settemp("g_dm", "0"); cvar_settemp("skill", ftos(baseskill)); diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 1d5e240b38..d79c630f20 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -611,7 +611,8 @@ void PutPlayerInServer(entity this) this.respawn_flags = 0; this.respawn_time = 0; STAT(RESPAWN_TIME, this) = 0; - this.scale = autocvar_sv_player_scale; + bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox; + this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale); this.fade_time = 0; this.pain_frame = 0; this.pain_finished = 0; diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 6928957d6d..ad9cab8e72 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -635,15 +635,22 @@ void ClientCommand_spectate(entity caller, int request) { if (!intermission_running && IS_CLIENT(caller)) { - if((IS_SPEC(caller) || IS_OBSERVER(caller)) && argv(1) != "") + if(argv(1) != "") { - entity client = GetFilteredEntity(argv(1)); - int spec_accepted = VerifyClientEntity(client, false, false); - if(spec_accepted > 0 && IS_PLAYER(client)) + if(IS_SPEC(caller) || IS_OBSERVER(caller)) { - if(Spectate(caller, client)) - return; // fall back to regular handling + entity client = GetFilteredEntity(argv(1)); + int spec_accepted = VerifyClientEntity(client, false, false); + if(spec_accepted > 0 && IS_PLAYER(client)) + { + Spectate(caller, client); + } + else + sprint(caller, "can't spectate ", argv(1), "^7\n"); } + else + sprint(caller, "cmd spectate client only works when you are spectator/observer\n"); + return; } int mutator_returnvalue = MUTATOR_CALLHOOK(ClientCommand_Spectate, caller); @@ -660,7 +667,7 @@ void ClientCommand_spectate(entity caller, int request) default: case CMD_REQUEST_USAGE: { - sprint(caller, "\nUsage:^3 cmd spectate \n"); + sprint(caller, "\nUsage:^3 cmd spectate [client]\n"); sprint(caller, " Where 'client' can be the player to spectate.\n"); return; } diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 6ee29474e5..c3dc5be39f 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -330,6 +330,7 @@ void cvar_changes_init() BADCVAR("g_balance_kill_delay"); BADCVAR("g_buffs_pickup_anyway"); BADCVAR("g_buffs_randomize"); + BADCVAR("g_buffs_randomize_teamplay"); BADCVAR("g_campcheck_distance"); BADCVAR("g_ca_point_leadlimit"); BADCVAR("g_ca_point_limit"); @@ -872,6 +873,9 @@ spawnfunc(worldspawn) MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1); + if(fexists(strcat("scripts/", mapname, ".arena"))) + cvar_settemp("sv_q3acompat_machineshotgunswap", "1"); + if(fexists(strcat("scripts/", mapname, ".defi"))) cvar_settemp("sv_q3defragcompat", "1"); diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index dd14a049e1..7f852782c1 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -33,6 +33,7 @@ #include "../common/state.qh" #include "../common/effects/qc/globalsound.qh" #include "../common/wepent.qh" +#include #include "../lib/csqcmodel/sv_model.qh" #include "../lib/warpzone/anglestransform.qh" #include "../lib/warpzone/server.qh" @@ -214,21 +215,6 @@ string NearestLocation(vector p) return ret; } -string AmmoNameFromWeaponentity(Weapon wep) -{ - string ammoitems = "batteries"; - switch (wep.ammo_type) - { - case RES_SHELLS: ammoitems = ITEM_Shells.m_name; break; - case RES_BULLETS: ammoitems = ITEM_Bullets.m_name; break; - case RES_ROCKETS: ammoitems = ITEM_Rockets.m_name; break; - case RES_CELLS: ammoitems = ITEM_Cells.m_name; break; - case RES_PLASMA: ammoitems = ITEM_Plasma.m_name; break; - case RES_FUEL: ammoitems = ITEM_JetpackFuel.m_name; break; - } - return ammoitems; -} - string PlayerHealth(entity this) { float myhealth = floor(GetResource(this, RES_HEALTH)); @@ -311,7 +297,7 @@ string formatmessage(entity this, string msg) case "y": replacement = NearestLocation(cursor); break; case "d": replacement = NearestLocation(this.death_origin); break; case "w": replacement = WeaponNameFromWeaponentity(this, weaponentity); break; - case "W": replacement = AmmoNameFromWeaponentity(this.(weaponentity).m_weapon); break; + case "W": replacement = GetAmmoName(this.(weaponentity).m_weapon.ammo_type); break; case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break; case "s": replacement = ftos(vlen(this.velocity - this.velocity_z * '0 0 1')); break; case "S": replacement = ftos(vlen(this.velocity)); break; @@ -638,8 +624,6 @@ void weaponarena_available_most_update(entity this) void readplayerstartcvars() { - float i, t; - // initialize starting values for players start_weapons = '0 0 0'; start_weapons_default = '0 0 0'; @@ -723,11 +707,11 @@ void readplayerstartcvars() else { g_weaponarena = 1; - t = tokenize_console(s); + float t = tokenize_console(s); g_weaponarena_list = ""; - for (i = 0; i < t; ++i) + for (int j = 0; j < t; ++j) { - s = argv(i); + s = argv(j); Weapon wep = Weapons_fromstr(s); if(wep != WEP_Null) { @@ -1211,11 +1195,10 @@ bool SUB_NoImpactCheck(entity this, entity toucher) return false; } -#define SUB_OwnerCheck(ent,oth) ((oth) && ((oth) == (ent).owner)) - bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher) { - if(SUB_OwnerCheck(this, toucher)) + // owner check + if(toucher && toucher == this.owner) return true; if(SUB_NoImpactCheck(this, toucher)) { @@ -1263,9 +1246,9 @@ void URI_Get_Callback(float id, float status, string data) } } -string uid2name(string myuid) { - string s; - s = db_get(ServerProgsDB, strcat("/uid2name/", myuid)); +string uid2name(string myuid) +{ + string s = db_get(ServerProgsDB, strcat("/uid2name/", myuid)); // FIXME remove this later after 0.6 release // convert old style broken records to correct style @@ -1284,20 +1267,18 @@ string uid2name(string myuid) { return s; } -float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) +bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance) { - float m, i; - vector start, org, delta, end, enddown, mstart; - - m = e.dphitcontentsmask; + float m = e.dphitcontentsmask; e.dphitcontentsmask = goodcontents | badcontents; - org = boundmin; - delta = boundmax - boundmin; + vector org = boundmin; + vector delta = boundmax - boundmin; + vector start, end; start = end = org; - - for (i = 0; i < attempts; ++i) + int j; // used after the loop + for(j = 0; j < attempts; ++j) { start.x = org.x + random() * delta.x; start.y = org.y + random() * delta.y; @@ -1319,13 +1300,13 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma // rule 2: if we are too high, lower the point if (trace_fraction * delta.z > maxaboveground) start = trace_endpos + '0 0 1' * maxaboveground; - enddown = trace_endpos; + vector enddown = trace_endpos; // rule 3: make sure we aren't outside the map. This only works // for somewhat well formed maps. A good rule of thumb is that // the map should have a convex outside hull. // these can be traceLINES as we already verified the starting box - mstart = start + 0.5 * (e.mins + e.maxs); + vector mstart = start + 0.5 * (e.mins + e.maxs); traceline(mstart, mstart + '1 0 0' * delta.x, MOVE_NORMAL, e); if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") continue; @@ -1342,35 +1323,35 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") continue; - // rule 4: we must "see" some spawnpoint or item - entity sp = NULL; - IL_EACH(g_spawnpoints, checkpvs(mstart, it), - { - if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1) - { - sp = it; - break; - } - }); - if(!sp) - { - int items_checked = 0; - IL_EACH(g_items, checkpvs(mstart, it), + // rule 4: we must "see" some spawnpoint or item + entity sp = NULL; + IL_EACH(g_spawnpoints, checkpvs(mstart, it), + { + if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1) + { + sp = it; + break; + } + }); + if(!sp) { - if((traceline(mstart, it.origin + (it.mins + it.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1) + int items_checked = 0; + IL_EACH(g_items, checkpvs(mstart, it), { - sp = it; - break; - } + if((traceline(mstart, it.origin + (it.mins + it.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1) + { + sp = it; + break; + } - ++items_checked; - if(items_checked >= attempts) - break; // sanity - }); + ++items_checked; + if(items_checked >= attempts) + break; // sanity + }); - if(!sp) - continue; - } + if(!sp) + continue; + } // find a random vector to "look at" end.x = org.x + random() * delta.x; @@ -1380,17 +1361,17 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma // rule 4: start TO end must not be too short tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e); - if (trace_startsolid) + if(trace_startsolid) continue; - if (trace_fraction < minviewdistance / vlen(delta)) + if(trace_fraction < minviewdistance / vlen(delta)) continue; // rule 5: don't want to look at sky - if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) continue; // rule 6: we must not end up in trigger_hurt - if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown)) + if(tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown)) continue; break; @@ -1398,15 +1379,14 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma e.dphitcontentsmask = m; - if (i < attempts) + if(j < attempts) { setorigin(e, start); e.angles = vectoangles(end - start); - LOG_DEBUG("Needed ", ftos(i + 1), " attempts"); + LOG_DEBUG("Needed ", ftos(j + 1), " attempts"); return true; } - else - return false; + return false; } float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) @@ -1488,24 +1468,13 @@ void follow_sameorigin(entity e, entity to) e.v_angle = e.angles - to.angles; // relative angles } +#if 0 +// TODO: unused, likely for a reason, possibly needs extensions (allow setting the new movetype as a parameter?) void unfollow_sameorigin(entity e) { set_movetype(e, MOVETYPE_NONE); } - -entity gettaginfo_relative_ent; -vector gettaginfo_relative(entity e, float tag) -{ - if (!gettaginfo_relative_ent) - { - gettaginfo_relative_ent = spawn(); - gettaginfo_relative_ent.effects = EF_NODRAW; - } - gettaginfo_relative_ent.model = e.model; - gettaginfo_relative_ent.modelindex = e.modelindex; - gettaginfo_relative_ent.frame = e.frame; - return gettaginfo(gettaginfo_relative_ent, tag); -} +#endif .string aiment_classname; .float aiment_deadflag; diff --git a/qcsrc/server/miscfunctions.qh b/qcsrc/server/miscfunctions.qh index 2b85a0476f..a67920f77c 100644 --- a/qcsrc/server/miscfunctions.qh +++ b/qcsrc/server/miscfunctions.qh @@ -90,14 +90,12 @@ float LostMovetypeFollow(entity ent); string uid2name(string myuid); -float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance); +bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance); float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance); string NearestLocation(vector p); -string AmmoNameFromWeaponentity(Weapon wep); - void play2(entity e, string filename); string playername(entity p, bool team_colorize); diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index 0410c2f9ec..59812425d6 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -374,14 +374,7 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( restartanim = fr != WFRAME_IDLE; } - vector a = '0 0 0'; this.wframe = fr; - if (fr == WFRAME_IDLE) a = this.anim_idle; - else if (fr == WFRAME_FIRE1) a = this.anim_fire1; - else if (fr == WFRAME_FIRE2) a = this.anim_fire2; - else // if (fr == WFRAME_RELOAD) - a = this.anim_reload; - a.z *= g_weaponratefactor; if (this.weapon_think == w_ready && func != w_ready && this.state == WS_RAISE) backtrace( "Tried to override initial weapon think function - should this really happen?"); @@ -408,7 +401,7 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( { FOREACH_CLIENT(true, { if(it == actor || (IS_SPEC(it) && it.enemy == actor)) - wframe_send(it, this, a, restartanim); + wframe_send(it, this, fr, g_weaponratefactor, restartanim); }); } diff --git a/ruleset-overkill.cfg b/ruleset-overkill.cfg index cb39b2a10c..8b3f70a941 100644 --- a/ruleset-overkill.cfg +++ b/ruleset-overkill.cfg @@ -34,3 +34,5 @@ g_spawn_near_teammate "!g_assault !g_freezetag" g_spawn_near_teammate_ignore_spawnpoint 1 g_spawnshieldtime 0.5 g_respawn_delay_forced 2 + +g_ballistics_solidpenetration_exponent 0.25 diff --git a/vehicles.cfg b/vehicles.cfg index d3a2c0bc56..7aa6e888f9 100644 --- a/vehicles.cfg +++ b/vehicles.cfg @@ -226,7 +226,7 @@ set g_vehicle_raptor_bouncepain "1 4 1000" set g_vehicle_raptor_cannon_cost 1 set g_vehicle_raptor_cannon_damage 10 set g_vehicle_raptor_cannon_radius 60 -set g_vehicle_raptor_cannon_refire 0.03 +set g_vehicle_raptor_cannon_refire 0.033333 set g_vehicle_raptor_cannon_speed 24000 set g_vehicle_raptor_cannon_spread 0.01 set g_vehicle_raptor_cannon_force 25 diff --git a/xonotic-server.cfg b/xonotic-server.cfg index 25c7b74845..c7f12c46f6 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -345,7 +345,7 @@ set g_maplist_votable_timeout 30 "timeout for the map voting; must be below 50 s set g_maplist_votable_suggestions 2 "number of maps a player is allowed to suggest for the map voting screen using 'suggestmap'" set g_maplist_votable_suggestions_override_mostrecent 0 "allow players to suggest maps that have been played recently" set g_maplist_votable_nodetail 0 "hide per-map vote counts (to avoid influential first votes)" -set g_maplist_votable_abstain 0 "offer a "\don't care\" option on the voting screen" +set g_maplist_votable_abstain 0 "offer a \"don't care\" option on the voting screen" set g_maplist_votable_screenshot_dir "maps levelshots" "where to look for map screenshots" set sv_vote_gametype 0 "show a vote screen for gametypes before map vote screen" @@ -430,7 +430,7 @@ set g_ballistics_mindistance 2 "when shooting through walls thinner than this, t set g_ballistics_density_player 0.50 "how hard players are to shoot through compared to walls" set g_ballistics_density_corpse 0.10 "how hard corpses are to shoot through compared to walls" set g_ballistics_penetrate_clips 1 "allow ballistics to pass through weapon clips" -set g_ballistics_solidpenetration_exponent 0.25 "how fast damage falls off when bullets pass through walls - 1 means linear, lower values mean slower initial falloff but faster once there's little solidpenetration left (damage_fraction = solidpen_fraction^exp for solidpen_fraction between 0 and 1)" +set g_ballistics_solidpenetration_exponent 1 "how fast damage falls off when bullets pass through walls - 1 means linear, lower values mean slower initial falloff but faster once there's little solidpenetration left (damage_fraction = solidpen_fraction^exp for solidpen_fraction between 0 and 1)" sv_status_show_qcstatus 1 "Xonotic uses this field instead of frags" set g_full_getstatus_responses 0 "this currently breaks qstat" @@ -569,4 +569,6 @@ set sv_showspectators 1 "Show who's spectating who in the player info panel when set sv_damagetext 2 "<= 0: disabled, >= 1: visible to spectators, >= 2: visible to attacker, >= 3: all players see everyone's damage" set sv_showfps 5 "Show player's FPS counters in the scoreboard. This setting acts as a delay in seconds between updates" -set autocvar_sv_doors_always_open 0 "If set to 1 don't close doors which after they were open" +set sv_doors_always_open 0 "If set to 1 don't close doors which after they were open" + +set sv_warpzone_allow_selftarget 0 "do not touch"