]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/gamemode_composition 244/head
authorTimePath <andrew.hardaker1995@gmail.com>
Fri, 23 Oct 2015 03:57:11 +0000 (14:57 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Fri, 23 Oct 2015 03:57:11 +0000 (14:57 +1100)
# Conflicts:
# qcsrc/common/mapinfo.qh
# qcsrc/server/mutators/events.qh
# qcsrc/server/mutators/mutator/sandbox.qc

31 files changed:
defaultXonotic.cfg
qcsrc/client/hook.qc
qcsrc/common/mapinfo.qh
qcsrc/common/monsters/all.qh
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/target/music.qh
qcsrc/common/triggers/trigger/multi.qc
qcsrc/common/weapons/calculations.qc
qcsrc/common/weapons/calculations.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/lib/_all.inc
qcsrc/lib/linkedlist.qh [new file with mode: 0644]
qcsrc/lib/net.qh
qcsrc/menu/item/listbox.qc
qcsrc/menu/menu.qc
qcsrc/menu/xonotic/dialog_settings_game.qc
qcsrc/menu/xonotic/dialog_settings_game_model.qc
qcsrc/menu/xonotic/gametypelist.qc
qcsrc/menu/xonotic/slider.qc
qcsrc/menu/xonotic/textslider.qc
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/sandbox.qc
qcsrc/server/t_items.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh

index c972168b0dfacd1b87dc6e3fd4ceb066b0abf119..5bd49b8ff4af75e2ece339e0d1e1f7eafa2966da 100644 (file)
@@ -410,7 +410,6 @@ pausable 0
 set g_spawnshieldtime 1 "number of seconds you are invincible after you spawned, this shield is lost after you fire"
 set g_antilag 2        "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)"
 set g_antilag_nudge 0 "don't touch"
-set g_shootfromclient 2 "let client decide if it has the gun left or right; if set to 2, center handedness is allowed; see also cl_gunalign"
 set g_shootfromeye 0 "shots are fired from your eye/crosshair; visual gun position can still be influenced by cl_gunalign 1 and 2"
 set g_shootfromcenter 0 "weapon gets moved to the center, shots still come from the barrel of your weapon; visual gun position can still be influenced by cl_gunalign 1 and 2"
 set g_shootfromfixedorigin "" "if set to a string like 0 y z, the gun is moved to the given y and z coordinates. If set to a string like x y z, the whole shot origin is used"
index 3f623b276ed068bb3baeb4582680b37c495b0ea7..5b8d09312049202197e379e5cb616b504fb8892b 100644 (file)
@@ -31,7 +31,6 @@ void Draw_GrapplingHook(entity this)
        string tex;
        vector rgb;
        float t;
-       int s;
        vector vs;
        float intensity, offset;
 
@@ -44,10 +43,8 @@ void Draw_GrapplingHook(entity this)
 
        InterpolateOrigin_Do();
 
-       s = autocvar_cl_gunalign;
-       if(s != 1 && s != 2 && s != 4)
-               s = 3; // default value
-       --s;
+       int s = W_GetGunAlignment(world);
+
        switch(self.HookType)
        {
                default:
index 46019ff1f28dd31e46335523ae75d42472b0fb33..4107290fc0ee97d387b204e43795de8a6269eec5 100644 (file)
@@ -61,11 +61,11 @@ int MAPINFO_TYPE_ALL;
 #define IS_GAMETYPE(NAME) \
     (MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
 
-REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,false,"","timelimit=20 pointlimit=30 leadlimit=0",_("Score as many frags as you can."));
+REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,false,"","timelimit=20 pointlimit=30 leadlimit=0",_("Score as many frags as you can"));
 
-REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,false,"","timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left."));
+REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,false,"","timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
 
-REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,false,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line."))
+REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,false,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"))
 {
     if (!k) {
        cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit"));
@@ -82,7 +82,7 @@ REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,false,"","timelimit=20 qualifying_tim
 REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,false,"","timelimit=20",_("Race for fastest time."));
 #define g_cts IS_GAMETYPE(CTS)
 
-REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,true,"","timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team."))
+REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,true,"","timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team"))
 {
     if (!k) {
         cvar_set("g_tdm_teams", cvar_defstring("g_tdm_teams"));
@@ -96,10 +96,10 @@ REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,true,"","timeli
 }
 #define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH)
 
-REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team."));
+REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team"));
 #define g_ctf IS_GAMETYPE(CTF)
 
-REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round."))
+REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round"))
 {
     if (!k) {
         cvar_set("g_ca_teams", cvar_defstring("g_ca_teams"));
@@ -113,7 +113,7 @@ REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,true,"","timelimit=20 pointlimit=10
 }
 #define g_ca IS_GAMETYPE(CA)
 
-REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win."))
+REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win"))
 {
     if (!k) {
         cvar_set("g_domination_default_teams", cvar_defstring("g_domination_default_teams"));
@@ -126,7 +126,7 @@ REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,true,"","timelimit
     }
 }
 
-REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round."))
+REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"))
 {
     if (!k) {
        cvar_set("g_keyhunt_teams", cvar_defstring("g_keyhunt_teams"));
@@ -139,15 +139,15 @@ REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,true,"","timelimit=20 point
     }
 }
 
-REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,true,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out."));
+REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,true,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
 #define g_assault IS_GAMETYPE(ASSAULT)
 
-REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator."));
+REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
 
-REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean."));
+REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean"));
 #define g_nexball IS_GAMETYPE(NEXBALL)
 
-REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them, freeze the most enemies to win."))
+REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them, freeze the most enemies to win"))
 {
     if (!k) {
         cvar_set("g_freezetag_teams", cvar_defstring("g_freezetag_teams"));
@@ -161,9 +161,9 @@ REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,true,"","timelimit=20
 }
 #define g_freezetag IS_GAMETYPE(FREEZETAG)
 
-REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,true,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills."));
+REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,true,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
 
-REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,false,"","pointlimit=50 teams=0",_("Survive against waves of monsters."))
+REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,false,"","pointlimit=50 teams=0",_("Survive against waves of monsters"))
 {
     switch (k) {
         case "teams":
index 39a928a85749b98f4299e728d583f9d6e4aaa47c..05eb4346db90d2cf958358410ec2d02e5546879a 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "monster.qh"
 
-REGISTRY(Monsters, BIT(3))
+REGISTRY(Monsters, BIT(4))
 REGISTER_REGISTRY(RegisterMonsters)
 const int MON_FIRST = 1;
 #define MON_LAST (Monsters_COUNT - 1)
index 257de8be5708c52bf2a11e1410f7173a179fa53a..ebecb18e317e3da64b8999a4624914722d298a0a 100644 (file)
@@ -33,6 +33,17 @@ void target_music_reset()
        if(self.targetname == "")
                target_music_sendto(MSG_ALL, 1);
 }
+void target_music_kill()
+{
+       for(self = world; (self = find(self, classname, "target_music")); )
+       {
+               self.volume = 0;
+               if(self.targetname == "")
+                       target_music_sendto(MSG_ALL, 1);
+               else
+                       target_music_sendto(MSG_ALL, 0);
+       }
+}
 void target_music_use()
 {
        if(!activator)
index 712d412f6ac4b003daee36eca37de96aa33b804a..d46c460554c83d26829ecc0083cec760926017e4 100644 (file)
@@ -23,6 +23,9 @@ void Ent_TriggerMusic_Think();
 void Ent_TriggerMusic_Remove();
 
 void Ent_ReadTriggerMusic();
+
+#elif defined(SVQC)
+void target_music_kill();
 #endif
 
 #endif
index 3261520d7a19e951ebdd198c7293facdf38a1de0..bc5821c809383597f1b8d1d92b0fea2229b86436 100644 (file)
@@ -23,6 +23,10 @@ void multi_trigger()
                return;         // allready been triggered
        }
 
+       if(self.spawnflags & 16384)
+       if(!IS_PLAYER(self.enemy))
+               return; // only players
+
        if (self.classname == "trigger_secret")
        {
                if (!IS_PLAYER(self.enemy))
index 16b507d14eee683e65c13e28a42399efdd48054f..97c1999f84299fc98642f2c2597b84891f215cef 100644 (file)
@@ -142,6 +142,20 @@ vector findperpendicular(vector v)
        return normalize(cliptoplane(p, v));
 }
 
+int W_GetGunAlignment(entity player)
+{
+#ifdef SVQC
+       int gunalign = player.cvar_cl_gunalign;
+#else
+       int gunalign = autocvar_cl_gunalign;
+#endif
+       if(gunalign < 1 || gunalign > 4)
+               gunalign = 3; // default value
+       --gunalign;
+
+       return gunalign;
+}
+
 vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
 {
        float sigma;
index d91d22c67c2c0491c9da5bad2b5d2d09ad034aae..4feed9fc549e16a48d44c204435f4a83e21672d7 100644 (file)
@@ -2,4 +2,5 @@
 #define CALCULATIONS_H
 vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
 vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle);
+int W_GetGunAlignment(entity player);
 #endif
index 99eb17d031b89453a0d2da13ec56fd7fedb83702..8d8f4c43b47737354e23fe19c897d6916c75cedb 100644 (file)
@@ -1156,11 +1156,7 @@ void Ent_ReadArcBeam(float isnew)
 
        if(isnew)
        {
-               // calculate shot origin offset from gun alignment
-               int gunalign = autocvar_cl_gunalign;
-               if(gunalign != 1 && gunalign != 2 && gunalign != 4)
-                       gunalign = 3; // default value
-               --gunalign;
+               int gunalign = W_GetGunAlignment(world);
 
                self.beam_shotorigin = arc_shotorigin[gunalign];
 
index 49b8ef7798bccac4f833edb868f31cb79c7161fd..9bc9ca2aefdc29f1cd96ffa5d8cbb0af8497659e 100644 (file)
@@ -41,6 +41,7 @@
 #include "int.qh"
 #include "iter.qh"
 #include "lazy.qh"
+#include "linkedlist.qh"
 #include "log.qh"
 #include "math.qh"
 #include "misc.qh"
diff --git a/qcsrc/lib/linkedlist.qh b/qcsrc/lib/linkedlist.qh
new file mode 100644 (file)
index 0000000..be57bb5
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef LINKEDLIST_H
+#define LINKEDLIST_H
+
+CLASS(LinkedListNode, Object)
+    ATTRIB(LinkedListNode, ll_data, entity, NULL)
+    ATTRIB(LinkedListNode, ll_prev, LinkedListNode, NULL)
+    ATTRIB(LinkedListNode, ll_next, LinkedListNode, NULL)
+ENDCLASS(LinkedListNode)
+
+CLASS(LinkedList, Object)
+    ATTRIB(LinkedList, ll_head, LinkedListNode, NULL);
+    ATTRIB(LinkedList, ll_tail, LinkedListNode, NULL);
+ENDCLASS(LinkedList)
+
+#define LL_NEW() NEW(LinkedList)
+
+/**
+ * Push to tail
+ */
+entity LL_PUSH(LinkedList this, entity e) {
+    LinkedListNode n = NEW(LinkedListNode);
+    n.ll_data = e;
+    n.ll_prev = this.ll_tail;
+    LinkedListNode tail = this.ll_tail;
+    if (tail) {
+        tail.ll_next = n;
+    } else {
+        this.ll_head = this.ll_tail = n;
+    }
+    return e;
+}
+
+/**
+ * Pop from tail
+ */
+entity LL_POP(LinkedList this) {
+    if (!this.ll_tail) return NULL;
+    LinkedListNode n = this.ll_tail;
+    entity e = n.ll_data;
+    LinkedListNode prev = n.ll_prev;
+    if (prev) {
+        prev.ll_next = NULL;
+    } else {
+        this.ll_head = this.ll_tail = NULL;
+    }
+    return e;
+}
+
+#define LL_EACH(list, cond, body) do {                                  \
+    noref int i = 0;                                                    \
+    for (entity _it = list.ll_head; _it; (_it = _it.ll_next, ++i)) {    \
+        noref entity it = _it.ll_data;                                  \
+        if (cond) { body }                                              \
+    }                                                                   \
+} while(0)
+
+#endif
index 04faffc4a07ef4bc02178706186af916b735ed7e..834de760f503e8a2739b3b3bcda3b448bc811566 100644 (file)
@@ -11,9 +11,9 @@ bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, t
 
 void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
 {
-    if (!e.classname) e.classname = "net_linked";
+    if (e.classname == "") e.classname = "net_linked";
 
-    if (!e.model || !self.modelindex) {
+    if (e.model == "" || self.modelindex == 0) {
         vector mi = e.mins;
         vector ma = e.maxs;
         _setmodel(e, "null");
index 87f1719b4e14779f5abe809d1c39d8a9b1b52bd5..9210e14b384c90e262ece0be368b87e397cd1178 100644 (file)
@@ -14,6 +14,7 @@ CLASS(ListBox, Item)
        ATTRIB(ListBox, focusable, float, 1)
        ATTRIB(ListBox, focusedItem, int, -1)
        ATTRIB(ListBox, focusedItemAlpha, float, 0.3)
+       METHOD(ListBox, setFocusedItem, void(entity, int));
        ATTRIB(ListBox, mouseMoveOffset, float, -1) // let know where the cursor is when the list scrolls without moving the cursor
        ATTRIB(ListBox, allowFocusSound, float, 1)
        ATTRIB(ListBox, selectedItem, int, 0)
@@ -21,6 +22,7 @@ CLASS(ListBox, Item)
        ATTRIB(ListBox, origin, vector, '0 0 0')
        ATTRIB(ListBox, scrollPos, float, 0) // measured in window heights, fixed when needed
        ATTRIB(ListBox, scrollPosTarget, float, 0)
+       METHOD(ListBox, isScrolling, bool(entity));
        ATTRIB(ListBox, needScrollToItem, float, -1)
        METHOD(ListBox, scrollToItem, void(entity, int));
        ATTRIB(ListBox, previousValue, float, 0)
@@ -53,6 +55,7 @@ CLASS(ListBox, Item)
        METHOD(ListBox, clickListBoxItem, void(entity, float, vector)); // item number, relative clickpos
        METHOD(ListBox, doubleClickListBoxItem, void(entity, float, vector)); // item number, relative clickpos
        METHOD(ListBox, setSelected, void(entity, float));
+       METHOD(ListBox, focusedItemChangeNotify, void(entity));
 
        METHOD(ListBox, getLastFullyVisibleItemAtScrollPos, float(entity, float));
        METHOD(ListBox, getFirstFullyVisibleItemAtScrollPos, float(entity, float));
@@ -84,6 +87,11 @@ ENDCLASS(ListBox)
 #endif
 
 #ifdef IMPLEMENTATION
+bool ListBox_isScrolling(entity me)
+{
+       return (me.scrollPos != me.scrollPosTarget);
+}
+
 void ListBox_scrollToItem(entity me, int i)
 {
        // scroll doesn't work properly until itemHeight is set to the correct value
@@ -163,7 +171,7 @@ float ListBox_keyDown(entity me, float key, float ascii, float shift)
        }
        else if(key == K_MWHEELDOWN)
        {
-               me.scrollPosTarget = min(me.scrollPosTarget + 0.5, me.getTotalHeight(me) - 1);
+               me.scrollPosTarget = min(me.scrollPosTarget + 0.5, max(0, me.getTotalHeight(me) - 1));
        }
        else if(key == K_PGUP || key == K_KP_PGUP)
        {
@@ -246,7 +254,7 @@ float ListBox_mouseMove(entity me, vector pos)
                me.mouseMoveOffset = pos.y;
        else
        {
-               me.focusedItem = -1;
+               me.setFocusedItem(me, -1);
                me.mouseMoveOffset = -1;
        }
        return 1;
@@ -278,7 +286,7 @@ float ListBox_mouseDrag(entity me, vector pos)
        else if(me.pressed == 2)
        {
                me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos.y));
-               me.focusedItem = me.selectedItem;
+               me.setFocusedItem(me, me.selectedItem);
                me.mouseMoveOffset = -1;
        }
        return 1;
@@ -317,10 +325,21 @@ float ListBox_mousePress(entity me, vector pos)
                me.pressed = 2;
                // an item has been clicked. Select it, ...
                me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos.y));
-               me.focusedItem = me.selectedItem;
+               me.setFocusedItem(me, me.selectedItem);
        }
        return 1;
 }
+void ListBox_setFocusedItem(entity me, int item)
+{
+       float focusedItem_save = me.focusedItem;
+       me.focusedItem = (item < me.nItems) ? item : -1;
+       if(focusedItem_save != me.focusedItem)
+       {
+               me.focusedItemChangeNotify(me);
+               if(me.focusedItem >= 0)
+                       me.focusedItemAlpha = SKINALPHA_LISTBOX_FOCUSED;
+       }
+}
 float ListBox_mouseRelease(entity me, vector pos)
 {
        if(me.pressed == 1)
@@ -334,7 +353,7 @@ float ListBox_mouseRelease(entity me, vector pos)
                // item dragging mode
                // select current one one last time...
                me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos.y));
-               me.focusedItem = me.selectedItem;
+               me.setFocusedItem(me, me.selectedItem);
                // and give it a nice click event
                if(me.nItems > 0)
                {
@@ -358,7 +377,7 @@ void ListBox_focusLeave(entity me)
        // by a mouse click on an item of the list
        // for example showing a dialog on right click
        me.pressed = 0;
-       me.focusedItem = -1;
+       me.setFocusedItem(me, -1);
        me.mouseMoveOffset = -1;
 }
 void ListBox_updateControlTopBottom(entity me)
@@ -407,12 +426,8 @@ void ListBox_draw(entity me)
        vector oldshift, oldscale;
 
        // we can't do this in mouseMove as the list can scroll without moving the cursor
-       float focusedItem_save = me.focusedItem;
        if(me.mouseMoveOffset != -1)
-               me.focusedItem = me.getItemAtPos(me, me.scrollPos + me.mouseMoveOffset);
-       if(me.focusedItem >= 0)
-       if(focusedItem_save != me.focusedItem)
-               me.focusedItemAlpha = SKINALPHA_LISTBOX_FOCUSED;
+               me.setFocusedItem(me, me.getItemAtPos(me, me.scrollPos + me.mouseMoveOffset));
 
        if(me.needScrollToItem >= 0)
        {
@@ -476,6 +491,10 @@ void ListBox_draw(entity me)
        SUPER(ListBox).draw(me);
 }
 
+void ListBox_focusedItemChangeNotify(entity me)
+{
+}
+
 void ListBox_clickListBoxItem(entity me, float i, vector where)
 {
        // template method
index 06722c7a3142978ef4457cc281784e563373fced..13d8fcd49ef2d1b154b544ad02c0d09f344b29f8 100644 (file)
@@ -408,7 +408,7 @@ vector menuTooltipOrigin;
 vector menuTooltipSize;
 float menuTooltipAlpha;
 string menuTooltipText;
-float menuTooltipState; // 0: static, 1: fading in, 2: fading out
+float menuTooltipState; // 0: static, 1: fading in, 2: fading out, 3: forced fading out
 float m_testmousetooltipbox(vector pos)
 {
        if(pos.x >= menuTooltipOrigin.x && pos.x < menuTooltipOrigin.x + menuTooltipSize.x)
@@ -535,6 +535,7 @@ string gettooltip()
        }
        return menuTooltipItem.tooltip;
 }
+string prev_tooltip;
 void m_tooltip(vector pos)
 {
        float f, i, w;
@@ -557,13 +558,30 @@ void m_tooltip(vector pos)
                menuTooltipAveragedMousePos = menuTooltipAveragedMousePos * (1 - f) + pos * f;
                f = vlen(pos - menuTooltipAveragedMousePos);
                if(f < 0.01)
+               {
                        it = m_findtooltipitem(main, pos);
+
+                       if(it.instanceOfListBox && it.isScrolling(it))
+                               it = world;
+
+                       if(it && prev_tooltip != it.tooltip)
+                       {
+                               // fade out if tooltip of a certain item has changed
+                               menuTooltipState = 3;
+                               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
                        it = NULL;
        }
        fontsize = '1 0 0' * (SKINFONTSIZE_TOOLTIP / conwidth) + '0 1 0' * (SKINFONTSIZE_TOOLTIP / conheight);
 
-       // float menuTooltipState; // 0: static, 1: fading in, 2: fading out
+       // float menuTooltipState; // 0: static, 1: fading in, 2: fading out, 3: forced fading out
        if(it != menuTooltipItem)
        {
                switch(menuTooltipState)
@@ -614,18 +632,15 @@ void m_tooltip(vector pos)
        else if(menuTooltipState == 2) // re-fade in?
                menuTooltipState = 1;
 
-       if(menuTooltipItem)
-               if(!m_testmousetooltipbox(pos))
-                       menuTooltipState = 2; // fade out if mouse touches it
-
        switch(menuTooltipState)
        {
-               case 1:
+               case 1: // fade in
                        menuTooltipAlpha = bound(0, menuTooltipAlpha + 5 * frametime, 1);
                        if(menuTooltipAlpha == 1)
                                menuTooltipState = 0;
                        break;
-               case 2:
+               case 2: // fade out
+               case 3: // forced fade out
                        menuTooltipAlpha = bound(0, menuTooltipAlpha - 2 * frametime, 1);
                        if(menuTooltipAlpha == 0)
                        {
index 69ab6758226e19356fd8d9cd459c93dcd5f6ebe7..3c1503b29774472af5b256b37930c7736c454d81 100644 (file)
@@ -12,6 +12,13 @@ CLASS(SettingSource, DataSource)
         if (returns) returns(it.title, string_null);
         return it;
     }
+    METHOD(SettingSource, getEntryTooltip, entity(entity this, int i, void(string theTooltip) returns))
+    {
+        Lazy l = Settings[i];
+        entity it = l.m_get();
+        if (returns) returns(it.tooltip);
+        return it;
+    }
     METHOD(SettingSource, reload, int(entity this, string filter)) { return Settings_COUNT; }
 ENDCLASS(SettingSource)
 
@@ -30,15 +37,23 @@ CLASS(XonoticRegisteredSettingsList, XonoticListBox)
     ATTRIB(XonoticRegisteredSettingsList, source, DataSource, NULL)
        ATTRIB(XonoticRegisteredSettingsList, onChange, void(entity, entity), func_null)
        ATTRIB(XonoticRegisteredSettingsList, onChangeEntity, entity, NULL)
+       METHOD(XonoticRegisteredSettingsList, focusedItemChangeNotify, void(entity));
+
        string XonoticRegisteredSettingsList_cb_name;
-       void XonoticRegisteredSettingsList_cb(string _name, string _icon)
+       string XonoticRegisteredSettingsList_cb_tooltip;
+       void XonoticRegisteredSettingsList_getNameIcon_cb(string _name, string _icon)
        {
                XonoticRegisteredSettingsList_cb_name = _name;
        }
+       void XonoticRegisteredSettingsList_getTooltip_cb(string _tooltip)
+       {
+               XonoticRegisteredSettingsList_cb_tooltip = _tooltip;
+       }
+
        METHOD(XonoticRegisteredSettingsList, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused))
        {
                if (!this.source) return;
-               if (!this.source.getEntry(this.source, i, XonoticRegisteredSettingsList_cb)) return;
+               if (!this.source.getEntry(this.source, i, XonoticRegisteredSettingsList_getNameIcon_cb)) return;
                string name = XonoticRegisteredSettingsList_cb_name;
                if (isSelected) {
                        draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
@@ -49,6 +64,26 @@ CLASS(XonoticRegisteredSettingsList, XonoticListBox)
                string s = draw_TextShortenToWidth(strdecolorize(name), 1, 0, this.realFontSize);
                draw_Text(this.realUpperMargin * eY + (0.5 * this.realFontSize.x) * eX, s, this.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
        }
+
+       METHOD(XonoticRegisteredSettingsList, focusedItemChangeNotify, void(entity this))
+       {
+               if (this.focusedItem == -1 || !this.source)
+               {
+                       clearTooltip(this);
+                       return;
+               }
+               if (!this.source.getEntryTooltip(this, this.focusedItem, XonoticRegisteredSettingsList_getTooltip_cb))
+               {
+                       clearTooltip(this);
+                       return;
+               }
+               string theTooltip = XonoticRegisteredSettingsList_cb_tooltip;
+               if(theTooltip != "")
+                       setZonedTooltip(this, theTooltip, string_null);
+               else
+                       clearTooltip(this);
+       }
+
        METHOD(XonoticRegisteredSettingsList, refilter, void(entity this))
        {
                if (!this.source) {
index 7b0794bdd782e671c84693eb6b60b715dbba2b48..45d7aee3048bd743f2cf018cd64d5643b3ec1859 100644 (file)
@@ -5,6 +5,7 @@ CLASS(XonoticGameModelSettingsTab, XonoticTab)
        METHOD(XonoticGameModelSettingsTab, fill, void(entity));
        METHOD(XonoticGameModelSettingsTab, showNotify, void(entity));
        ATTRIB(XonoticGameModelSettingsTab, title, string, _("Models"))
+       ATTRIB(XonoticGameModelSettingsTab, tooltip, string, _("Customize how players and items are displayed in game"))
        ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameModelSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameModelSettingsTab, columns, float, 5)
index e2fdfa8e72b60e52881c621e77f57379080c5c99..5522e13c7f75f4fd81302e3af353c5f94e370a44 100644 (file)
@@ -11,6 +11,7 @@ CLASS(XonoticGametypeList, XonoticListBox)
        METHOD(XonoticGametypeList, saveCvars, void(entity));
        METHOD(XonoticGametypeList, keyDown, float(entity, float, float, float));
        METHOD(XonoticGametypeList, clickListBoxItem, void(entity, float, vector));
+       METHOD(XonoticGametypeList, focusedItemChangeNotify, void(entity));
 
        ATTRIB(XonoticGametypeList, realFontSize, vector, '0 0 0')
        ATTRIB(XonoticGametypeList, realUpperMargin, float, 0)
@@ -137,4 +138,11 @@ void XonoticGametypeList_clickListBoxItem(entity me, float i, vector where)
 {
        m_play_click_sound(MENU_SOUND_SELECT);
 }
+void XonoticGametypeList_focusedItemChangeNotify(entity me)
+{
+       if(me.focusedItem >= 0)
+               setZonedTooltip(me, MapInfo_Type_Description(GameType_GetID(me.focusedItem)), string_null);
+       else
+               clearTooltip(me);
+}
 #endif
index 7ecd7a9d0a4e6a03ead4ee4e262ddaea22136813..2b0bd6ce0ac6343140b40783b3ee4e6f7f62a9b6 100644 (file)
@@ -4,6 +4,7 @@
 CLASS(XonoticSlider, Slider)
        METHOD(XonoticSlider, configureXonoticSlider, void(entity, float, float, float, string, string));
        METHOD(XonoticSlider, setValue, void(entity, float));
+       METHOD(XonoticSlider, setValue_noAnim, void(entity, float));
        ATTRIB(XonoticSlider, fontSize, float, SKINFONTSIZE_NORMAL)
        ATTRIB(XonoticSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT)
        ATTRIB(XonoticSlider, image, string, SKINGFX_SLIDER)
@@ -66,6 +67,14 @@ void XonoticSlider_setValue(entity me, float val)
                me.saveCvars(me);
        }
 }
+void XonoticSlider_setValue_noAnim(entity me, float val)
+{
+       if(val != me.value)
+       {
+               SUPER(XonoticSlider).setValue_noAnim(me, val);
+               me.saveCvars(me);
+       }
+}
 void XonoticSlider_loadCvars(entity me)
 {
        if (!me.cvarName)
index 8c4682ee0ffbf9a25d5692bdd18ed1c267014777..c21b07734fcd8c10749969a1972e2a8017d44a1b 100644 (file)
@@ -4,6 +4,7 @@
 CLASS(XonoticTextSlider, TextSlider)
        METHOD(XonoticTextSlider, configureXonoticTextSlider, void(entity, string, string));
        METHOD(XonoticTextSlider, setValue, void(entity, float));
+       METHOD(XonoticTextSlider, setValue_noAnim, void(entity, float));
        METHOD(XonoticTextSlider, configureXonoticTextSliderValues, void(entity));
        ATTRIB(XonoticTextSlider, fontSize, float, SKINFONTSIZE_NORMAL)
        ATTRIB(XonoticTextSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT)
@@ -55,6 +56,14 @@ void XonoticTextSlider_setValue(entity me, float val)
                me.saveCvars(me);
        }
 }
+void XonoticTextSlider_setValue_noAnim(entity me, float val)
+{
+       if(val != me.value)
+       {
+               SUPER(XonoticTextSlider).setValue_noAnim(me, val);
+               me.saveCvars(me);
+       }
+}
 void XonoticTextSlider_loadCvars(entity me)
 {
        if (!me.cvarName)
index 912bd49ded78ab410ee181349999499b6b6d7118..d3c9007f33c5896b2ab8360e3ae786ad56e44d75 100644 (file)
@@ -295,7 +295,6 @@ float autocvar_g_respawn_ghosts_speed;
 int autocvar_g_respawn_waves;
 bool autocvar_g_running_guns;
 bool autocvar_g_shootfromcenter;
-int autocvar_g_shootfromclient;
 bool autocvar_g_shootfromeye;
 string autocvar_g_shootfromfixedorigin;
 int autocvar_g_showweaponspawns;
index 5089b7a12a48d1abd12315f60519d96a7d5b1846..c4b078e14888a82fc1311584f3be5bd064bc7e0f 100644 (file)
@@ -749,6 +749,8 @@ void SetNewParms (void)
 {
        // initialize parms for a new player
        parm1 = -(86400 * 366);
+
+       MUTATOR_CALLHOOK(SetNewParms);
 }
 
 /*
@@ -760,6 +762,8 @@ void SetChangeParms (void)
 {SELFPARAM();
        // save parms for level change
        parm1 = self.parm_idlesince - time;
+
+       MUTATOR_CALLHOOK(SetChangeParms);
 }
 
 /*
@@ -776,6 +780,8 @@ void DecodeLevelParms (void)
 
        // whatever happens, allow 60 seconds of idling directly after connect for map loading
        self.parm_idlesince = max(self.parm_idlesince, time - sv_maxidle + 60);
+
+       MUTATOR_CALLHOOK(DecodeLevelParms);
 }
 
 /*
index 7a77d4aff695a0a1fbfdb50ef10a838223c6d77c..f95115a2ca465a8f8fbe01679da18eed973229a6 100644 (file)
@@ -151,10 +151,7 @@ void GrapplingHookThink()
 
        self.nextthink = time;
 
-       int s = self.realowner.cvar_cl_gunalign;
-       if(s != 1 && s != 2 && s != 4)
-               s = 3; // default value
-       --s;
+       int s = W_GetGunAlignment(self.realowner);
        vs = hook_shotorigin[s];
 
        makevectors(self.realowner.v_angle);
@@ -353,10 +350,7 @@ void FireGrapplingHook (void)
 
        makevectors(self.v_angle);
 
-       int s = self.cvar_cl_gunalign;
-       if(s != 1 && s != 2 && s != 4)
-               s = 3; // default value
-       --s;
+       int s = W_GetGunAlignment(self);
        vs = hook_shotorigin[s];
 
        // UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
index 06913e06aad7c37a7812124b6495d15a7157cde7..c3932f3fb8062a3d254507537dfff60db4c30ff1 100644 (file)
@@ -31,6 +31,7 @@
 #include "../common/stats.qh"
 #include "../common/teams.qh"
 #include "../common/triggers/trigger/secret.qh"
+#include "../common/triggers/target/music.qh"
 #include "../common/util.qh"
 #include "../common/items/all.qh"
 #include "../common/weapons/all.qh"
@@ -1548,6 +1549,10 @@ void NextLevel()
                        bprint(other.netname, " ^7wins.\n");
        }
 
+       entity oldself = self;
+       target_music_kill();
+       self = oldself;
+
        if(autocvar_g_campaign)
                CampaignPreIntermission();
 
index 95133eb2e4b591d4b8ba6861aa262b08e90f096b..3a4680ebb94366867b11d1c9c11829e055302eec 100644 (file)
@@ -1521,94 +1521,6 @@ void write_recordmarker(entity pl, float tstart, float dt)
                  " ", ftos(tstart), " ", ftos(dt), "\n"));
 }
 
-vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter, float algn)
-{
-       switch(algn)
-       {
-               default:
-               case 3: // right
-                       break;
-
-               case 4: // left
-                       vecs.y = -vecs.y;
-                       break;
-
-               case 1:
-                       if(allowcenter) // 2: allow center handedness
-                       {
-                               // center
-                               vecs.y = 0;
-                               vecs.z -= 2;
-                       }
-                       else
-                       {
-                               // right
-                       }
-                       break;
-
-               case 2:
-                       if(allowcenter) // 2: allow center handedness
-                       {
-                               // center
-                               vecs.y = 0;
-                               vecs.z -= 2;
-                       }
-                       else
-                       {
-                               // left
-                               vecs.y = -vecs.y;
-                       }
-                       break;
-       }
-       return vecs;
-}
-
-vector shotorg_adjust_values(vector vecs, float y_is_right, float visual, float algn)
-{
-       string s;
-       vector v;
-
-       if (autocvar_g_shootfromeye)
-       {
-               if (visual)
-               {
-                       if (autocvar_g_shootfromclient) { vecs = shotorg_adjustfromclient(vecs, y_is_right, (autocvar_g_shootfromclient >= 2), algn); }
-                       else { vecs.y = 0; vecs.z -= 2; }
-               }
-               else
-               {
-                       vecs.y = 0;
-                       vecs.z = 0;
-               }
-       }
-       else if (autocvar_g_shootfromcenter)
-       {
-               vecs.y = 0;
-               vecs.z -= 2;
-       }
-       else if ((s = autocvar_g_shootfromfixedorigin) != "")
-       {
-               v = stov(s);
-               if (y_is_right)
-                       v.y = -v.y;
-               if (v.x != 0)
-                       vecs.x = v.x;
-               vecs.y = v.y;
-               vecs.z = v.z;
-       }
-       else if (autocvar_g_shootfromclient)
-       {
-               vecs = shotorg_adjustfromclient(vecs, y_is_right, (autocvar_g_shootfromclient >= 2), algn);
-       }
-       return vecs;
-}
-
-vector shotorg_adjust(vector vecs, float y_is_right, float visual)
-{SELFPARAM();
-       return shotorg_adjust_values(vecs, y_is_right, visual, self.owner.cvar_cl_gunalign);
-}
-
-
 void attach_sameorigin(entity e, entity to, string tag)
 {
     vector org, t_forward, t_left, t_up, e_forward, e_up;
index 050da2bc08b9af97fbcab4c1b0e953f00cd7839a..c61e505e91a4be949255b0decfa43d6c8f01b7f0 100644 (file)
@@ -64,8 +64,6 @@ void stopsoundto(float _dest, entity e, float chan);
 void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float _atten);
 float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d);
 
-vector shotorg_adjust(vector vecs, float y_is_right, float visual);
-
 float DistributeEvenly_amount;
 float DistributeEvenly_totalweight;
 void objerror(string s);
@@ -118,8 +116,6 @@ void remove_unsafely(entity e);
 
 void SetMovetypeFollow(entity ent, entity e);
 
-vector shotorg_adjust_values(vector vecs, float y_is_right, float visual, float algn);
-
 void soundto(float dest, entity e, float chan, string samp, float vol, float atten);
 
 void stopsound(entity e, float chan);
index 52a1aa351165d20d73ba0be9d96f1c21227b8689..d5a842a6ef301114723b687bbb8c636b0318a4c3 100644 (file)
@@ -641,6 +641,12 @@ MUTATOR_HOOKABLE(BuffModel_Customize, EV_BuffModel_Customize);
     /**/
 MUTATOR_HOOKABLE(BuffTouch, EV_BuffTouch);
 
+MUTATOR_HOOKABLE(SetNewParms, EV_NO_ARGS);
+
+MUTATOR_HOOKABLE(SetChangeParms, EV_NO_ARGS);
+
+MUTATOR_HOOKABLE(DecodeLevelParms, EV_NO_ARGS);
+
 #define EV_GetRecords(i, o) \
     /**/ i(int, record_page) \
     /**/ i(string, ret_string) \
index caa87a0bb20063fc23f4c575d4311894c6d45d11..dbee6a1375750a94f5cfe2cd99e4ec38d7c9147b 100644 (file)
@@ -825,10 +825,4 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_StartFrame)
 
        return true;
 }
-
-MUTATOR_HOOKFUNCTION(sandbox, SetModname)
-{
-       modname = "Sandbox";
-       return true;
-}
 #endif
index 8cde49cbd5bff4e3176db1dab2f7d279ad398e0e..cb76f97f9a9a730cd9f750a3889a68d388ead5e4 100644 (file)
@@ -574,7 +574,7 @@ float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax
 
        if (item.spawnshieldtime)
        {
-               if ((player.(ammotype) < ammomax) || item.pickup_anyway)
+               if ((player.(ammotype) < ammomax) || item.pickup_anyway > 0)
                {
                        player.(ammotype) = bound(player.(ammotype), ammomax, player.(ammotype) + item.(ammotype));
                        goto YEAH;
@@ -645,7 +645,7 @@ float Item_GiveTo(entity item, entity player)
                it = item.weapons;
                it &= ~player.weapons;
 
-               if (it || (item.spawnshieldtime && item.pickup_anyway))
+               if (it || (item.spawnshieldtime && item.pickup_anyway > 0))
                {
                        pickedup = true;
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
@@ -1070,12 +1070,12 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                // it's a level item
                if(self.spawnflags & 1)
                        self.noalign = 1;
-               if (self.noalign)
+               if (self.noalign > 0)
                        self.movetype = MOVETYPE_NONE;
                else
                        self.movetype = MOVETYPE_TOSS;
                // do item filtering according to game mode and other things
-               if (!self.noalign)
+               if (self.noalign <= 0)
                {
                        // first nudge it off the floor a little bit to avoid math errors
                        setorigin(self, self.origin + '0 0 1');
@@ -1086,7 +1086,8 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                                setsize (self, '-16 -16 0', '16 16 32');
                        self.SendFlags |= ISF_SIZE;
                        // note droptofloor returns false if stuck/or would fall too far
-                       droptofloor();
+                       if(!self.noalign)
+                               droptofloor();
                        waypoint_spawnforitem(self);
                }
 
@@ -1154,11 +1155,14 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 
        self.SendFlags |= ISF_SIZE;
 
-       if(itemflags & FL_POWERUP)
-               self.ItemStatus |= ITS_ANIMATE1;
+       if(!(self.spawnflags & 1024))
+       {
+               if(itemflags & FL_POWERUP)
+                       self.ItemStatus |= ITS_ANIMATE1;
 
-       if(self.armorvalue || self.health)
-               self.ItemStatus |= ITS_ANIMATE2;
+               if(self.armorvalue || self.health)
+                       self.ItemStatus |= ITS_ANIMATE2;
+       }
 
        if(itemflags & FL_WEAPON)
        {
@@ -1167,7 +1171,8 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                else
                        self.gravity = 1;
 
-               self.ItemStatus |= ITS_ANIMATE1;
+               if(!(self.spawnflags & 1024))
+                       self.ItemStatus |= ITS_ANIMATE1;
                self.ItemStatus |= ISF_COLORMAP;
        }
 
index 8b0997bec52564435ffe67c067f06211c0c95e91..7fa14508688cc50ba50803fbd22e87d98b0a67b4 100644 (file)
 #include "../../common/weapons/all.qh"
 #include "../../lib/csqcmodel/sv_model.qh"
 
-/*
-===========================================================================
+vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
+{
+       switch(algn)
+       {
+               default: case 3: break; // right alignment
+               case 4: vecs.y = -vecs.y; break; // left
+               case 1: case 2: vecs.y = 0; vecs.z -= 2; break; // center
+       }
+
+       return vecs;
+}
+
+vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
+{
+       string s;
 
-  CLIENT WEAPONSYSTEM CODE
-  Bring back W_Weaponframe
+       if(visual)
+               vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
+       else if(autocvar_g_shootfromeye)
+               vecs.y = vecs.z = 0;
+       else if(autocvar_g_shootfromcenter)
+       {
+               vecs.y = 0;
+               vecs.z -= 2;
+       }
+       else if((s = autocvar_g_shootfromfixedorigin) != "")
+       {
+               vector v = stov(s);
+               if(y_is_right) { v.y = -v.y; }
+               if(v.x != 0) { vecs.x = v.x; }
+               vecs.y = v.y;
+               vecs.z = v.z;
+       }
+       else // just do the same as top
+               vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
 
-===========================================================================
-*/
+       return vecs;
+}
+
+vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn)
+{
+       return shotorg_adjust_values(vecs, y_is_right, visual, algn);
+}
 
 .int state;
 
@@ -254,8 +289,8 @@ void CL_WeaponEntity_SetModel(string name)
        {
                vector v0;
                v0 = self.movedir;
-               self.movedir = shotorg_adjust(v0, false, false);
-               self.view_ofs = shotorg_adjust(v0, false, true) - v0;
+               self.movedir = shotorg_adjust(v0, false, false, self.owner.cvar_cl_gunalign);
+               self.view_ofs = shotorg_adjust(v0, false, true, self.owner.cvar_cl_gunalign) - v0;
        }
        self.owner.stat_shotorg = compressShotOrigin(self.movedir);
        self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly
index e1fc0922d62f53d50ce4b99fbe436b82b1bd20e7..86d31119568c33f7518bfbb7cc01c176f1acc8a5 100644 (file)
@@ -14,6 +14,10 @@ const float WFRAME_FIRE2 = 1;
 const float WFRAME_IDLE = 2;
 const float WFRAME_RELOAD = 3;
 
+vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn);
+
+vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
+
 void CL_SpawnWeaponentity(entity e);
 
 vector CL_Weapon_GetShotOrg(float wpn);