~ubuntu-branches/ubuntu/lucid/warzone2100/lucid

« back to all changes in this revision

Viewing changes to src/message.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger, Paul Wise, Christoph Egger
  • Date: 2009-06-29 17:12:52 UTC
  • mfrom: (1.1.11 upstream) (2.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090629171252-5ddnlfg3zfchrega
Tags: 2.2.1+dfsg1-1
[ Paul Wise ]
* New upstream release (Closes: #534962)
* Adjust the flex build-depends to take account of the conflict
  with all the versions of flex 2.5.34 (LP: #372872)
* Make the -music Recommends more strict, 2.1 music doesn't work
  with 2.2.
* Upstream moved the downloads to sourceforge, update the watch file
* Bump Standards-Version, no changes needed
* Drop use of dh_desktop since it no longer does anything
* Recommend the new warzone2100-video package, version 2.2 or similar
* Mention the warzone2100 crash reports in the -dbg package description

[ Christoph Egger ]
* Replace CC-2.0 graphic from cybersphinx, create a new tarball
* Add myself to uploaders

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
        This file is part of Warzone 2100.
3
3
        Copyright (C) 1999-2004  Eidos Interactive
4
 
        Copyright (C) 2005-2007  Warzone Resurrection Project
 
4
        Copyright (C) 2005-2009  Warzone Resurrection Project
5
5
 
6
6
        Warzone 2100 is free software; you can redistribute it and/or modify
7
7
        it under the terms of the GNU General Public License as published by
28
28
#include "lib/framework/frame.h"
29
29
#include "lib/framework/strres.h"
30
30
#include "lib/framework/frameresource.h"
 
31
#include "lib/framework/lexer_input.h"
31
32
#include "message.h"
32
33
#include "stats.h"
33
34
#include "text.h"
38
39
#include "lib/ivis_common/piedef.h"
39
40
#include "objmem.h"
40
41
#include "map.h"
 
42
#include "message_parser.tab.h"
 
43
#include "messagely.h"
41
44
 
42
45
#include "multiplay.h"
43
46
 
44
 
//max number of text strings or sequences for viewdata
45
 
#define MAX_DATA                4
46
 
 
47
47
//array of pointers for the view data
48
48
static VIEWDATA_LIST            *apsViewData;
49
49
 
67
67
static void removeProxDisp(MESSAGE *psMessage, UDWORD player);
68
68
static void checkMessages(MSG_VIEWDATA *psViewData);
69
69
 
70
 
 
71
70
/* Creating a new message
72
71
 * new is a pointer to a pointer to the new message
73
72
 * type is the type of the message
76
75
{
77
76
        MESSAGE *newMsg;
78
77
 
79
 
        ASSERT(player < MAX_PLAYERS, "createMessage: Bad player");
80
 
        ASSERT(msgType < MSG_TYPES, "createMessage: Bad message");
 
78
        ASSERT_OR_RETURN(NULL, player < MAX_PLAYERS, "Bad player");
 
79
        ASSERT_OR_RETURN(NULL, msgType < MSG_TYPES, "Bad message");
81
80
        if (player >= MAX_PLAYERS || msgType >= MSG_TYPES)
82
81
        {
83
82
                return NULL;
110
109
{
111
110
        MESSAGE *psCurr = NULL, *psPrev = NULL;
112
111
 
113
 
        ASSERT(msg != NULL, "addMessageToList: Invalid message pointer");
114
 
        ASSERT(player < MAX_PLAYERS, "addMessageToList: Bad player");
 
112
        ASSERT_OR_RETURN( , msg != NULL, "Invalid message pointer");
 
113
        ASSERT_OR_RETURN( , player < MAX_PLAYERS, "Bad player");
115
114
 
116
115
        // If there is no message list, create one
117
116
        if (list[player] == NULL)
123
122
        }
124
123
 
125
124
        switch (msg->type)
126
 
        {
 
125
                {
127
126
                case MSG_CAMPAIGN:
128
127
                        /*add it before the first mission/research/prox message */
129
128
                        for(psCurr = list[player]; psCurr != NULL; psCurr = psCurr->psNext)
130
129
                        {
131
130
                                if (psCurr->type == MSG_MISSION ||
132
 
                                    psCurr->type == MSG_RESEARCH ||
133
 
                                    psCurr->type == MSG_PROXIMITY)
 
131
                                        psCurr->type == MSG_RESEARCH ||
 
132
                                        psCurr->type == MSG_PROXIMITY)
134
133
                                        break;
135
134
 
136
135
                                psPrev = psCurr;
188
187
 
189
188
                        break;
190
189
                default:
191
 
                        debug(LOG_ERROR, "addMessageToList: unknown message type");
 
190
                        debug(LOG_ERROR, "unknown message type");
192
191
                        break;
193
192
        }
194
193
}
203
202
{
204
203
        MESSAGE *psPrev = NULL, *psCurr;
205
204
 
206
 
        ASSERT(del != NULL, "removeMessageFromList: Invalid message pointer");
207
 
        ASSERT(player < MAX_PLAYERS, "removeMessageFromList: Bad player");
 
205
        ASSERT_OR_RETURN( , del != NULL, "Invalid message pointer");
 
206
        ASSERT_OR_RETURN( , player < MAX_PLAYERS, "Bad player");
208
207
 
209
208
        // If the message to remove is the first one in the list then mark the next one as the first
210
209
        if (list[player] == del)
220
219
                psPrev = psCurr;
221
220
        }
222
221
 
223
 
        ASSERT(psCurr != NULL, "removeMessage: message not found in list");
 
222
        ASSERT(psCurr != NULL, "message not found in list");
224
223
 
225
224
        if (psCurr != NULL)
226
225
        {
242
241
                // Iterate through all messages in list
243
242
                for(psCurr = list[i]; psCurr != NULL; psCurr = psNext)
244
243
                {
245
 
                        psNext = psCurr->psNext;
 
244
                        psNext = psCurr->psNext;
246
245
                        free(psCurr);
247
246
                }
248
247
                list[i] = NULL;
277
276
{
278
277
        MESSAGE* psBeaconMsgToAdd = addMessage(msgType, proxPos, player);
279
278
 
280
 
        ASSERT(psBeaconMsgToAdd, "addBeaconMessage: createMessage failed");
 
279
        ASSERT_OR_RETURN(NULL, psBeaconMsgToAdd, "createMessage failed");
281
280
 
282
281
        // remember we are storing beacon data in this message
283
282
        psBeaconMsgToAdd->dataType = MSG_DATA_BEACON;
316
315
{
317
316
        PROXIMITY_DISPLAY *psToAdd;
318
317
 
319
 
        ASSERT(player < MAX_PLAYERS, "addProximityDisplay: Bad player");
 
318
        ASSERT_OR_RETURN( , player < MAX_PLAYERS, "Bad player");
320
319
        debug(LOG_MSG, "Added prox display for player %u (proxPos=%d)", player, (int)proxPos);
321
320
 
322
321
        //create the proximity display
323
322
        psToAdd = (PROXIMITY_DISPLAY*)malloc(sizeof(PROXIMITY_DISPLAY));
324
323
        if (psToAdd == NULL)
325
324
        {
326
 
                ASSERT(false, "addProximityDisplay: out of memory");
 
325
                ASSERT(false, "out of memory");
327
326
                return;
328
327
        }
329
328
 
339
338
        psToAdd->screenX = 0;
340
339
        psToAdd->screenY = 0;
341
340
        psToAdd->screenR = 0;
342
 
        psToAdd->radarX = 0;
343
 
        psToAdd->radarY = 0;
344
341
        psToAdd->player = player;
345
342
        psToAdd->timeLastDrawn = 0;
346
343
        psToAdd->frameNumber = 0;
356
353
        currentNumProxDisplays++;
357
354
}
358
355
 
359
 
 /*remove a message */
 
356
/*remove a message */
360
357
void removeMessage(MESSAGE *psDel, UDWORD player)
361
358
{
362
 
        ASSERT(player < MAX_PLAYERS, "removeMessage: Bad player");
363
 
        ASSERT(psDel != NULL, "removeMessage: Bad message");
364
 
        debug(LOG_MSG, "removeMessage: removing message for player %d", player);
 
359
        ASSERT_OR_RETURN( , player < MAX_PLAYERS, "Bad player");
 
360
        ASSERT_OR_RETURN( , psDel != NULL, "Bad message");
 
361
        debug(LOG_MSG, "removing message for player %d", player);
365
362
 
366
363
        if (psDel->type == MSG_PROXIMITY)
367
364
        {
375
372
{
376
373
        PROXIMITY_DISPLAY               *psCurr, *psPrev;
377
374
 
378
 
        ASSERT(player < MAX_PLAYERS, "removeProxDisp: Bad player");
379
 
        ASSERT(psMessage != NULL, "removeProxDisp: Bad message");
 
375
        ASSERT_OR_RETURN( , player < MAX_PLAYERS, "Bad player");
 
376
        ASSERT_OR_RETURN( , psMessage != NULL, "Bad message");
380
377
 
381
378
        //find the proximity display for this message
382
379
        if (apsProxDisp[player]->psMessage == psMessage)
423
420
        {
424
421
                for(psCurr = apsProxDisp[player]; psCurr != NULL; psCurr = psNext)
425
422
                {
426
 
                        psNext = psCurr->psNext;
 
423
                        psNext = psCurr->psNext;
427
424
                        //remove message associated with this display
428
425
                        removeMessage(psCurr->psMessage, player);
429
426
                }
447
444
        return true;
448
445
}
449
446
 
450
 
static BOOL addToViewDataList(VIEWDATA *psViewData, UBYTE numData)
 
447
bool addToViewDataList(VIEWDATA* psViewData, unsigned int numData)
451
448
{
452
449
        VIEWDATA_LIST           *psAdd = (VIEWDATA_LIST*)malloc(sizeof(VIEWDATA_LIST));
453
450
 
454
451
        if (psAdd == NULL)
455
452
        {
456
 
                ASSERT(false, "addToViewDataList: out of memory");
 
453
                ASSERT(false, "out of memory");
457
454
                return false;
458
455
        }
459
456
 
469
466
/*load the view data for the messages from the file */
470
467
VIEWDATA *loadViewData(const char *pViewMsgData, UDWORD bufferSize)
471
468
{
472
 
        UDWORD                          i, id, dataInc, seqInc, numFrames, numData, count, count2;
 
469
        UDWORD                          i, dataInc, seqInc, dummy, numData, count, count2;
473
470
        VIEWDATA                        *psViewData, *pData;
474
471
        VIEW_RESEARCH           *psViewRes;
475
472
        VIEW_REPLAY                     *psViewReplay;
479
476
        char                            audioName[MAX_STR_LENGTH];
480
477
        SDWORD                          LocX,LocY,LocZ, audioID;
481
478
        PROX_TYPE       proxType;
482
 
        int cnt;
 
479
        int cnt;
483
480
 
484
481
        numData = numCR(pViewMsgData, bufferSize);
485
482
        if (numData > UBYTE_MAX)
486
483
        {
487
 
                ASSERT(false, "loadViewData: Didn't expect 256 viewData messages!");
 
484
                ASSERT(false, "Didn't expect 256 viewData messages!");
488
485
                return NULL;
489
486
        }
490
487
 
513
510
 
514
511
                //read the data into the storage - the data is delimeted using comma's
515
512
                sscanf(pViewMsgData,"%[^','],%d%n",name, &numText,&cnt);
516
 
                pViewMsgData += cnt;
 
513
                pViewMsgData += cnt;
517
514
 
518
515
                //check not loading up too many text strings
519
516
                if (numText > MAX_DATA)
524
521
                psViewData->numText=(UBYTE)numText;
525
522
 
526
523
                //allocate storage for the name
527
 
                psViewData->pName = malloc(strlen(name) + 1);
 
524
                psViewData->pName = strdup(name);
528
525
                if (psViewData->pName == NULL)
529
526
                {
530
527
                        ASSERT(false, "Out of memory");
531
528
                        return NULL;
532
529
                }
533
 
                strcpy(psViewData->pName, name);
534
530
                debug(LOG_MSG, "Loaded %s", psViewData->pName);
535
531
 
536
532
                //allocate space for text strings
544
540
                {
545
541
                        name[0] = '\0';
546
542
                        sscanf(pViewMsgData,",%[^',']%n",name,&cnt);
547
 
                        pViewMsgData += cnt;
 
543
                        pViewMsgData += cnt;
548
544
 
549
 
                        //get the ID for the string
550
 
                        if (!strresGetIDNum(psStringRes, name, &id))
 
545
                        // Get the string from the ID string
 
546
                        psViewData->ppTextMsg[dataInc] = strresGetString(psStringRes, name);
 
547
                        if (!psViewData->ppTextMsg[dataInc])
551
548
                        {
552
 
                                ASSERT(false, "Cannot find the view data string id %s ", name);
 
549
                                ASSERT(!"Cannot find string resource", "Cannot find the view data string with id \"%s\"", name);
553
550
                                return NULL;
554
551
                        }
555
 
                        //get the string from the id
556
 
                        psViewData->ppTextMsg[dataInc] = strresGetString(psStringRes, id);
557
552
                }
558
553
 
559
554
                sscanf(pViewMsgData, ",%d%n", &readint, &cnt);
560
555
                psViewData->type = readint;
561
 
                pViewMsgData += cnt;
 
556
                pViewMsgData += cnt;
562
557
 
563
558
                //allocate data according to type
564
559
                switch (psViewData->type)
575
570
                        string[0] = '\0';
576
571
                        audioName[0] = '\0';
577
572
                        sscanf(pViewMsgData,",%[^','],%[^','],%[^','],%[^','],%d%n",
578
 
                                imdName, imdName2, string, audioName, &numFrames,&cnt);
579
 
                        pViewMsgData += cnt;
 
573
                                imdName, imdName2, string, audioName, &dummy, &cnt);
 
574
                        pViewMsgData += cnt;
580
575
                        psViewRes = (VIEW_RESEARCH *)psViewData->pData;
581
576
                        psViewRes->pIMD = (iIMDShape *) resGetData("IMD", imdName);
582
577
                        if (psViewRes->pIMD == NULL)
583
578
                        {
584
 
                                ASSERT(LOG_ERROR, "Cannot find the PIE for message %s", name);
 
579
                                ASSERT(false, "Cannot find the PIE for message %s", name);
585
580
                                return NULL;
586
581
                        }
587
582
                        if (strcmp(imdName2, "0"))
597
592
                        {
598
593
                                psViewRes->pIMD2 = NULL;
599
594
                        }
600
 
                        strcpy(psViewRes->sequenceName, string);
 
595
                        sstrcpy(psViewRes->sequenceName, string);
601
596
                        //get the audio text string
602
597
                        if (strcmp(audioName, "0"))
603
598
                        {
604
599
                                //allocate space
605
 
                                psViewRes->pAudio = (char *) malloc(strlen(audioName) + 1);
 
600
                                psViewRes->pAudio = strdup(audioName);
606
601
                                if (psViewRes->pAudio == NULL)
607
602
                                {
608
603
                                        ASSERT(false, "loadViewData - Out of memory");
609
604
                                        return NULL;
610
605
                                }
611
 
                                strcpy(psViewRes->pAudio, audioName);
612
606
                        }
613
607
                        else
614
608
                        {
615
609
                                psViewRes->pAudio = NULL;
616
610
                        }
617
 
                        //this is for the PSX only
618
 
                        psViewRes->numFrames = (UWORD)numFrames;
619
611
                        break;
620
612
                case VIEW_RPL:
621
613
                case VIEW_RPLX:
632
624
                        //read in number of sequences for this message
633
625
                        //sscanf(pViewMsgData, "%d", &psViewReplay->numSeq);
634
626
                        sscanf(pViewMsgData, ",%d%n", &count,&cnt);
635
 
                        pViewMsgData += cnt;
 
627
                        pViewMsgData += cnt;
636
628
 
637
629
                        if (count > MAX_DATA)
638
630
                        {
639
 
                                ASSERT(false, "loadViewData: too many sequence for %s", psViewData->pName);
 
631
                                ASSERT(false, "too many sequence for %s", psViewData->pName);
640
632
                                return NULL;
641
633
                        }
642
634
 
654
646
                                if (psViewData->type == VIEW_RPL)
655
647
                                {
656
648
                                        sscanf(pViewMsgData, ",%[^','],%d%n", name, &count,&cnt);
657
 
                                        pViewMsgData += cnt;
 
649
                                        pViewMsgData += cnt;
658
650
                                        if (count > MAX_DATA)
659
651
                                        {
660
 
                                                ASSERT(false, "loadViewData: too many strings for %s", psViewData->pName);
 
652
                                                ASSERT(false, "too many strings for %s", psViewData->pName);
661
653
                                                return NULL;
662
654
                                        }
663
655
                                        psViewReplay->pSeqList[dataInc].numText = (UBYTE)count;
667
659
                                else //extended type
668
660
                                {
669
661
                                        sscanf(pViewMsgData, ",%[^','],%d,%d%n", name, &count,  &count2,&cnt);
670
 
                                        pViewMsgData += cnt;
 
662
                                        pViewMsgData += cnt;
671
663
                                        if (count > MAX_DATA)
672
664
                                        {
673
 
                                                ASSERT(false, "loadViewData: invalid video playback flag %s", psViewData->pName);
 
665
                                                ASSERT(false, "invalid video playback flag %s", psViewData->pName);
674
666
                                                return NULL;
675
667
                                        }
676
668
                                        psViewReplay->pSeqList[dataInc].flag = (UBYTE)count;
677
669
                                        //check not loading up too many text strings
678
670
                                        if (count2 > MAX_DATA)
679
671
                                        {
680
 
                                                ASSERT(false, "loadViewData: too many text strings for seq for %s", psViewData->pName);
 
672
                                                ASSERT(false, "too many text strings for seq for %s", psViewData->pName);
681
673
                                                return NULL;
682
674
                                        }
683
675
                                        psViewReplay->pSeqList[dataInc].numText = (UBYTE)count2;
688
680
                                //allocate space for text strings
689
681
                                if (psViewReplay->pSeqList[dataInc].numText)
690
682
                                {
691
 
                                        psViewReplay->pSeqList[dataInc].ppTextMsg = (char **) malloc(
 
683
                                        psViewReplay->pSeqList[dataInc].ppTextMsg = (const char **) malloc(
692
684
                                                psViewReplay->pSeqList[dataInc].numText * sizeof(char *));
693
685
                                }
694
686
                                //read in the data for the text strings
697
689
                                {
698
690
                                        name[0] = '\0';
699
691
                                        sscanf(pViewMsgData,",%[^',']%n", name,&cnt);
700
 
                                        pViewMsgData += cnt;
701
 
                                        //get the ID for the string
702
 
                                        if (!strresGetIDNum(psStringRes, name, &id))
 
692
                                        pViewMsgData += cnt;
 
693
 
 
694
                                        // Get the string from the ID string
 
695
                                        psViewReplay->pSeqList[dataInc].ppTextMsg[seqInc] = strresGetString(psStringRes, name);
 
696
                                        if (!psViewReplay->pSeqList[dataInc].ppTextMsg[seqInc])
703
697
                                        {
704
 
                                                ASSERT(false, "Cannot find the view data string id %s ", name);
 
698
                                                ASSERT(!"Cannot find string resource", "Cannot find the view data string with id \"%s\"", name);
705
699
                                                return NULL;
706
700
                                        }
707
 
 
708
 
                                        //get the string from the id
709
 
                                        psViewReplay->pSeqList[dataInc].ppTextMsg[seqInc] = strresGetString(psStringRes, id);
710
701
                                }
711
702
                                //get the audio text string
712
 
                                sscanf(pViewMsgData,",%[^','],%d%n", audioName, &count,&cnt);
713
 
                                pViewMsgData += cnt;
714
 
 
715
 
                                ASSERT( count < UWORD_MAX, "loadViewData: numFrames too high for %s", name );
716
 
 
717
 
                                psViewReplay->pSeqList[dataInc].numFrames = (UWORD)count;
 
703
                                sscanf(pViewMsgData,",%[^','],%d%n", audioName, &dummy, &cnt);
 
704
                                pViewMsgData += cnt;
718
705
 
719
706
                                if (strcmp(audioName, "0"))
720
707
                                {
721
708
                                        //allocate space
722
 
                                        psViewReplay->pSeqList[dataInc].pAudio = (char *) malloc(
723
 
                                                strlen(audioName) + 1);
 
709
                                        psViewReplay->pSeqList[dataInc].pAudio = strdup(audioName);
724
710
                                        if (psViewReplay->pSeqList[dataInc].pAudio == NULL)
725
711
                                        {
726
712
                                                ASSERT(LOG_ERROR, "loadViewData - Out of memory");
727
713
                                                return NULL;
728
714
                                        }
729
 
                                        strcpy(psViewReplay->pSeqList[dataInc].pAudio, audioName);
730
715
                                }
731
716
                                else
732
717
                                {
742
727
                        {
743
728
                                ASSERT(false, "Unable to allocate memory");
744
729
                                return NULL;
745
 
                        } else {
 
730
                        }
 
731
                        else
 
732
                        {
746
733
                                int tmp;
747
734
 
748
735
                                audioName[0] = '\0';
749
736
                                sscanf( pViewMsgData, ", %d,%d,%d,%[^','],%d%n", &LocX, &LocY, &LocZ,
750
 
                                        audioName, &tmp, &cnt);
 
737
                                                audioName, &tmp, &cnt);
751
738
                                proxType = tmp;
752
739
                        }
753
740
                        pViewMsgData += cnt;
761
748
                        {
762
749
                                if ( (audioID = audio_GetIDFromStr( audioName )) == NO_SOUND )
763
750
                                {
764
 
                                        ASSERT(false, "loadViewData: couldn't get ID %d for weapon sound %s", audioID, audioName);
 
751
                                        ASSERT(false, "couldn't get ID %d for weapon sound %s", audioID, audioName);
765
752
                                        return false;
766
753
                                }
767
754
 
779
766
 
780
767
                        if (LocX < 0)
781
768
                        {
782
 
                                ASSERT(false, "loadViewData: Negative X coord for prox message - %s",name);
 
769
                                ASSERT(false, "Negative X coord for prox message - %s",name);
783
770
                                return NULL;
784
771
                        }
785
772
                        ((VIEW_PROXIMITY *)psViewData->pData)->x = (UDWORD)LocX;
786
773
                        if (LocY < 0)
787
774
                        {
788
 
                                ASSERT(false, "loadViewData: Negative Y coord for prox message - %s",name);
 
775
                                ASSERT(false, "Negative Y coord for prox message - %s",name);
789
776
                                return NULL;
790
777
                        }
791
778
                        ((VIEW_PROXIMITY *)psViewData->pData)->y = (UDWORD)LocY;
792
779
                        if (LocZ < 0)
793
780
                        {
794
 
                                ASSERT(false, "loadViewData: Negative Z coord for prox message - %s",name);
 
781
                                ASSERT(false, "Negative Z coord for prox message - %s",name);
795
782
                                return NULL;
796
783
                        }
797
784
                        ((VIEW_PROXIMITY *)psViewData->pData)->z = (UDWORD)LocZ;
816
803
        return pData;
817
804
}
818
805
 
 
806
VIEWDATA* loadResearchViewData(const char* fileName)
 
807
{
 
808
        bool retval;
 
809
        lexerinput_t input;
 
810
        VIEWDATA* psViewData;
 
811
 
 
812
        input.type = LEXINPUT_PHYSFS;
 
813
        input.input.physfsfile = PHYSFS_openRead(fileName);
 
814
        debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName);
 
815
        if (!input.input.physfsfile)
 
816
        {
 
817
                debug(LOG_ERROR, "PHYSFS_openRead(\"%s\") failed with error: %s\n", fileName, PHYSFS_getLastError());
 
818
                return NULL;
 
819
        }
 
820
 
 
821
        message_set_extra(&input);
 
822
        retval = (message_parse(&psViewData) == 0);
 
823
 
 
824
        message_lex_destroy();
 
825
        PHYSFS_close(input.input.physfsfile);
 
826
 
 
827
        return retval ? psViewData : NULL;
 
828
}
 
829
 
819
830
/*get the view data identified by the name */
820
831
VIEWDATA * getViewData(const char *pName)
821
832
{
849
860
/* Release the viewdata memory */
850
861
void viewDataShutDown(VIEWDATA *psViewData)
851
862
{
852
 
        VIEWDATA_LIST   *psList, *psPrev;
853
 
        UDWORD                  seqInc;
854
 
        VIEW_REPLAY             *psViewReplay;
855
 
        VIEW_RESEARCH   *psViewRes;
856
 
        UBYTE                   i;
857
 
 
858
 
        psPrev = apsViewData;
859
 
 
860
 
        for (psList = apsViewData; psList != NULL; psList = psList->psNext)
 
863
        VIEWDATA_LIST   *psList, **psPrev;
 
864
 
 
865
        for (psList = apsViewData, psPrev = &apsViewData; psList != NULL; psPrev = &psList->psNext, psList = psList->psNext)
861
866
        {
862
 
                if (psList->psViewData == psViewData)
863
 
                {
864
 
                        for (i = 0; i < psList->numViewData; i++)
865
 
                        {
866
 
                                psViewData = &psList->psViewData[i];
867
 
 
868
 
                                //check for any messages using this viewdata
869
 
                                checkMessages((MSG_VIEWDATA *)psViewData);
870
 
 
871
 
                                free(psViewData->pName);
872
 
                                psViewData->pName = NULL;
873
 
 
874
 
                                //free the space allocated for the text messages
875
 
                                if (psViewData->numText)
876
 
                                {
877
 
                                        free(psViewData->ppTextMsg);
878
 
                                        psViewData->ppTextMsg = NULL;
879
 
                                }
880
 
 
881
 
                                //free the space allocated for multiple sequences
882
 
                                if (psViewData->type == VIEW_RPL)
883
 
                                {
884
 
                                        psViewReplay = (VIEW_REPLAY *)psViewData->pData;
885
 
                                        if (psViewReplay->numSeq)
886
 
                                        {
887
 
                                                for (seqInc = 0; seqInc < psViewReplay->numSeq; seqInc++)
888
 
                                                {
889
 
                                                        //free the space allocated for the text messages
890
 
                                                        if (psViewReplay->pSeqList[seqInc].numText)
891
 
                                                        {
892
 
                                                                free(psViewReplay->pSeqList[seqInc].ppTextMsg);
893
 
                                                                psViewReplay->pSeqList[seqInc].ppTextMsg = NULL;
894
 
                                                        }
895
 
                                                        if (psViewReplay->pSeqList[seqInc].pAudio)
896
 
                                                        {
897
 
                                                                free(psViewReplay->pSeqList[seqInc].pAudio);
898
 
                                                                psViewReplay->pSeqList[seqInc].pAudio = NULL;
899
 
                                                        }
900
 
                                                }
901
 
                                                free(psViewReplay->pSeqList);
902
 
                                                psViewReplay->pSeqList = NULL;
903
 
                                        }
904
 
                                }
905
 
                                else if (psViewData->type == VIEW_RES)
906
 
                                {
907
 
                                        psViewRes = (VIEW_RESEARCH *)psViewData->pData;
908
 
                                        if (psViewRes->pAudio)
909
 
                                        {
910
 
                                                free(psViewRes->pAudio);
911
 
                                                psViewRes->pAudio = NULL;
912
 
                                        }
913
 
                                }
914
 
                                free(psViewData->pData);
915
 
                                psViewData->pData = NULL;
916
 
                        }
917
 
                        free(psList->psViewData);
918
 
                        psList->psViewData = NULL;
919
 
 
920
 
                        //remove viewData list from the heap
921
 
                        if (psList == apsViewData)
922
 
                        {
923
 
                                apsViewData = psList->psNext;
924
 
                                free(psList);
925
 
                        }
926
 
                        else
927
 
                        {
928
 
                                psPrev->psNext = psList->psNext;
929
 
                                free(psList);
930
 
                        }
931
 
                        break;
932
 
                }
 
867
                unsigned int i;
 
868
 
 
869
                // Skip non-matching etnries
 
870
                if (psList->psViewData != psViewData)
 
871
                {
 
872
                        continue;
 
873
                }
 
874
 
 
875
                for (i = 0; i < psList->numViewData; ++i)
 
876
                {
 
877
                        psViewData = &psList->psViewData[i];
 
878
 
 
879
                        //check for any messages using this viewdata
 
880
                        checkMessages((MSG_VIEWDATA *)psViewData);
 
881
 
 
882
                        free(psViewData->pName);
 
883
 
 
884
                        //free the space allocated for the text messages
 
885
                        if (psViewData->numText)
 
886
                        {
 
887
                                free(psViewData->ppTextMsg);
 
888
                        }
 
889
 
 
890
                        //free the space allocated for multiple sequences
 
891
                        if (psViewData->type == VIEW_RPL)
 
892
                        {
 
893
                                VIEW_REPLAY* const psViewReplay = (VIEW_REPLAY *)psViewData->pData;
 
894
                                if (psViewReplay->numSeq)
 
895
                                {
 
896
                                        unsigned int seqInc;
 
897
                                        for (seqInc = 0; seqInc < psViewReplay->numSeq; ++seqInc)
 
898
                                        {
 
899
                                                //free the space allocated for the text messages
 
900
                                                if (psViewReplay->pSeqList[seqInc].numText)
 
901
                                                {
 
902
                                                        free(psViewReplay->pSeqList[seqInc].ppTextMsg);
 
903
                                                }
 
904
                                                if (psViewReplay->pSeqList[seqInc].pAudio)
 
905
                                                {
 
906
                                                        free(psViewReplay->pSeqList[seqInc].pAudio);
 
907
                                                }
 
908
                                        }
 
909
                                        free(psViewReplay->pSeqList);
 
910
                                }
 
911
                        }
 
912
                        else if (psViewData->type == VIEW_RES)
 
913
                        {
 
914
                                VIEW_RESEARCH* const psViewRes = (VIEW_RESEARCH *)psViewData->pData;
 
915
                                if (psViewRes->pAudio)
 
916
                                {
 
917
                                        free(psViewRes->pAudio);
 
918
                                }
 
919
                        }
 
920
                        free(psViewData->pData);
 
921
                }
 
922
                free(psList->psViewData);
 
923
 
 
924
                // remove viewData list from the list
 
925
                *psPrev = psList->psNext;
 
926
                free(psList);
 
927
 
 
928
                /* Although we're a O(n) algorithm, lets not go for fullblown
 
929
                 * O(n) behaviour if not required.
 
930
                 */
 
931
                break;
933
932
        }
934
 
        psPrev = psList;
935
933
}
936
934
 
937
935
/* Looks through the players list of messages to find one with the same viewData
940
938
{
941
939
        MESSAGE                                 *psCurr;
942
940
 
943
 
        ASSERT(player < MAX_PLAYERS, "findMessage: Bad player");
944
 
        ASSERT(type < MSG_TYPES, "removeMessage: Bad message type");
 
941
        ASSERT_OR_RETURN(NULL, player < MAX_PLAYERS, "Bad player");
 
942
        ASSERT_OR_RETURN(NULL , type < MSG_TYPES, "Bad message type");
945
943
 
946
944
        for (psCurr = apsMessages[player]; psCurr != NULL; psCurr = psCurr->psNext)
947
945
        {
982
980
        {
983
981
                FEATURE *psFeature = (FEATURE *)psProxDisp->psMessage->pViewData;
984
982
 
985
 
                ASSERT( ((BASE_OBJECT *)psProxDisp->psMessage->pViewData)->type ==
986
 
                        OBJ_FEATURE, "displayProximityMessage: invalid feature" );
 
983
                ASSERT_OR_RETURN( , ((BASE_OBJECT *)psProxDisp->psMessage->pViewData)->type ==
 
984
                        OBJ_FEATURE, "invalid feature" );
987
985
 
988
986
                if (psFeature->psStats->subType == FEAT_OIL_RESOURCE)
989
987
                {
1046
1044
//add proximity messages for all untapped VISIBLE oil resources
1047
1045
void addOilResourceProximities(void)
1048
1046
{
1049
 
    FEATURE     *psFeat;
1050
 
    MESSAGE     *psMessage;
 
1047
        FEATURE     *psFeat;
 
1048
        MESSAGE     *psMessage;
1051
1049
 
1052
 
    //look thru the features to find oil resources
1053
 
    for (psFeat = apsFeatureLists[0]; psFeat != NULL; psFeat = psFeat->psNext)
1054
 
    {
1055
 
        if (psFeat->psStats->subType == FEAT_OIL_RESOURCE)
1056
 
        {
1057
 
            //check to see if the feature is visible to the selected player
1058
 
            if (psFeat->visible[selectedPlayer])
1059
 
            {
1060
 
                //if there isn't an oil derrick built on it
 
1050
        //look thru the features to find oil resources
 
1051
        for (psFeat = apsFeatureLists[0]; psFeat != NULL; psFeat = psFeat->psNext)
 
1052
        {
 
1053
                if (psFeat->psStats->subType == FEAT_OIL_RESOURCE)
 
1054
                {
 
1055
                        //check to see if the feature is visible to the selected player
 
1056
                        if (psFeat->visible[selectedPlayer])
 
1057
                        {
 
1058
                                //if there isn't an oil derrick built on it
1061
1059
                                if (!TileHasStructure(mapTile(map_coord(psFeat->pos.x),
1062
1060
                                        map_coord(psFeat->pos.y))))
1063
1061
                                {
1064
 
                    //add a proximity message
 
1062
                                        //add a proximity message
1065
1063
                                        psMessage = addMessage(MSG_PROXIMITY, true, selectedPlayer);
1066
1064
                                        if (psMessage)
1067
1065
                                        {
1068
1066
                                                psMessage->pViewData = (MSG_VIEWDATA *)psFeat;
1069
1067
                                        }
1070
 
                }
1071
 
            }
1072
 
        }
1073
 
    }
 
1068
                                }
 
1069
                        }
 
1070
                }
 
1071
        }
1074
1072
}