]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Rough support for animated models as a separate optional model (and client side weapo...
authorMario <mario@smbclan.net>
Mon, 3 Jul 2017 14:35:22 +0000 (00:35 +1000)
committerMario <mario@smbclan.net>
Mon, 3 Jul 2017 14:35:22 +0000 (00:35 +1000)
12 files changed:
defaultXonotic.cfg
models/weapons/h_gl_animated.iqm [new file with mode: 0644]
models/weapons/h_gl_animated.iqm.framegroups [new file with mode: 0644]
models/weapons/h_rl_animated.iqm [new file with mode: 0644]
models/weapons/h_rl_animated.iqm.framegroups [new file with mode: 0644]
models/weapons/v_gl_animated.md3 [new file with mode: 0644]
models/weapons/v_rl_animated.md3 [new file with mode: 0644]
qcsrc/client/autocvars.qh
qcsrc/common/models/all.inc
qcsrc/common/models/model.qh
qcsrc/common/weapons/all.qc
qcsrc/server/weapons/weaponsystem.qc

index f2a6a201237ff547f7c6b245444c8d5a7cd8f4e8..77f9f2fb11a76f11fc4a8e3935bef3a0ec4a646d 100644 (file)
@@ -1074,6 +1074,8 @@ seta cl_weaponpriority8 ""
 seta cl_weaponpriority9 ""                                                              "use weapon_priority_9_prev for prev gun from this list, weapon_priority_9_best for best gun, weapon_priority_9_next for next gun"
 seta cl_weaponimpulsemode 0 "0: only cycle between currently usable weapons in weapon priority order; 1: cycle between all possible weapons on a key in weapon priority order"
 
+seta cl_weapons_animate 0 "Use animated weapon models"
+
 set g_maplist_allow_hidden 0           "allow hidden maps to be, e.g., voted for and in the maplist"
 set g_maplist_allow_frustrating 0      "allow impossible maps to be, e.g., voted for and in the maplist (if set to 2, ONLY impossible maps are allowed)"
 
diff --git a/models/weapons/h_gl_animated.iqm b/models/weapons/h_gl_animated.iqm
new file mode 100644 (file)
index 0000000..63f514b
Binary files /dev/null and b/models/weapons/h_gl_animated.iqm differ
diff --git a/models/weapons/h_gl_animated.iqm.framegroups b/models/weapons/h_gl_animated.iqm.framegroups
new file mode 100644 (file)
index 0000000..c7e79a9
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+Generated framegroups file for h_gl
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 25 30 0 // h_gl fire
+26 25 30 0 // h_gl fire
+51 101 3 1 // h_gl idle
+152 101 3 1 // h_gl idle
diff --git a/models/weapons/h_rl_animated.iqm b/models/weapons/h_rl_animated.iqm
new file mode 100644 (file)
index 0000000..1868b2c
Binary files /dev/null and b/models/weapons/h_rl_animated.iqm differ
diff --git a/models/weapons/h_rl_animated.iqm.framegroups b/models/weapons/h_rl_animated.iqm.framegroups
new file mode 100644 (file)
index 0000000..c4f4127
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+Generated framegroups file for h_rl
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 31 30 0 // h_rl fire
+32 31 30 0 // h_rl fire
+63 101 3 1 // h_rl idle
+164 101 3 1 // h_rl idle
diff --git a/models/weapons/v_gl_animated.md3 b/models/weapons/v_gl_animated.md3
new file mode 100644 (file)
index 0000000..970ca86
Binary files /dev/null and b/models/weapons/v_gl_animated.md3 differ
diff --git a/models/weapons/v_rl_animated.md3 b/models/weapons/v_rl_animated.md3
new file mode 100644 (file)
index 0000000..534e616
Binary files /dev/null and b/models/weapons/v_rl_animated.md3 differ
index d95958392bb9626e2cadba13cd6edf88394bdb98..9af6f0e283fdedb47f7ee8786cea0122616313a6 100644 (file)
@@ -445,3 +445,4 @@ float autocvar_g_jetpack_attenuation;
 bool autocvar_cl_showspectators;
 int autocvar_cl_nade_timer;
 bool autocvar_r_drawviewmodel;
+bool autocvar_cl_weapons_animate;
index f47d8e7c5afdd76ea2ce79630d28a11e4ee608e6..dc2f94ea6c16db3ec538c2abfe5b992a341054c8 100644 (file)
@@ -156,109 +156,157 @@ MODEL(CASING_BULLET,                    "models/casing_bronze.iqm");
 MODEL(BUFF,                             "models/relics/relic.md3");
 
 MODEL(BLASTER_VIEW,                     W_Model("h_laser.iqm"));
+MODEL(BLASTER_VIEW_ANIMATED,            W_Model("h_laser_animated.iqm"));
 MODEL(BLASTER_WORLD,                    W_Model("v_laser.md3"));
+MODEL(BLASTER_WORLD_ANIMATED,           W_Model("v_laser_animated.md3"));
 MODEL(BLASTER_ITEM,                     W_Model("g_laser.md3"));
 
 MODEL(SHOTGUN_MUZZLEFLASH,              "models/uziflash.md3");
 MODEL(SHOTGUN_VIEW,                     W_Model("h_shotgun.iqm"));
+MODEL(SHOTGUN_VIEW_ANIMATED,            W_Model("h_shotgun_animated.iqm"));
 MODEL(SHOTGUN_WORLD,                    W_Model("v_shotgun.md3"));
+MODEL(SHOTGUN_WORLD_ANIMATED,           W_Model("v_shotgun_animated.md3"));
 MODEL(SHOTGUN_ITEM,                     W_Model("g_shotgun.md3"));
 
 MODEL(MACHINEGUN_MUZZLEFLASH,           "models/uziflash.md3");
 MODEL(MACHINEGUN_VIEW,                  W_Model("h_uzi.iqm"));
+MODEL(MACHINEGUN_VIEW_ANIMATED,         W_Model("h_uzi_animated.iqm"));
 MODEL(MACHINEGUN_WORLD,                 W_Model("v_uzi.md3"));
+MODEL(MACHINEGUN_WORLD_ANIMATED,        W_Model("v_uzi_animated.md3"));
 MODEL(MACHINEGUN_ITEM,                  W_Model("g_uzi.md3"));
 
 MODEL(MORTAR_VIEW,                      W_Model("h_gl.iqm"));
+MODEL(MORTAR_VIEW_ANIMATED,             W_Model("h_gl_animated.iqm"));
 MODEL(MORTAR_WORLD,                     W_Model("v_gl.md3"));
+MODEL(MORTAR_WORLD_ANIMATED,            W_Model("v_gl_animated.md3"));
 MODEL(MORTAR_ITEM,                      W_Model("g_gl.md3"));
 
 MODEL(MINELAYER_MUZZLEFLASH,            "models/flash.md3");
 MODEL(MINELAYER_MINE,                   "models/mine.md3");
 MODEL(MINELAYER_VIEW,                   W_Model("h_minelayer.iqm"));
+MODEL(MINELAYER_VIEW_ANIMATED,          W_Model("h_minelayer_animated.iqm"));
 MODEL(MINELAYER_WORLD,                  W_Model("v_minelayer.md3"));
+MODEL(MINELAYER_WORLD_ANIMATED,         W_Model("v_minelayer_animated.md3"));
 MODEL(MINELAYER_ITEM,                   W_Model("g_minelayer.md3"));
 
 MODEL(ELECTRO_VIEW,                     W_Model("h_electro.iqm"));
+MODEL(ELECTRO_VIEW_ANIMATED,            W_Model("h_electro_animated.iqm"));
 MODEL(ELECTRO_WORLD,                    W_Model("v_electro.md3"));
+MODEL(ELECTRO_WORLD_ANIMATED,           W_Model("v_electro_animated.md3"));
 MODEL(ELECTRO_ITEM,                     W_Model("g_electro.md3"));
 
 MODEL(CRYLINK_VIEW,                     W_Model("h_crylink.iqm"));
+MODEL(CRYLINK_VIEW_ANIMATED,            W_Model("h_crylink_animated.iqm"));
 MODEL(CRYLINK_WORLD,                    W_Model("v_crylink.md3"));
+MODEL(CRYLINK_WORLD_ANIMATED,           W_Model("v_crylink_animated.md3"));
 MODEL(CRYLINK_ITEM,                     W_Model("g_crylink.md3"));
 
 MODEL(VORTEX_MUZZLEFLASH,               "models/nexflash.md3");
 MODEL(VORTEX_VIEW,                      W_Model("h_nex.iqm"));
+MODEL(VORTEX_VIEW_ANIMATED,             W_Model("h_nex_animated.iqm"));
 MODEL(VORTEX_WORLD,                     W_Model("v_nex.md3"));
+MODEL(VORTEX_WORLD_ANIMATED,            W_Model("v_nex_animated.md3"));
 MODEL(VORTEX_ITEM,                      W_Model("g_nex.md3"));
 
 MODEL(HAGAR_VIEW,                       W_Model("h_hagar.iqm"));
+MODEL(HAGAR_VIEW_ANIMATED,              W_Model("h_hagar_animated.iqm"));
 MODEL(HAGAR_WORLD,                      W_Model("v_hagar.md3"));
+MODEL(HAGAR_WORLD_ANIMATED,             W_Model("v_hagar_animated.md3"));
 MODEL(HAGAR_ITEM,                       W_Model("g_hagar.md3"));
 
 MODEL(DEVASTATOR_MUZZLEFLASH,           "models/flash.md3");
 MODEL(DEVASTATOR_VIEW,                  W_Model("h_rl.iqm"));
+MODEL(DEVASTATOR_VIEW_ANIMATED,         W_Model("h_rl_animated.iqm"));
 MODEL(DEVASTATOR_WORLD,                 W_Model("v_rl.md3"));
+MODEL(DEVASTATOR_WORLD_ANIMATED,        W_Model("v_rl_animated.md3"));
 MODEL(DEVASTATOR_ITEM,                  W_Model("g_rl.md3"));
 
 MODEL(PORTAL,                           "models/portal.md3");
 MODEL(PORTO_VIEW,                       W_Model("h_porto.iqm"));
+MODEL(PORTO_VIEW_ANIMATED,              W_Model("h_porto_animated.iqm"));
 MODEL(PORTO_WORLD,                      W_Model("v_porto.md3"));
+MODEL(PORTO_WORLD_ANIMATED,             W_Model("v_porto_animated.md3"));
 MODEL(PORTO_ITEM,                       W_Model("g_porto.md3"));
 
 MODEL(VAPORIZER_MUZZLEFLASH,            "models/nexflash.md3");
 MODEL(VAPORIZER_VIEW,                   W_Model("h_minstanex.iqm"));
+MODEL(VAPORIZER_VIEW_ANIMATED,          W_Model("h_minstanex_animated.iqm"));
 MODEL(VAPORIZER_WORLD,                  W_Model("v_minstanex.md3"));
+MODEL(VAPORIZER_WORLD_ANIMATED,         W_Model("v_minstanex_animated.md3"));
 MODEL(VAPORIZER_ITEM,                   W_Model("g_minstanex.md3"));
 
 MODEL(HOOK,                             "models/hook.md3");
 MODEL(HOOK_VIEW,                        W_Model("h_hookgun.iqm"));
+MODEL(HOOK_VIEW_ANIMATED,               W_Model("h_hookgun_animated.iqm"));
 MODEL(HOOK_WORLD,                       W_Model("v_hookgun.md3"));
+MODEL(HOOK_WORLD_ANIMATED,              W_Model("v_hookgun_animated.md3"));
 MODEL(HOOK_ITEM,                        W_Model("g_hookgun.md3"));
 
 MODEL(HLAC_VIEW,                        W_Model("h_hlac.iqm"));
+MODEL(HLAC_VIEW_ANIMATED,               W_Model("h_hlac_animated.iqm"));
 MODEL(HLAC_WORLD,                       W_Model("v_hlac.md3"));
+MODEL(HLAC_WORLD_ANIMATED,              W_Model("v_hlac_animated.md3"));
 MODEL(HLAC_ITEM,                        W_Model("g_hlac.md3"));
 
 MODEL(TUBA_VIEW,                        W_Model("h_tuba.iqm"));
+MODEL(TUBA_VIEW_ANIMATED,               W_Model("h_tuba_animated.iqm"));
 MODEL(TUBA_WORLD,                       W_Model("v_tuba.md3"));
+MODEL(TUBA_WORLD_ANIMATED,              W_Model("v_tuba_animated.md3"));
 MODEL(TUBA_ITEM,                        W_Model("g_tuba.md3"));
 MODEL(ACCORDION_VIEW,                   W_Model("h_akordeon.iqm"));
+MODEL(ACCORDION_VIEW_ANIMATED,          W_Model("h_akordeon_animated.iqm"));
 MODEL(ACCORDION_WORLD,                  W_Model("v_akordeon.md3"));
+MODEL(ACCORDION_WORLD_ANIMATED,         W_Model("v_akordeon_animated.md3"));
 MODEL(KLEINBOTTLE_VIEW,                 W_Model("h_kleinbottle.iqm"));
+MODEL(KLEINBOTTLE_VIEW_ANIMATED,        W_Model("h_kleinbottle_animated.iqm"));
 MODEL(KLEINBOTTLE_WORLD,                W_Model("v_kleinbottle.md3"));
+MODEL(KLEINBOTTLE_WORLD_ANIMATED,       W_Model("v_kleinbottle_animated.md3"));
 
 MODEL(RIFLE_VIEW,                       W_Model("h_campingrifle.iqm"));
+MODEL(RIFLE_VIEW_ANIMATED,              W_Model("h_campingrifle_animated.iqm"));
 MODEL(RIFLE_WORLD,                      W_Model("v_campingrifle.md3"));
+MODEL(RIFLE_WORLD_ANIMATED,             W_Model("v_campingrifle_animated.md3"));
 MODEL(RIFLE_ITEM,                       W_Model("g_campingrifle.md3"));
 
 MODEL(FIREBALL_SPHERE,                  "models/sphere/sphere.md3");
 MODEL(FIREBALL_VIEW,                    W_Model("h_fireball.iqm"));
+MODEL(FIREBALL_VIEW_ANIMATED,           W_Model("h_fireball_animated.iqm"));
 MODEL(FIREBALL_WORLD,                   W_Model("v_fireball.md3"));
+MODEL(FIREBALL_WORLD_ANIMATED,          W_Model("v_fireball_animated.md3"));
 MODEL(FIREBALL_ITEM,                    W_Model("g_fireball.md3"));
 
 MODEL(SEEKER_VIEW,                      W_Model("h_seeker.iqm"));
+MODEL(SEEKER_VIEW_ANIMATED,             W_Model("h_seeker_animated.iqm"));
 MODEL(SEEKER_WORLD,                     W_Model("v_seeker.md3"));
+MODEL(SEEKER_WORLD_ANIMATED,            W_Model("v_seeker_animated.md3"));
 MODEL(SEEKER_ITEM,                      W_Model("g_seeker.md3"));
 
 MODEL(SHOCKWAVE_MUZZLEFLASH,            "models/uziflash.md3");
 MODEL(SHOCKWAVE_VIEW,                   W_Model("h_shotgun.iqm"));
+MODEL(SHOCKWAVE_VIEW_ANIMATED,          W_Model("h_shotgun_animated.iqm"));
 MODEL(SHOCKWAVE_WORLD,                  W_Model("v_shotgun.md3"));
+MODEL(SHOCKWAVE_WORLD_ANIMATED,         W_Model("v_shotgun_animated.md3"));
 MODEL(SHOCKWAVE_ITEM,                   W_Model("g_shotgun.md3"));
 
 MODEL(ARC_MUZZLEFLASH,                  "models/flash.md3");
 MODEL(ARC_VIEW,                         W_Model("h_arc.iqm"));
+MODEL(ARC_VIEW_ANIMATED,                W_Model("h_arc_animated.iqm"));
 MODEL(ARC_WORLD,                        W_Model("v_arc.md3"));
+MODEL(ARC_WORLD_ANIMATED,               W_Model("v_arc_animated.md3"));
 MODEL(ARC_ITEM,                         W_Model("g_arc.md3"));
 
 MODEL(HMG_MUZZLEFLASH,                  "models/uziflash.md3");
 MODEL(HMG_VIEW,                         W_Model("h_ok_hmg.iqm"));
+MODEL(HMG_VIEW_ANIMATED,                W_Model("h_ok_hmg_animated.iqm"));
 MODEL(HMG_WORLD,                        W_Model("v_ok_hmg.md3"));
+MODEL(HMG_WORLD_ANIMATED,               W_Model("v_ok_hmg_animated.md3"));
 MODEL(HMG_ITEM,                         W_Model("g_ok_hmg.md3"));
 
 MODEL(RPC_MUZZLEFLASH,                  "models/flash.md3");
 MODEL(RPC_VIEW,                         W_Model("h_ok_rl.iqm"));
+MODEL(RPC_VIEW_ANIMATED,                W_Model("h_ok_rl_animated.iqm"));
 MODEL(RPC_WORLD,                        W_Model("v_ok_rl.md3"));
+MODEL(RPC_WORLD_ANIMATED,               W_Model("v_ok_rl_animated.md3"));
 MODEL(RPC_ITEM,                         W_Model("g_ok_rl.md3"));
 
 MODEL(TUR_GIB_BASE1,                    "models/turrets/base-gib1.md3");
index 7a1e7d73c2a471c802a1cf496d9a68e15c0d49e9..4eb01c31b9cf022a614999b99619b6ab0b3ea5f6 100644 (file)
@@ -15,7 +15,8 @@ CLASS(Model, Object)
         TC(Model, this);
         string s = this.model_str();
         if (s != "" && s != "null" && !fexists(s)) {
-            LOG_WARNF("Missing model: \"%s\"", s);
+            if(substring(s, 0, 14) != "models/weapons")
+                LOG_WARNF("Missing model: \"%s\"", s);
             return;
         }
         profile(sprintf("precache_model(\"%s\")", s));
index d8c76dbf39fbb81b3199407229e0fee7cefc91b8..37c6724dd452b67601311eeb44b8715bd4ceb471 100644 (file)
@@ -404,11 +404,26 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
        {
                // if there is a child entity, hide it until we're sure we use it
                if (this.weaponchild) this.weaponchild.model = "";
-               _setmodel(this, W_Model(strcat("v_", name, ".md3")));
+               bool use_animated = false;
+               string wmodel = W_Model(strcat("v_", name, ".md3"));
+               string hmodel = W_Model(strcat("h_", name, ".iqm"));
+       #ifdef CSQC
+               use_animated = autocvar_cl_weapons_animate;
+       #endif
+               if(use_animated)
+               {
+                       string tmdl = W_Model(strcat("v_", name, "_animated.md3"));
+                       string ymdl = W_Model(strcat("h_", name, "_animated.iqm"));
+                       if(fexists(tmdl))
+                               wmodel = tmdl;
+                       if(fexists(ymdl))
+                               hmodel = ymdl;
+               }
+               _setmodel(this, wmodel);
                int v_shot_idx;  // used later
                (v_shot_idx = gettagindex(this, "shot")) || (v_shot_idx = gettagindex(this, "tag_shot"));
 
-               _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
+               _setmodel(this, hmodel);
                // preset some defaults that work great for renamed zym files (which don't need an animinfo)
                this.anim_fire1  = animfixfps(this, '0 1 0.01', '0 0 0');
                this.anim_fire2  = animfixfps(this, '1 1 0.01', '0 0 0');
@@ -428,7 +443,7 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
                                this.weaponchild.renderflags |= RF_VIEWMODEL;
 #endif
                        }
-                       _setmodel(this.weaponchild, W_Model(strcat("v_", name, ".md3")));
+                       _setmodel(this.weaponchild, wmodel);
                        setsize(this.weaponchild, '0 0 0', '0 0 0');
                        setattachment(this.weaponchild, this, t);
                }
@@ -555,14 +570,22 @@ REGISTER_NET_TEMP(wframe)
 #ifdef CSQC
 NET_HANDLE(wframe, bool isNew)
 {
-       vector a;
-       a.x = ReadCoord();
-    a.y = ReadCoord();
-    a.z = ReadCoord();
+       int fr = ReadByte();
+       float wrate = ReadCoord();
     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
+       vector a = '0 0 0';
+    if (fr == WFRAME_IDLE) a = wepent.anim_idle;
+    else if (fr == WFRAME_FIRE1) a = wepent.anim_fire1;
+    else if (fr == WFRAME_FIRE2) a = wepent.anim_fire2;
+    else  // if (fr == WFRAME_RELOAD)
+        a = wepent.anim_reload;
+    a.z *= wrate;
+
+    //LOG_INFO(vtos(a), " ", ftos(fr), " ", ftos(wrate), "\n");
+
+       if(fr == WFRAME_IDLE) // we don't need to enforce idle animation
                wepent.animstate_looping = false;
        else
                anim_set(wepent, a, !restartanim, restartanim, restartanim);
@@ -585,15 +608,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 a, bool restartanim)
 {
        if (!IS_REAL_CLIENT(actor)) return;
        int channel = MSG_ONE;
        msg_entity = actor;
        WriteHeader(channel, wframe);
-       WriteCoord(channel, a.x);
-       WriteCoord(channel, a.y);
-       WriteCoord(channel, a.z);
+       WriteByte(channel, a);
+       WriteCoord(channel, W_WeaponRateFactor(actor));
        WriteByte(channel, weaponslot(weaponentity.weaponentity_fld));
        WriteByte(channel, restartanim);
        WriteByte(channel, weaponentity.state);
index 2e4e160b3e16f1727a810cf3418a8d41b1a81b1e..a0cc62b2a15900369f768e8d16c942f5698a8938 100644 (file)
@@ -331,7 +331,7 @@ bool weapon_prepareattack(Weapon thiswep, entity actor, .entity weaponentity, bo
        return false;
 }
 
-void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim);
+void wframe_send(entity actor, entity weaponentity, int a, bool restartanim);
 
 /**
  * @param t defer thinking until time + t
@@ -357,15 +357,6 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(
        vector or = v_right;
        vector ou = v_up;
 
-       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;
-
        v_forward = of;
        v_right = or;
        v_up = ou;
@@ -395,7 +386,7 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(
        {
                FOREACH_CLIENT(true, LAMBDA(
                        if(it == actor || (IS_SPEC(it) && it.enemy == actor))
-                               wframe_send(it, this, a, restartanim);
+                               wframe_send(it, this, fr, restartanim);
                ));
        }