UFO: Alien Invasion
Loading...
Searching...
No Matches
cl_sequence.cpp
Go to the documentation of this file.
1
8
9/*
10Copyright (C) 2002-2025 UFO: Alien Invasion.
11
12This program is free software; you can redistribute it and/or
13modify it under the terms of the GNU General Public License
14as published by the Free Software Foundation; either version 2
15of the License, or (at your option) any later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20
21See the GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; if not, write to the Free Software
25Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27*/
28
29#include "cl_sequence.h"
30#include "../client.h"
33#include "../renderer/r_main.h"
34#include "../renderer/r_draw.h"
35#include "../renderer/r_misc.h" /* R_PushMatrix, R_PopMatrix */
37#include "../cl_language.h"
38#include "../../shared/parse.h"
39#include "../ui/ui_render.h"
40
41#define MAX_DATA_LENGTH 512
42
43struct sequenceContext_s;
44
49typedef int (*sequenceHandler_t) (struct sequenceContext_s* context, const char* name, const char* data);
50
51typedef struct seqCmd_s {
55} seqCmd_t;
56
57typedef struct sequence_s {
58 char name[MAX_VAR];
59 int start;
60 int length;
62
63typedef struct seqCamera_s {
68 float dist;
69 float ddist;
70 float zoom;
71 float dzoom;
73
93
116
117#define MAX_SEQCMDS 768
118#define MAX_SEQUENCES 32
119#define MAX_SEQENTS 128
120#define MAX_SEQ2DS 128
121
124
127static int numSequences;
128
131static int numSeqCmds;
132
165
167static 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
180static 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
195static 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
219static 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
234 AngleVectors(cl.cam.angles, cl.cam.axis[0], cl.cam.axis[1], cl.cam.axis[2]);
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
248static 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
266static 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
286static 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;
295 refdef.mapTiles = cl.mapTiles;
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
331 refdef.rendererFlags |= RDF_NOWORLDMODEL;
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();
346 R_PopMatrix();
347}
348
349
356static 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
451bool 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
477{
478 context->endClickLoop = true;
479}
480
486static 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
567static 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
584static int SEQ_ExecuteWait (sequenceContext_t* context, const char* name, const char* data)
585{
586 context->time += 1000 * atof(name);
587 return 1;
588}
589
594static int SEQ_ExecuteAnimSpeed (sequenceContext_t* context, const char* name, const char* data)
595{
596 context->animspeed = atoi(name);
597 return 1;
598}
599
606static 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);
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);
618 data += strlen(data) + 1;
619 }
620 } else
621 Com_Printf("SEQ_ExecutePrecache: unknown format '%s'\n", name);
622 return 1;
623}
624
628static 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
653static 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
710static 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
721static int SEQ_ExecuteSound (sequenceContext_t* context, const char* name, const char* data)
722{
724 return 1;
725}
726
733static 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:
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
789static 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
813static 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
822static 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
859
864static 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
878void 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 */
895 Com_Error(ERR_FATAL, "Too many sequences");
896
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
998void SEQ_Shutdown (void)
999{
1001 numSequences = 0;
1002 seqCmds = nullptr;
1003 numSeqCmds = 0;
1004}
clientBattleScape_t cl
const float MIN_ZOOM
Definition cl_camera.cpp:40
const char * CL_Translate(const char *t)
client_static_t cls
Definition cl_main.cpp:83
memPool_t * cl_genericPool
Definition cl_main.cpp:86
#define VID_NORM_WIDTH
Definition cl_renderer.h:40
#define RDF_NOWORLDMODEL
Definition cl_renderer.h:34
#define VID_NORM_HEIGHT
Definition cl_renderer.h:41
rendererData_t refdef
Definition r_main.cpp:45
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition r_state.cpp:1011
static int SEQ_ExecuteObj2D(sequenceContext_t *context, const char *name, const char *data)
Parse 2D objects like text and images.
bool SEQ_InitContext(sequenceContext_t *context, const char *name)
Initialize a sequence context from data of a named script sequence.
static void SEQ_SetCamera(sequenceContext_t *context)
Set the camera values for a sequence.
void CL_ParseSequence(const char *name, const char **text)
Reads the sequence values from given text-pointer.
static const value_t seq2D_vals[]
valid id names for 2d entity
static int SEQ_ExecuteDelete(sequenceContext_t *context, const char *name, const char *data)
Removed a sequence entity from the current sequence.
static sequenceHandler_t seqCmdFunc[]
Function to exeute all available commands.
static const value_t seqEnt_vals[]
valid entity names for a sequence
void SEQ_SendClickEvent(sequenceContext_t *context)
Unlock a click event for the current sequence or ends the current sequence if not locked.
void SEQ_FreeContext(sequenceContext_t *context)
Free a sequence context.
static int SEQ_ExecuteMusic(sequenceContext_t *context, const char *name, const char *data)
Changes the music in the sequence.
static int SEQ_ExecuteAnimSpeed(sequenceContext_t *context, const char *name, const char *data)
Set the animation speed, default value is 1000.
#define MAX_SEQ2DS
#define MAX_SEQENTS
void SEQ_SetView(sequenceContext_t *context, vec2_t pos, vec2_t size)
Define the position of the viewport on the screen.
static const value_t seqCamera_vals[]
valid id names for camera
void SEQ_Shutdown(void)
static int SEQ_ExecuteWait(sequenceContext_t *context, const char *name, const char *data)
Increase the sequence time.
static int SEQ_ExecuteClick(sequenceContext_t *context, const char *name, const char *data)
Wait until someone clicks with the mouse.
static void SEQ_Render3D(sequenceContext_t *context)
static int numSequences
#define MAX_DATA_LENGTH
static int CL_FindSequenceCommand(const char *commandName)
static void SEQ_StopSequence(sequenceContext_t *context)
#define MAX_SEQCMDS
static seqEnt_t * SEQ_FindEnt(sequenceContext_t *context, const char *name)
Finds a given entity in all sequence entities.
static int SEQ_ExecuteCamera(sequenceContext_t *context, const char *name, const char *data)
Parse the values for the camera like given in seqCamera.
static char const *const seqCmdName[]
int(* sequenceHandler_t)(struct sequenceContext_s *context, const char *name, const char *data)
execution function of a command
static int SEQ_ExecuteSound(sequenceContext_t *context, const char *name, const char *data)
Plays a sound in a sequence.
sequenceContext_t * SEQ_AllocContext(void)
Allocate a sequence context.
static int SEQ_ExecuteModel(sequenceContext_t *context, const char *name, const char *data)
Parse values for a sequence model.
#define MAX_SEQUENCES
static bool SEQ_Execute(sequenceContext_t *context)
Move the sequence to the right position according to the current time.
static void SEQ_Render2D(sequenceContext_t *context, bool backgroundObjects)
Renders text and images.
static sequence_t sequences[MAX_SEQUENCES]
static seqCmd_t * seqCmds
static int SEQ_ExecuteCommand(sequenceContext_t *context, const char *name, const char *data)
Executes a sequence command.
static int SEQ_ExecutePrecache(sequenceContext_t *context, const char *name, const char *data)
Precaches the models and images for a sequence.
#define SEQ_NUMCMDS
static int numSeqCmds
bool SEQ_Render(sequenceContext_t *context)
Execute and render a sequence.
static seq2D_t * SEQ_Find2D(sequenceContext_t *context, const char *name)
Finds a given 2d object in the current sequence data.
viddef_t viddef
Definition cl_video.cpp:34
void CL_ViewUpdateRenderData(void)
Updates the refdef.
Definition cl_view.cpp:210
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
cvar_t * cl_isometric
Definition cl_input.cpp:73
Primary header for client.
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
Definition cmd.cpp:126
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define ERR_DROP
Definition common.h:211
#define ERR_FATAL
Definition common.h:210
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition cvar.cpp:615
#define DEBUG_CLIENT
Definition defines.h:59
voidpf void uLong size
Definition ioapi.h:42
voidpf uLong int origin
Definition ioapi.h:45
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void LIST_Delete(linkedList_t **list)
Definition list.cpp:195
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
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
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_PoolStrDupTo(in, out, pool, tagNum)
Definition mem.h:49
#define Mem_AllocType(type)
Definition mem.h:39
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
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
Shared parsing functions.
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
void R_DrawImage(float x, float y, const image_t *image)
Draws an image or parts of it.
Definition r_draw.cpp:341
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 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
entity_t * R_GetFreeEntity(void)
Get the next free entry in the entity list (the last one).
Definition r_entity.cpp:684
void R_EntitySetOrigin(entity_t *ent, const vec3_t origin)
setter for entity origin
Definition r_entity.cpp:47
#define RF_NONE
Definition r_entity.h:34
QGL_EXTERN int GLboolean GLfloat * v
Definition r_gl.h:120
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition r_image.cpp:603
const image_t * R_FindPics(const char *name)
Searches for an image in the image array.
Definition r_image.cpp:673
@ it_pic
Definition r_image.h:45
void R_RenderFrame(void)
Definition r_main.cpp:298
void R_AnimRun(animState_t *as, const model_t *mod, int msec)
Run the animation of the given model.
void R_AnimChange(animState_t *as, const model_t *mod, const char *name)
Changes the animation for md2 models.
void R_PopMatrix(void)
Removes the current matrix from the stack.
Definition r_misc.cpp:248
void R_PushMatrix(void)
Push a new matrix to the stack.
Definition r_misc.cpp:240
model_t * R_FindModel(const char *name)
Tries to load a model.
Definition r_model.cpp:203
void S_StartLocalSample(const char *s, float volume)
Plays a sample without spatialization.
Definition s_mix.cpp:184
#define SND_VOLUME_DEFAULT
Definition s_main.h:42
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
bool Com_ParseList(const char **text, linkedList_t **list)
Definition scripts.cpp:1363
int Com_EParseValue(void *base, const char *token, valueTypes_t type, int ofs, size_t size)
Definition scripts.cpp:964
align_t
We need this here for checking the boundaries from script values.
Definition scripts.h:89
T & Com_GetValue(void *const object, value_t const *const value)
Definition scripts.h:174
@ V_BOOL
Definition scripts.h:50
@ V_FLOAT
Definition scripts.h:54
@ V_TRANSLATION_STRING
Definition scripts.h:59
@ V_HUNK_STRING
Definition scripts.h:69
@ V_NULL
Definition scripts.h:49
@ V_STRING
Definition scripts.h:58
@ V_ALIGN
Definition scripts.h:61
@ V_INT
Definition scripts.h:52
@ V_VECTOR
Definition scripts.h:56
@ V_COLOR
Definition scripts.h:57
@ V_POS
Definition scripts.h:55
#define MEMBER_SIZEOF(TYPE, MEMBER)
Definition scripts.h:34
#define Q_streq(a, b)
Definition shared.h:136
#define OBJZERO(obj)
Definition shared.h:178
#define MAX_VAR
Definition shared.h:36
#define lengthof(x)
Definition shared.h:105
#define CASSERT(x)
Definition shared.h:107
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
float alpha
Definition r_entity.h:111
vec3_t angles
Definition r_entity.h:98
struct model_s * model
Definition r_entity.h:97
const char * tagname
Definition r_entity.h:107
int skinnum
Definition r_entity.h:110
animState_t as
Definition r_entity.h:117
struct entity_s * tagent
Definition r_entity.h:106
vec3_t oldorigin
Definition r_entity.h:102
linkedList_t * next
Definition list.h:32
Represents a text object or image object.
vec2_t speed
char font[MAX_VAR]
vec4_t bgcolor
vec2_t pos
vec4_t fade
vec4_t bordercolor
vec2_t enlarge
vec4_t color
bool inBackground
align_t align
vec2_t size
char image[MAX_VAR]
char name[MAX_VAR]
bool relativePos
char * text
char name[MAX_VAR]
sequenceHandler_t handler
char data[MAX_DATA_LENGTH]
vec3_t color
vec3_t speed
entity_t * ep
float alpha
animState_t as
vec3_t angles
char parent[MAX_VAR]
vec3_t origin
char tag[MAX_VAR]
model_t * model
char name[MAX_VAR]
vec3_t omega
char name[MAX_VAR]
seq2D_t obj2Ds[MAX_SEQ2DS]
seqEnt_t ents[MAX_SEQENTS]
size_t ofs
Definition scripts.h:170
const char * string
Definition scripts.h:168
size_t size
Definition scripts.h:171
valueTypes_t type
Definition scripts.h:169
vec_t vec3_t[3]
Definition ufotypes.h:39
vec_t vec4_t[4]
Definition ufotypes.h:40
vec_t vec2_t[2]
Definition ufotypes.h:38
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)
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
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorSet(v, x, y, z)
Definition vector.h:59