]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Factor out animation decisions and gameplay
authorRudolf Polzer <divverent@xonotic.org>
Wed, 21 Nov 2012 10:57:11 +0000 (11:57 +0100)
committerRudolf Polzer <divverent@xonotic.org>
Wed, 21 Nov 2012 10:57:11 +0000 (11:57 +0100)
This will later allow performing the animation decision on the client,
using flags networked by the server. Requirement for animation blending.

13 files changed:
qcsrc/common/animdecide.qc [new file with mode: 0644]
qcsrc/common/animdecide.qh [new file with mode: 0644]
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_physics.qc
qcsrc/server/cl_player.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/defs.qh
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/progs.src
qcsrc/server/t_jumppads.qc
qcsrc/server/w_electro.qc

diff --git a/qcsrc/common/animdecide.qc b/qcsrc/common/animdecide.qc
new file mode 100644 (file)
index 0000000..79004cf
--- /dev/null
@@ -0,0 +1,258 @@
+// implicit anim state
+.float anim_implicit_state;
+.float anim_implicit_time;
+
+// actions
+.float anim_lower_action;
+.float anim_lower_time;
+.float anim_upper_action;
+.float anim_upper_time;
+
+// player animation data for this model
+// each vector is as follows:
+// _x = startframe
+// _y = numframes
+// _z = framerate
+.vector anim_die1; // player dies
+.vector anim_die2; // player dies differently
+.vector anim_draw; // player pulls out a weapon
+.vector anim_duckwalk; // player walking while crouching
+.vector anim_duckjump; // player jumping from a crouch
+.vector anim_duckidle; // player idling while crouching
+.vector anim_idle; // player standing
+.vector anim_jump; // player jump
+.vector anim_pain1; // player flinches from pain
+.vector anim_pain2; // player flinches from pain, differently
+.vector anim_shoot; // player shoots
+.vector anim_taunt; // player taunts others (FIXME: no code references this)
+.vector anim_run; // player running forward
+.vector anim_runbackwards; // player running backward
+.vector anim_strafeleft; // player shuffling left quickly
+.vector anim_straferight; // player shuffling right quickly
+.vector anim_forwardright; // player running forward and right
+.vector anim_forwardleft; // player running forward and left
+.vector anim_backright; // player running backward and right
+.vector anim_backleft; // player running back and left
+.vector anim_melee; // player doing the melee action
+.vector anim_duck; // player doing the melee action
+.vector anim_duckwalkbackwards;
+.vector anim_duckwalkstrafeleft;
+.vector anim_duckwalkstraferight;
+.vector anim_duckwalkforwardright;
+.vector anim_duckwalkforwardleft;
+.vector anim_duckwalkbackright;
+.vector anim_duckwalkbackleft;
+
+void animdecide_init(entity e)
+{
+       self.anim_die1 = animfixfps(self, '0 1 0.5'); // 2 seconds
+       self.anim_die2 = animfixfps(self, '1 1 0.5'); // 2 seconds
+       self.anim_draw = animfixfps(self, '2 1 3');
+       self.anim_duckwalk = animfixfps(self, '4 1 1');
+       self.anim_duckjump = '5 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
+       self.anim_duckidle = animfixfps(self, '6 1 1');
+       self.anim_idle = animfixfps(self, '7 1 1');
+       self.anim_jump = '8 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
+       self.anim_pain1 = animfixfps(self, '9 1 2'); // 0.5 seconds
+       self.anim_pain2 = animfixfps(self, '10 1 2'); // 0.5 seconds
+       self.anim_shoot = animfixfps(self, '11 1 5'); // analyze models and set framerate
+       self.anim_taunt = animfixfps(self, '12 1 0.33');
+       self.anim_run = animfixfps(self, '13 1 1');
+       self.anim_runbackwards = animfixfps(self, '14 1 1');
+       self.anim_strafeleft = animfixfps(self, '15 1 1');
+       self.anim_straferight = animfixfps(self, '16 1 1');
+       self.anim_forwardright = animfixfps(self, '19 1 1');
+       self.anim_forwardleft = animfixfps(self, '20 1 1');
+       self.anim_backright = animfixfps(self, '21 1 1');
+       self.anim_backleft  = animfixfps(self, '22 1 1');
+       self.anim_melee = animfixfps(self, '23 1 1');
+       self.anim_duckwalkbackwards = animfixfps(self, '24 1 1');
+       self.anim_duckwalkstrafeleft = animfixfps(self, '25 1 1');
+       self.anim_duckwalkstraferight = animfixfps(self, '26 1 1');
+       self.anim_duckwalkforwardright = animfixfps(self, '27 1 1');
+       self.anim_duckwalkforwardleft = animfixfps(self, '28 1 1');
+       self.anim_duckwalkbackright = animfixfps(self, '29 1 1');
+       self.anim_duckwalkbackleft  = animfixfps(self, '30 1 1');
+}
+
+#define ANIMPRIO_IDLE 0
+#define ANIMPRIO_STATIC 1
+#define ANIMPRIO_ACTIVE 2
+#define ANIMPRIO_DEAD 3
+
+vector animdecide_getupperanim(entity e)
+{
+       // is there an action?
+       vector outframe = '-1 0 0';
+       switch(e.anim_upper_action)
+       {
+               case ANIMACTION_DRAW: outframe = e.anim_draw; break;
+               case ANIMACTION_PAIN1: outframe = e.anim_pain1; break;
+               case ANIMACTION_PAIN2: outframe = e.anim_pain2; break;
+               case ANIMACTION_SHOOT: outframe = e.anim_shoot; break;
+               case ANIMACTION_TAUNT: outframe = e.anim_taunt; break;
+               case ANIMACTION_MELEE: outframe = e.anim_melee; break;
+       }
+       if(outframe_x >= 0)
+       {
+               if(time <= e.anim_upper_time + outframe_y / outframe_z)
+               {
+                       // animation is running!
+                       return vec3(outframe_x, e.anim_upper_time, ANIMPRIO_ACTIVE);
+               }
+       }
+       float t = max(e.anim_time, e.anim_implicit_time);
+       // or, decide the anim by state
+       // but all states are for lower body!
+       return vec3(e.anim_idle_x, t, ANIMPRIO_IDLE);
+}
+
+vector animdecide_getloweranim(entity e)
+{
+       // death etc.
+       if(e.anim_state & ANIMSTATE_FROZEN)
+               return vec3(e.anim_idle_x, e.anim_time, ANIMPRIO_DEAD);
+       if(e.anim_state & ANIMSTATE_DEAD1)
+               return vec3(e.anim_die1_x, e.anim_time, ANIMPRIO_DEAD);
+       if(e.anim_state & ANIMSTATE_DEAD2)
+               return vec3(e.anim_die2_x, e.anim_time, ANIMPRIO_DEAD);
+
+       // is there an action?
+       vector outframe = '-1 0 0';
+       switch(e.anim_lower_action)
+       {
+               case ANIMACTION_JUMP: if(e.anim_state & ANIMSTATE_DUCK) outframe = e.anim_duckjump; else outframe = e.anim_jump; break;
+       }
+       if(outframe_x >= 0)
+       {
+               if(time <= e.anim_lower_time + outframe_y / outframe_z)
+               {
+                       // animation is running!
+                       return vec3(outframe_x, e.anim_lower_time, ANIMPRIO_ACTIVE);
+               }
+       }
+       float t = max(e.anim_time, e.anim_implicit_time);
+       // or, decide the anim by state
+       if(e.anim_state & ANIMSTATE_DUCK)
+       {
+               switch(self.anim_implicit_state & (ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT | ANIMIMPLICITSTATE_RIGHT))
+               {
+                       case ANIMIMPLICITSTATE_FORWARD:
+                               return vec3(e.anim_duckwalk_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_BACKWARDS:
+                               return vec3(e.anim_duckwalkbackwards_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_RIGHT:
+                               return vec3(e.anim_duckwalkstraferight_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_LEFT:
+                               return vec3(e.anim_duckwalkstrafeleft_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_RIGHT:
+                               return vec3(e.anim_duckwalkforwardright_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_LEFT:
+                               return vec3(e.anim_duckwalkforwardleft_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_RIGHT:
+                               return vec3(e.anim_duckwalkbackright_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
+                               return vec3(e.anim_duckwalkbackleft_x, t, ANIMPRIO_ACTIVE);
+                       default:
+                               return vec3(e.anim_duckidle_x, t, ANIMPRIO_STATIC);
+               }
+       }
+       else if(e.anim_implicit_state & ANIMIMPLICITSTATE_RUN)
+       {
+               switch(self.anim_implicit_state & (ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT | ANIMIMPLICITSTATE_RIGHT))
+               {
+                       case ANIMIMPLICITSTATE_FORWARD:
+                               return vec3(e.anim_run_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_BACKWARDS:
+                               return vec3(e.anim_runbackwards_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_RIGHT:
+                               return vec3(e.anim_straferight_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_LEFT:
+                               return vec3(e.anim_strafeleft_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_RIGHT:
+                               return vec3(e.anim_forwardright_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_LEFT:
+                               return vec3(e.anim_forwardleft_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_RIGHT:
+                               return vec3(e.anim_backright_x, t, ANIMPRIO_ACTIVE);
+                       case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
+                               return vec3(e.anim_backleft_x, t, ANIMPRIO_ACTIVE);
+                       default:
+                               return vec3(e.anim_run_x, t, ANIMPRIO_STATIC);
+               }
+       }
+       return vec3(e.anim_idle_x, t, ANIMPRIO_IDLE);
+}
+
+void animdecide_setimplicitstate(entity e)
+{
+       float s;
+       s = 0;
+
+       makevectors(self.angles);
+       if(self.velocity * v_forward > 0)
+               s |= ANIMIMPLICITSTATE_FORWARD;
+       if(self.velocity * v_forward < 0)
+               s |= ANIMIMPLICITSTATE_BACKWARDS;
+       if(self.velocity * v_right > 0)
+               s |= ANIMIMPLICITSTATE_RIGHT;
+       if(self.velocity * v_right < 0)
+               s |= ANIMIMPLICITSTATE_LEFT;
+       if(vlen(self.velocity) > 100)
+               s |= ANIMIMPLICITSTATE_RUN;
+
+       // TODO infer jumping too!
+}
+void animdecide_setframes(entity e, float support_blending)
+{
+       animdecide_setimplicitstate(e);
+       // _x: frame
+       // _y: priority
+       // _z: start time
+       vector upper = animdecide_getupperanim(e);
+       vector lower = animdecide_getloweranim(e);
+       if(upper_y > lower_y)
+               lower = upper;
+       else if(lower_y > upper_y)
+               upper = lower;
+       if(support_blending)
+       {
+               self.frame = upper_x;
+               self.frame1time = upper_z;
+               self.frame2 = lower_x;
+               self.frame2time = lower_z;
+       }
+       else
+       {
+               self.frame = upper_x;
+               self.frame1time = upper_z;
+       }
+}
+
+void animdecide_setstate(entity e, float newstate, float restart)
+{
+       if(!restart)
+               if(newstate == e.anim_state)
+                       return;
+       e.anim_state = newstate;
+       e.anim_time = time;
+}
+void animdecide_setaction(entity e, float action, float restart)
+{
+       if(action < 0)
+       {
+               if(!restart)
+                       if(action == e.anim_lower_action)
+                               return;
+               e.anim_lower_action = action;
+               e.anim_lower_time = time;
+       }
+       else
+       {
+               if(!restart)
+                       if(action == e.anim_upper_action)
+                               return;
+               e.anim_upper_action = action;
+               e.anim_upper_time = time;
+       }
+}
diff --git a/qcsrc/common/animdecide.qh b/qcsrc/common/animdecide.qh
new file mode 100644 (file)
index 0000000..e26abe3
--- /dev/null
@@ -0,0 +1,33 @@
+// client side frame inferring
+void animdecide_init(entity e);
+void animdecide_setframes(entity e, float support_blending);
+
+// please network this one
+.float anim_state;
+.float anim_time;
+#define ReadAnimState() do { self.anim_state = ReadByte(); self.anim_time = ReadApproxPastTime(); } while(0)
+#define WriteAnimState(dest) do { WriteByte(dest, self.anim_state); WriteApproxPastTime(dest, self.anim_time); } while(0)
+
+// explicit anim states (networked)
+void animdecide_setstate(entity e, float newstate, float restart);
+#define ANIMSTATE_DEAD1 1 // base frames: die1
+#define ANIMSTATE_DEAD2 2 // base frames: die2
+#define ANIMSTATE_DUCK 4 // turns walk into duckwalk, jump into duckjump, etc.
+#define ANIMSTATE_FROZEN 8 // force idle
+
+// implicit anim states (inferred from velocity, etc.)
+#define ANIMIMPLICITSTATE_RUN 1
+#define ANIMIMPLICITSTATE_FORWARD 2
+#define ANIMIMPLICITSTATE_BACKWARDS 4
+#define ANIMIMPLICITSTATE_LEFT 8
+#define ANIMIMPLICITSTATE_RIGHT 16
+
+// explicit actions (networked); negative values are for lower body
+void animdecide_setaction(entity e, float action, float restart);
+#define ANIMACTION_JUMP -1 // jump
+#define ANIMACTION_DRAW 1 // draw
+#define ANIMACTION_PAIN1 2 // pain
+#define ANIMACTION_PAIN2 3 // pain
+#define ANIMACTION_SHOOT 4 // shoot
+#define ANIMACTION_TAUNT 5 // taunt
+#define ANIMACTION_MELEE 6 // melee
index 53c14cfb0cd1798a706bb96cb36bce8afd924ba8..331e464b87a7d1f7b66df3554c02eb6834a8c315 100644 (file)
@@ -2463,3 +2463,12 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
        for(queue_start = e; queue_start; queue_start = queue_start.fld)
                queue_start.FindConnectedComponent_processing = 0;
 }
+
+vector vec3(float x, float y, float z)
+{
+       vector v;
+       v_x = x;
+       v_y = y;
+       v_z = z;
+       return v;
+}
index faa605f887598c0dba17c7a6d5ae99654eb8e409..9b5608025cb9064f0f514831ea21dba49716a2ef 100644 (file)
@@ -361,3 +361,5 @@ float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor);
 typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_t;
 typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
+
+vector vec3(float x, float y, float z);
index 9d6bcf798d8b3026e6fb542731491923ba99b715..71431693ae22e138fbe8f49102d2b81b7e62943b 100644 (file)
@@ -2785,7 +2785,7 @@ void PlayerPreThink (void)
                self.prevorigin = self.origin;
 
                if (!self.vehicle)
-               if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen) // prevent crouching if using melee attack
+               if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && !self.freezetag_frozen) // FIXME-CSAD: prevent crouching if using melee attack
                {
                        if (!self.crouch)
                        {
index 3e2268d89748d1eb193892407968c8ee721f66a5..95dba951df6efb1109ab3c1f29d810c8b348a099 100644 (file)
@@ -169,10 +169,7 @@ void PlayerJump (void)
        self.flags &~= FL_ONGROUND;
        self.flags &~= FL_JUMPRELEASED;
 
-       if (self.crouch)
-               setanim(self, self.anim_duckjump, FALSE, TRUE, TRUE);
-       else if (self.animstate_startframe != self.anim_melee_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // jump animation shouldn't override melee until we have animation blending (or until the anim finished, 21/20 = numframes/fps)
-               setanim(self, self.anim_jump, FALSE, TRUE, TRUE);
+       animdecide_setaction(self, ANIMACTION_JUMP, TRUE);
 
        if(g_jump_grunt)
                PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
index 3e560bd2452a71020d339d7ed22830a76b212ec8..5b4b1c001c44ad300151c59e788881753dd63a29 100644 (file)
@@ -225,132 +225,64 @@ float player_getspecies()
 
 void player_setupanimsformodel()
 {
-       // defaults for legacy .zym models without animinfo files
-       self.anim_die1 = animfixfps(self, '0 1 0.5'); // 2 seconds
-       self.anim_die2 = animfixfps(self, '1 1 0.5'); // 2 seconds
-       self.anim_draw = animfixfps(self, '2 1 3');
-       // self.anim_duck = '3 1 100'; // This anim is broken, use slot 3 as a new free slot in the future ;)
-       self.anim_duckwalk = animfixfps(self, '4 1 1');
-       self.anim_duckjump = '5 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
-       self.anim_duckidle = animfixfps(self, '6 1 1');
-       self.anim_idle = animfixfps(self, '7 1 1');
-       self.anim_jump = '8 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
-       self.anim_pain1 = animfixfps(self, '9 1 2'); // 0.5 seconds
-       self.anim_pain2 = animfixfps(self, '10 1 2'); // 0.5 seconds
-       self.anim_shoot = animfixfps(self, '11 1 5'); // analyze models and set framerate
-       self.anim_taunt = animfixfps(self, '12 1 0.33');
-       self.anim_run = animfixfps(self, '13 1 1');
-       self.anim_runbackwards = animfixfps(self, '14 1 1');
-       self.anim_strafeleft = animfixfps(self, '15 1 1');
-       self.anim_straferight = animfixfps(self, '16 1 1');
-       //self.anim_dead1 = animfixfps(self, '17 1 1');
-       //self.anim_dead2 = animfixfps(self, '18 1 1');
-       self.anim_forwardright = animfixfps(self, '19 1 1');
-       self.anim_forwardleft = animfixfps(self, '20 1 1');
-       self.anim_backright = animfixfps(self, '21 1 1');
-       self.anim_backleft  = animfixfps(self, '22 1 1');
-       self.anim_melee = animfixfps(self, '23 1 1');
-       self.anim_duckwalkbackwards = animfixfps(self, '24 1 1');
-       self.anim_duckwalkstrafeleft = animfixfps(self, '25 1 1');
-       self.anim_duckwalkstraferight = animfixfps(self, '26 1 1');
-       self.anim_duckwalkforwardright = animfixfps(self, '27 1 1');
-       self.anim_duckwalkforwardleft = animfixfps(self, '28 1 1');
-       self.anim_duckwalkbackright = animfixfps(self, '29 1 1');
-       self.anim_duckwalkbackleft  = animfixfps(self, '30 1 1');
-       // TODO introspect models for finding right "fps" value (1/duration)
-       // reset animstate now
-       setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
+       // load animation info
+       animdecide_init(self);
+       animdecide_setstate(self, 0, FALSE);
 }
 
 void player_anim (void)
 {
-       updateanim(self);
-       if (self.weaponentity)
-               updateanim(self.weaponentity);
-
-       if (self.deadflag != DEAD_NO)
-               return;
-
-       if (!self.animstate_override)
+       float deadbits = (self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
+       if(self.deadflag && !deadbits)
+               if(random() < 0.5)
+                       deadbits = ANIMSTATE_DEAD1;
+               else
+                       deadbits = ANIMSTATE_DEAD2;
+       float animbits = deadbits;
+       if(self.freezetag_frozen)
+               animbits |= ANIMSTATE_FROZEN;
+       if(self.crouch)
+               animbits |= ANIMSTATE_DUCK;
+       animdecide_setstate(self, animbits, FALSE);
+
+       /* FIXME-CSAD port this to animdecide.qc
+       if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
        {
-               if (self.freezetag_frozen)
-                       setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
-               else if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
+               if (self.crouch)
                {
-                       if (self.crouch)
+                       if (self.animstate_startframe != self.anim_duckjump_x) // don't perform another trace if already playing the crouch jump anim
                        {
-                               if (self.animstate_startframe != self.anim_duckjump_x) // don't perform another trace if already playing the crouch jump anim
+                               traceline(self.origin + '0 0 1' * PL_CROUCH_MIN_z, self.origin + '0 0 1' * (PL_CROUCH_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
+                               if(!trace_startsolid && trace_fraction == 1 || !(self.animstate_startframe == self.anim_duckwalk_x || self.animstate_startframe == self.anim_duckidle_x)) // don't get stuck on non-crouch anims
                                {
-                                       traceline(self.origin + '0 0 1' * PL_CROUCH_MIN_z, self.origin + '0 0 1' * (PL_CROUCH_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
-                                       if(!trace_startsolid && trace_fraction == 1 || !(self.animstate_startframe == self.anim_duckwalk_x || self.animstate_startframe == self.anim_duckidle_x)) // don't get stuck on non-crouch anims
-                                       {
-                                               setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump);
-                                               self.restart_jump = FALSE;
-                                       }
+                                       setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump);
+                                       self.restart_jump = FALSE;
                                }
                        }
-                       else
-                       {
-                if (self.animstate_startframe != self.anim_jump_x) // don't perform another trace if already playing the jump anim
-                {
-                    traceline(self.origin + '0 0 1' * PL_MIN_z, self.origin + '0 0 1' * (PL_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
-                    if(!trace_startsolid && trace_fraction == 1 || self.animstate_startframe == self.anim_idle_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // don't get stuck on idle animation in midair, nor melee after it finished
-                    {
-                        setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump);
-                        self.restart_jump = FALSE;
-                    }
-                }
-                       }
-               }
-               else if (self.crouch)
-               {
-                       if (self.movement_x > 0 && self.movement_y == 0)
-                               setanim(self, self.anim_duckwalk, TRUE, FALSE, FALSE);
-                       else if (self.movement_x < 0 && self.movement_y == 0)
-                               setanim(self, self.anim_duckwalkbackwards, TRUE, FALSE, FALSE);
-                       else if (self.movement_x == 0 && self.movement_y > 0)
-                               setanim(self, self.anim_duckwalkstraferight, TRUE, FALSE, FALSE);
-                       else if (self.movement_x == 0 && self.movement_y < 0)
-                               setanim(self, self.anim_duckwalkstrafeleft, TRUE, FALSE, FALSE);
-                       else if (self.movement_x > 0 && self.movement_y > 0)
-                               setanim(self, self.anim_duckwalkforwardright, TRUE, FALSE, FALSE);
-                       else if (self.movement_x > 0 && self.movement_y < 0)
-                               setanim(self, self.anim_duckwalkforwardleft, TRUE, FALSE, FALSE);
-                       else if (self.movement_x < 0 && self.movement_y > 0)
-                               setanim(self, self.anim_duckwalkbackright, TRUE, FALSE, FALSE);
-                       else if (self.movement_x < 0 && self.movement_y < 0)
-                               setanim(self, self.anim_duckwalkbackleft, TRUE, FALSE, FALSE);
-                       else
-                               setanim(self, self.anim_duckidle, TRUE, FALSE, FALSE);
                }
-               else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)
+               else
                {
-                       if (self.movement_x > 0 && self.movement_y == 0)
-                               setanim(self, self.anim_run, TRUE, FALSE, FALSE);
-                       else if (self.movement_x < 0 && self.movement_y == 0)
-                               setanim(self, self.anim_runbackwards, TRUE, FALSE, FALSE);
-                       else if (self.movement_x == 0 && self.movement_y > 0)
-                               setanim(self, self.anim_straferight, TRUE, FALSE, FALSE);
-                       else if (self.movement_x == 0 && self.movement_y < 0)
-                               setanim(self, self.anim_strafeleft, TRUE, FALSE, FALSE);
-                       else if (self.movement_x > 0 && self.movement_y > 0)
-                               setanim(self, self.anim_forwardright, TRUE, FALSE, FALSE);
-                       else if (self.movement_x > 0 && self.movement_y < 0)
-                               setanim(self, self.anim_forwardleft, TRUE, FALSE, FALSE);
-                       else if (self.movement_x < 0 && self.movement_y > 0)
-                               setanim(self, self.anim_backright, TRUE, FALSE, FALSE);
-                       else if (self.movement_x < 0 && self.movement_y < 0)
-                               setanim(self, self.anim_backleft, TRUE, FALSE, FALSE);
-                       else
-                               setanim(self, self.anim_run, TRUE, FALSE, FALSE);
+                       if (self.animstate_startframe != self.anim_jump_x) // don't perform another trace if already playing the jump anim
+                       {
+                               traceline(self.origin + '0 0 1' * PL_MIN_z, self.origin + '0 0 1' * (PL_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
+                               if(!trace_startsolid && trace_fraction == 1 || self.animstate_startframe == self.anim_idle_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // don't get stuck on idle animation in midair, nor melee after it finished
+                               {
+                                       setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump);
+                                       self.restart_jump = FALSE;
+                               }
+                       }
                }
-               else
-                       setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
        }
+       */
+
+       animdecide_setframes(self, FALSE);
 
        if (self.weaponentity)
-       if (!self.weaponentity.animstate_override)
-               setanim(self.weaponentity, self.weaponentity.anim_idle, TRUE, FALSE, FALSE);
+       {
+               updateanim(self.weaponentity);
+               if (!self.weaponentity.animstate_override)
+                       setanim(self.weaponentity, self.weaponentity.anim_idle, TRUE, FALSE, FALSE);
+       }
 }
 
 void SpawnThrownWeapon (vector org, float w)
@@ -542,9 +474,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                                                if (!self.animstate_override)
                                                {
                                                        if (random() > 0.5)
-                                                               setanim(self, self.anim_pain1, FALSE, TRUE, TRUE);
+                                                               animdecide_setaction(self, ANIMACTION_PAIN1, TRUE);
                                                        else
-                                                               setanim(self, self.anim_pain2, FALSE, TRUE, TRUE);
+                                                               animdecide_setaction(self, ANIMACTION_PAIN2, TRUE);
                                                }
                                        }
 
@@ -771,9 +703,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                        self.respawn_countdown = -1; // do not count down
                self.death_time = time;
                if (random() < 0.5)
-                       setanim(self, self.anim_die1, FALSE, TRUE, TRUE);
+                       animdecide_setstate(self, self.anim_state | ANIMSTATE_DEAD1, TRUE);
                else
-                       setanim(self, self.anim_die2, FALSE, TRUE, TRUE);
+                       animdecide_setstate(self, self.anim_state | ANIMSTATE_DEAD2, TRUE);
                if (self.maxs_z > 5)
                {
                        self.maxs_z = 5;
@@ -1252,7 +1184,7 @@ void FakeGlobalSound(string sample, float chan, float voicetype)
                case VOICETYPE_TAUNT:
                        if(self.classname == "player")
                                if(self.deadflag == DEAD_NO)
-                                       setanim(self, self.anim_taunt, FALSE, TRUE, TRUE);
+                                       animdecide_setaction(self, ANIMACTION_TAUNT, TRUE);
                        if(!sv_taunt)
                                break;
                        if(sv_gentle)
@@ -1349,7 +1281,7 @@ void GlobalSound(string sample, float chan, float voicetype)
                case VOICETYPE_TAUNT:
                        if(self.classname == "player")
                                if(self.deadflag == DEAD_NO)
-                                       setanim(self, self.anim_taunt, FALSE, TRUE, TRUE);
+                                       animdecide_setaction(self, ANIMACTION_TAUNT, TRUE);
                        if(!sv_taunt)
                                break;
                        if(sv_gentle)
index 402b692af1230fba959a89c1fce3aef5a999ab13..4ab5ade72bca92a4f5db34e987245785b455af3f 100644 (file)
@@ -1048,23 +1048,13 @@ void weapon_thinkf(float fr, float t, void() func)
 
        // The shoot animation looks TERRIBLE without animation blending! Yay for moonwalking while shooting!
        //anim = self.anim_shoot;
-       if (restartanim)
        if (t)
        if (!self.crouch) // shoot anim stands up, this looks bad
        {
-               vector anim;
                if(self.weapon == WEP_SHOTGUN && self.BUTTON_ATCK2)
-               {
-                       anim = self.anim_melee;
-                       anim_z = anim_y / (t + sys_frametime);
-                       setanim(self, anim, FALSE, TRUE, TRUE);
-               }
-               else if (self.animstate_startframe == self.anim_idle_x) // only allow shoot anim to override idle animation until we have animation blending
-               {
-                       anim = self.anim_shoot;
-                       anim_z = anim_y / (t + sys_frametime);
-                       setanim(self, anim, FALSE, TRUE, TRUE);
-               }
+                       animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
+               else
+                       animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
        }
 }
 
index 9068fa75bf53e95400df5e635e8551faa3ae3a2c..d81f22924589640bf40b32c98232fa16d47aa693 100644 (file)
@@ -116,44 +116,6 @@ float maxclients;
 .float animstate_override;
 .float animstate_looping;
 
-// player animation data for this model
-// each vector is as follows:
-// _x = startframe
-// _y = numframes
-// _z = framerate
-.vector anim_die1; // player dies
-.vector anim_die2; // player dies differently
-.vector anim_draw; // player pulls out a weapon
-// .vector anim_duck; // player crouches (from idle to duckidle)
-.vector anim_duckwalk; // player walking while crouching
-.vector anim_duckjump; // player jumping from a crouch
-.vector anim_duckidle; // player idling while crouching
-.vector anim_idle; // player standing
-.vector anim_jump; // player jump
-.vector anim_pain1; // player flinches from pain
-.vector anim_pain2; // player flinches from pain, differently
-.vector anim_shoot; // player shoots
-.vector anim_taunt; // player taunts others (FIXME: no code references this)
-.vector anim_run; // player running forward
-.vector anim_runbackwards; // player running backward
-.vector anim_strafeleft; // player shuffling left quickly
-.vector anim_straferight; // player shuffling right quickly
-//.vector anim_dead1; // player dead (must be identical to last frame of die1)
-//.vector anim_dead2; // player dead (must be identical to last frame of die2)
-.vector anim_forwardright; // player running forward and right
-.vector anim_forwardleft; // player running forward and left
-.vector anim_backright; // player running backward and right
-.vector anim_backleft; // player running back and left
-.vector anim_melee; // player doing the melee action
-.vector anim_duck; // player doing the melee action
-.vector anim_duckwalkbackwards;
-.vector anim_duckwalkstrafeleft;
-.vector anim_duckwalkstraferight;
-.vector anim_duckwalkforwardright;
-.vector anim_duckwalkforwardleft;
-.vector anim_duckwalkbackright;
-.vector anim_duckwalkbackleft;
-
 // weapon animation vectors:
 .vector anim_fire1;
 .vector anim_fire2;
index bdd39b1283f487fe0e74ab42135b6d66f4b180c7..969c980a298dd44d7f085672385b4cf28650b815 100644 (file)
@@ -117,7 +117,7 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
                if (autocvar_sv_dodging_sound == 1)
                        PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
 
-               setanim(self, self.anim_jump, TRUE, FALSE, TRUE);
+               animdecide_setaction(self, ANIMACTION_JUMP, TRUE);
 
                self.dodging_single_action = 0;
        }
index 028519372f025ae24aa923d472ba0a6593de86b7..0ef33f85403daa2840106d6b6fb241e4dbf663ca 100644 (file)
@@ -22,6 +22,7 @@ sys-post.qh
 ../common/command/generic.qh
 ../common/command/shared_defs.qh
 ../common/net_notice.qh
+../common/animdecide.qh
 
 autocvars.qh
 constants.qh
@@ -229,6 +230,7 @@ mutators/mutator_superspec.qc
 ../warpzonelib/util_server.qc
 ../warpzonelib/server.qc
 
+../common/animdecide.qc
 ../common/util.qc
 
 ../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail
index 8923c19f18300e1f742acd0586e61539744c3c15..2458e262f27fae92a74d7ab48c1bced632ebcac4 100644 (file)
@@ -200,14 +200,8 @@ void trigger_push_touch()
                        else
                                other.lastteleporttime = time;
 
-                       if (!other.animstate_override)
                        if (other.deadflag == DEAD_NO)
-                       {
-                               if (other.crouch)
-                                       setanim(other, other.anim_duckjump, FALSE, TRUE, TRUE);
-                               else
-                                       setanim(other, other.anim_jump, FALSE, TRUE, TRUE);
-                       }
+                               animdecide_setaction(other, ANIMACTION_JUMP, TRUE);
                }
                else
                        other.jumppadcount = TRUE;
index 7a91cbd89cae366bfde23606899c9fd9807281a9..575ff677e2090caec7f14acb5477cacdc20d9a3d 100644 (file)
@@ -436,13 +436,8 @@ float w_electro(float req)
                {
                        if(autocvar_g_balance_electro_lightning)
                                if(self.BUTTON_ATCK_prev)
-                               {
-                                       // prolong the animtime while the gun is being fired
-                                       if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
-                                               weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_electro_primary_animtime, w_ready);
-                                       else
-                                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
-                               }
+                                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
+
                        if (weapon_prepareattack(0, (autocvar_g_balance_electro_lightning ? 0 : autocvar_g_balance_electro_primary_refire)))
                        {
                                if(autocvar_g_balance_electro_lightning)