UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cl_sequence.cpp
Go to the documentation of this file.
1 
9 /*
10 Copyright (C) 2002-2020 UFO: Alien Invasion.
11 
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16 
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 
21 See the GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 
27 */
28 
29 #include "cl_sequence.h"
30 #include "../client.h"
31 #include "../battlescape/cl_localentity.h"
32 #include "../battlescape/cl_view.h"
33 #include "../renderer/r_main.h"
34 #include "../renderer/r_draw.h"
35 #include "../renderer/r_misc.h" /* R_PushMatrix, R_PopMatrix */
36 #include "../renderer/r_mesh_anim.h"
37 #include "../cl_language.h"
38 #include "../../shared/parse.h"
39 #include "../ui/ui_render.h"
40 
41 #define MAX_DATA_LENGTH 512
42 
43 struct sequenceContext_s;
44 
49 typedef int (*sequenceHandler_t) (struct sequenceContext_s* context, const char* name, const char* data);
50 
51 typedef struct seqCmd_s {
53  char name[MAX_VAR];
55 } seqCmd_t;
56 
57 typedef struct sequence_s {
58  char name[MAX_VAR];
59  int start;
60  int length;
61 } sequence_t;
62 
63 typedef struct seqCamera_s {
68  float dist;
69  float ddist;
70  float zoom;
71  float dzoom;
72 } seqCamera_t;
73 
77 typedef struct seqEnt_s {
78  bool inuse;
79  char name[MAX_VAR];
81  int skin;
87  float alpha;
88  char parent[MAX_VAR];
89  char tag[MAX_VAR];
92 } seqEnt_t;
93 
97 typedef struct seq2D_s {
98  bool inuse;
99  char name[MAX_VAR];
100  char* text;
101  char font[MAX_VAR];
102  char image[MAX_VAR];
112  int border;
114  bool relativePos;
115 } seq2D_t;
116 
117 #define MAX_SEQCMDS 768
118 #define MAX_SEQUENCES 32
119 #define MAX_SEQENTS 128
120 #define MAX_SEQ2DS 128
121 
127 static int numSequences;
128 
131 static int numSeqCmds;
132 
135 typedef struct sequenceContext_s {
140 
142  int time;
148  int endCmd;
149 
152 
155 
158  int numEnts;
159 
163 
165 
167 static const value_t seqCamera_vals[] = {
168  {"origin", V_VECTOR, offsetof(seqCamera_t, origin), MEMBER_SIZEOF(seqCamera_t, origin)},
169  {"speed", V_VECTOR, offsetof(seqCamera_t, speed), MEMBER_SIZEOF(seqCamera_t, speed)},
170  {"angles", V_VECTOR, offsetof(seqCamera_t, angles), MEMBER_SIZEOF(seqCamera_t, angles)},
171  {"omega", V_VECTOR, offsetof(seqCamera_t, omega), MEMBER_SIZEOF(seqCamera_t, omega)},
172  {"dist", V_FLOAT, offsetof(seqCamera_t, dist), MEMBER_SIZEOF(seqCamera_t, dist)},
173  {"ddist", V_FLOAT, offsetof(seqCamera_t, ddist), MEMBER_SIZEOF(seqCamera_t, ddist)},
174  {"zoom", V_FLOAT, offsetof(seqCamera_t, zoom), MEMBER_SIZEOF(seqCamera_t, zoom)},
175  {"dzoom", V_FLOAT, offsetof(seqCamera_t, dzoom), MEMBER_SIZEOF(seqCamera_t, dzoom)},
176  {nullptr, V_NULL, 0, 0}
177 };
178 
180 static const value_t seqEnt_vals[] = {
181  {"name", V_STRING, offsetof(seqEnt_t, name), 0},
182  {"skin", V_INT, offsetof(seqEnt_t, skin), MEMBER_SIZEOF(seqEnt_t, skin)},
183  {"alpha", V_FLOAT, offsetof(seqEnt_t, alpha), MEMBER_SIZEOF(seqEnt_t, alpha)},
184  {"origin", V_VECTOR, offsetof(seqEnt_t, origin), MEMBER_SIZEOF(seqEnt_t, origin)},
185  {"speed", V_VECTOR, offsetof(seqEnt_t, speed), MEMBER_SIZEOF(seqEnt_t, speed)},
186  {"angles", V_VECTOR, offsetof(seqEnt_t, angles), MEMBER_SIZEOF(seqEnt_t, angles)},
187  {"omega", V_VECTOR, offsetof(seqEnt_t, omega), MEMBER_SIZEOF(seqEnt_t, omega)},
188  {"color", V_VECTOR, offsetof(seqEnt_t, color), MEMBER_SIZEOF(seqEnt_t, color)},
189  {"parent", V_STRING, offsetof(seqEnt_t, parent), 0},
190  {"tag", V_STRING, offsetof(seqEnt_t, tag), 0},
191  {nullptr, V_NULL, 0, 0}
192 };
193 
195 static const value_t seq2D_vals[] = {
196  {"name", V_STRING, offsetof(seq2D_t, name), 0},
197  {"text", V_TRANSLATION_STRING, offsetof(seq2D_t, text), 0},
198  {"font", V_STRING, offsetof(seq2D_t, font), 0},
199  {"image", V_STRING, offsetof(seq2D_t, image), 0},
200  {"pos", V_POS, offsetof(seq2D_t, pos), MEMBER_SIZEOF(seq2D_t, pos)},
201  {"speed", V_POS, offsetof(seq2D_t, speed), MEMBER_SIZEOF(seq2D_t, speed)},
202  {"size", V_POS, offsetof(seq2D_t, size), MEMBER_SIZEOF(seq2D_t, size)},
203  {"enlarge", V_POS, offsetof(seq2D_t, enlarge), MEMBER_SIZEOF(seq2D_t, enlarge)},
204  {"bgcolor", V_COLOR, offsetof(seq2D_t, bgcolor), MEMBER_SIZEOF(seq2D_t, bgcolor)},
205  {"color", V_COLOR, offsetof(seq2D_t, color), MEMBER_SIZEOF(seq2D_t, color)},
206  {"fade", V_COLOR, offsetof(seq2D_t, fade), MEMBER_SIZEOF(seq2D_t, fade)},
207  {"align", V_ALIGN, offsetof(seq2D_t, align), MEMBER_SIZEOF(seq2D_t, align)},
208  {"bordercolor", V_COLOR, offsetof(seq2D_t, bordercolor), MEMBER_SIZEOF(seq2D_t, bordercolor)},
209  {"border", V_INT, offsetof(seq2D_t, border), MEMBER_SIZEOF(seq2D_t, border)},
210  {"inbackground", V_BOOL, offsetof(seq2D_t, inBackground), MEMBER_SIZEOF(seq2D_t, inBackground)},
211  {"relative", V_BOOL, offsetof(seq2D_t, relativePos), MEMBER_SIZEOF(seq2D_t, relativePos)},
212  {nullptr, V_NULL, 0, 0}
213 };
214 
219 static void SEQ_SetCamera (sequenceContext_t* context)
220 {
221  if (!context->size[0] || !context->size[1])
222  return;
223 
224  /* advance time */
225  VectorMA(context->camera.origin, cls.frametime, context->camera.speed, context->camera.origin);
226  VectorMA(context->camera.angles, cls.frametime, context->camera.omega, context->camera.angles);
227  context->camera.zoom += cls.frametime * context->camera.dzoom;
228  context->camera.dist += cls.frametime * context->camera.ddist;
229 
230  /* set camera */
231  VectorCopy(context->camera.origin, cl.cam.origin);
232  VectorCopy(context->camera.angles, cl.cam.angles);
233 
235  VectorMA(cl.cam.origin, -context->camera.dist, cl.cam.axis[0], cl.cam.camorg);
236  cl.cam.zoom = std::max(context->camera.zoom, MIN_ZOOM);
237  /* fudge to get isometric and perspective modes looking similar */
238  if (cl_isometric->integer)
239  cl.cam.zoom /= 1.35;
241 }
242 
243 
248 static seqEnt_t* SEQ_FindEnt (sequenceContext_t* context, const char* name)
249 {
250  seqEnt_t* se;
251  int i;
252 
253  for (i = 0, se = context->ents; i < context->numEnts; i++, se++)
254  if (se->inuse && Q_streq(se->name, name))
255  break;
256  if (i < context->numEnts)
257  return se;
258  return nullptr;
259 }
260 
261 
266 static seq2D_t* SEQ_Find2D (sequenceContext_t* context, const char* name)
267 {
268  seq2D_t* s2d;
269  int i;
270 
271  for (i = 0, s2d = context->obj2Ds; i < context->numObj2Ds; i++, s2d++)
272  if (s2d->inuse && Q_streq(s2d->name, name))
273  break;
274  if (i < context->numObj2Ds)
275  return s2d;
276  return nullptr;
277 }
278 
286 static void SEQ_Render3D (sequenceContext_t* context)
287 {
288  if (context->numEnts == 0)
289  return;
290 
291  /* set camera */
292  SEQ_SetCamera(context);
293 
294  refdef.numEntities = 0;
296 
297  /* render sequence */
298  for (int i = 0; i < context->numEnts; i++) {
299  seqEnt_t* se = &context->ents[i];
300  if (!se->inuse)
301  continue;
302 
303  /* advance in time */
304  VectorMA(se->origin, cls.frametime, se->speed, se->origin);
305  VectorMA(se->angles, cls.frametime, se->omega, se->angles);
306  R_AnimRun(&se->as, se->model, context->animspeed * cls.frametime);
307 
308  /* add to scene */
309  entity_t ent(RF_NONE);
310  ent.model = se->model;
311  ent.skinnum = se->skin;
312  ent.as = se->as;
313  ent.alpha = se->alpha;
314 
315  R_EntitySetOrigin(&ent, se->origin);
316  VectorCopy(se->origin, ent.oldorigin);
317  VectorCopy(se->angles, ent.angles);
318 
319  if (se->parent && se->tag) {
320  seqEnt_t* parent = SEQ_FindEnt(context, se->parent);
321  if (parent)
322  ent.tagent = parent->ep;
323  ent.tagname = se->tag;
324  }
325 
326  /* add to render list */
327  se->ep = R_GetFreeEntity();
328  R_AddEntity(&ent);
329  }
330 
332 
333  /* use a relative fixed size */
334  viddef.x = context->pos[0];
335  viddef.y = context->pos[1];
336  viddef.viewWidth = context->size[0];
337  viddef.viewHeight = context->size[1];
338 
339  /* update refdef */
341 
343  /* render the world */
344  R_PushMatrix();
345  R_RenderFrame();
346  R_PopMatrix();
347 }
348 
349 
356 static void SEQ_Render2D (sequenceContext_t* context, bool backgroundObjects)
357 {
358  int height = 0;
359 
360  /* add texts */
361  for (int i = 0; i < context->numObj2Ds; i++) {
362  seq2D_t* s2d = &context->obj2Ds[i];
363  if (!s2d->inuse)
364  continue;
365  if (backgroundObjects != s2d->inBackground)
366  continue;
367 
368  if (s2d->relativePos && height > 0) {
369  s2d->pos[1] += height;
370  s2d->relativePos = false;
371  }
372  /* advance in time */
373  for (int j = 0; j < 4; j++) {
374  s2d->color[j] += cls.frametime * s2d->fade[j];
375  if (s2d->color[j] < 0.0)
376  s2d->color[j] = 0.0;
377  else if (s2d->color[j] > 1.0)
378  s2d->color[j] = 1.0;
379  }
380  for (int j = 0; j < 2; j++) {
381  s2d->pos[j] += cls.frametime * s2d->speed[j];
382  s2d->size[j] += cls.frametime * s2d->enlarge[j];
383  }
384 
385  /* outside the screen? */
387  /*if (s2d->pos[1] >= VID_NORM_HEIGHT || s2d->pos[0] >= VID_NORM_WIDTH)
388  continue;*/
389 
390  /* render */
391  R_Color(s2d->color);
392 
393  /* image can be background */
394  if (s2d->image[0] != '\0') {
395  const image_t* image = R_FindImage(s2d->image, it_pic);
396  R_DrawImage(s2d->pos[0], s2d->pos[1], image);
397  }
398 
399  /* bgcolor can be overlay */
400  if (s2d->bgcolor[3] > 0.0)
401  R_DrawFill(s2d->pos[0], s2d->pos[1], s2d->size[0], s2d->size[1], s2d->bgcolor);
402 
403  /* border */
404  if (s2d->border > 0 && s2d->bordercolor[3] > 0.0)
405  R_DrawRect(s2d->pos[0], s2d->pos[1], s2d->size[0], s2d->size[1], s2d->bordercolor, s2d->border, 0xFFFF);
406 
407  /* render */
408  R_Color(s2d->color);
409 
410  /* gettext placeholder */
411  if (s2d->text) {
412  int maxWidth = (int) s2d->size[0];
413  if (maxWidth <= 0)
414  maxWidth = VID_NORM_WIDTH;
415  height += UI_DrawString(s2d->font, s2d->align, s2d->pos[0], s2d->pos[1], s2d->pos[0], maxWidth, -1 , CL_Translate(s2d->text));
416  }
417  }
418  R_Color(nullptr);
419 }
420 
427 {
428  context->endClickLoop = true;
429 }
430 
438 {
439  context->pos[0] = pos[0];
440  context->pos[1] = pos[1];
441  context->size[0] = size[0];
442  context->size[1] = size[1];
443 }
444 
451 bool SEQ_InitContext (sequenceContext_t* context, const char* name)
452 {
453  sequence_t* sp;
454  int i;
455 
456  /* find sequence */
457  for (i = 0, sp = sequences; i < numSequences; i++, sp++)
458  if (Q_streq(name, sp->name))
459  break;
460  if (i >= numSequences) {
461  Com_Printf("Couldn't find sequence '%s'\n", name);
462  return false;
463  }
464 
465  OBJZERO(*context);
466  context->numEnts = 0;
467  context->numObj2Ds = 0;
468  context->time = cl.time;
469  context->currentCmd = sp->start;
470  context->endCmd = sp->start + sp->length;
471  context->animspeed = 1000;
472 
473  return true;
474 }
475 
476 static void SEQ_StopSequence (sequenceContext_t* context)
477 {
478  context->endClickLoop = true;
479 }
480 
486 static bool SEQ_Execute (sequenceContext_t* context)
487 {
488  /* we are inside a waiting command */
489  if (context->time > cl.time) {
490  /* if we clicked a button we end the waiting loop */
491  if (context->endClickLoop) {
492  context->time = cl.time;
493  context->endClickLoop = false;
494  }
495  }
496 
497  /* run script */
498  while (context->time <= cl.time) {
499  /* test for finish */
500  if (context->currentCmd >= context->endCmd) {
501  SEQ_StopSequence(context);
502  return false;
503  }
504 
505  /* call handler */
506  seqCmd_t* sc = &seqCmds[context->currentCmd];
507  context->currentCmd += sc->handler(context, sc->name, sc->data);
508  }
509 
510  return true;
511 }
512 
519 {
520  if (!context->size[0] || !context->size[1])
521  return true;
522 
523  if (!SEQ_Execute(context))
524  return false;
525 
526  /* center screen */
527  vec3_t pos;
528  pos[0] = context->pos[0] + (context->size[0] - VID_NORM_WIDTH) / 2;
529  pos[1] = context->pos[1] + (context->size[1] - VID_NORM_HEIGHT) / 2;
530  pos[2] = 0;
531  UI_Transform(pos, nullptr, nullptr);
532 
533  SEQ_Render2D(context, true);
534  SEQ_Render3D(context);
535  SEQ_Render2D(context, false);
536 
537  UI_Transform(nullptr, nullptr, nullptr);
538  return true;
539 }
540 
546 {
548  return context;
549 }
550 
556 {
557  Mem_Free(context);
558 }
559 
560 /* =========================================================== */
561 
567 static int SEQ_ExecuteClick (sequenceContext_t* context, const char* name, const char* data)
568 {
569  /* if a CL_SequenceClick_f event was called */
570  if (context->endClickLoop) {
571  context->endClickLoop = false;
572  /* increase the command counter by 1 */
573  return 1;
574  }
575  context->time += 1000;
576  /* don't increase the command counter - stay at click command */
577  return 0;
578 }
579 
584 static int SEQ_ExecuteWait (sequenceContext_t* context, const char* name, const char* data)
585 {
586  context->time += 1000 * atof(name);
587  return 1;
588 }
589 
594 static int SEQ_ExecuteAnimSpeed (sequenceContext_t* context, const char* name, const char* data)
595 {
596  context->animspeed = atoi(name);
597  return 1;
598 }
599 
606 static int SEQ_ExecutePrecache (sequenceContext_t* context, const char* name, const char* data)
607 {
608  if (Q_streq(name, "models")) {
609  while (*data) {
610  Com_DPrintf(DEBUG_CLIENT, "Precaching model: %s\n", data);
611  R_FindModel(data);
612  data += strlen(data) + 1;
613  }
614  } else if (Q_streq(name, "pics")) {
615  while (*data) {
616  Com_DPrintf(DEBUG_CLIENT, "Precaching image: %s\n", data);
617  R_FindPics(data);
618  data += strlen(data) + 1;
619  }
620  } else
621  Com_Printf("SEQ_ExecutePrecache: unknown format '%s'\n", name);
622  return 1;
623 }
624 
628 static int SEQ_ExecuteCamera (sequenceContext_t* context, const char* name, const char* data)
629 {
630  /* get values */
631  while (*data) {
632  const value_t* vp;
633  for (vp = seqCamera_vals; vp->string; vp++)
634  if (Q_streq(data, vp->string)) {
635  data += strlen(data) + 1;
636  Com_EParseValue(&context->camera, data, vp->type, vp->ofs, vp->size);
637  break;
638  }
639  if (!vp->string)
640  Com_Printf("SEQ_ExecuteCamera: unknown token '%s'\n", data);
641 
642  data += strlen(data) + 1;
643  }
644  return 1;
645 }
646 
653 static int SEQ_ExecuteModel (sequenceContext_t* context, const char* name, const char* data)
654 {
655  /* get sequence entity */
656  seqEnt_t* se = SEQ_FindEnt(context, name);
657  if (!se) {
658  int i;
659  /* create new sequence entity */
660  for (i = 0, se = context->ents; i < context->numEnts; i++, se++)
661  if (!se->inuse)
662  break;
663  if (i >= context->numEnts) {
664  if (context->numEnts >= MAX_SEQENTS)
665  Com_Error(ERR_FATAL, "Too many sequence entities");
666  se = &context->ents[context->numEnts++];
667  }
668  /* allocate */
669  OBJZERO(*se);
670  se->inuse = true;
671  Q_strncpyz(se->name, name, sizeof(se->name));
672  VectorSet(se->color, 0.7, 0.7, 0.7);
673  }
674 
675  /* get values */
676  while (*data) {
677  const value_t* vp;
678  for (vp = seqEnt_vals; vp->string; vp++)
679  if (Q_streq(data, vp->string)) {
680  data += strlen(data) + 1;
681  Com_EParseValue(se, data, vp->type, vp->ofs, vp->size);
682  break;
683  }
684  if (!vp->string) {
685  if (Q_streq(data, "model")) {
686  data += strlen(data) + 1;
687  Com_DPrintf(DEBUG_CLIENT, "Registering model: %s\n", data);
688  se->model = R_FindModel(data);
689  if (se->model == nullptr)
690  se->inuse = false;
691  } else if (Q_streq(data, "anim")) {
692  if (se->model == nullptr)
693  Com_Error(ERR_FATAL, "could not change the animation - no model loaded yet");
694  data += strlen(data) + 1;
695  Com_DPrintf(DEBUG_CLIENT, "Change anim to: %s\n", data);
696  R_AnimChange(&se->as, se->model, data);
697  } else
698  Com_Printf("SEQ_ExecuteModel: unknown token '%s'\n", data);
699  }
700 
701  data += strlen(data) + 1;
702  }
703  return 1;
704 }
705 
710 static int SEQ_ExecuteMusic (sequenceContext_t* context, const char* name, const char* data)
711 {
712  Com_DPrintf(DEBUG_CLIENT, "Change music to %s\n", name);
713  Cvar_Set("snd_music", "%s", name);
714  return 1;
715 }
716 
721 static int SEQ_ExecuteSound (sequenceContext_t* context, const char* name, const char* data)
722 {
724  return 1;
725 }
726 
733 static int SEQ_ExecuteObj2D (sequenceContext_t* context, const char* name, const char* data)
734 {
735  /* get sequence text */
736  seq2D_t* s2d = SEQ_Find2D(context, name);
737  if (!s2d) {
738  /* create new sequence text */
739  int i;
740  for (i = 0, s2d = context->obj2Ds; i < context->numObj2Ds; i++, s2d++)
741  if (!s2d->inuse)
742  break;
743  if (i >= context->numObj2Ds) {
744  if (context->numObj2Ds >= MAX_SEQ2DS)
745  Com_Error(ERR_FATAL, "Too many sequence 2d objects");
746  s2d = &context->obj2Ds[context->numObj2Ds++];
747  }
748  /* allocate */
749  OBJZERO(*s2d);
750  for (i = 0; i < 4; i++)
751  s2d->color[i] = 1.0f;
752  s2d->inuse = true;
753  Q_strncpyz(s2d->font, "f_big", sizeof(s2d->font)); /* default font */
754  Q_strncpyz(s2d->name, name, sizeof(s2d->name));
755  }
756 
757  /* get values */
758  while (*data) {
759  const value_t* vp;
760  for (vp = seq2D_vals; vp->string; vp++)
761  if (Q_streq(data, vp->string)) {
762  data += strlen(data) + 1;
763  switch (vp->type) {
765  case V_HUNK_STRING:
766  Mem_PoolStrDupTo(data, &Com_GetValue<char*>(s2d, vp), cl_genericPool, 0);
767  break;
768 
769  default:
770  Com_EParseValue(s2d, data, vp->type, vp->ofs, vp->size);
771  break;
772  }
773  break;
774  }
775  if (!vp->string)
776  Com_Printf("SEQ_ExecuteObj2D: unknown token '%s'\n", data);
777 
778  data += strlen(data) + 1;
779  }
780  return 1;
781 }
782 
789 static int SEQ_ExecuteDelete (sequenceContext_t* context, const char* name, const char* data)
790 {
791  seqEnt_t* se = SEQ_FindEnt(context, name);
792  if (se)
793  se->inuse = false;
794 
795  seq2D_t* s2d = SEQ_Find2D(context, name);
796  if (s2d) {
797  s2d->inuse = false;
798 
799  Mem_Free(s2d->text);
800  s2d->text = nullptr;
801  }
802 
803  if (!se && !s2d)
804  Com_Printf("SEQ_ExecuteDelete: couldn't find '%s'\n", name);
805  return 1;
806 }
807 
813 static int SEQ_ExecuteCommand (sequenceContext_t* context, const char* name, const char* data)
814 {
815  /* add the command */
816  Cbuf_AddText("%s\n", name);
817  return 1;
818 }
819 
820 /* =========================================================== */
821 
822 static char const* const seqCmdName[] = {
823  "end",
824  "wait",
825  "click",
826  "precache",
827  "camera",
828  "model",
829  "obj2d",
830  "music",
831  "sound",
832  "rem",
833  "delete",
834  "animspeed",
835  "cmd"
836 };
837 
838 #define SEQ_NUMCMDS lengthof(seqCmdName)
839 
844  nullptr,
857 };
859 
864 static int CL_FindSequenceCommand (const char* commandName)
865 {
866  for (int i = 0; i < SEQ_NUMCMDS; i++) {
867  if (Q_streq(commandName, seqCmdName[i])) {
868  return i;
869  }
870  }
871  return -1;
872 }
873 
878 void CL_ParseSequence (const char* name, const char** text)
879 {
880  const char* errhead = "CL_ParseSequence: unexpected end of file (sequence ";
881  int i;
882 
883  /* search for sequences with same name */
884  for (i = 0; i < numSequences; i++)
885  if (Q_streq(name, sequences[i].name))
886  break;
887 
888  if (i < numSequences) {
889  Com_Printf("CL_ParseSequence: sequence def \"%s\" with same name found, second ignored\n", name);
890  return;
891  }
892 
893  /* initialize the sequence */
894  if (numSequences >= MAX_SEQUENCES)
895  Com_Error(ERR_FATAL, "Too many sequences");
896 
897  sequence_t* sp = &sequences[numSequences++];
898  OBJZERO(*sp);
899  Q_strncpyz(sp->name, name, sizeof(sp->name));
900  sp->start = numSeqCmds;
901 
902  /* get it's body */
903  const char* token = Com_Parse(text);
904 
905  if (!*text || *token != '{') {
906  Com_Printf("CL_ParseSequence: sequence def \"%s\" without body ignored\n", name);
907  numSequences--;
908  return;
909  }
910 
911  do {
912  token = Com_EParse(text, errhead, name);
913  if (!*text)
914  break;
915  if (*token == '}')
916  break;
917 
918  /* check for commands */
919  int i = CL_FindSequenceCommand(token);
920  if (i != -1) {
921  int maxLength = MAX_DATA_LENGTH;
922  char* data;
923 
924  /* found a command */
925  token = Com_EParse(text, errhead, name);
926  if (!*text)
927  return;
928 
929  if (numSeqCmds >= MAX_SEQCMDS)
930  Com_Error(ERR_FATAL, "Too many sequence commands for %s\n", name);
931 
932  /* init seqCmd */
933  if (seqCmds == nullptr)
935  seqCmd_t* sc = &seqCmds[numSeqCmds++];
936  OBJZERO(*sc);
937  sc->handler = seqCmdFunc[i];
938  sp->length++;
939 
940  /* copy name */
941  Q_strncpyz(sc->name, token, sizeof(sc->name));
942 
943  /* read data */
944  token = Com_EParse(text, errhead, name);
945  if (!*text)
946  return;
947  if (*token == '{') {
948  // TODO depth is useless IMHO (bayo)
949  int depth = 1;
950  data = &sc->data[0];
951  while (depth) {
952  if (maxLength <= 0) {
953  Com_Printf("Too much data for sequence %s\n", sc->name);
954  break;
955  }
956  token = Com_EParse(text, errhead, name);
957  if (!*text)
958  return;
959 
960  if (*token == '{')
961  depth++;
962  else if (*token == '}')
963  depth--;
964  if (depth) {
965  Q_strncpyz(data, token, maxLength);
966  data += strlen(token) + 1;
967  maxLength -= (strlen(token) + 1);
968  }
969  }
970  } else if (*token == '(') {
971  linkedList_t* list;
973  if (!Com_ParseList(text, &list)) {
974  Com_Error(ERR_DROP, "CL_ParseSequence: error while reading list (sequence \"%s\")", name);
975  }
976  data = &sc->data[0];
977  for (linkedList_t* element = list; element != nullptr; element = element->next) {
978  if (maxLength <= 0) {
979  Com_Printf("Too much data for sequence %s", sc->name);
980  break;
981  }
982  const char* v = (char*)element->data;
983  Q_strncpyz(data, v, maxLength);
984  data += strlen(v) + 1;
985  maxLength -= (strlen(v) + 1);
986  }
987  LIST_Delete(&list);
988  } else {
990  }
991  } else {
992  Com_Printf("CL_ParseSequence: unknown command \"%s\" ignored (sequence %s)\n", token, name);
993  Com_EParse(text, errhead, name);
994  }
995  } while (*text);
996 }
997 
998 void SEQ_Shutdown (void)
999 {
1000  OBJZERO(sequences);
1001  numSequences = 0;
1002  seqCmds = nullptr;
1003  numSeqCmds = 0;
1004 }
struct sequence_s sequence_t
CASSERT(lengthof(seqCmdFunc)==lengthof(seqCmdName))
#define VectorCopy(src, dest)
Definition: vector.h:51
int(* sequenceHandler_t)(struct sequenceContext_s *context, const char *name, const char *data)
execution function of a command
Definition: cl_sequence.cpp:49
struct sequenceContext_s sequenceContext_t
static int numSequences
seq2D_t obj2Ds[MAX_SEQ2DS]
static int SEQ_ExecuteModel(sequenceContext_t *context, const char *name, const char *data)
Parse values for a sequence model.
char image[MAX_VAR]
int viewHeight
Definition: cl_video.h:76
#define VectorSet(v, x, y, z)
Definition: vector.h:59
struct seqCamera_s seqCamera_t
void R_DrawImage(float x, float y, const image_t *image)
Draws an image or parts of it.
Definition: r_draw.cpp:341
const float MIN_ZOOM
Definition: cl_camera.cpp:40
static const value_t seq2D_vals[]
valid id names for 2d entity
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb)
Definition: mathlib.cpp:261
static seqEnt_t * SEQ_FindEnt(sequenceContext_t *context, const char *name)
Finds a given entity in all sequence entities.
vec4_t fade
static int SEQ_ExecuteWait(sequenceContext_t *context, const char *name, const char *data)
Increase the sequence time.
vec3_t omega
Definition: cl_sequence.cpp:67
bool inBackground
vec4_t color
static bool SEQ_Execute(sequenceContext_t *context)
Move the sequence to the right position according to the current time.
#define SEQ_NUMCMDS
voidpf uLong int origin
Definition: ioapi.h:45
char data[MAX_DATA_LENGTH]
Definition: cl_sequence.cpp:54
static int SEQ_ExecuteClick(sequenceContext_t *context, const char *name, const char *data)
Wait until someone clicks with the mouse.
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
Definition: cmd.cpp:126
const image_t * R_FindPics(const char *name)
Searches for an image in the image array.
Definition: r_image.cpp:673
vec4_t bordercolor
vec2_t pos
viddef_t viddef
Definition: cl_video.cpp:34
char font[MAX_VAR]
bool inuse
Definition: cl_sequence.cpp:98
bool SEQ_InitContext(sequenceContext_t *context, const char *name)
Initialize a sequence context from data of a named script sequence.
vec2_t enlarge
bool relativePos
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
void SEQ_SendClickEvent(sequenceContext_t *context)
Unlock a click event for the current sequence or ends the current sequence if not locked...
char name[MAX_VAR]
Definition: cl_sequence.cpp:58
valueTypes_t type
Definition: scripts.h:170
Definition: r_image.h:45
void LIST_Delete(linkedList_t **list)
Definition: list.cpp:195
void SEQ_FreeContext(sequenceContext_t *context)
Free a sequence context.
struct seqEnt_s seqEnt_t
int integer
Definition: cvar.h:81
#define ERR_FATAL
Definition: common.h:210
memPool_t * cl_genericPool
Definition: cl_main.cpp:86
#define Mem_PoolStrDupTo(in, out, pool, tagNum)
Definition: mem.h:49
void R_AnimChange(animState_t *as, const model_t *mod, const char *name)
Changes the animation for md2 models.
#define MAX_SEQENTS
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition: r_state.cpp:1011
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
static sequenceHandler_t seqCmdFunc[]
Function to exeute all available commands.
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition: r_image.cpp:603
animState_t as
Definition: cl_sequence.cpp:90
mapTiles_t * mapTiles
client_static_t cls
Definition: cl_main.cpp:83
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Create the rotation matrix in order to rotate something.
Definition: mathlib.cpp:631
char name[MAX_VAR]
Definition: cl_sequence.cpp:79
align_t
We need this here for checking the boundaries from script values.
Definition: scripts.h:90
static int SEQ_ExecuteSound(sequenceContext_t *context, const char *name, const char *data)
Plays a sound in a sequence.
#define ERR_DROP
Definition: common.h:211
float frametime
Definition: client.h:59
#define DEBUG_CLIENT
Definition: defines.h:59
void CL_ParseSequence(const char *name, const char **text)
Reads the sequence values from given text-pointer.
int x
Definition: cl_video.h:76
vec3_t origin
Definition: cl_camera.h:31
GLsizei size
Definition: r_gl.h:152
rendererData_t refdef
Definition: r_main.cpp:45
#define OBJZERO(obj)
Definition: shared.h:178
char parent[MAX_VAR]
Definition: cl_sequence.cpp:88
#define MAX_VAR
Definition: shared.h:36
entity_t * R_GetFreeEntity(void)
Get the next free entry in the entity list (the last one)
Definition: r_entity.cpp:684
static seq2D_t * SEQ_Find2D(sequenceContext_t *context, const char *name)
Finds a given 2d object in the current sequence data.
#define MAX_SEQ2DS
model_t * model
Definition: cl_sequence.cpp:80
void SEQ_Shutdown(void)
vec3_t origin
Definition: cl_sequence.cpp:82
static const value_t seqCamera_vals[]
valid id names for camera
entity_t * ep
Definition: cl_sequence.cpp:91
clientBattleScape_t cl
const char * Com_EParse(const char **text, const char *errhead, const char *errinfo, char *target, size_t size)
Parsing function that prints an error message when there is no text in the buffer.
Definition: scripts.cpp:277
vec3_t speed
Definition: cl_sequence.cpp:65
sequenceHandler_t handler
Definition: cl_sequence.cpp:52
static int SEQ_ExecuteDelete(sequenceContext_t *context, const char *name, const char *data)
Removed a sequence entity from the current sequence.
void CL_ViewCalcFieldOfViewX(void)
Calculates refdef's FOV_X. Should generally be called after any changes are made to the zoom level (v...
Definition: cl_view.cpp:189
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
#define MAX_DATA_LENGTH
Definition: cl_sequence.cpp:41
vec3_t origin
Definition: cl_sequence.cpp:64
model_t * R_FindModel(const char *name)
Tries to load a model.
Definition: r_model.cpp:203
#define RF_NONE
Definition: r_entity.h:34
vec3_t omega
Definition: cl_sequence.cpp:85
void R_AnimRun(animState_t *as, const model_t *mod, int msec)
Run the animation of the given model.
void UI_Transform(const vec3_t transform, const vec3_t rotate, const vec3_t scale)
Pushes a new matrix, normalize to current resolution and move, rotate and scale the matrix to the giv...
Definition: ui_render.cpp:68
static char const *const seqCmdName[]
cvar_t * cl_isometric
Definition: cl_input.cpp:77
const char * string
Definition: scripts.h:169
#define RDF_NOWORLDMODEL
Definition: cl_renderer.h:34
char * text
#define VID_NORM_WIDTH
Definition: cl_renderer.h:40
void S_StartLocalSample(const char *s, float volume)
Plays a sample without spatialization.
Definition: s_mix.cpp:184
size_t ofs
Definition: scripts.h:171
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
int Com_EParseValue(void *base, const char *token, valueTypes_t type, int ofs, size_t size)
Definition: scripts.cpp:978
align_t align
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
Definition: scripts.h:49
static int SEQ_ExecutePrecache(sequenceContext_t *context, const char *name, const char *data)
Precaches the models and images for a sequence.
char name[MAX_VAR]
Definition: cl_sequence.cpp:53
#define VID_NORM_HEIGHT
Definition: cl_renderer.h:41
bool Com_ParseList(const char **text, linkedList_t **list)
Definition: scripts.cpp:1385
float alpha
Definition: cl_sequence.cpp:87
QGL_EXTERN GLint i
Definition: r_gl.h:113
const char * CL_Translate(const char *t)
void R_PopMatrix(void)
Removes the current matrix from the stack.
Definition: r_misc.cpp:248
Definition: scripts.h:50
int viewWidth
Definition: cl_video.h:76
vec4_t bgcolor
static seqCmd_t * seqCmds
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
void CL_ViewUpdateRenderData(void)
Updates the refdef.
Definition: cl_view.cpp:210
char tag[MAX_VAR]
Definition: cl_sequence.cpp:89
static int numSeqCmds
#define Mem_Free(ptr)
Definition: mem.h:35
char name[MAX_VAR]
Definition: cl_sequence.cpp:99
vec3_t angles
Definition: cl_camera.h:34
bool SEQ_Render(sequenceContext_t *context)
Execute and render a sequence.
#define MEMBER_SIZEOF(TYPE, MEMBER)
Definition: scripts.h:34
void R_EntitySetOrigin(entity_t *ent, const vec3_t origin)
setter for entity origin
Definition: r_entity.cpp:47
size_t size
Definition: scripts.h:172
vec3_t speed
Definition: cl_sequence.cpp:83
int R_AddEntity(const entity_t *ent)
Adds a copy of the specified entity to the list of all known render entities.
Definition: r_entity.cpp:706
vec_t vec3_t[3]
Definition: ufotypes.h:39
vec_t vec2_t[2]
Definition: ufotypes.h:38
static int SEQ_ExecuteCamera(sequenceContext_t *context, const char *name, const char *data)
Parse the values for the camera like given in seqCamera.
linkedList_t * next
Definition: list.h:32
static sequence_t sequences[MAX_SEQUENCES]
#define MAX_SEQUENCES
Definition: scripts.h:52
static int SEQ_ExecuteObj2D(sequenceContext_t *context, const char *name, const char *data)
Parse 2D objects like text and images.
void R_DrawRect(int x, int y, int w, int h, const vec4_t color, float lineWidth, int pattern)
Draws a rect to the screen. Also has support for stippled rendering of the rect.
Definition: r_draw.cpp:390
int UI_DrawString(const char *fontID, align_t align, int x, int y, int absX, int maxWidth, int lineHeight, const char *c, int boxHeight, int scrollPos, int *curLine, bool increaseLine, longlines_t method)
Definition: ui_render.cpp:371
sequenceContext_t * SEQ_AllocContext(void)
Allocate a sequence context.
static int SEQ_ExecuteAnimSpeed(sequenceContext_t *context, const char *name, const char *data)
Set the animation speed, default value is 1000.
struct seq2D_s seq2D_t
Represents a text object or image object.
vec3_t angles
Definition: cl_sequence.cpp:66
vec3_t camorg
Definition: cl_camera.h:32
#define Mem_AllocType(type)
Definition: mem.h:39
vec2_t size
int y
Definition: cl_video.h:76
void Com_UnParseLastToken(void)
Put back the last token into the parser The next call of Com_Parse will return the same token again...
Definition: parse.cpp:42
#define lengthof(x)
Definition: shared.h:105
static void SEQ_SetCamera(sequenceContext_t *context)
Set the camera values for a sequence.
GLsizei const GLvoid * data
Definition: r_gl.h:152
float zoom
Definition: cl_camera.h:39
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition: cvar.cpp:615
#define Q_streq(a, b)
Definition: shared.h:136
void R_DrawFill(int x, int y, int w, int h, const vec4_t color)
Fills a box of pixels with a single color.
Definition: r_draw.cpp:188
struct seqCmd_s seqCmd_t
void R_PushMatrix(void)
Push a new matrix to the stack.
Definition: r_misc.cpp:240
void R_RenderFrame(void)
Definition: r_main.cpp:298
vec2_t speed
seqEnt_t ents[MAX_SEQENTS]
static int CL_FindSequenceCommand(const char *commandName)
void SEQ_SetView(sequenceContext_t *context, vec2_t pos, vec2_t size)
Define the position of the viewport on the screen.
seqCamera_t camera
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
static int SEQ_ExecuteCommand(sequenceContext_t *context, const char *name, const char *data)
Executes a sequence command.
bool inuse
Definition: cl_sequence.cpp:78
static const value_t seqEnt_vals[]
valid entity names for a sequence
Definition: scripts.h:55
static void SEQ_Render2D(sequenceContext_t *context, bool backgroundObjects)
Renders text and images.
mapTiles_t * mapTiles
Definition: cl_renderer.h:203
vec3_t angles
Definition: cl_sequence.cpp:84
static int SEQ_ExecuteMusic(sequenceContext_t *context, const char *name, const char *data)
Changes the music in the sequence.
static void SEQ_Render3D(sequenceContext_t *context)
vec3_t axis[3]
Definition: cl_camera.h:36
vec3_t color
Definition: cl_sequence.cpp:86
#define MAX_SEQCMDS
#define SND_VOLUME_DEFAULT
Definition: s_main.h:42
static void SEQ_StopSequence(sequenceContext_t *context)
vec_t vec4_t[4]
Definition: ufotypes.h:40
Represents a text object or image object.
Definition: cl_sequence.cpp:97