1 #include "Civ_Quotes.h"
2 #include "Directories.h"
3 #include "Font_Control.h"
4 #include "Local.h"
5 #include "MouseSystem.h"
6 #include "Soldier_Find.h"
7 #include "StrategicMap.h"
8 #include "Timer_Control.h"
9 #include "MessageBoxScreen.h"
10 #include "Queen_Command.h"
11 #include "Overhead.h"
12 #include "AI.h"
13 #include "Render_Dirty.h"
14 #include "MercTextBox.h"
15 #include "Text.h"
16 #include "ScreenIDs.h"
17 #include "Animation_Data.h"
18 #include "Video.h"
19 #include "Message.h"
20 #include "RenderWorld.h"
21 #include "Cursors.h"
22 #include "Dialogue_Control.h"
23 #include "Quests.h"
24 #include "MapScreen.h"
25 #include "Strategic_Town_Loyalty.h"
26 #include "NPC.h"
27 #include "Strategic_Mines.h"
28 #include "Random.h"
29 #include "FileMan.h"
30 #include "UILayout.h"
31
32 #include "ContentManager.h"
33 #include "GameInstance.h"
34
35 #include <string_theory/format>
36 #include <string_theory/string>
37
38
39 #define CIV_QUOTE_TEXT_SIZE 160
40
41
42 #define DIALOGUE_DEFAULT_WIDTH 200
43 #define EXTREAMLY_LOW_TOWN_LOYALTY 20
44 #define HIGH_TOWN_LOYALTY 80
45 #define CIV_QUOTE_HINT 99
46
47
48 static UINT8 const gubNumEntries[NUM_CIV_QUOTES] =
49 {
50 15,
51 15,
52 15,
53 15,
54 15,
55 15,
56 15,
57 15,
58 15,
59 15,
60
61 15,
62 15,
63 15,
64 15,
65 15,
66 15,
67 15,
68 15,
69 15,
70 15,
71
72 5,
73 5,
74 15,
75 15,
76 15,
77 15,
78 15,
79 15,
80 15,
81 15,
82
83 15,
84 15,
85 2,
86 15,
87 15,
88 10,
89 10,
90 5,
91 3,
92 10,
93
94 3,
95 3,
96 3,
97 3,
98 3,
99 3,
100 3,
101 3,
102 3,
103 3
104 };
105
106
107 struct QUOTE_SYSTEM_STRUCT
108 {
109 BOOLEAN bActive;
110 MOUSE_REGION MouseRegion;
111 VIDEO_OVERLAY *video_overlay;
112 MercPopUpBox *dialogue_box;
113 UINT32 uiTimeOfCreation;
114 UINT32 uiDelayTime;
115 SOLDIERTYPE *pCiv;
116 };
117
118
119 static QUOTE_SYSTEM_STRUCT gCivQuoteData;
120
121 static UINT16 gusCivQuoteBoxWidth;
122 static UINT16 gusCivQuoteBoxHeight;
123
124
GetCivQuoteText(UINT8 ubCivQuoteID,UINT8 ubEntryID,ST::string & zQuote)125 static BOOLEAN GetCivQuoteText(UINT8 ubCivQuoteID, UINT8 ubEntryID, ST::string& zQuote)
126 try
127 {
128 char zFileName[164];
129
130 // Build filename....
131 if ( ubCivQuoteID == CIV_QUOTE_HINT )
132 {
133 if ( gbWorldSectorZ > 0 )
134 {
135 sprintf(zFileName, NPCDATADIR "/civ%02d.edt", CIV_QUOTE_MINERS_NOT_FOR_PLAYER);
136 }
137 else
138 {
139 sprintf(zFileName, NPCDATADIR "/%c%d.edt", 'a' + (gWorldSectorY - 1) , gWorldSectorX);
140 }
141 }
142 else
143 {
144 sprintf(zFileName, NPCDATADIR "/civ%02d.edt", ubCivQuoteID);
145 }
146
147 zQuote = GCM->loadEncryptedString(zFileName, CIV_QUOTE_TEXT_SIZE * ubEntryID, CIV_QUOTE_TEXT_SIZE);
148 return !zQuote.empty();
149 }
150 catch (...) { return FALSE; }
151
152
SurrenderMessageBoxCallBack(MessageBoxReturnValue const ubExitValue)153 static void SurrenderMessageBoxCallBack(MessageBoxReturnValue const ubExitValue)
154 {
155 if ( ubExitValue == MSG_BOX_RETURN_YES )
156 {
157 // CJC Dec 1 2002: fix multiple captures
158 BeginCaptureSquence();
159
160 // Do capture....
161 FOR_EACH_IN_TEAM(i, OUR_TEAM)
162 {
163 SOLDIERTYPE& s = *i;
164 if (!s.bInSector) continue;
165 if (s.bLife == 0) continue;
166 EnemyCapturesPlayerSoldier(&s);
167 RemoveSoldierFromTacticalSector(s);
168 }
169
170 EndCaptureSequence( );
171
172 gfSurrendered = TRUE;
173 SetCustomizableTimerCallbackAndDelay( 3000, CaptureTimerCallback, FALSE );
174
175 ActionDone( gCivQuoteData.pCiv );
176 }
177 else
178 {
179 ActionDone( gCivQuoteData.pCiv );
180 }
181 }
182
183
ShutDownQuoteBox(BOOLEAN fForce)184 static void ShutDownQuoteBox(BOOLEAN fForce)
185 {
186 if ( !gCivQuoteData.bActive )
187 {
188 return;
189 }
190
191 // Check for min time....
192 if ( ( GetJA2Clock( ) - gCivQuoteData.uiTimeOfCreation ) > 300 || fForce )
193 {
194 RemoveVideoOverlay(gCivQuoteData.video_overlay);
195
196 // Remove mouse region...
197 MSYS_RemoveRegion( &(gCivQuoteData.MouseRegion) );
198
199 RemoveMercPopupBox(gCivQuoteData.dialogue_box);
200 gCivQuoteData.dialogue_box = 0;
201 gCivQuoteData.bActive = FALSE;
202
203 // do we need to do anything at the end of the civ quote?
204 if ( gCivQuoteData.pCiv && gCivQuoteData.pCiv->bAction == AI_ACTION_OFFER_SURRENDER )
205 {
206 DoMessageBox(MSG_BOX_BASIC_STYLE, g_langRes->Message[STR_SURRENDER], GAME_SCREEN, MSG_BOX_FLAG_YESNO, SurrenderMessageBoxCallBack, NULL);
207 }
208 }
209 }
210
ShutDownQuoteBoxIfActive()211 BOOLEAN ShutDownQuoteBoxIfActive( )
212 {
213 if ( gCivQuoteData.bActive )
214 {
215 ShutDownQuoteBox( TRUE );
216
217 return( TRUE );
218 }
219
220 return( FALSE );
221 }
222
223
GetCivType(const SOLDIERTYPE * pCiv)224 INT8 GetCivType(const SOLDIERTYPE* pCiv)
225 {
226 if ( pCiv->ubProfile != NO_PROFILE )
227 {
228 return( CIV_TYPE_NA );
229 }
230
231 // ATE: Check if this person is married.....
232 // 1 ) check sector....
233 if ( gWorldSectorX == 10 && gWorldSectorY == 6 && gbWorldSectorZ == 0 )
234 {
235 // 2 ) the only female....
236 if ( pCiv->ubCivilianGroup == 0 && pCiv->bTeam != OUR_TEAM && pCiv->ubBodyType == REGFEMALE )
237 {
238 // She's a ho!
239 return( CIV_TYPE_MARRIED_PC );
240 }
241 }
242
243 // OK, look for enemy type - MUST be on enemy team, merc bodytype
244 if ( pCiv->bTeam == ENEMY_TEAM && IS_MERC_BODY_TYPE( pCiv ) )
245 {
246 return( CIV_TYPE_ENEMY );
247 }
248
249 if ( pCiv->bTeam != CIV_TEAM && pCiv->bTeam != MILITIA_TEAM )
250 {
251 return( CIV_TYPE_NA );
252 }
253
254 switch( pCiv->ubBodyType )
255 {
256 case REGMALE:
257 case BIGMALE:
258 case STOCKYMALE:
259 case REGFEMALE:
260 case FATCIV:
261 case MANCIV:
262 case MINICIV:
263 case DRESSCIV:
264 case CRIPPLECIV:
265 return( CIV_TYPE_ADULT );
266
267 case ADULTFEMALEMONSTER:
268 case AM_MONSTER:
269 case YAF_MONSTER:
270 case YAM_MONSTER:
271 case LARVAE_MONSTER:
272 case INFANT_MONSTER:
273 case QUEENMONSTER:
274 return( CIV_TYPE_NA );
275
276 case HATKIDCIV:
277 case KIDCIV:
278 return( CIV_TYPE_KID );
279
280 default:
281 return( CIV_TYPE_NA );
282 }
283 }
284
285
RenderCivQuoteBoxOverlay(VIDEO_OVERLAY * pBlitter)286 static void RenderCivQuoteBoxOverlay(VIDEO_OVERLAY* pBlitter)
287 {
288 if (gCivQuoteData.video_overlay == NULL)
289 return;
290 RenderMercPopUpBox(gCivQuoteData.dialogue_box, pBlitter->sX, pBlitter->sY, pBlitter->uiDestBuff);
291 InvalidateRegion(pBlitter->sX, pBlitter->sY, pBlitter->sX + gusCivQuoteBoxWidth,
292 pBlitter->sY + gusCivQuoteBoxHeight);
293 }
294
295
QuoteOverlayClickCallback(MOUSE_REGION * pRegion,INT32 iReason)296 static void QuoteOverlayClickCallback(MOUSE_REGION* pRegion, INT32 iReason)
297 {
298 static BOOLEAN fLButtonDown = FALSE;
299
300 if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
301 {
302 fLButtonDown = TRUE;
303 }
304
305 if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP && fLButtonDown )
306 {
307 // Shutdown quote box....
308 ShutDownQuoteBox( FALSE );
309 }
310 else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
311 {
312 fLButtonDown = FALSE;
313 }
314 }
315
316
BeginCivQuote(SOLDIERTYPE * pCiv,UINT8 ubCivQuoteID,UINT8 ubEntryID,INT16 sX,INT16 sY)317 void BeginCivQuote( SOLDIERTYPE *pCiv, UINT8 ubCivQuoteID, UINT8 ubEntryID, INT16 sX, INT16 sY )
318 {
319 // OK, do we have another on?
320 if ( gCivQuoteData.bActive )
321 {
322 // Delete?
323 ShutDownQuoteBox( TRUE );
324 }
325
326 // get text
327 ST::string zQuote;
328 if ( !GetCivQuoteText( ubCivQuoteID, ubEntryID, zQuote ) )
329 {
330 return;
331 }
332
333 ST::string gzCivQuote;
334 gzCivQuote = ST::format("\"{}\"", zQuote);
335
336 if ( ubCivQuoteID == CIV_QUOTE_HINT )
337 {
338 MapScreenMessage( FONT_MCOLOR_WHITE, MSG_DIALOG, ST::format("{}", gzCivQuote) );
339 }
340
341 // Prepare text box
342 gCivQuoteData.dialogue_box = PrepareMercPopupBox(0, BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, gzCivQuote, DIALOGUE_DEFAULT_WIDTH, 0, 0, 0, &gusCivQuoteBoxWidth, &gusCivQuoteBoxHeight);
343
344 // OK, find center for box......
345 sX = sX - ( gusCivQuoteBoxWidth / 2 );
346 sY = sY - ( gusCivQuoteBoxHeight / 2 );
347
348 // OK, limit to screen......
349 {
350 if ( sX < 0 )
351 {
352 sX = 0;
353 }
354
355 // CHECK FOR LEFT/RIGHT
356 if (sX + gusCivQuoteBoxWidth > SCREEN_WIDTH)
357 {
358 sX = SCREEN_WIDTH - gusCivQuoteBoxWidth;
359 }
360
361 // Now check for top
362 if ( sY < gsVIEWPORT_WINDOW_START_Y )
363 {
364 sY = gsVIEWPORT_WINDOW_START_Y;
365 }
366
367 // Check for bottom
368 sY = MIN(sY, gsVIEWPORT_WINDOW_END_Y - gusCivQuoteBoxHeight);
369 }
370
371 UINT16 const w = gusCivQuoteBoxWidth;
372 UINT16 const h = gusCivQuoteBoxHeight;
373
374 gCivQuoteData.video_overlay = RegisterVideoOverlay(RenderCivQuoteBoxOverlay, sX, sY, w, h);
375
376 //Define main region
377 MSYS_DefineRegion(&gCivQuoteData.MouseRegion, sX, sY, sX + w, sY + h, MSYS_PRIORITY_HIGHEST, CURSOR_NORMAL, MSYS_NO_CALLBACK, QuoteOverlayClickCallback);
378
379 gCivQuoteData.bActive = TRUE;
380
381 gCivQuoteData.uiTimeOfCreation = GetJA2Clock( );
382
383 gCivQuoteData.uiDelayTime = FindDelayForString( gzCivQuote ) + 500;
384
385 gCivQuoteData.pCiv = pCiv;
386
387 }
388
389
DetermineCivQuoteEntry(SOLDIERTYPE * pCiv,UINT8 * pubCivHintToUse,BOOLEAN fCanUseHints)390 static UINT8 DetermineCivQuoteEntry(SOLDIERTYPE* pCiv, UINT8* pubCivHintToUse, BOOLEAN fCanUseHints)
391 {
392 UINT8 ubCivType;
393 BOOLEAN bCivLowLoyalty = FALSE;
394 BOOLEAN bCivHighLoyalty = FALSE;
395 INT8 bCivHint;
396 INT8 bMineId;
397 BOOLEAN bMiners = FALSE;
398
399 (*pubCivHintToUse) = 0;
400
401 ubCivType = GetCivType( pCiv );
402
403 if ( ubCivType == CIV_TYPE_ENEMY )
404 {
405 // Determine what type of quote to say...
406 // Are are we going to attack?
407
408 if ( pCiv->bAction == AI_ACTION_TOSS_PROJECTILE || pCiv->bAction == AI_ACTION_FIRE_GUN ||
409 pCiv->bAction == AI_ACTION_FIRE_GUN || pCiv->bAction == AI_ACTION_KNIFE_MOVE )
410 {
411 return( CIV_QUOTE_ENEMY_THREAT );
412 }
413 else if ( pCiv->bAction == AI_ACTION_OFFER_SURRENDER )
414 {
415 return( CIV_QUOTE_ENEMY_OFFER_SURRENDER );
416 }
417 // Hurt?
418 else if ( pCiv->bLife < 30 )
419 {
420 return( CIV_QUOTE_ENEMY_HURT );
421 }
422 // elite?
423 else if ( pCiv->ubSoldierClass == SOLDIER_CLASS_ELITE )
424 {
425 return( CIV_QUOTE_ENEMY_ELITE );
426 }
427 else
428 {
429 return( CIV_QUOTE_ENEMY_ADMIN );
430 }
431 }
432
433 // Are we in a town sector?
434 UINT8 const bTownId = GetTownIdForSector(SECTOR(gWorldSectorX, gWorldSectorY));
435
436 // If a married PC...
437 if ( ubCivType == CIV_TYPE_MARRIED_PC )
438 {
439 return( CIV_QUOTE_PC_MARRIED );
440 }
441
442 // CIV GROUPS FIRST!
443 // Hicks.....
444 if ( pCiv->ubCivilianGroup == HICKS_CIV_GROUP )
445 {
446 // Are they friendly?
447 //if ( gTacticalStatus.fCivGroupHostile[ HICKS_CIV_GROUP ] < CIV_GROUP_WILL_BECOME_HOSTILE )
448 if ( pCiv->bNeutral )
449 {
450 return( CIV_QUOTE_HICKS_FRIENDLY );
451 }
452 else
453 {
454 return( CIV_QUOTE_HICKS_ENEMIES );
455 }
456 }
457
458 // Goons.....
459 if ( pCiv->ubCivilianGroup == KINGPIN_CIV_GROUP )
460 {
461 // Are they friendly?
462 //if ( gTacticalStatus.fCivGroupHostile[ KINGPIN_CIV_GROUP ] < CIV_GROUP_WILL_BECOME_HOSTILE )
463 if ( pCiv->bNeutral )
464 {
465 return( CIV_QUOTE_GOONS_FRIENDLY );
466 }
467 else
468 {
469 return( CIV_QUOTE_GOONS_ENEMIES );
470 }
471 }
472
473 // ATE: Cowering people take precedence....
474 if ( ( pCiv->uiStatusFlags & SOLDIER_COWERING ) || ( pCiv->bTeam == CIV_TEAM && ( gTacticalStatus.uiFlags & INCOMBAT ) ) )
475 {
476 if ( ubCivType == CIV_TYPE_ADULT )
477 {
478 return( CIV_QUOTE_ADULTS_COWER );
479 }
480 else
481 {
482 return( CIV_QUOTE_KIDS_COWER );
483 }
484 }
485
486 // Kid slaves...
487 if ( pCiv->ubCivilianGroup == FACTORY_KIDS_GROUP )
488 {
489 // Check fact.....
490 if ( CheckFact( FACT_DOREEN_HAD_CHANGE_OF_HEART, 0 ) || !CheckFact( FACT_DOREEN_ALIVE, 0 ) )
491 {
492 return( CIV_QUOTE_KID_SLAVES_FREE );
493 }
494 else
495 {
496 return( CIV_QUOTE_KID_SLAVES );
497 }
498 }
499
500 // BEGGERS
501 if ( pCiv->ubCivilianGroup == BEGGARS_CIV_GROUP )
502 {
503 // Check if we are in a town...
504 if( bTownId != BLANK_SECTOR && gbWorldSectorZ == 0 )
505 {
506 if ( bTownId == SAN_MONA && ubCivType == CIV_TYPE_ADULT )
507 {
508 return( CIV_QUOTE_SAN_MONA_BEGGERS );
509 }
510 }
511
512 // DO normal beggers...
513 if ( ubCivType == CIV_TYPE_ADULT )
514 {
515 return( CIV_QUOTE_ADULTS_BEGGING );
516 }
517 else
518 {
519 return( CIV_QUOTE_KIDS_BEGGING );
520 }
521 }
522
523 // REBELS
524 if ( pCiv->ubCivilianGroup == REBEL_CIV_GROUP )
525 {
526 // DO normal beggers...
527 if ( ubCivType == CIV_TYPE_ADULT )
528 {
529 return( CIV_QUOTE_ADULTS_REBELS );
530 }
531 else
532 {
533 return( CIV_QUOTE_KIDS_REBELS );
534 }
535 }
536
537 // Do miltitia...
538 if ( pCiv->bTeam == MILITIA_TEAM )
539 {
540 // Different types....
541 if ( pCiv->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
542 {
543 return( CIV_QUOTE_GREEN_MILITIA );
544 }
545 if ( pCiv->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
546 {
547 return( CIV_QUOTE_MEDIUM_MILITIA );
548 }
549 if ( pCiv->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA )
550 {
551 return( CIV_QUOTE_ELITE_MILITIA );
552 }
553 }
554
555 // If we are in medunna, and queen is dead, use these...
556 if ( bTownId == MEDUNA && CheckFact( FACT_QUEEN_DEAD, 0 ) )
557 {
558 return( CIV_QUOTE_DEIDRANNA_DEAD );
559 }
560
561 // if in a town
562 if( ( bTownId != BLANK_SECTOR ) && ( gbWorldSectorZ == 0 ) && gfTownUsesLoyalty[ bTownId ] )
563 {
564 // Check loyalty special quotes.....
565 // EXTREMELY LOW TOWN LOYALTY...
566 if ( gTownLoyalty[ bTownId ].ubRating < EXTREAMLY_LOW_TOWN_LOYALTY )
567 {
568 bCivLowLoyalty = TRUE;
569 }
570
571 // HIGH TOWN LOYALTY...
572 if ( gTownLoyalty[ bTownId ].ubRating >= HIGH_TOWN_LOYALTY )
573 {
574 bCivHighLoyalty = TRUE;
575 }
576 }
577
578
579 // ATE: OK, check if we should look for a civ hint....
580 if ( fCanUseHints )
581 {
582 bCivHint = ConsiderCivilianQuotes( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE );
583 }
584 else
585 {
586 bCivHint = -1;
587 }
588
589 // ATE: check miners......
590 if ( pCiv->ubSoldierClass == SOLDIER_CLASS_MINER )
591 {
592 bMiners = TRUE;
593
594 // If not a civ hint available...
595 if ( bCivHint == -1 )
596 {
597 // Check if they are under our control...
598
599 // Should I go talk to miner?
600 // Not done yet.
601
602 // Are they working for us?
603 bMineId = GetIdOfMineForSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
604
605 if ( PlayerControlsMine( bMineId ) )
606 {
607 return( CIV_QUOTE_MINERS_FOR_PLAYER );
608 }
609 else
610 {
611 return( CIV_QUOTE_MINERS_NOT_FOR_PLAYER );
612 }
613 }
614 }
615
616
617 // Is one availible?
618 // If we are to say low loyalty, do chance
619 if ( bCivHint != -1 && bCivLowLoyalty && !bMiners )
620 {
621 if ( Random( 100 ) < 25 )
622 {
623 // Get rid of hint...
624 bCivHint = -1;
625 }
626 }
627
628 // Say hint if availible...
629 if ( bCivHint != -1 )
630 {
631 if ( ubCivType == CIV_TYPE_ADULT )
632 {
633 (*pubCivHintToUse) = bCivHint;
634
635 // Set quote as used...
636 ConsiderCivilianQuotes( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE );
637
638 // retrun value....
639 return( CIV_QUOTE_HINT );
640 }
641 }
642
643 if ( bCivLowLoyalty )
644 {
645 if ( ubCivType == CIV_TYPE_ADULT )
646 {
647 return( CIV_QUOTE_ADULTS_EXTREMLY_LOW_LOYALTY );
648 }
649 else
650 {
651 return( CIV_QUOTE_KIDS_EXTREMLY_LOW_LOYALTY );
652 }
653 }
654
655 if ( bCivHighLoyalty )
656 {
657 if ( ubCivType == CIV_TYPE_ADULT )
658 {
659 return( CIV_QUOTE_ADULTS_HIGH_LOYALTY );
660 }
661 else
662 {
663 return( CIV_QUOTE_KIDS_HIGH_LOYALTY );
664 }
665 }
666
667
668 // All purpose quote here....
669 if ( ubCivType == CIV_TYPE_ADULT )
670 {
671 return( CIV_QUOTE_ADULTS_ALL_PURPOSE );
672 }
673 else
674 {
675 return( CIV_QUOTE_KIDS_ALL_PURPOSE );
676 }
677
678 }
679
680
HandleCivQuote()681 void HandleCivQuote( )
682 {
683 if ( gCivQuoteData.bActive )
684 {
685 // Check for min time....
686 if ( ( GetJA2Clock( ) - gCivQuoteData.uiTimeOfCreation ) > gCivQuoteData.uiDelayTime )
687 {
688 // Stop!
689 ShutDownQuoteBox( TRUE );
690 }
691 }
692 }
693
StartCivQuote(SOLDIERTYPE * pCiv)694 void StartCivQuote( SOLDIERTYPE *pCiv )
695 {
696 UINT8 ubCivQuoteID;
697 INT16 sX, sY;
698 UINT8 ubEntryID = 0;
699 INT16 sScreenX, sScreenY;
700 UINT8 ubCivHintToUse;
701
702 // ATE: Check for old quote.....
703 // This could have been stored on last attempt...
704 if ( pCiv->bCurrentCivQuote == CIV_QUOTE_HINT )
705 {
706 // Determine which quote to say.....
707 // CAN'T USE HINTS, since we just did one...
708 pCiv->bCurrentCivQuote = -1;
709 pCiv->bCurrentCivQuoteDelta = 0;
710 ubCivQuoteID = DetermineCivQuoteEntry( pCiv, &ubCivHintToUse, FALSE );
711 }
712 else
713 {
714 // Determine which quote to say.....
715 ubCivQuoteID = DetermineCivQuoteEntry( pCiv, &ubCivHintToUse, TRUE );
716 }
717
718 // Determine entry id
719 // ATE: Try and get entry from soldier pointer....
720 if ( ubCivQuoteID != CIV_QUOTE_HINT )
721 {
722 if ( pCiv->bCurrentCivQuote == -1 )
723 {
724 // Pick random one
725 pCiv->bCurrentCivQuote = (INT8)Random(gubNumEntries[ubCivQuoteID] - 2);
726 pCiv->bCurrentCivQuoteDelta = 0;
727 }
728
729 ubEntryID = pCiv->bCurrentCivQuote + pCiv->bCurrentCivQuoteDelta;
730 }
731 else
732 {
733 ubEntryID = ubCivHintToUse;
734
735 // ATE: set value for quote ID.....
736 pCiv->bCurrentCivQuote = ubCivQuoteID;
737 pCiv->bCurrentCivQuoteDelta = ubEntryID;
738
739 }
740
741 // Determine location...
742 // Get location of civ on screen.....
743 GetSoldierScreenPos( pCiv, &sScreenX, &sScreenY );
744 sX = sScreenX;
745 sY = sScreenY;
746
747 // begin quote
748 BeginCivQuote( pCiv, ubCivQuoteID, ubEntryID, sX, sY );
749
750 // Increment use
751 if ( ubCivQuoteID != CIV_QUOTE_HINT )
752 {
753 pCiv->bCurrentCivQuoteDelta++;
754
755 if ( pCiv->bCurrentCivQuoteDelta == 2 )
756 {
757 pCiv->bCurrentCivQuoteDelta = 0;
758 }
759 }
760 }
761
762
InitCivQuoteSystem()763 void InitCivQuoteSystem( )
764 {
765 gCivQuoteData = QUOTE_SYSTEM_STRUCT{};
766 gCivQuoteData.bActive = FALSE;
767 gCivQuoteData.video_overlay = NULL;
768 gCivQuoteData.dialogue_box = 0;
769 }
770
771
SaveCivQuotesToSaveGameFile(HWFILE const f)772 void SaveCivQuotesToSaveGameFile(HWFILE const f)
773 {
774 FileSeek(f, NUM_CIV_QUOTES * 2, FILE_SEEK_FROM_CURRENT);
775 }
776
777
LoadCivQuotesFromLoadGameFile(HWFILE const f)778 void LoadCivQuotesFromLoadGameFile(HWFILE const f)
779 {
780 FileSeek(f, NUM_CIV_QUOTES * 2, FILE_SEEK_FROM_CURRENT);
781 }
782