]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'terencehill/frametime_checks' into 'master'
authorMario <mario.mario@y7mail.com>
Tue, 7 Jan 2020 14:40:04 +0000 (14:40 +0000)
committerMario <mario.mario@y7mail.com>
Tue, 7 Jan 2020 14:40:04 +0000 (14:40 +0000)
Frametime checks

See merge request xonotic/xonotic-data.pk3dir!751

27 files changed:
crosshairs.cfg
qcsrc/Makefile
qcsrc/client/view.qc
qcsrc/common/mutators/events.qh
qcsrc/common/mutators/mutator/bloodloss/_mod.inc
qcsrc/common/mutators/mutator/bloodloss/_mod.qh
qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/bloodloss/bloodloss.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qc [deleted file]
qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qh [deleted file]
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/player.qc
qcsrc/common/stats.qh
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/menu/xonotic/campaign.qc
qcsrc/menu/xonotic/campaign.qh
qcsrc/menu/xonotic/dialog_settings_game_view.qc
qcsrc/menu/xonotic/dialog_settings_game_weapons.qc
qcsrc/menu/xonotic/dialog_singleplayer.qc
qcsrc/server/campaign.qc
qcsrc/server/client.qc
qcsrc/server/g_hook.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh
xonotic-client.cfg
xonotic-common.cfg

index 47631f0fa6cb70b4a664e493ff5dd06bd300bfae..ae3fec0805b9dfbeeccec68a43bc63d8df6c639f 100644 (file)
@@ -32,10 +32,10 @@ seta crosshair_hitindication_speed 5
 
 // hit testing/tracing for special effects for the crosshair
 set g_trueaim_minrange 44 "TrueAim minimum range (TrueAim adjusts shots so they hit the crosshair point even though the gun is not at the screen center)"
-seta crosshair_hittest 1 "do a crosshair hit evaluation, applying effects from the _blur, _scale, and _showipact cvars"
+seta crosshair_hittest 1 "do a crosshair hit evaluation, applying effects from the _blur and _scale cvars"
 seta crosshair_hittest_blur 1 "blur the crosshair if the shot is obstructed"
 seta crosshair_hittest_scale 1.25 "shrink crosshair if shot is obstructed or aiming at a teammate"
-seta crosshair_hittest_showimpact 0 "move the crosshair to the actual impact location if obstructed"
+seta crosshair_hittest_showimpact 0 "move the crosshair to the actual impact location if obstructed (debug setting, very glitchy!)"
 
 // change color based on special case
 seta crosshair_color_special 1 "special color handling for crosshair... 1 = per-weapon crosshair color (see crosshair_per_weapon), 2 = crosshair changes color based on health, 3 = rainbow/random color selection"
index d09b2c5ccffa730255a6545d0f411a11adc05fc5..7c8e3b8ad16f7207d5296f16a4cde3a61863c540 100644 (file)
@@ -93,8 +93,8 @@ pk3: csprogs-$(VER).pk3
        $(eval DAT=$(PROG)-$(VER).dat)
        $(eval LNO=$(PROG)-$(VER).lno)
        @ echo "http://xonotic.org" > $(TXT)
-       @ ln -f $(PROGS_OUT)/$(PROG).dat $(DAT)
-       @ ln -f $(PROGS_OUT)/$(PROG).lno $(LNO)
+       @ cp -f $(PROGS_OUT)/$(PROG).dat $(DAT)
+       @ cp -f $(PROGS_OUT)/$(PROG).lno $(LNO)
        @ $(RM) *.pk3
        $(ZIP) $(PK3) $(TXT) $(DAT) $(LNO)
        @ $(RM) $(TXT) $(DAT) $(LNO)
index 66f80ad2c45b878fdafc3a9ea070fde4ef29c2ec..1b1e8ebdc4f74e81e25f6986b591e152844db521 100644 (file)
@@ -48,7 +48,7 @@
 #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
 
 float autocvar_cl_viewmodel_scale;
-float autocvar_cl_viewmodel_alpha;
+float autocvar_cl_viewmodel_alpha = 1;
 
 bool autocvar_cl_bobmodel;
 float autocvar_cl_bobmodel_speed;
index cf858487058de2bbeac734fff836481bae3e4504..6ee9574d057ed13876ea96d22e8ac7bc1dd72f42 100644 (file)
@@ -112,3 +112,11 @@ MUTATOR_HOOKABLE(WeaponSound, EV_WeaponSound);
     /**/          o(string, MUTATOR_ARGV_1_string) \
     /**/
 MUTATOR_HOOKABLE(WeaponModel, EV_WeaponModel);
+
+/** decides whether a player can crouch or not */
+#define EV_PlayerCanCrouch(i, o) \
+    /** player */      i(entity, MUTATOR_ARGV_0_entity) \
+    /** do_crouch */   i(bool, MUTATOR_ARGV_1_bool) \
+    /**/               o(bool, MUTATOR_ARGV_1_bool) \
+    /**/
+MUTATOR_HOOKABLE(PlayerCanCrouch, EV_PlayerCanCrouch);
index 768808db71f1cb41d9acf29090865a5c7d35a09c..16e6308acf9d39e466c350241b96d3ece7f990e6 100644 (file)
@@ -1,4 +1,2 @@
 // generated file; do not modify
-#ifdef SVQC
-    #include <common/mutators/mutator/bloodloss/sv_bloodloss.qc>
-#endif
+#include <common/mutators/mutator/bloodloss/bloodloss.qc>
index e6ad248c622d6aaad3d8f0e2b93744037e9c5577..b1d45e2791b07d3e3d1b8572fed442328348f863 100644 (file)
@@ -1,4 +1,2 @@
 // generated file; do not modify
-#ifdef SVQC
-    #include <common/mutators/mutator/bloodloss/sv_bloodloss.qh>
-#endif
+#include <common/mutators/mutator/bloodloss/bloodloss.qh>
diff --git a/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc b/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc
new file mode 100644 (file)
index 0000000..2a0ebec
--- /dev/null
@@ -0,0 +1,70 @@
+#include "bloodloss.qh"
+
+#ifdef GAMEQC
+#ifdef SVQC
+REGISTER_MUTATOR(bloodloss, autocvar_g_bloodloss);
+#elif defined(CSQC)
+REGISTER_MUTATOR(bloodloss, true);
+#endif
+
+#ifdef SVQC
+.float bloodloss_timer;
+
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerPreThink)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(game_stopped)
+               return; // during intermission, the player's health changes to strange values for the engine, let's not cause damage during this phase!
+
+       if(IS_PLAYER(player))
+       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss && !IS_DEAD(player) && time >= player.bloodloss_timer)
+       {
+               if(player.vehicle)
+                       vehicles_exit(player.vehicle, VHEF_RELEASE); // TODO: boots player out of their vehicle each health rot tick!
+               if(player.event_damage)
+                       player.event_damage(player, player, player, 1, DEATH_ROT.m_id, DMG_NOWEP, player.origin, '0 0 0');
+               player.bloodloss_timer = time + 0.5 + random() * 0.5;
+       }
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerCanCrouch)
+{
+       entity player = M_ARGV(0, entity);
+       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss)
+               M_ARGV(1, bool) = true; // do_crouch
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss)
+               return true;
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsString)
+{
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":bloodloss");
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsPrettyString)
+{
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Blood loss");
+}
+#endif
+
+#ifdef CSQC
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerCanCrouch)
+{
+       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+               M_ARGV(1, bool) = true; // do_crouch
+}
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
+{
+       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+               return true;
+}
+#endif
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qh b/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
diff --git a/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qc b/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qc
deleted file mode 100644 (file)
index a89691d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "sv_bloodloss.qh"
-
-float autocvar_g_bloodloss;
-REGISTER_MUTATOR(bloodloss, autocvar_g_bloodloss);
-
-.float bloodloss_timer;
-
-MUTATOR_HOOKFUNCTION(bloodloss, PlayerPreThink)
-{
-       entity player = M_ARGV(0, entity);
-
-       if(IS_PLAYER(player))
-       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss && !IS_DEAD(player))
-       {
-               PHYS_INPUT_BUTTON_CROUCH(player) = true;
-
-               if(time >= player.bloodloss_timer)
-               {
-                       if(player.vehicle)
-                               vehicles_exit(player.vehicle, VHEF_RELEASE);
-                       if(player.event_damage)
-                               player.event_damage(player, player, player, 1, DEATH_ROT.m_id, DMG_NOWEP, player.origin, '0 0 0');
-                       player.bloodloss_timer = time + 0.5 + random() * 0.5;
-               }
-       }
-}
-
-MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
-{
-       entity player = M_ARGV(0, entity);
-
-       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss)
-               return true;
-}
-
-MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsString)
-{
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":bloodloss");
-}
-
-MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsPrettyString)
-{
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Blood loss");
-}
diff --git a/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qh b/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qh
deleted file mode 100644 (file)
index 6f70f09..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#pragma once
index 108782ef95f78df41bd385f938dec22210c72403..bbd86d62e3f0a25074751573f0322b9341f17fa6 100644 (file)
@@ -331,17 +331,7 @@ void _Movetype_Impact(entity this, entity oth)  // SV_Impact
                gettouch(this)(this, oth);
 
        if(oth.solid != SOLID_NOT && gettouch(oth))
-       {
-               trace_endpos = oth.origin;
-               trace_plane_normal = -trace_plane_normal;
-               trace_plane_dist = -trace_plane_dist;
-               trace_ent = this;
-               trace_dpstartcontents = 0;
-               trace_dphitcontents = 0;
-               trace_dphitq3surfaceflags = 0;
-               trace_dphittexturename = string_null;
                gettouch(oth)(oth, this);
-       }
 }
 
 void _Movetype_LinkEdict_TouchAreaGrid(entity this)  // SV_LinkEdict_TouchAreaGrid
@@ -427,16 +417,20 @@ bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
     entity this = _Movetype_TestEntityPosition_ent;
        vector org = this.origin + ofs;
 
-       int cont = this.dphitcontentsmask;
-       this.dphitcontentsmask = DPCONTENTS_SOLID;
+       //int cont = this.dphitcontentsmask;
+       //this.dphitcontentsmask = DPCONTENTS_SOLID;
        tracebox(org, this.mins, this.maxs, org, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
-       this.dphitcontentsmask = cont;
+       //this.dphitcontentsmask = cont;
 
        if(trace_startsolid)
                return true;
 
        if(vdist(trace_endpos - this.origin, >, 0.0001))
-               this.origin = trace_endpos;
+       {
+               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos, MOVE_NOMONSTERS, this);
+               if(!trace_startsolid)
+                       this.origin = trace_endpos;
+       }
        return false;
 }
 
@@ -447,6 +441,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
            return UNSTICK_FINE;
        }
        #define X(v) if (_Movetype_TestEntityPosition(v))
+       X('0  0  -1') X(' 0  0  1')
        X('-1  0  0') X(' 1  0  0')
        X(' 0 -1  0') X(' 0  1  0')
        X('-1 -1  0') X(' 1 -1  0')
@@ -456,7 +451,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
         #define X(i) \
             if (_Movetype_TestEntityPosition('0 0 -1' * i)) \
             if (_Movetype_TestEntityPosition('0 0 1' * i))
-        X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8)
+        X(2) X(3) X(4) X(5) X(6) X(7) X(8)
         X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16)
         X(17)
         #undef X
@@ -468,7 +463,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
        }
        LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
                etof(this), this.classname, vtos(this.origin));
-       _Movetype_LinkEdict(this, true);
+       _Movetype_LinkEdict(this, false);
        return UNSTICK_FIXED;
 }
 
index 5ba6e82685b3204ce2caa5da04c5862253f0c974..9f7ddab502d31764b79c546bfd40fc3b8e7b176e 100644 (file)
@@ -145,6 +145,9 @@ void PM_ClientMovement_UpdateStatus(entity this)
                do_crouch = false;
     }
 
+    MUTATOR_CALLHOOK(PlayerCanCrouch, this, do_crouch);
+    do_crouch = M_ARGV(1, bool);
+
        if (do_crouch) {
                if (!IS_DUCKED(this)) {
                        SET_DUCKED(this);
index 1a9b35ec01f393e224d87640ea8d1598ae84ce4a..8b769538e900f03bb467eb3d1cdb21c00b6e3a3d 100644 (file)
@@ -288,6 +288,11 @@ REGISTER_STAT(WALLJUMP_DELAY, float, autocvar_g_walljump_delay)
 REGISTER_STAT(WALLJUMP_FORCE, float, autocvar_g_walljump_force)
 REGISTER_STAT(LASTWJ, float)
 
+#ifdef SVQC
+float autocvar_g_bloodloss;
+#endif
+REGISTER_STAT(BLOODLOSS, float, autocvar_g_bloodloss)
+
 // freeze tag, clan arena
 REGISTER_STAT(REDALIVE, int)
 REGISTER_STAT(BLUEALIVE, int)
index 4d41cd316103ef35a59b99c6578b44b0d2ba8179..f49c5f6dbd93ab621aea33c531ea47d5c7653380 100644 (file)
@@ -240,7 +240,7 @@ bool autocvar_v_deathtilt;
 float autocvar_v_deathtiltangle;
 void CSQCPlayer_ApplyDeathTilt(entity this)
 {
-       if(!IS_DEAD(this) || !autocvar_v_deathtilt)
+       if(!this.csqcmodel_isdead || !autocvar_v_deathtilt)
                return;
        view_angles.z = autocvar_v_deathtiltangle;
 }
@@ -279,7 +279,7 @@ float bobfall_speed;
 float bob2_smooth;
 vector CSQCPlayer_ApplyBobbing(entity this, vector v)
 {
-       if(IS_DEAD(this))
+       if(this.csqcmodel_isdead)
                return v;
 
        // bounded XY speed, used by several effects below
index a3ad36355d9cece13deb37c750054cfe8794d0d2..0f64aefdbc1a207248f7d1b29e206610b8d7c18e 100644 (file)
@@ -183,6 +183,9 @@ void XonoticCampaignList_resizeNotify(entity me, vector relOrigin, vector relSiz
 
        me.checkMarkOrigin = eY + eX * (me.columnCheckMarkOrigin + me.columnCheckMarkSize) - me.checkMarkSize;
 
+       me.typeIconOrigin = vec3(me.columnPreviewSize - me.checkMarkSize.x, me.checkMarkOrigin.y, 0);
+       me.typeIconSize = me.checkMarkSize;
+
        rewrapCampaign(me.columnNameSize, me.rowsPerItem - 3, me.emptyLineHeight, me.realFontSize);
 }
 void XonoticCampaignList_doubleClickListBoxItem(entity me, float i, vector where)
@@ -226,6 +229,10 @@ void XonoticCampaignList_drawListBoxItem(entity me, int i, vector absSize, bool
        else
                draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", campaign_mapname[i]), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
 
+       s = strcat("/gfx/menu/", cvar_string("menu_skin"), "/gametype_", campaign_gametype[i]);
+       if(i <= me.campaignIndex && draw_PictureSize(s) != '0 0 0')
+               draw_Picture(me.typeIconOrigin, s, me.typeIconSize, '1 1 1', 1);
+
        if(i < me.campaignIndex)
                draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1);
        if(i <= me.campaignIndex)
index 298e27587466697572311d048684b11a2dc21db9..d6c674e8d6343ef21cf9722ebecd0cab9e1d2290 100644 (file)
@@ -23,6 +23,8 @@ CLASS(XonoticCampaignList, XonoticListBox)
        ATTRIB(XonoticCampaignList, columnCheckMarkSize, float, 0);
        ATTRIB(XonoticCampaignList, checkMarkOrigin, vector, '0 0 0');
        ATTRIB(XonoticCampaignList, checkMarkSize, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, typeIconOrigin, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, typeIconSize, vector, '0 0 0');
        ATTRIB(XonoticCampaignList, realUpperMargin1, float, 0);
        ATTRIB(XonoticCampaignList, realUpperMargin2, float, 0);
 
index 0b3a9ff6c4402253b2a30fb8ab277ab41b6a3c3d..ed21eeae0b46d996abb396b337a54192532b7eb8 100644 (file)
@@ -24,7 +24,6 @@ void XonoticGameViewSettingsTab_fill(entity me)
 
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "chase_active", "0", _("1st person perspective")));
-               makeMulti(e, "crosshair_hittest_showimpact");
        me.TR(me);
                me.TDempty(me, 0.2);
                me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_eventchase_death", _("Slide to third person upon death")));
@@ -49,7 +48,6 @@ void XonoticGameViewSettingsTab_fill(entity me)
        me.TR(me);
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "chase_active", "1", _("3rd person perspective")));
-               makeMulti(e, "crosshair_hittest_showimpact");
        me.TR(me);
                me.TDempty(me, 0.2);
                me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Back distance")));
index 8eac7301abc705df0d96c214107ddb7683b5957a..5c77faffb501ed0ca2aebf740dd8d559548b94d4 100644 (file)
@@ -3,6 +3,7 @@
 #include "weaponslist.qh"
 #include "commandbutton.qh"
 #include "textlabel.qh"
+#include "textslider.qh"
 #include "checkbox.qh"
 #include "button.qh"
 #include "radiobutton.qh"
@@ -72,6 +73,18 @@ void XonoticGameWeaponsSettingsTab_fill(entity me)
                me.TD(me, 1, 1.0, e = makeXonoticRadioButton_T(1, "cl_gunalign", "3", _("Right align"),
                        _("Position of the weapon model; requires reconnect")));
                        setDependent(e, "r_drawviewmodel", 1, 1);
+       me.TR(me);
+                       me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Weapon model opacity:")));
+                               setDependent(e, "r_drawviewmodel", 1, 1);
+
+                       me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_viewmodel_alpha"));
+                               setDependent(e, "r_drawviewmodel", 1, 1);
+                               e.addValue(e, "15%", "0.15");
+                               e.addValue(e, "25%", "0.25");
+                               e.addValue(e, "50%", "0.5");
+                               e.addValue(e, "75%", "0.75");
+                               e.addValue(e, "100%", "1");
+                               e.configureXonoticTextSliderValues(e);
        me.TR(me);
        me.TR(me);
                me.TDempty(me, 0.2);
index dc39346aa61f962f323964e81b05eccec083dc4f..b2ae8c0ba9269752bbeddf82c4beb723d5cf8e70 100644 (file)
@@ -128,8 +128,8 @@ void XonoticSingleplayerDialog_fill(entity me)
        me.gotoRC(me, me.rows - 2, 0);
                me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Campaign Difficulty:")));
                me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "-2", ZCTX(_("CSKL^Easy"))));
-               me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "-1", ZCTX(_("CSKL^Medium"))));
-               me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "0", ZCTX(_("CSKL^Hard"))));
+               me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "0", ZCTX(_("CSKL^Medium"))));
+               me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "2", ZCTX(_("CSKL^Hard"))));
                me.TR(me);
                me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Singleplayer!"), '0 0 0'));
                        e.onClick = CampaignList_LoadMap;
index 76e2cdeb8480069230118925719d77d9e105ae5b..6fdb6d33986a3afecfe0259e2c272b8d95a16304 100644 (file)
@@ -98,11 +98,7 @@ void CampaignPreInit()
                return;
        }
 
-       baseskill = autocvar_g_campaign_skill;
-       baseskill = baseskill + campaign_botskill[0];
-       if(baseskill < 0)
-               baseskill = 0;
-
+       baseskill = max(0, autocvar_g_campaign_skill + campaign_botskill[0]);
        campaign_forcewin = false;
 
        cvar_set("sv_public", "0");
index 4fa113ce8b684e7683d21dcb593164cf4d9a3850..1d5e240b3872969166294ccf93211e1d131e3068 100644 (file)
@@ -25,6 +25,7 @@
 #include "campaign.qh"
 #include "command/common.qh"
 #include "scores_rules.qh"
+#include "weapons/common.qh"
 
 #include "bot/api.qh"
 
@@ -713,10 +714,7 @@ void PutPlayerInServer(entity this)
        for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
                .entity weaponentity = weaponentities[slot];
-               entity oldwep = this.(weaponentity);
                CL_SpawnWeaponentity(this, weaponentity);
-               if(oldwep && oldwep.owner == this)
-                       this.(weaponentity).m_gunalign = oldwep.m_gunalign;
        }
        this.alpha = default_player_alpha;
        this.colormod = '1 1 1' * autocvar_g_player_brightness;
@@ -778,6 +776,7 @@ void PutPlayerInServer(entity this)
 
        if (CS(this).impulse) ImpulseCommands(this);
 
+       W_ResetGunAlign(this, CS(this).cvar_cl_gunalign);
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
                .entity weaponentity = weaponentities[slot];
@@ -2085,6 +2084,7 @@ bool joinAllowed(entity this)
 
 .int items_added;
 .string shootfromfixedorigin;
+.bool dualwielding_prev;
 bool PlayerThink(entity this)
 {
        if (game_stopped || intermission_running) {
@@ -2187,6 +2187,15 @@ bool PlayerThink(entity this)
                stuffcmd(this, sprintf("\ncl_shootfromfixedorigin \"%s\"\n", autocvar_g_shootfromfixedorigin));
        }
 
+       // reset gun alignment when dual wielding status changes
+       // to ensure guns are always aligned right and left
+       bool dualwielding = W_DualWielding(this);
+       if(this.dualwielding_prev != dualwielding)
+       {
+               W_ResetGunAlign(this, CS(this).cvar_cl_gunalign);
+               this.dualwielding_prev = dualwielding;
+       }
+
        // LordHavoc: allow firing on move frames (sub-ticrate), this gives better timing on slow servers
        //if(frametime)
        {
index b2b91bc02baf71cea1adf089e8236eea2a397667..aa970f4be3626a6ef4187417ad8c6f4a3f84769a 100644 (file)
@@ -359,9 +359,13 @@ void FireGrapplingHook(entity actor, .entity weaponentity)
        if(weaponLocked(actor)) return;
        if(actor.vehicle) return;
 
-       // TODO: offhand hook shoots from eye
+       int s = W_GunAlign(actor.(weaponentity), STAT(GUNALIGN, actor)) - 1;
+       vector vs = hook_shotorigin[s];
+       vector oldmovedir = actor.(weaponentity).movedir;
+       actor.(weaponentity).movedir = vs;
        W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', true, 0, SND_HOOK_FIRE, CH_WEAPON_B, 0, WEP_HOOK.m_id);
        Send_Effect(EFFECT_HOOK_MUZZLEFLASH, w_shotorg, '0 0 0', 1);
+       actor.(weaponentity).movedir = oldmovedir;
 
        entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
        missile.owner = missile.realowner = actor;
index 6082dbc9baf376b02ad6028a3b29036ba6096ac4..dd14a049e1bbb661464ab7bfb112c20ccf92c45f 100644 (file)
@@ -500,6 +500,8 @@ void GetCvars(entity this, entity store, int f)
                }
                if (s == "cl_allow_uidtracking")
                        PlayerStats_GameReport_AddPlayer(this);
+               //if (s == "cl_gunalign")
+                       //W_ResetGunAlign(this, store.cvar_cl_gunalign);
        }
 }
 
index 3191a763624cbd0287aa1e988f7a499422f925a6..0410c2f9ec45129c606efd30d0d7806fbbcc824d 100644 (file)
@@ -445,6 +445,28 @@ bool weaponLocked(entity player)
        return false;
 }
 
+void W_ResetGunAlign(entity player, int preferred_alignment)
+{
+       if(W_DualWielding(player))
+               preferred_alignment = 3; // right align, the second gun will default to left
+
+       // clear current weapon slots' alignments so we can redo the calculations!
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if (player.(weaponentity))
+                       player.(weaponentity).m_gunalign = 0;
+       }
+
+       // now set the new values
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if (player.(weaponentity))
+                       player.(weaponentity).m_gunalign = W_GunAlign(player.(weaponentity), preferred_alignment);
+       }
+}
+
 .bool hook_switchweapon;
 
 void W_WeaponFrame(Player actor, .entity weaponentity)
index 91879feb2a9a95548eb6008c500498bc79a07a09..986756aa510344405c4f27e9db7f9b57effef938 100644 (file)
@@ -23,6 +23,8 @@ void W_DropEvent(.void(Weapon, entity actor, .entity) event, entity player, floa
 
 void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sent_sound);
 
+void W_ResetGunAlign(entity player, int preferred_alignment);
+
 void W_WeaponFrame(Player actor, .entity weaponentity);
 
 float W_WeaponRateFactor(entity this);
index fe08cabdd7f7745fefed87e7defb92dcaa2306bb..e940811df04e2b6c5193a5fa346887ff3b8c5639 100644 (file)
@@ -735,7 +735,7 @@ seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_c
 seta cl_movement_errorcompensation 1 "try to compensate for prediction errors and reduce perceived lag"
 seta cl_movement_intermissionrunning 0 "keep velocity after the match ends, players may appear to continue running while stationary"
 
-seta cl_viewmodel_alpha 0 "Maximum transparency of the view model, set to 0 to disable"
+seta cl_viewmodel_alpha 1 "Maximum opacity of the view model, use a value between 0 and 1"
 
 set debugdraw 0
 set debugdraw_filter ""
index f44d9c96f969fa5853216a289a2d8c7e0bdeffb9..4fd0ee0c1488965a1eae4bd06164ab018a710b4e 100644 (file)
@@ -48,7 +48,7 @@ fs_empty_files_in_pack_mark_deletions 1 // makes patches able to delete files
 set g_campaign 0
 set g_campaign_forceteam 0 "Forces the player to a given team in campaign mode, 1 = red, 2 = blue, 3 = yellow, 4 = pink"
 seta g_campaign_name "xonoticbeta"
-seta g_campaign_skill -1 // -2 easy -1 medium 0 hard
+seta g_campaign_skill 0 // -2 easy, 0 medium, 2 hard
 
 alias singleplayer_start "g_campaign_index 0; set scmenu_campaign_goto 0"
 alias singleplayer_continue "set scmenu_campaign_goto -1"