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