]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/animdecide.qc
Merge branch 'master' into terencehill/menu_optimization
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / animdecide.qc
1 #include "animdecide.qh"
2
3 #include "monsters/all.qh"
4
5 #if defined(SVQC)
6     #include "util.qh"
7     #include "../server/defs.qh"
8 #endif
9
10 bool monsters_animoverride(entity e)
11 {
12         Monster monster_id = NULL;
13         for(int i = MON_FIRST; i <= MON_LAST; ++i)
14         {
15                 entity mon = get_monsterinfo(i);
16
17                 //if(substring(e.model, 0, strlen(mon.model) - 4) == substring(mon.model, 0, strlen(mon.model) - 4))
18                 if(e.model == mon.model)
19                 {
20                         monster_id = mon;
21                         break;
22                 }
23         }
24
25         if(!monster_id) { return false; }
26
27         monster_id.mr_anim(monster_id);
28
29         vector none = '0 0 0';
30         e.anim_duckwalk = e.anim_walk;
31         e.anim_duckjump = animfixfps(e, '5 1 10', none);
32         e.anim_duckidle = e.anim_idle;
33         e.anim_jump = animfixfps(e, '8 1 10', none);
34         e.anim_taunt = animfixfps(e, '12 1 0.33', none);
35         e.anim_runbackwards = e.anim_run;
36         e.anim_strafeleft = e.anim_run;
37         e.anim_straferight = e.anim_run;
38         e.anim_forwardright = e.anim_run;
39         e.anim_forwardleft = e.anim_run;
40         e.anim_backright = e.anim_run;
41         e.anim_backleft  = e.anim_run;
42         e.anim_duckwalkbackwards = e.anim_walk;
43         e.anim_duckwalkstrafeleft = e.anim_walk;
44         e.anim_duckwalkstraferight = e.anim_walk;
45         e.anim_duckwalkforwardright = e.anim_walk;
46         e.anim_duckwalkforwardleft = e.anim_walk;
47         e.anim_duckwalkbackright = e.anim_walk;
48         e.anim_duckwalkbackleft  = e.anim_walk;
49
50         // these anims ought to stay until stopped explicitly by weaponsystem
51         e.anim_shoot_z = 0.001;
52         e.anim_melee_z = 0.001;
53
54         return true;
55 }
56
57 void animdecide_load_if_needed(entity e)
58 {
59         int mdlidx = e.modelindex;
60         if (mdlidx == e.animdecide_modelindex) return;
61         e.animdecide_modelindex = mdlidx;
62
63         if(substring(e.model, 0, 16) == "models/monsters/")
64         {
65                 if(monsters_animoverride(e))
66                         return;
67         }
68
69 #define ANIM_VEC(a, frames, rate) anim_vec(ANIM_##a, mdlidx, frames, rate)
70
71         vector none = '0 0 0';
72         e.anim_die1 = animfixfps(e, ANIM_VEC(die1, 1, 0.5), none); // 2 seconds
73         e.anim_die2 = animfixfps(e, ANIM_VEC(die2, 1, 0.5), none); // 2 seconds
74         e.anim_draw = animfixfps(e, ANIM_VEC(draw, 1, 3), none);
75         e.anim_duckwalk = animfixfps(e, ANIM_VEC(duckwalk, 1, 1), none);
76         e.anim_duckjump = animfixfps(e, ANIM_VEC(duckjump, 1, 10), none);
77         e.anim_duckidle = animfixfps(e, ANIM_VEC(duckidle, 1, 1), none);
78         e.anim_idle = animfixfps(e, ANIM_VEC(idle, 1, 1), none);
79         e.anim_jump = animfixfps(e, ANIM_VEC(jump, 1, 10), none);
80         e.anim_pain1 = animfixfps(e, ANIM_VEC(pain1, 1, 2), none); // 0.5 seconds
81         e.anim_pain2 = animfixfps(e, ANIM_VEC(pain2, 1, 2), none); // 0.5 seconds
82         e.anim_shoot = animfixfps(e, ANIM_VEC(shoot, 1, 5), none); // analyze models and set framerate
83         e.anim_taunt = animfixfps(e, ANIM_VEC(taunt, 1, 0.33), none);
84         e.anim_run = animfixfps(e, ANIM_VEC(run, 1, 1), none);
85         e.anim_runbackwards = animfixfps(e, ANIM_VEC(runbackwards, 1, 1), none);
86         e.anim_strafeleft = animfixfps(e, ANIM_VEC(strafeleft, 1, 1), none);
87         e.anim_straferight = animfixfps(e, ANIM_VEC(straferight, 1, 1), none);
88         e.anim_forwardright = animfixfps(e, ANIM_VEC(forwardright, 1, 1), ANIM_VEC(straferight, 1, 1));
89         e.anim_forwardleft = animfixfps(e, ANIM_VEC(forwardleft, 1, 1), ANIM_VEC(strafeleft, 1, 1));
90         e.anim_backright = animfixfps(e, ANIM_VEC(backright, 1, 1), ANIM_VEC(straferight, 1, 1));
91         e.anim_backleft  = animfixfps(e, ANIM_VEC(backleft , 1, 1), ANIM_VEC(strafeleft, 1, 1));
92         e.anim_melee = animfixfps(e, ANIM_VEC(melee, 1, 1), ANIM_VEC(shoot, 1, 1));
93         e.anim_duckwalkbackwards = animfixfps(e, ANIM_VEC(duckwalkbackwards, 1, 1), ANIM_VEC(duckwalk, 1, 1));
94         e.anim_duckwalkstrafeleft = animfixfps(e, ANIM_VEC(duckwalkstrafeleft, 1, 1), ANIM_VEC(duckwalk, 1, 1));
95         e.anim_duckwalkstraferight = animfixfps(e, ANIM_VEC(duckwalkstraferight, 1, 1), ANIM_VEC(duckwalk, 1, 1));
96         e.anim_duckwalkforwardright = animfixfps(e, ANIM_VEC(duckwalkforwardright, 1, 1), ANIM_VEC(duckwalk, 1, 1));
97         e.anim_duckwalkforwardleft = animfixfps(e, ANIM_VEC(duckwalkforwardleft, 1, 1), ANIM_VEC(duckwalk, 1, 1));
98         e.anim_duckwalkbackright = animfixfps(e, ANIM_VEC(duckwalkbackright, 1,  1), ANIM_VEC(duckwalk, 1, 1));
99         e.anim_duckwalkbackleft  = animfixfps(e, ANIM_VEC(duckwalkbackleft , 1,  1), ANIM_VEC(duckwalk, 1, 1));
100
101 #undef ANIM_VEC
102
103         // these anims ought to stay until stopped explicitly by weaponsystem
104         e.anim_shoot_z = 0.001;
105         e.anim_melee_z = 0.001;
106 }
107
108 const float ANIMPRIO_IDLE = 0;
109 const float ANIMPRIO_ACTIVE = 1;
110 const float ANIMPRIO_CROUCH = 2;
111 const float ANIMPRIO_DEAD = 3;
112
113 vector animdecide_getupperanim(entity e)
114 {
115         // death etc.
116         if(e.anim_state & ANIMSTATE_FROZEN)
117                 return vec3(e.anim_idle.x, e.anim_time, ANIMPRIO_DEAD);
118         if(e.anim_state & ANIMSTATE_DEAD1)
119                 return vec3(e.anim_die1_x, e.anim_time, ANIMPRIO_DEAD);
120         if(e.anim_state & ANIMSTATE_DEAD2)
121                 return vec3(e.anim_die2_x, e.anim_time, ANIMPRIO_DEAD);
122
123         // is there an action?
124         vector outframe = '-1 0 0';
125         float t, a;
126         if(e.anim_upper_time >= e.anim_upper_implicit_time)
127         {
128                 a = e.anim_upper_action;
129                 t = e.anim_upper_time;
130         }
131         else
132         {
133                 a = e.anim_upper_implicit_action;
134                 t = e.anim_upper_implicit_time;
135         }
136         switch(a)
137         {
138                 case ANIMACTION_DRAW: outframe = e.anim_draw; break;
139                 case ANIMACTION_PAIN1: outframe = e.anim_pain1; break;
140                 case ANIMACTION_PAIN2: outframe = e.anim_pain2; break;
141                 case ANIMACTION_SHOOT: outframe = e.anim_shoot; break;
142                 case ANIMACTION_TAUNT: outframe = e.anim_taunt; break;
143                 case ANIMACTION_MELEE: outframe = e.anim_melee; break;
144         }
145         if(outframe.x >= 0)
146         {
147                 if(time <= t + outframe.y / outframe.z)
148                 {
149                         // animation is running!
150                         return vec3(outframe.x, t, ANIMPRIO_ACTIVE);
151                 }
152         }
153         // or, decide the anim by state
154         t = max(e.anim_time, e.anim_implicit_time);
155         // but all states are for lower body!
156         return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
157 }
158
159 vector animdecide_getloweranim(entity e)
160 {
161         // death etc.
162         if(e.anim_state & ANIMSTATE_FOLLOW)
163                 return vec3(((e.anim_state & ANIMSTATE_DUCK) ? e.anim_duckidle_x : e.anim_idle_x), e.anim_time, ANIMPRIO_DEAD); // dead priority so it's above all
164         if(e.anim_state & ANIMSTATE_FROZEN)
165                 return vec3(e.anim_idle.x, e.anim_time, ANIMPRIO_DEAD);
166         if(e.anim_state & ANIMSTATE_DEAD1)
167                 return vec3(e.anim_die1_x, e.anim_time, ANIMPRIO_DEAD);
168         if(e.anim_state & ANIMSTATE_DEAD2)
169                 return vec3(e.anim_die2_x, e.anim_time, ANIMPRIO_DEAD);
170
171         // is there an action?
172         vector outframe = '-1 0 0';
173         float t, a;
174         if(e.anim_lower_time >= e.anim_lower_implicit_time)
175         {
176                 a = e.anim_lower_action;
177                 t = e.anim_lower_time;
178         }
179         else
180         {
181                 a = e.anim_lower_implicit_action;
182                 t = e.anim_lower_implicit_time;
183         }
184         switch(a)
185         {
186                 case ANIMACTION_JUMP: if(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR) { if(e.anim_state & ANIMSTATE_DUCK) outframe = e.anim_duckjump; else outframe = e.anim_jump; } break;
187         }
188         if(outframe.x >= 0)
189         {
190                 if(time <= t + outframe.y / outframe.z)
191                 {
192                         // animation is running!
193                         return vec3(outframe.x, t, ANIMPRIO_ACTIVE);
194                 }
195         }
196         // or, decide the anim by state
197         t = max(e.anim_time, e.anim_implicit_time);
198         if(e.anim_state & ANIMSTATE_DUCK)
199         {
200                 if(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR)
201                         return vec3(e.anim_duckjump.x, 0, ANIMPRIO_CROUCH); // play the END of the jump anim
202                 else switch(e.anim_implicit_state & (ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT | ANIMIMPLICITSTATE_RIGHT))
203                 {
204                         case ANIMIMPLICITSTATE_FORWARD:
205                                 return vec3(e.anim_duckwalk.x, t, ANIMPRIO_CROUCH);
206                         case ANIMIMPLICITSTATE_BACKWARDS:
207                                 return vec3(e.anim_duckwalkbackwards.x, t, ANIMPRIO_CROUCH);
208                         case ANIMIMPLICITSTATE_RIGHT:
209                                 return vec3(e.anim_duckwalkstraferight.x, t, ANIMPRIO_CROUCH);
210                         case ANIMIMPLICITSTATE_LEFT:
211                                 return vec3(e.anim_duckwalkstrafeleft.x, t, ANIMPRIO_CROUCH);
212                         case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_RIGHT:
213                                 return vec3(e.anim_duckwalkforwardright.x, t, ANIMPRIO_CROUCH);
214                         case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_LEFT:
215                                 return vec3(e.anim_duckwalkforwardleft.x, t, ANIMPRIO_CROUCH);
216                         case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_RIGHT:
217                                 return vec3(e.anim_duckwalkbackright.x, t, ANIMPRIO_CROUCH);
218                         case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
219                                 return vec3(e.anim_duckwalkbackleft.x, t, ANIMPRIO_CROUCH);
220                         default:
221                                 return vec3(e.anim_duckidle.x, t, ANIMPRIO_CROUCH);
222                 }
223         }
224         else
225         {
226                 if(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR)
227                         return vec3(e.anim_jump.x, 0, ANIMPRIO_ACTIVE); // play the END of the jump anim
228                 else switch(e.anim_implicit_state & (ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT | ANIMIMPLICITSTATE_RIGHT))
229                 {
230                         case ANIMIMPLICITSTATE_FORWARD:
231                                 return vec3(e.anim_run.x, t, ANIMPRIO_ACTIVE);
232                         case ANIMIMPLICITSTATE_BACKWARDS:
233                                 return vec3(e.anim_runbackwards.x, t, ANIMPRIO_ACTIVE);
234                         case ANIMIMPLICITSTATE_RIGHT:
235                                 return vec3(e.anim_straferight.x, t, ANIMPRIO_ACTIVE);
236                         case ANIMIMPLICITSTATE_LEFT:
237                                 return vec3(e.anim_strafeleft.x, t, ANIMPRIO_ACTIVE);
238                         case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_RIGHT:
239                                 return vec3(e.anim_forwardright.x, t, ANIMPRIO_ACTIVE);
240                         case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_LEFT:
241                                 return vec3(e.anim_forwardleft.x, t, ANIMPRIO_ACTIVE);
242                         case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_RIGHT:
243                                 return vec3(e.anim_backright.x, t, ANIMPRIO_ACTIVE);
244                         case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
245                                 return vec3(e.anim_backleft.x, t, ANIMPRIO_ACTIVE);
246                         default:
247                                 return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
248                 }
249         }
250         // can't get here
251         return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
252 }
253
254 void animdecide_setimplicitstate(entity e, float onground)
255 {
256         int s = 0;
257
258         makevectors(e.angles);
259         vector v;
260         v.x = e.velocity * v_forward;
261         v.y = e.velocity * v_right;
262         v.z = 0;
263
264         // we want to match like this:
265         // the 8 directions shall be "evenly spaced"
266         // that means, the forward key includes anything from -67.5 to +67.5 degrees
267         // which then means x > |y| * cot(3pi/8)
268         //
269         // BUT, the engine's clip-movement-to-keyboard function uses 0.5 here,
270         // which would be an angle range from -63.43 to +63.43 degrees, making
271         // it slightly less likely to "hit two keys at once", so let's do this
272         // here too
273
274         if(vlen(v) > 10)
275         {
276                 if(v.x >  fabs(v.y) * 0.5)
277                         s |= ANIMIMPLICITSTATE_FORWARD;
278                 if(v.x < -fabs(v.y) * 0.5)
279                         s |= ANIMIMPLICITSTATE_BACKWARDS;
280                 if(v.y >  fabs(v.x) * 0.5)
281                         s |= ANIMIMPLICITSTATE_RIGHT;
282                 if(v.y < -fabs(v.x) * 0.5)
283                         s |= ANIMIMPLICITSTATE_LEFT;
284         }
285         if(!onground)
286                 s |= ANIMIMPLICITSTATE_INAIR;
287
288         // detect some kinds of otherwise misdetected jumps (ground to air transition)
289         // NOTE: currently, in CSQC this is the only jump detection, as the explicit jump action is never called!
290         if(!(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR) && (s & ANIMIMPLICITSTATE_INAIR))
291         {
292                 e.anim_lower_implicit_action = ANIMACTION_JUMP;
293                 e.anim_lower_implicit_time = time;
294         }
295
296         if(s != e.anim_implicit_state)
297         {
298                 e.anim_implicit_state = s;
299                 e.anim_implicit_time = time;
300         }
301 }
302 void animdecide_setframes(entity e, float support_blending, .float fld_frame, .float fld_frame1time, .float fld_frame2, .float fld_frame2time)
303 {
304         // _x: frame
305         // _y: start time
306         // _z: priority
307         vector upper = animdecide_getupperanim(e);
308         vector lower = animdecide_getloweranim(e);
309         //print("UPPER: ", vtos(upper), ", LOWER: ", vtos(lower), "\n");
310         if(support_blending)
311         {
312                 if(upper.z && !lower.z)
313                         lower = upper;
314                 else if(lower.z && !upper.z)
315                         upper = lower;
316                 if(e.frame1time != upper.y || e.frame2time != lower.y)
317                         BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
318                 e.(fld_frame) = upper.x;
319                 e.(fld_frame1time) = upper.y;
320                 e.(fld_frame2) = lower.x;
321                 e.(fld_frame2time) = lower.y;
322         }
323         else
324         {
325                 if(upper.z > lower.z)
326                         lower = upper;
327                 else if(lower.z > upper.z)
328                         upper = lower;
329                 if(e.frame1time != upper.y)
330                         BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
331                 e.(fld_frame) = upper.x;
332                 e.(fld_frame1time) = upper.y;
333         }
334 }
335
336 void animdecide_setstate(entity e, int newstate, float restart)
337 {
338         if(!restart)
339                 if(newstate == e.anim_state)
340                         return;
341         e.anim_state = newstate;
342         e.anim_time = time;
343 }
344 void animdecide_setaction(entity e, float action, float restart)
345 {
346         if(action < 0)
347         {
348                 if(!restart)
349                         if(action == e.anim_lower_action)
350                                 return;
351                 e.anim_lower_action = action;
352                 e.anim_lower_time = time;
353         }
354         else
355         {
356                 if(!restart)
357                         if(action == e.anim_upper_action)
358                                 return;
359                 e.anim_upper_action = action;
360                 e.anim_upper_time = time;
361         }
362 }