Dialogue Control.c 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875
  1. #ifdef PRECOMPILEDHEADERS
  2. #include "Tactical All.h"
  3. #include "PreBattle Interface.h"
  4. #else
  5. #include "sgp.h"
  6. #include "soldier control.h"
  7. #include "Encrypted File.h"
  8. #include "faces.h"
  9. #include "wcheck.h"
  10. #include "gap.h"
  11. #include "overhead.h"
  12. #include "sound control.h"
  13. #include "dialogue control.h"
  14. #include "Message.h"
  15. #include "render dirty.h"
  16. #include "soldier profile.h"
  17. #include "wordwrap.h"
  18. #include "sysutil.h"
  19. #include "vobject_blitters.h"
  20. #include "AimMembers.h"
  21. #include "mercs.h"
  22. #include "interface dialogue.h"
  23. #include "merctextbox.h"
  24. #include "renderworld.h"
  25. #include "soldier macros.h"
  26. #include "squads.h"
  27. #include "screenids.h"
  28. #include "interface utils.h"
  29. #include "strategicmap.h"
  30. #include "PreBattle Interface.h"
  31. #include "Game Clock.h"
  32. #include "Quests.h"
  33. #include "cursors.h"
  34. #include "gamescreen.h"
  35. #include "Random.h"
  36. #include "Map Screen Helicopter.h"
  37. #include "GameSettings.h"
  38. #include "ShopKeeper Interface.h"
  39. #include "Map Screen Interface.h"
  40. #include "text.h"
  41. #include "Merc Contract.h"
  42. #include "history.h"
  43. #include "Town Militia.h"
  44. #include "meanwhile.h"
  45. #include "SkillCheck.h"
  46. #include "Interface Control.h"
  47. #include "finances.h"
  48. #endif
  49. #define DIALOGUESIZE 480
  50. #define QUOTE_MESSAGE_SIZE 520
  51. #define TALK_PANEL_FACE_X 6
  52. #define TALK_PANEL_FACE_Y 9
  53. #define TALK_PANEL_NAME_X 5
  54. #define TALK_PANEL_NAME_Y 114
  55. #define TALK_PANEL_NAME_WIDTH 92
  56. #define TALK_PANEL_NAME_HEIGHT 15
  57. #define TALK_PANEL_MENU_STARTY 8
  58. #define TALK_PANEL_MENU_HEIGHT 24
  59. #define TALK_MENU_WIDTH 96
  60. #define TALK_MENU_HEIGHT 16
  61. #define DIALOGUE_DEFAULT_SUBTITLE_WIDTH 200
  62. #define TEXT_DELAY_MODIFIER 60
  63. typedef struct
  64. {
  65. UINT16 usQuoteNum;
  66. UINT8 ubCharacterNum;
  67. INT8 bUIHandlerID;
  68. INT32 iFaceIndex;
  69. INT32 iTimeStamp;
  70. UINT32 uiSpecialEventFlag;
  71. UINT32 uiSpecialEventData;
  72. UINT32 uiSpecialEventData2;
  73. UINT32 uiSpecialEventData3;
  74. UINT32 uiSpecialEventData4;
  75. BOOLEAN fFromSoldier;
  76. BOOLEAN fDelayed;
  77. BOOLEAN fPauseTime;
  78. } DIALOGUE_Q_STRUCT, *DIALOGUE_Q_STRUCT_PTR;
  79. extern INT32 giMapInvPrev;
  80. extern INT32 giMapInvNext;
  81. extern BOOLEAN gfSKIScreenExit;
  82. extern SOLDIERTYPE *pProcessingSoldier;
  83. extern BOOLEAN fProcessingAMerc;
  84. extern UINT32 guiPendingScreen;
  85. extern BOOLEAN fReDrawFace;
  86. extern BOOLEAN gfWaitingForTriggerTimer;
  87. BOOLEAN fExternFacesLoaded = FALSE;
  88. UINT32 uiExternalStaticNPCFaces[ NUMBER_OF_EXTERNAL_NPC_FACES ];
  89. UINT32 uiExternalFaceProfileIds[ NUMBER_OF_EXTERNAL_NPC_FACES ]=
  90. {
  91. 97,
  92. 106,
  93. 148,
  94. 156,
  95. 157,
  96. 158,
  97. };
  98. UINT8 gubMercValidPrecedentQuoteID[ NUMBER_VALID_MERC_PRECEDENT_QUOTES ] =
  99. { 80, 81, 82, 83, 86, 87, 88, 95, 97, 99, 100, 101, 102 };
  100. extern INT32 iInterfaceDialogueBox;
  101. extern BOOLEAN gfRerenderInterfaceFromHelpText;
  102. extern UINT32 guiSKI_TransactionButton;
  103. UINT16 gusStopTimeQuoteList[ ] =
  104. {
  105. QUOTE_BOOBYTRAP_ITEM,
  106. QUOTE_SUSPICIOUS_GROUND
  107. };
  108. UINT8 gubNumStopTimeQuotes = 2;
  109. // QUEUE UP DIALOG!
  110. #define INITIAL_Q_SIZE 10
  111. HQUEUE ghDialogueQ = NULL;
  112. FACETYPE *gpCurrentTalkingFace = NULL;
  113. UINT8 gubCurrentTalkingID = NO_PROFILE;
  114. INT8 gbUIHandlerID;
  115. INT32 giNPCReferenceCount = 0;
  116. INT32 giNPCSpecialReferenceCount = 0;
  117. INT16 gsExternPanelXPosition = DEFAULT_EXTERN_PANEL_X_POS;
  118. INT16 gsExternPanelYPosition = DEFAULT_EXTERN_PANEL_Y_POS;
  119. BOOLEAN gfDialogueQueuePaused = FALSE;
  120. UINT16 gusSubtitleBoxWidth;
  121. UINT16 gusSubtitleBoxHeight;
  122. INT32 giTextBoxOverlay = -1;
  123. BOOLEAN gfFacePanelActive = FALSE;
  124. UINT32 guiScreenIDUsedWhenUICreated;
  125. INT16 gzQuoteStr[ QUOTE_MESSAGE_SIZE ];
  126. MOUSE_REGION gTextBoxMouseRegion;
  127. MOUSE_REGION gFacePopupMouseRegion;
  128. BOOLEAN gfUseAlternateDialogueFile = FALSE;
  129. // set the top position value for merc dialogue pop up boxes
  130. INT16 gsTopPosition = 20;
  131. INT32 iDialogueBox = -1;
  132. void RenderSubtitleBoxOverlay( VIDEO_OVERLAY *pBlitter );
  133. void RenderFaceOverlay( VIDEO_OVERLAY *pBlitter );
  134. extern BOOLEAN ContinueDialogue(SOLDIERTYPE *pSoldier, BOOLEAN fDone );
  135. extern void HandlePendingInitConv( );
  136. extern BOOLEAN WillMercRenew( SOLDIERTYPE *pSoldier, BOOLEAN fSayQuote );
  137. extern void DrawFace( INT16 sCharNumber );
  138. // the next said quote will pause time
  139. BOOLEAN fPausedTimeDuringQuote = FALSE;
  140. BOOLEAN fWasPausedDuringDialogue = FALSE;
  141. extern BOOLEAN gfLockPauseState;
  142. INT8 gubLogForMeTooBleeds = FALSE;
  143. // has the text region been created?
  144. BOOLEAN fTextBoxMouseRegionCreated = FALSE;
  145. BOOLEAN fExternFaceBoxRegionCreated = FALSE;
  146. // due to last quote system?
  147. BOOLEAN fDialogueBoxDueToLastMessage = FALSE;
  148. // last quote timers
  149. UINT32 guiDialogueLastQuoteTime = 0;
  150. UINT32 guiDialogueLastQuoteDelay = 0;
  151. void CheckForStopTimeQuotes( UINT16 usQuoteNum );
  152. void TextOverlayClickCallback( MOUSE_REGION * pRegion, INT32 iReason );
  153. void FaceOverlayClickCallback( MOUSE_REGION * pRegion, INT32 iReason );
  154. // Handler functions for tactical ui diaplay
  155. void HandleTacticalTextUI( INT32 iFaceIndex, SOLDIERTYPE *pSoldier, INT16 *zQuoteStr );
  156. void HandleTacticalNPCTextUI( UINT8 ubCharacterNum, INT16 *zQuoteStr );
  157. void HandleTacticalSpeechUI( UINT8 ubCharacterNum, INT32 iFaceIndex );
  158. void DisplayTextForExternalNPC( UINT8 ubCharacterNum, STR16 zQuoteStr );
  159. void CreateTalkingUI( INT8 bUIHandlerID, INT32 iFaceIndex, UINT8 ubCharacterNum, SOLDIERTYPE *pSoldier, INT16 *zQuoteStr );
  160. void HandleExternNPCSpeechFace( INT32 iIndex );
  161. extern BOOLEAN ContinueDialogue(SOLDIERTYPE *pSoldier, BOOLEAN fDone );
  162. extern BOOLEAN DoSkiMessageBox( UINT8 ubStyle, INT16 *zString, UINT32 uiExitScreen, UINT8 ubFlags, MSGBOX_CALLBACK ReturnCallback );
  163. void UnPauseGameDuringNextQuote( void )
  164. {
  165. fPausedTimeDuringQuote = FALSE;
  166. return;
  167. }
  168. void PauseTimeDuringNextQuote( void )
  169. {
  170. fPausedTimeDuringQuote = TRUE;
  171. return;
  172. }
  173. BOOLEAN DialogueActive( )
  174. {
  175. if ( gpCurrentTalkingFace != NULL )
  176. {
  177. return( TRUE );
  178. }
  179. return( FALSE );
  180. }
  181. BOOLEAN InitalizeDialogueControl()
  182. {
  183. ghDialogueQ = CreateQueue( INITIAL_Q_SIZE, sizeof( DIALOGUE_Q_STRUCT_PTR ) );
  184. // Initalize subtitle popup box
  185. //
  186. giNPCReferenceCount = 0;
  187. if ( ghDialogueQ == NULL )
  188. {
  189. return( FALSE );
  190. }
  191. else
  192. {
  193. return( TRUE );
  194. }
  195. }
  196. void ShutdownDialogueControl()
  197. {
  198. if( ghDialogueQ != NULL )
  199. {
  200. // Empty
  201. EmptyDialogueQueue( );
  202. // Delete
  203. DeleteQueue( ghDialogueQ );
  204. ghDialogueQ=NULL;
  205. }
  206. // shutdown external static NPC faces
  207. ShutdownStaticExternalNPCFaces( );
  208. // gte rid of portraits for cars
  209. UnLoadCarPortraits( );
  210. //
  211. }
  212. void InitalizeStaticExternalNPCFaces( void )
  213. {
  214. INT32 iCounter = 0;
  215. // go and grab all external NPC faces that are needed for the game who won't exist as soldiertypes
  216. if( fExternFacesLoaded == TRUE )
  217. {
  218. return;
  219. }
  220. fExternFacesLoaded = TRUE;
  221. for( iCounter = 0; iCounter < NUMBER_OF_EXTERNAL_NPC_FACES; iCounter++ )
  222. {
  223. uiExternalStaticNPCFaces[ iCounter ] = ( UINT32 )InitFace( ( UINT8 )( uiExternalFaceProfileIds[ iCounter ] ), NOBODY, FACE_FORCE_SMALL );
  224. }
  225. return;
  226. }
  227. void ShutdownStaticExternalNPCFaces( void )
  228. {
  229. INT32 iCounter = 0;
  230. if( fExternFacesLoaded == FALSE )
  231. {
  232. return;
  233. }
  234. fExternFacesLoaded = FALSE;
  235. // remove all external npc faces
  236. for( iCounter = 0; iCounter < NUMBER_OF_EXTERNAL_NPC_FACES; iCounter++ )
  237. {
  238. DeleteFace( uiExternalStaticNPCFaces[ iCounter ] );
  239. }
  240. }
  241. void EmptyDialogueQueue( )
  242. {
  243. // If we have anything left in the queue, remove!
  244. if( ghDialogueQ != NULL )
  245. {
  246. /*
  247. DEF: commented out because the Queue system ?? uses a contiguous memory block ??? for the queue
  248. so you cant delete a single node. The DeleteQueue, below, will free the entire memory block
  249. numDialogueItems = QueueSize( ghDialogueQ );
  250. for ( cnt = numDialogueItems-1; cnt >= 0; cnt-- )
  251. {
  252. if ( PeekQueue( ghDialogueQ, &QItem ) )
  253. {
  254. MemFree( QItem );
  255. }
  256. }
  257. */
  258. // Delete list
  259. DeleteQueue( ghDialogueQ );
  260. ghDialogueQ=NULL;
  261. // Recreate list
  262. ghDialogueQ = CreateQueue( INITIAL_Q_SIZE, sizeof( DIALOGUE_Q_STRUCT_PTR ) );
  263. }
  264. gfWaitingForTriggerTimer = FALSE;
  265. }
  266. BOOLEAN DialogueQueueIsEmpty( )
  267. {
  268. INT32 numDialogueItems;
  269. if( ghDialogueQ != NULL )
  270. {
  271. numDialogueItems = QueueSize( ghDialogueQ );
  272. if ( numDialogueItems == 0 )
  273. {
  274. return( TRUE );
  275. }
  276. }
  277. return( FALSE );
  278. }
  279. BOOLEAN DialogueQueueIsEmptyOrSomebodyTalkingNow( )
  280. {
  281. if ( gpCurrentTalkingFace != NULL )
  282. {
  283. return( FALSE );
  284. }
  285. if ( !DialogueQueueIsEmpty( ) )
  286. {
  287. return( FALSE );
  288. }
  289. return( TRUE );
  290. }
  291. void DialogueAdvanceSpeech( )
  292. {
  293. // Shut them up!
  294. InternalShutupaYoFace( gpCurrentTalkingFace->iID, FALSE );
  295. }
  296. void StopAnyCurrentlyTalkingSpeech( )
  297. {
  298. // ATE; Make sure guys stop talking....
  299. if ( gpCurrentTalkingFace != NULL )
  300. {
  301. InternalShutupaYoFace( gpCurrentTalkingFace->iID, TRUE );
  302. }
  303. }
  304. // ATE: Handle changes like when face goes from
  305. // 'external' to on the team panel...
  306. void HandleDialogueUIAdjustments( )
  307. {
  308. SOLDIERTYPE *pSoldier;
  309. // OK, check if we are still taking
  310. if ( gpCurrentTalkingFace != NULL )
  311. {
  312. if ( gpCurrentTalkingFace->fTalking )
  313. {
  314. // ATE: Check for change in state for the guy currently talking on 'external' panel....
  315. if ( gfFacePanelActive )
  316. {
  317. pSoldier = FindSoldierByProfileID( gubCurrentTalkingID, FALSE );
  318. if ( pSoldier )
  319. {
  320. if ( 0 )
  321. {
  322. // A change in plans here...
  323. // We now talk through the interface panel...
  324. if ( gpCurrentTalkingFace->iVideoOverlay != -1 )
  325. {
  326. RemoveVideoOverlay( gpCurrentTalkingFace->iVideoOverlay );
  327. gpCurrentTalkingFace->iVideoOverlay = -1;
  328. }
  329. gfFacePanelActive = FALSE;
  330. RemoveVideoOverlay( giTextBoxOverlay );
  331. giTextBoxOverlay = -1;
  332. if ( fTextBoxMouseRegionCreated )
  333. {
  334. MSYS_RemoveRegion( &gTextBoxMouseRegion );
  335. fTextBoxMouseRegionCreated = FALSE;
  336. }
  337. // Setup UI again!
  338. CreateTalkingUI( gbUIHandlerID, pSoldier->iFaceIndex, pSoldier->ubProfile, pSoldier, gzQuoteStr );
  339. }
  340. }
  341. }
  342. }
  343. }
  344. }
  345. void HandleDialogue( )
  346. {
  347. INT32 iQSize;
  348. DIALOGUE_Q_STRUCT *QItem;
  349. static BOOLEAN fOldEngagedInConvFlagOn = FALSE;
  350. BOOLEAN fDoneTalking = FALSE;
  351. SOLDIERTYPE *pSoldier = NULL;
  352. CHAR16 zText[ 512 ];
  353. CHAR16 zMoney[128];
  354. // we don't want to just delay action of some events, we want to pause the whole queue, regardless of the event
  355. if( gfDialogueQueuePaused )
  356. {
  357. return;
  358. }
  359. iQSize = QueueSize( ghDialogueQ );
  360. if ( iQSize == 0 && gpCurrentTalkingFace == NULL )
  361. {
  362. HandlePendingInitConv( );
  363. }
  364. HandleCivQuote( );
  365. // Alrighty, check for a change in state, do stuff appropriately....
  366. // Turned on
  367. if ( fOldEngagedInConvFlagOn == FALSE && ( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) )
  368. {
  369. // OK, we have just entered...
  370. fOldEngagedInConvFlagOn = TRUE;
  371. // pause game..
  372. PauseGame();
  373. LockPauseState( 14 );
  374. }
  375. else if ( fOldEngagedInConvFlagOn == TRUE && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) )
  376. {
  377. // OK, we left...
  378. fOldEngagedInConvFlagOn = FALSE;
  379. // Unpause game..
  380. UnLockPauseState();
  381. UnPauseGame();
  382. // if we're exiting boxing with the UI lock set then DON'T OVERRIDE THIS!
  383. if ( !(gTacticalStatus.bBoxingState == WON_ROUND || gTacticalStatus.bBoxingState == LOST_ROUND || gTacticalStatus.bBoxingState == DISQUALIFIED) && !( gTacticalStatus.uiFlags & IGNORE_ENGAGED_IN_CONV_UI_UNLOCK ) )
  384. {
  385. guiPendingOverrideEvent = LU_ENDUILOCK;
  386. HandleTacticalUI( );
  387. // ATE: If this is NOT the player's turn.. engage AI UI lock!
  388. if ( gTacticalStatus.ubCurrentTeam != gbPlayerNum )
  389. {
  390. // Setup locked UI
  391. guiPendingOverrideEvent = LU_BEGINUILOCK;
  392. HandleTacticalUI( );
  393. }
  394. }
  395. gTacticalStatus.uiFlags &= ( ~IGNORE_ENGAGED_IN_CONV_UI_UNLOCK );
  396. }
  397. if ( gTacticalStatus.uiFlags & ENGAGED_IN_CONV )
  398. {
  399. // Are we in here because of the dialogue system up?
  400. if ( !gfInTalkPanel )
  401. {
  402. // ATE: NOT if we have a message box pending....
  403. if ( guiPendingScreen != MSG_BOX_SCREEN && guiCurrentScreen != MSG_BOX_SCREEN )
  404. {
  405. // No, so we should lock the UI!
  406. guiPendingOverrideEvent = LU_BEGINUILOCK;
  407. HandleTacticalUI( );
  408. }
  409. }
  410. }
  411. // OK, check if we are still taking
  412. if ( gpCurrentTalkingFace != NULL )
  413. {
  414. if ( gpCurrentTalkingFace->fTalking )
  415. {
  416. // ATE: OK, MANAGE THE DISPLAY OF OUR CURRENTLY ACTIVE FACE IF WE / IT CHANGES STATUS
  417. // THINGS THAT CAN CHANGE STATUS:
  418. // CHANGE TO MAPSCREEN
  419. // CHANGE TO GAMESCREEN
  420. // CHANGE IN MERC STATUS TO BE IN A SQUAD
  421. // CHANGE FROM TEAM TO INV INTERFACE
  422. // Where are we and where did this face once exist?
  423. if ( guiScreenIDUsedWhenUICreated == GAME_SCREEN && guiCurrentScreen == MAP_SCREEN )
  424. {
  425. // GO FROM GAMESCREEN TO MAPSCREEN
  426. // REMOVE OLD UI
  427. // Set face inactive!
  428. //gpCurrentTalkingFace->fCanHandleInactiveNow = TRUE;
  429. //SetAutoFaceInActive( gpCurrentTalkingFace->iID );
  430. //gfFacePanelActive = FALSE;
  431. // delete face panel if there is one!
  432. if ( gfFacePanelActive )
  433. {
  434. // Set face inactive!
  435. if ( gpCurrentTalkingFace->iVideoOverlay != -1 )
  436. {
  437. RemoveVideoOverlay( gpCurrentTalkingFace->iVideoOverlay );
  438. gpCurrentTalkingFace->iVideoOverlay = -1;
  439. }
  440. if ( fExternFaceBoxRegionCreated )
  441. {
  442. fExternFaceBoxRegionCreated = FALSE;
  443. MSYS_RemoveRegion(&(gFacePopupMouseRegion) );
  444. }
  445. // Set face inactive....
  446. gpCurrentTalkingFace->fCanHandleInactiveNow = TRUE;
  447. SetAutoFaceInActive( gpCurrentTalkingFace->iID );
  448. HandleTacticalSpeechUI( gubCurrentTalkingID, gpCurrentTalkingFace->iID );
  449. // ATE: Force mapscreen to set face active again.....
  450. fReDrawFace = TRUE;
  451. DrawFace( bSelectedInfoChar );
  452. gfFacePanelActive = FALSE;
  453. }
  454. guiScreenIDUsedWhenUICreated = guiCurrentScreen;
  455. }
  456. else if ( guiScreenIDUsedWhenUICreated == MAP_SCREEN && guiCurrentScreen == GAME_SCREEN )
  457. {
  458. HandleTacticalSpeechUI( gubCurrentTalkingID, gpCurrentTalkingFace->iID );
  459. guiScreenIDUsedWhenUICreated = guiCurrentScreen;
  460. }
  461. return;
  462. }
  463. else
  464. {
  465. // Check special flags
  466. // If we are done, check special face flag for trigger NPC!
  467. if ( gpCurrentTalkingFace->uiFlags & FACE_PCTRIGGER_NPC )
  468. {
  469. // Decrement refrence count...
  470. giNPCReferenceCount--;
  471. TriggerNPCRecord( (UINT8)gpCurrentTalkingFace->uiUserData1, (UINT8)gpCurrentTalkingFace->uiUserData2 );
  472. //Reset flag!
  473. gpCurrentTalkingFace->uiFlags &= (~FACE_PCTRIGGER_NPC );
  474. }
  475. if ( gpCurrentTalkingFace->uiFlags & FACE_MODAL )
  476. {
  477. gpCurrentTalkingFace->uiFlags &= (~FACE_MODAL );
  478. EndModalTactical( );
  479. ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Ending Modal Tactical Quote." );
  480. }
  481. if ( gpCurrentTalkingFace->uiFlags & FACE_TRIGGER_PREBATTLE_INT )
  482. {
  483. UnLockPauseState();
  484. InitPreBattleInterface( (GROUP*)gpCurrentTalkingFace->uiUserData1, TRUE );
  485. //Reset flag!
  486. gpCurrentTalkingFace->uiFlags &= (~FACE_TRIGGER_PREBATTLE_INT );
  487. }
  488. gpCurrentTalkingFace = NULL;
  489. gubCurrentTalkingID = NO_PROFILE;
  490. gTacticalStatus.ubLastQuoteProfileNUm = NO_PROFILE;
  491. fDoneTalking = TRUE;
  492. }
  493. }
  494. if( ( fDoneTalking ) && ( fWasPausedDuringDialogue ) )
  495. {
  496. fWasPausedDuringDialogue = FALSE;
  497. // unlock pause state
  498. UnLockPauseState();
  499. UnPauseGame();
  500. }
  501. if ( iQSize == 0 )
  502. {
  503. if ( gfMikeShouldSayHi == TRUE )
  504. {
  505. SOLDIERTYPE * pMike;
  506. INT16 sPlayerGridNo;
  507. UINT8 ubPlayerID;
  508. pMike = FindSoldierByProfileID( MIKE, FALSE );
  509. if ( pMike )
  510. {
  511. sPlayerGridNo = ClosestPC( pMike, NULL );
  512. if (sPlayerGridNo != NOWHERE )
  513. {
  514. ubPlayerID = WhoIsThere2( sPlayerGridNo, 0 );
  515. if (ubPlayerID != NOBODY)
  516. {
  517. InitiateConversation( pMike, MercPtrs[ ubPlayerID ], NPC_INITIAL_QUOTE, 0 );
  518. gMercProfiles[ pMike->ubProfile ].ubMiscFlags2 |= PROFILE_MISC_FLAG2_SAID_FIRSTSEEN_QUOTE;
  519. // JA2Gold: special hack value of 2 to prevent dialogue from coming up more than once
  520. gfMikeShouldSayHi = 2;
  521. }
  522. }
  523. }
  524. }
  525. return;
  526. }
  527. // ATE: Remove any civ quotes....
  528. // ShutDownQuoteBoxIfActive( TRUE );
  529. // If here, pick current one from queue and play
  530. // Get new one
  531. RemfromQueue( ghDialogueQ, &QItem );
  532. // If we are in auto bandage, ignore any quotes!
  533. if ( gTacticalStatus.fAutoBandageMode )
  534. {
  535. if( QItem -> fPauseTime )
  536. {
  537. UnLockPauseState();
  538. UnPauseGame();
  539. }
  540. // Delete memory
  541. MemFree( QItem );
  542. return;
  543. }
  544. // Check time delay
  545. // Alrighty, check if this one is to be delayed until we gain control.
  546. // If so, place it back in!
  547. if ( QItem->fDelayed )
  548. {
  549. // Are we not in our turn and not interrupted
  550. if ( gTacticalStatus.ubCurrentTeam != gbPlayerNum )
  551. {
  552. //Place back in!
  553. // Add to queue
  554. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  555. return;
  556. }
  557. }
  558. // ATE: OK: If a battle sound, and delay value was given, set time stamp
  559. // now...
  560. if ( QItem->uiSpecialEventFlag == DIALOGUE_SPECIAL_EVENT_DO_BATTLE_SND )
  561. {
  562. if ( QItem->uiSpecialEventData2 != 0 )
  563. {
  564. if ( ( GetJA2Clock( ) - QItem->iTimeStamp ) < QItem->uiSpecialEventData2 )
  565. {
  566. //Place back in!
  567. // Add to queue
  568. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  569. return;
  570. }
  571. }
  572. }
  573. // Try to find soldier...
  574. pSoldier = FindSoldierByProfileID( QItem->ubCharacterNum, TRUE );
  575. if ( pSoldier != NULL )
  576. {
  577. if ( SoundIsPlaying( pSoldier->uiBattleSoundID ) )
  578. {
  579. //Place back in!
  580. // Add to queue
  581. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  582. return;
  583. }
  584. }
  585. if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) && ( QItem->uiSpecialEventFlag == 0 ) )
  586. {
  587. QItem-> fPauseTime = TRUE;
  588. }
  589. if( QItem-> fPauseTime )
  590. {
  591. if( GamePaused( ) == FALSE )
  592. {
  593. PauseGame();
  594. LockPauseState( 15 );
  595. fWasPausedDuringDialogue = TRUE;
  596. }
  597. }
  598. // Now play first item in queue
  599. // If it's not a 'special' dialogue event, continue
  600. if ( QItem->uiSpecialEventFlag == 0 )
  601. {
  602. if( pSoldier )
  603. {
  604. // wake grunt up to say
  605. if( pSoldier->fMercAsleep )
  606. {
  607. pSoldier->fMercAsleep = FALSE;
  608. // refresh map screen
  609. fCharacterInfoPanelDirty = TRUE;
  610. fTeamPanelDirty = TRUE;
  611. // allow them to go back to sleep
  612. TacticalCharacterDialogueWithSpecialEvent( pSoldier, QItem->usQuoteNum, DIALOGUE_SPECIAL_EVENT_SLEEP, 1,0 );
  613. }
  614. }
  615. gTacticalStatus.ubLastQuoteSaid = (UINT8)QItem->usQuoteNum;
  616. gTacticalStatus.ubLastQuoteProfileNUm = (UINT8)QItem->ubCharacterNum;
  617. // Setup face pointer
  618. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  619. gubCurrentTalkingID = QItem->ubCharacterNum;
  620. ExecuteCharacterDialogue( QItem->ubCharacterNum, QItem->usQuoteNum, QItem->iFaceIndex, QItem->bUIHandlerID, QItem->fFromSoldier );
  621. }
  622. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SKIP_A_FRAME )
  623. {
  624. }
  625. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_LOCK_INTERFACE )
  626. {
  627. // locking or unlocking?
  628. if( QItem->uiSpecialEventData )
  629. {
  630. switch( QItem->uiSpecialEventData2 )
  631. {
  632. case( MAP_SCREEN ):
  633. fLockOutMapScreenInterface = TRUE;
  634. break;
  635. }
  636. }
  637. else
  638. {
  639. switch( QItem->uiSpecialEventData2 )
  640. {
  641. case( MAP_SCREEN ):
  642. fLockOutMapScreenInterface = FALSE;
  643. break;
  644. }
  645. }
  646. }
  647. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_REMOVE_EPC )
  648. {
  649. gMercProfiles[ (UINT8) QItem->uiSpecialEventData ].ubMiscFlags &= ~PROFILE_MISC_FLAG_FORCENPCQUOTE;
  650. UnRecruitEPC( (UINT8) QItem->uiSpecialEventData );
  651. ReBuildCharactersList();
  652. }
  653. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_CONTRACT_WANTS_TO_RENEW )
  654. {
  655. HandleMercIsWillingToRenew( (UINT8)QItem->uiSpecialEventData );
  656. }
  657. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_CONTRACT_NOGO_TO_RENEW )
  658. {
  659. HandleMercIsNotWillingToRenew( (UINT8)QItem->uiSpecialEventData );
  660. }
  661. else
  662. {
  663. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_USE_ALTERNATE_FILES )
  664. {
  665. gfUseAlternateDialogueFile = TRUE;
  666. // Setup face pointer
  667. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  668. gubCurrentTalkingID = QItem->ubCharacterNum;
  669. ExecuteCharacterDialogue( QItem->ubCharacterNum, QItem->usQuoteNum, QItem->iFaceIndex, QItem->bUIHandlerID, QItem->fFromSoldier );
  670. gfUseAlternateDialogueFile = FALSE;
  671. }
  672. // We could have a special flag, but dialogue as well
  673. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_PCTRIGGERNPC )
  674. {
  675. // Setup face pointer
  676. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  677. gubCurrentTalkingID = QItem->ubCharacterNum;
  678. ExecuteCharacterDialogue( QItem->ubCharacterNum, QItem->usQuoteNum, QItem->iFaceIndex, QItem->bUIHandlerID, QItem->fFromSoldier );
  679. // Setup face with data!
  680. gpCurrentTalkingFace->uiFlags |= FACE_PCTRIGGER_NPC;
  681. gpCurrentTalkingFace->uiUserData1 = QItem->uiSpecialEventData;
  682. gpCurrentTalkingFace->uiUserData2 = QItem->uiSpecialEventData2;
  683. }
  684. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SHOW_CONTRACT_MENU )
  685. {
  686. // Setup face pointer
  687. // ATE: THis is working with MARK'S STUFF :(
  688. // Need this stuff so that bSelectedInfoChar is set...
  689. SetInfoChar( pSoldier->ubID );
  690. fShowContractMenu = TRUE;
  691. RebuildContractBoxForMerc( pSoldier );
  692. bSelectedContractChar = bSelectedInfoChar;
  693. pProcessingSoldier = pSoldier;
  694. fProcessingAMerc = TRUE;
  695. }
  696. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_DO_BATTLE_SND )
  697. {
  698. // grab soldier ptr from profile ID
  699. pSoldier = FindSoldierByProfileID( QItem->ubCharacterNum, FALSE );
  700. // Do battle snounds......
  701. if ( pSoldier )
  702. {
  703. InternalDoMercBattleSound( pSoldier, (UINT8)QItem->uiSpecialEventData, 0 );
  704. }
  705. }
  706. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SIGNAL_ITEM_LOCATOR_START )
  707. {
  708. // Turn off item lock for locators...
  709. gTacticalStatus.fLockItemLocators = FALSE;
  710. // Slide to location!
  711. SlideToLocation( 0, (UINT16)QItem->uiSpecialEventData );
  712. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  713. gubCurrentTalkingID = QItem->ubCharacterNum;
  714. ExecuteCharacterDialogue( QItem->ubCharacterNum, QItem->usQuoteNum, QItem->iFaceIndex, QItem->bUIHandlerID, QItem->fFromSoldier );
  715. }
  716. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_ENABLE_AI )
  717. {
  718. //OK, allow AI to work now....
  719. UnPauseAI();
  720. }
  721. if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_TRIGGERPREBATTLEINTERFACE )
  722. {
  723. UnLockPauseState();
  724. InitPreBattleInterface( (GROUP*)QItem->uiSpecialEventData, TRUE );
  725. }
  726. if( QItem->uiSpecialEventFlag & DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX )
  727. {
  728. INT32 iReason = 0;
  729. SOLDIERTYPE *pUpdateSoldier = NULL;
  730. iReason = QItem->uiSpecialEventData;
  731. switch( iReason )
  732. {
  733. case( UPDATE_BOX_REASON_ADDSOLDIER ):
  734. pUpdateSoldier = &Menptr[ QItem->uiSpecialEventData2 ];
  735. if( pUpdateSoldier->bActive == TRUE )
  736. {
  737. AddSoldierToUpdateBox( pUpdateSoldier );
  738. }
  739. break;
  740. case( UPDATE_BOX_REASON_SET_REASON ):
  741. SetSoldierUpdateBoxReason( QItem->uiSpecialEventData2 );
  742. break;
  743. case( UPDATE_BOX_REASON_SHOW_BOX ):
  744. ShowUpdateBox( );
  745. break;
  746. }
  747. }
  748. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_BEGINPREBATTLEINTERFACE )
  749. {
  750. // Setup face pointer
  751. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  752. gubCurrentTalkingID = QItem->ubCharacterNum;
  753. ExecuteCharacterDialogue( QItem->ubCharacterNum, QItem->usQuoteNum, QItem->iFaceIndex, QItem->bUIHandlerID, QItem->fFromSoldier );
  754. // Setup face with data!
  755. gpCurrentTalkingFace->uiFlags |= FACE_TRIGGER_PREBATTLE_INT;
  756. gpCurrentTalkingFace->uiUserData1 = QItem->uiSpecialEventData;
  757. gpCurrentTalkingFace->uiUserData2 = QItem->uiSpecialEventData2;
  758. }
  759. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SHOPKEEPER )
  760. {
  761. if( QItem->uiSpecialEventData < 3 )
  762. {
  763. // post a notice if the player wants to withdraw money from thier account to cover the difference?
  764. swprintf( zMoney, L"%d", QItem->uiSpecialEventData2 );
  765. InsertCommasForDollarFigure( zMoney );
  766. InsertDollarSignInToString( zMoney );
  767. }
  768. switch( QItem->uiSpecialEventData )
  769. {
  770. case( 0 ):
  771. swprintf( zText, SkiMessageBoxText[ SKI_SHORT_FUNDS_TEXT ], zMoney );
  772. //popup a message stating the player doesnt have enough money
  773. DoSkiMessageBox( MSG_BOX_BASIC_STYLE, zText, SHOPKEEPER_SCREEN, MSG_BOX_FLAG_OK, ConfirmDontHaveEnoughForTheDealerMessageBoxCallBack );
  774. break;
  775. case( 1 ):
  776. //if the player is trading items
  777. swprintf( zText, SkiMessageBoxText[ SKI_QUESTION_TO_DEDUCT_MONEY_FROM_PLAYERS_ACCOUNT_TO_COVER_DIFFERENCE ], zMoney );
  778. //ask them if we should deduct money out the players account to cover the difference
  779. DoSkiMessageBox( MSG_BOX_BASIC_STYLE, zText, SHOPKEEPER_SCREEN, MSG_BOX_FLAG_YESNO, ConfirmToDeductMoneyFromPlayersAccountMessageBoxCallBack );
  780. break;
  781. case( 2 ):
  782. swprintf( zText, SkiMessageBoxText[ SKI_QUESTION_TO_DEDUCT_MONEY_FROM_PLAYERS_ACCOUNT_TO_COVER_COST ], zMoney );
  783. //ask them if we should deduct money out the players account to cover the difference
  784. DoSkiMessageBox( MSG_BOX_BASIC_STYLE, zText, SHOPKEEPER_SCREEN, MSG_BOX_FLAG_YESNO, ConfirmToDeductMoneyFromPlayersAccountMessageBoxCallBack );
  785. break;
  786. case( 3 ):
  787. // this means a dialogue event is in progress
  788. giShopKeepDialogueEventinProgress = QItem->uiSpecialEventData2;
  789. break;
  790. case( 4 ):
  791. // this means a dialogue event has ended
  792. giShopKeepDialogueEventinProgress = -1;
  793. break;
  794. case( 5 ):
  795. // this means a dialogue event has ended
  796. gfSKIScreenExit = TRUE;
  797. break;
  798. case( 6 ):
  799. if( guiCurrentScreen == SHOPKEEPER_SCREEN )
  800. {
  801. DisableButton( guiSKI_TransactionButton );
  802. }
  803. break;
  804. case( 7 ):
  805. if( guiCurrentScreen == SHOPKEEPER_SCREEN )
  806. {
  807. EnableButton( guiSKI_TransactionButton );
  808. }
  809. break;
  810. }
  811. }
  812. if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_EXIT_MAP_SCREEN )
  813. {
  814. // select sector
  815. ChangeSelectedMapSector( ( INT16 )QItem->uiSpecialEventData, ( INT16 )QItem->uiSpecialEventData2, ( INT8 )QItem->uiSpecialEventData3 );
  816. RequestTriggerExitFromMapscreen( MAP_EXIT_TO_TACTICAL );
  817. }
  818. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_DISPLAY_STAT_CHANGE )
  819. {
  820. // grab soldier ptr from profile ID
  821. pSoldier = FindSoldierByProfileID( QItem->ubCharacterNum, FALSE );
  822. if ( pSoldier )
  823. {
  824. CHAR16 wTempString[ 128 ];
  825. // tell player about stat increase
  826. BuildStatChangeString( wTempString, pSoldier->name, ( BOOLEAN ) QItem->uiSpecialEventData, ( INT16 ) QItem->uiSpecialEventData2, ( UINT8 ) QItem->uiSpecialEventData3 );
  827. ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, wTempString );
  828. }
  829. }
  830. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_UNSET_ARRIVES_FLAG )
  831. {
  832. gTacticalStatus.bMercArrivingQuoteBeingUsed = FALSE;
  833. }
  834. /*
  835. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_DISPLAY_INVASION_MESSAGE )
  836. {
  837. HandlePlayerNotifyInvasionByEnemyForces( (INT16)(QItem->uiSpecialEventData % MAP_WORLD_X), (INT16)(QItem->uiSpecialEventData / MAP_WORLD_X), 0, NULL );
  838. }
  839. */
  840. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SKYRIDERMAPSCREENEVENT )
  841. {
  842. // Setup face pointer
  843. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  844. gubCurrentTalkingID = QItem->ubCharacterNum;
  845. // handle the monologue event
  846. HandleSkyRiderMonologueEvent( QItem->uiSpecialEventData, QItem->uiSpecialEventData2 );
  847. }
  848. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT )
  849. {
  850. // Setup face pointer
  851. gpCurrentTalkingFace = &gFacesData[ QItem->iFaceIndex ];
  852. gubCurrentTalkingID = QItem->ubCharacterNum;
  853. // set up the mine highlgith events
  854. SetUpAnimationOfMineSectors( QItem->uiSpecialEventData );
  855. }
  856. //Switch on our special events
  857. if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_GIVE_ITEM )
  858. {
  859. if ( QItem->bUIHandlerID == DIALOGUE_NPC_UI )
  860. {
  861. HandleNPCItemGiven( (UINT8)QItem->uiSpecialEventData, (OBJECTTYPE*)QItem->uiSpecialEventData2, (INT8)QItem->uiSpecialEventData3 );
  862. }
  863. }
  864. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_TRIGGER_NPC )
  865. {
  866. if ( QItem->bUIHandlerID == DIALOGUE_NPC_UI )
  867. {
  868. HandleNPCTriggerNPC( (UINT8)QItem->uiSpecialEventData, (UINT8)QItem->uiSpecialEventData2, (BOOLEAN)QItem->uiSpecialEventData3, (UINT8)QItem->uiSpecialEventData4 );
  869. }
  870. }
  871. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_GOTO_GRIDNO )
  872. {
  873. if ( QItem->bUIHandlerID == DIALOGUE_NPC_UI )
  874. {
  875. HandleNPCGotoGridNo( (UINT8)QItem->uiSpecialEventData, (UINT16)QItem->uiSpecialEventData2, (UINT8)QItem->uiSpecialEventData3 );
  876. }
  877. }
  878. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_DO_ACTION )
  879. {
  880. if ( QItem->bUIHandlerID == DIALOGUE_NPC_UI )
  881. {
  882. HandleNPCDoAction( (UINT8)QItem->uiSpecialEventData, (UINT16)QItem->uiSpecialEventData2, (UINT8)QItem->uiSpecialEventData3 );
  883. }
  884. }
  885. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_CLOSE_PANEL )
  886. {
  887. if ( QItem->bUIHandlerID == DIALOGUE_NPC_UI )
  888. {
  889. HandleNPCClosePanel( );
  890. }
  891. }
  892. else if ( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SHOW_UPDATE_MENU )
  893. {
  894. SetUpdateBoxFlag( TRUE );
  895. }
  896. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_CONTINUE_TRAINING_MILITIA )
  897. {
  898. // grab soldier ptr from profile ID
  899. pSoldier = FindSoldierByProfileID( ( UINT8 )( QItem->uiSpecialEventData ), FALSE );
  900. // if soldier valid...
  901. if( pSoldier != NULL )
  902. {
  903. HandleInterfaceMessageForContinuingTrainingMilitia( pSoldier );
  904. }
  905. }
  906. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_ENTER_MAPSCREEN )
  907. {
  908. if( !(guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
  909. {
  910. gfEnteringMapScreen = TRUE;
  911. fEnterMapDueToContract = TRUE;
  912. }
  913. }
  914. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING )
  915. {
  916. // grab soldier ptr from profile ID
  917. pSoldier = FindSoldierByProfileID( QItem->ubCharacterNum, FALSE );
  918. // if soldier valid...
  919. if( pSoldier != NULL )
  920. {
  921. // .. remove the fired soldier again
  922. BeginStrategicRemoveMerc( pSoldier, (UINT8)QItem->uiSpecialEventData );
  923. }
  924. }
  925. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING_NO_ASK_EQUIP )
  926. {
  927. // grab soldier ptr from profile ID
  928. pSoldier = FindSoldierByProfileID( QItem->ubCharacterNum, FALSE );
  929. // if soldier valid...
  930. if( pSoldier != NULL )
  931. {
  932. // .. remove the fired soldier again
  933. StrategicRemoveMerc( pSoldier );
  934. }
  935. }
  936. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE )
  937. {
  938. if ( QItem->uiSpecialEventData & MULTIPURPOSE_SPECIAL_EVENT_DONE_KILLING_DEIDRANNA )
  939. {
  940. HandleDoneLastKilledQueenQuote( );
  941. }
  942. else if ( QItem->uiSpecialEventData & MULTIPURPOSE_SPECIAL_EVENT_TEAM_MEMBERS_DONE_TALKING )
  943. {
  944. HandleDoneLastEndGameQuote( );
  945. }
  946. }
  947. else if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_SLEEP )
  948. {
  949. // no soldier, leave now
  950. if( pSoldier == NULL )
  951. {
  952. return;
  953. }
  954. // wake merc up or put them back down?
  955. if( QItem->uiSpecialEventData == 1 )
  956. {
  957. pSoldier -> fMercAsleep = TRUE;
  958. }
  959. else
  960. {
  961. pSoldier -> fMercAsleep = FALSE;
  962. }
  963. // refresh map screen
  964. fCharacterInfoPanelDirty = TRUE;
  965. fTeamPanelDirty = TRUE;
  966. }
  967. }
  968. // grab soldier ptr from profile ID
  969. pSoldier = FindSoldierByProfileID( QItem->ubCharacterNum, FALSE );
  970. if ( pSoldier && pSoldier->bTeam == gbPlayerNum )
  971. {
  972. CheckForStopTimeQuotes( QItem->usQuoteNum );
  973. }
  974. if( QItem -> fPauseTime )
  975. {
  976. fWasPausedDuringDialogue = TRUE;
  977. }
  978. // Delete memory
  979. MemFree( QItem );
  980. }
  981. BOOLEAN GetDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, UINT32 iDataSize, UINT16 *zDialogueText, UINT32 *puiSoundID, CHAR8 *zSoundString );
  982. BOOLEAN DelayedTacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum )
  983. {
  984. if ( pSoldier->ubProfile == NO_PROFILE )
  985. {
  986. return( FALSE );
  987. }
  988. if (pSoldier->bLife < CONSCIOUSNESS )
  989. return( FALSE );
  990. if ( pSoldier->uiStatusFlags & SOLDIER_GASSED )
  991. return( FALSE );
  992. if ( (AM_A_ROBOT( pSoldier )) )
  993. {
  994. return( FALSE );
  995. }
  996. if (pSoldier->bLife < OKLIFE && usQuoteNum != QUOTE_SERIOUSLY_WOUNDED )
  997. return( FALSE );
  998. if( pSoldier->bAssignment == ASSIGNMENT_POW )
  999. {
  1000. return( FALSE );
  1001. }
  1002. return( CharacterDialogue( pSoldier->ubProfile, usQuoteNum, pSoldier->iFaceIndex, DIALOGUE_TACTICAL_UI, TRUE, TRUE ) );
  1003. }
  1004. BOOLEAN TacticalCharacterDialogueWithSpecialEvent( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2 )
  1005. {
  1006. if ( pSoldier->ubProfile == NO_PROFILE )
  1007. {
  1008. return( FALSE );
  1009. }
  1010. if ( uiFlag != DIALOGUE_SPECIAL_EVENT_DO_BATTLE_SND && uiData1 != BATTLE_SOUND_DIE1 )
  1011. {
  1012. if (pSoldier->bLife < CONSCIOUSNESS )
  1013. return( FALSE );
  1014. if ( pSoldier->uiStatusFlags & SOLDIER_GASSED )
  1015. return( FALSE );
  1016. }
  1017. return( CharacterDialogueWithSpecialEvent( pSoldier->ubProfile, usQuoteNum, pSoldier->iFaceIndex, DIALOGUE_TACTICAL_UI, TRUE, FALSE, uiFlag, uiData1, uiData2 ) );
  1018. }
  1019. BOOLEAN TacticalCharacterDialogueWithSpecialEventEx( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 )
  1020. {
  1021. if ( pSoldier->ubProfile == NO_PROFILE )
  1022. {
  1023. return( FALSE );
  1024. }
  1025. if ( uiFlag != DIALOGUE_SPECIAL_EVENT_DO_BATTLE_SND && uiData1 != BATTLE_SOUND_DIE1 )
  1026. {
  1027. if (pSoldier->bLife < CONSCIOUSNESS )
  1028. return( FALSE );
  1029. if ( pSoldier->uiStatusFlags & SOLDIER_GASSED )
  1030. return( FALSE );
  1031. if ( (AM_A_ROBOT( pSoldier )) )
  1032. {
  1033. return( FALSE );
  1034. }
  1035. if (pSoldier->bLife < OKLIFE && usQuoteNum != QUOTE_SERIOUSLY_WOUNDED )
  1036. return( FALSE );
  1037. if( pSoldier->bAssignment == ASSIGNMENT_POW )
  1038. {
  1039. return( FALSE );
  1040. }
  1041. }
  1042. return( CharacterDialogueWithSpecialEventEx( pSoldier->ubProfile, usQuoteNum, pSoldier->iFaceIndex, DIALOGUE_TACTICAL_UI, TRUE, FALSE, uiFlag, uiData1, uiData2, uiData3 ) );
  1043. }
  1044. BOOLEAN TacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum )
  1045. {
  1046. if ( pSoldier->ubProfile == NO_PROFILE )
  1047. {
  1048. return( FALSE );
  1049. }
  1050. if ( AreInMeanwhile( ) )
  1051. {
  1052. return( FALSE );
  1053. }
  1054. if (pSoldier->bLife < CONSCIOUSNESS )
  1055. return( FALSE );
  1056. if (pSoldier->bLife < OKLIFE && usQuoteNum != QUOTE_SERIOUSLY_WOUNDED )
  1057. return( FALSE );
  1058. if ( pSoldier->uiStatusFlags & SOLDIER_GASSED )
  1059. return( FALSE );
  1060. if ( (AM_A_ROBOT( pSoldier )) )
  1061. {
  1062. return( FALSE );
  1063. }
  1064. if( pSoldier->bAssignment == ASSIGNMENT_POW )
  1065. {
  1066. return( FALSE );
  1067. }
  1068. // OK, let's check if this is the exact one we just played, if so, skip.
  1069. if ( pSoldier->ubProfile == gTacticalStatus.ubLastQuoteProfileNUm &&
  1070. usQuoteNum == gTacticalStatus.ubLastQuoteSaid )
  1071. {
  1072. return( FALSE );
  1073. }
  1074. // If we are a robot, play the controller's quote!
  1075. if ( pSoldier->uiStatusFlags & SOLDIER_ROBOT )
  1076. {
  1077. if ( CanRobotBeControlled( pSoldier ) )
  1078. {
  1079. return( TacticalCharacterDialogue( MercPtrs[ pSoldier->ubRobotRemoteHolderID ], usQuoteNum ) );
  1080. }
  1081. else
  1082. {
  1083. return( FALSE );
  1084. }
  1085. }
  1086. if ( AM_AN_EPC( pSoldier ) && !(gMercProfiles[ pSoldier->ubProfile ].ubMiscFlags & PROFILE_MISC_FLAG_FORCENPCQUOTE) )
  1087. return( FALSE );
  1088. // Check for logging of me too bleeds...
  1089. if ( usQuoteNum == QUOTE_STARTING_TO_BLEED )
  1090. {
  1091. if ( gubLogForMeTooBleeds )
  1092. {
  1093. // If we are greater than one...
  1094. if ( gubLogForMeTooBleeds > 1 )
  1095. {
  1096. //Replace with me too....
  1097. usQuoteNum = QUOTE_ME_TOO;
  1098. }
  1099. gubLogForMeTooBleeds++;
  1100. }
  1101. }
  1102. return( CharacterDialogue( pSoldier->ubProfile, usQuoteNum, pSoldier->iFaceIndex, DIALOGUE_TACTICAL_UI, TRUE, FALSE ) );
  1103. }
  1104. // This function takes a profile num, quote num, faceindex and a UI hander ID.
  1105. // What it does is queues up the dialog to be ultimately loaded/displayed
  1106. // FACEINDEX
  1107. // The face index is an index into an ACTIVE face. The face is considered to
  1108. // be active, and if it's not, either that has to be handled by the UI handler
  1109. // ir nothing will show. What this function does is set the face to talking,
  1110. // and the face sprite system should handle the rest.
  1111. // bUIHandlerID
  1112. // Because this could be used in any place, the UI handleID is used to differentiate
  1113. // places in the game. For example, specific things happen in the tactical engine
  1114. // that may not be the place where in the AIM contract screen uses.....
  1115. // NB; The queued system is not yet implemented, but will be transpatent to the caller....
  1116. BOOLEAN CharacterDialogueWithSpecialEvent( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier, BOOLEAN fDelayed, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2 )
  1117. {
  1118. DIALOGUE_Q_STRUCT *QItem;
  1119. // Allocate new item
  1120. QItem = MemAlloc( sizeof( DIALOGUE_Q_STRUCT ) );
  1121. memset( QItem, 0, sizeof( DIALOGUE_Q_STRUCT ) );
  1122. QItem->ubCharacterNum = ubCharacterNum;
  1123. QItem->usQuoteNum = usQuoteNum;
  1124. QItem->iFaceIndex = iFaceIndex;
  1125. QItem->bUIHandlerID = bUIHandlerID;
  1126. QItem->iTimeStamp = GetJA2Clock( );
  1127. QItem->fFromSoldier = fFromSoldier;
  1128. QItem->fDelayed = fDelayed;
  1129. // Set flag for special event
  1130. QItem->uiSpecialEventFlag = uiFlag;
  1131. QItem->uiSpecialEventData = uiData1;
  1132. QItem->uiSpecialEventData2 = uiData2;
  1133. // Add to queue
  1134. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  1135. if ( uiFlag & DIALOGUE_SPECIAL_EVENT_PCTRIGGERNPC )
  1136. {
  1137. // Increment refrence count...
  1138. giNPCReferenceCount++;
  1139. }
  1140. return( TRUE );
  1141. }
  1142. BOOLEAN CharacterDialogueWithSpecialEventEx( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier, BOOLEAN fDelayed, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 )
  1143. {
  1144. DIALOGUE_Q_STRUCT *QItem;
  1145. // Allocate new item
  1146. QItem = MemAlloc( sizeof( DIALOGUE_Q_STRUCT ) );
  1147. memset( QItem, 0, sizeof( DIALOGUE_Q_STRUCT ) );
  1148. QItem->ubCharacterNum = ubCharacterNum;
  1149. QItem->usQuoteNum = usQuoteNum;
  1150. QItem->iFaceIndex = iFaceIndex;
  1151. QItem->bUIHandlerID = bUIHandlerID;
  1152. QItem->iTimeStamp = GetJA2Clock( );
  1153. QItem->fFromSoldier = fFromSoldier;
  1154. QItem->fDelayed = fDelayed;
  1155. // Set flag for special event
  1156. QItem->uiSpecialEventFlag = uiFlag;
  1157. QItem->uiSpecialEventData = uiData1;
  1158. QItem->uiSpecialEventData2 = uiData2;
  1159. QItem->uiSpecialEventData3 = uiData3;
  1160. // Add to queue
  1161. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  1162. if ( uiFlag & DIALOGUE_SPECIAL_EVENT_PCTRIGGERNPC )
  1163. {
  1164. // Increment refrence count...
  1165. giNPCReferenceCount++;
  1166. }
  1167. return( TRUE );
  1168. }
  1169. BOOLEAN CharacterDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier, BOOLEAN fDelayed )
  1170. {
  1171. DIALOGUE_Q_STRUCT *QItem;
  1172. // Allocate new item
  1173. QItem = MemAlloc( sizeof( DIALOGUE_Q_STRUCT ) );
  1174. memset( QItem, 0, sizeof( DIALOGUE_Q_STRUCT ) );
  1175. QItem->ubCharacterNum = ubCharacterNum;
  1176. QItem->usQuoteNum = usQuoteNum;
  1177. QItem->iFaceIndex = iFaceIndex;
  1178. QItem->bUIHandlerID = bUIHandlerID;
  1179. QItem->iTimeStamp = GetJA2Clock( );
  1180. QItem->fFromSoldier = fFromSoldier;
  1181. QItem->fDelayed = fDelayed;
  1182. // check if pause already locked, if so, then don't mess with it
  1183. if( gfLockPauseState == FALSE )
  1184. {
  1185. QItem->fPauseTime = fPausedTimeDuringQuote;
  1186. }
  1187. fPausedTimeDuringQuote = FALSE;
  1188. // Add to queue
  1189. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  1190. return( TRUE );
  1191. }
  1192. BOOLEAN SpecialCharacterDialogueEvent( UINT32 uiSpecialEventFlag, UINT32 uiSpecialEventData1, UINT32 uiSpecialEventData2, UINT32 uiSpecialEventData3, INT32 iFaceIndex, UINT8 bUIHandlerID )
  1193. {
  1194. DIALOGUE_Q_STRUCT *QItem;
  1195. // Allocate new item
  1196. QItem = MemAlloc( sizeof( DIALOGUE_Q_STRUCT ) );
  1197. memset( QItem, 0, sizeof( DIALOGUE_Q_STRUCT ) );
  1198. QItem->uiSpecialEventFlag = uiSpecialEventFlag;
  1199. QItem->uiSpecialEventData = uiSpecialEventData1;
  1200. QItem->uiSpecialEventData2 = uiSpecialEventData2;
  1201. QItem->uiSpecialEventData3 = uiSpecialEventData3;
  1202. QItem->iFaceIndex = iFaceIndex;
  1203. QItem->bUIHandlerID = bUIHandlerID;
  1204. QItem->iTimeStamp = GetJA2Clock( );
  1205. // if paused state not already locked
  1206. if( gfLockPauseState == FALSE )
  1207. {
  1208. QItem->fPauseTime = fPausedTimeDuringQuote;
  1209. }
  1210. fPausedTimeDuringQuote = FALSE;
  1211. // Add to queue
  1212. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  1213. return( TRUE );
  1214. }
  1215. BOOLEAN SpecialCharacterDialogueEventWithExtraParam( UINT32 uiSpecialEventFlag, UINT32 uiSpecialEventData1, UINT32 uiSpecialEventData2, UINT32 uiSpecialEventData3, UINT32 uiSpecialEventData4, INT32 iFaceIndex, UINT8 bUIHandlerID )
  1216. {
  1217. DIALOGUE_Q_STRUCT *QItem;
  1218. // Allocate new item
  1219. QItem = MemAlloc( sizeof( DIALOGUE_Q_STRUCT ) );
  1220. memset( QItem, 0, sizeof( DIALOGUE_Q_STRUCT ) );
  1221. QItem->uiSpecialEventFlag = uiSpecialEventFlag;
  1222. QItem->uiSpecialEventData = uiSpecialEventData1;
  1223. QItem->uiSpecialEventData2 = uiSpecialEventData2;
  1224. QItem->uiSpecialEventData3 = uiSpecialEventData3;
  1225. QItem->uiSpecialEventData4 = uiSpecialEventData4;
  1226. QItem->iFaceIndex = iFaceIndex;
  1227. QItem->bUIHandlerID = bUIHandlerID;
  1228. QItem->iTimeStamp = GetJA2Clock( );
  1229. // if paused state not already locked
  1230. if( gfLockPauseState == FALSE )
  1231. {
  1232. QItem->fPauseTime = fPausedTimeDuringQuote;
  1233. }
  1234. fPausedTimeDuringQuote = FALSE;
  1235. // Add to queue
  1236. ghDialogueQ = AddtoQueue( ghDialogueQ, &QItem );
  1237. return( TRUE );
  1238. }
  1239. BOOLEAN ExecuteCharacterDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier )
  1240. {
  1241. CHAR8 zSoundString[ 164 ];
  1242. UINT32 uiSoundID;
  1243. SOLDIERTYPE *pSoldier;
  1244. // Check if we are dead now or not....( if from a soldier... )
  1245. // Try to find soldier...
  1246. pSoldier = FindSoldierByProfileID( ubCharacterNum, TRUE );
  1247. if ( pSoldier != NULL )
  1248. {
  1249. // Check vital stats
  1250. if (pSoldier->bLife < CONSCIOUSNESS )
  1251. {
  1252. return( FALSE );
  1253. }
  1254. if ( pSoldier->uiStatusFlags & SOLDIER_GASSED )
  1255. return( FALSE );
  1256. if ( (AM_A_ROBOT( pSoldier )) )
  1257. {
  1258. return( FALSE );
  1259. }
  1260. if (pSoldier->bLife < OKLIFE && usQuoteNum != QUOTE_SERIOUSLY_WOUNDED )
  1261. {
  1262. return( FALSE );
  1263. }
  1264. if( pSoldier->bAssignment == ASSIGNMENT_POW )
  1265. {
  1266. return( FALSE );
  1267. }
  1268. // sleeping guys don't talk.. go to standby to talk
  1269. if( pSoldier->fMercAsleep == TRUE )
  1270. {
  1271. // check if the soldier was compaining about lack of sleep and was alseep, if so, leave them alone
  1272. if( ( usQuoteNum == QUOTE_NEED_SLEEP ) || ( usQuoteNum == QUOTE_OUT_OF_BREATH ) )
  1273. {
  1274. // leave them alone
  1275. return ( TRUE );
  1276. }
  1277. // may want to wake up any character that has VERY important dialogue to say
  1278. // MC to flesh out
  1279. }
  1280. // now being used in a different way...
  1281. /*
  1282. if ( ( (usQuoteNum == QUOTE_PERSONALITY_TRAIT &&
  1283. (gMercProfiles[ubCharacterNum].bPersonalityTrait == FORGETFUL ||
  1284. gMercProfiles[ubCharacterNum].bPersonalityTrait == CLAUSTROPHOBIC ||
  1285. gMercProfiles[ubCharacterNum].bPersonalityTrait == NERVOUS ||
  1286. gMercProfiles[ubCharacterNum].bPersonalityTrait == NONSWIMMER ||
  1287. gMercProfiles[ubCharacterNum].bPersonalityTrait == FEAR_OF_INSECTS))
  1288. //usQuoteNum == QUOTE_STARTING_TO_WHINE ||
  1289. #ifdef JA2BETAVERSION
  1290. || usQuoteNum == QUOTE_WHINE_EQUIPMENT) && (guiCurrentScreen != QUEST_DEBUG_SCREEN) )
  1291. #else
  1292. ) )
  1293. #endif
  1294. {
  1295. // This quote might spawn another quote from someone
  1296. iLoop = 0;
  1297. for ( pTeamSoldier = MercPtrs[ iLoop ]; iLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; iLoop++,pTeamSoldier++ )
  1298. {
  1299. if ( (pTeamSoldier->ubProfile != ubCharacterNum) && (OK_INSECTOR_MERC( pTeamSoldier )) && (SpacesAway( pSoldier->sGridNo, pTeamSoldier->sGridNo ) < 5) )
  1300. {
  1301. // if this merc disliked the whining character sufficiently and hasn't already retorted
  1302. if ( gMercProfiles[ pTeamSoldier->ubProfile ].bMercOpinion[ ubCharacterNum ] < -2 && !( pTeamSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_ANNOYING_MERC ) )
  1303. {
  1304. // make a comment!
  1305. TacticalCharacterDialogue( pTeamSoldier, QUOTE_ANNOYING_PC );
  1306. pTeamSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_ANNOYING_MERC;
  1307. break;
  1308. }
  1309. }
  1310. }
  1311. }
  1312. */
  1313. }
  1314. else
  1315. {
  1316. // If from a soldier, and he does not exist anymore, donot play!
  1317. if ( fFromSoldier )
  1318. {
  1319. return( FALSE );
  1320. }
  1321. }
  1322. // Check face index
  1323. CHECKF( iFaceIndex != -1 );
  1324. if ( !GetDialogue( ubCharacterNum,
  1325. usQuoteNum, DIALOGUESIZE, gzQuoteStr, &uiSoundID, zSoundString) )
  1326. {
  1327. return( FALSE );
  1328. }
  1329. if( bUIHandlerID == DIALOGUE_EXTERNAL_NPC_UI )
  1330. {
  1331. // external NPC
  1332. SetFaceTalking( iFaceIndex , zSoundString, gzQuoteStr, RATE_11025, 30, 1, MIDDLEPAN );
  1333. }
  1334. else
  1335. {
  1336. // start "talking" system (portrait animation and start wav sample)
  1337. SetFaceTalking( iFaceIndex, zSoundString, gzQuoteStr, RATE_11025, 30, 1, MIDDLEPAN );
  1338. }
  1339. // pSoldier can be null here... ( if NOT from an alive soldier )
  1340. CreateTalkingUI( bUIHandlerID, iFaceIndex, ubCharacterNum, pSoldier, gzQuoteStr );
  1341. // Set global handleer ID value, used when face desides it's done...
  1342. gbUIHandlerID = bUIHandlerID;
  1343. guiScreenIDUsedWhenUICreated = guiCurrentScreen;
  1344. return( TRUE );
  1345. }
  1346. void CreateTalkingUI( INT8 bUIHandlerID, INT32 iFaceIndex, UINT8 ubCharacterNum, SOLDIERTYPE *pSoldier, INT16 *zQuoteStr )
  1347. {
  1348. // Show text, if on
  1349. if ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] || !gFacesData[ iFaceIndex ].fValidSpeech )
  1350. {
  1351. switch( bUIHandlerID )
  1352. {
  1353. case DIALOGUE_TACTICAL_UI:
  1354. HandleTacticalTextUI( iFaceIndex, pSoldier, zQuoteStr );
  1355. break;
  1356. case DIALOGUE_NPC_UI:
  1357. HandleTacticalNPCTextUI( ubCharacterNum, zQuoteStr );
  1358. break;
  1359. case DIALOGUE_CONTACTPAGE_UI:
  1360. DisplayTextForMercFaceVideoPopUp( zQuoteStr );
  1361. break;
  1362. case DIALOGUE_SPECK_CONTACT_PAGE_UI:
  1363. DisplayTextForSpeckVideoPopUp( zQuoteStr );
  1364. break;
  1365. case DIALOGUE_EXTERNAL_NPC_UI:
  1366. DisplayTextForExternalNPC( ubCharacterNum, zQuoteStr );
  1367. break;
  1368. case DIALOGUE_SHOPKEEPER_UI:
  1369. InitShopKeeperSubTitledText( zQuoteStr );
  1370. break;
  1371. }
  1372. }
  1373. if ( gGameSettings.fOptions[ TOPTION_SPEECH ] )
  1374. {
  1375. switch( bUIHandlerID )
  1376. {
  1377. case DIALOGUE_TACTICAL_UI:
  1378. HandleTacticalSpeechUI( ubCharacterNum, iFaceIndex );
  1379. break;
  1380. case DIALOGUE_CONTACTPAGE_UI:
  1381. break;
  1382. case DIALOGUE_SPECK_CONTACT_PAGE_UI:
  1383. break;
  1384. case DIALOGUE_EXTERNAL_NPC_UI:
  1385. HandleExternNPCSpeechFace( iFaceIndex );
  1386. break;
  1387. }
  1388. }
  1389. }
  1390. INT8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN fWavFile )
  1391. {
  1392. static UINT8 zFileName[164];
  1393. UINT8 ubFileNumID;
  1394. // Are we an NPC OR an RPC that has not been recruited?
  1395. // ATE: Did the || clause here to allow ANY RPC that talks while the talking menu is up to use an npc quote file
  1396. if ( gfUseAlternateDialogueFile )
  1397. {
  1398. if ( fWavFile )
  1399. {
  1400. // build name of wav file (characternum + quotenum)
  1401. #ifdef RUSSIAN
  1402. sprintf( zFileName,"NPC_SPEECH\\g_%03d_%03d.wav",ubCharacterNum,usQuoteNum );
  1403. #else
  1404. sprintf( zFileName,"NPC_SPEECH\\d_%03d_%03d.wav",ubCharacterNum,usQuoteNum );
  1405. #endif
  1406. }
  1407. else
  1408. {
  1409. // assume EDT files are in EDT directory on HARD DRIVE
  1410. sprintf( zFileName,"NPCDATA\\d_%03d.EDT", ubCharacterNum );
  1411. }
  1412. }
  1413. else if ( ubCharacterNum >= FIRST_RPC &&
  1414. ( !( gMercProfiles[ ubCharacterNum ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED )
  1415. || ProfileCurrentlyTalkingInDialoguePanel( ubCharacterNum )
  1416. || (gMercProfiles[ ubCharacterNum ].ubMiscFlags & PROFILE_MISC_FLAG_FORCENPCQUOTE) )
  1417. )
  1418. {
  1419. ubFileNumID = ubCharacterNum;
  1420. // ATE: If we are merc profile ID #151-154, all use 151's data....
  1421. if ( ubCharacterNum >= 151 && ubCharacterNum <= 154 )
  1422. {
  1423. ubFileNumID = 151;
  1424. }
  1425. // If we are character #155, check fact!
  1426. if ( ubCharacterNum == 155 && !gubFact[ 220 ] )
  1427. {
  1428. ubFileNumID = 155;
  1429. }
  1430. if ( fWavFile )
  1431. {
  1432. sprintf( zFileName,"NPC_SPEECH\\%03d_%03d.wav",ubFileNumID,usQuoteNum );
  1433. }
  1434. else
  1435. {
  1436. // assume EDT files are in EDT directory on HARD DRIVE
  1437. sprintf( zFileName,"NPCDATA\\%03d.EDT", ubFileNumID );
  1438. }
  1439. }
  1440. else
  1441. {
  1442. if ( fWavFile )
  1443. {
  1444. #ifdef RUSSIAN
  1445. if( ubCharacterNum >= FIRST_RPC && gMercProfiles[ ubCharacterNum ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED )
  1446. {
  1447. sprintf( zFileName,"SPEECH\\r_%03d_%03d.wav",ubCharacterNum,usQuoteNum );
  1448. }
  1449. else
  1450. #endif
  1451. { // build name of wav file (characternum + quotenum)
  1452. sprintf( zFileName,"SPEECH\\%03d_%03d.wav",ubCharacterNum,usQuoteNum );
  1453. }
  1454. }
  1455. else
  1456. {
  1457. // assume EDT files are in EDT directory on HARD DRIVE
  1458. sprintf( zFileName,"MERCEDT\\%03d.EDT", ubCharacterNum );
  1459. }
  1460. }
  1461. return( zFileName );
  1462. }
  1463. // Used to see if the dialog text file exists
  1464. BOOLEAN DialogueDataFileExistsForProfile( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN fWavFile, UINT8 **ppStr )
  1465. {
  1466. UINT8 *pFilename;
  1467. pFilename = GetDialogueDataFilename( ubCharacterNum, usQuoteNum, fWavFile );
  1468. if ( ppStr )
  1469. {
  1470. (*ppStr ) = pFilename;
  1471. }
  1472. return( FileExists( pFilename ) );
  1473. }
  1474. BOOLEAN GetDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, UINT32 iDataSize, UINT16 *zDialogueText, UINT32 *puiSoundID, CHAR8 *zSoundString )
  1475. {
  1476. UINT8 *pFilename;
  1477. // first things first - grab the text (if player has SUBTITLE PREFERENCE ON)
  1478. //if ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] )
  1479. {
  1480. if ( DialogueDataFileExistsForProfile( ubCharacterNum, 0, FALSE, &pFilename ) )
  1481. {
  1482. LoadEncryptedDataFromFile( pFilename, zDialogueText, usQuoteNum * iDataSize, iDataSize );
  1483. if(zDialogueText[0] == 0)
  1484. {
  1485. swprintf( zDialogueText, L"I have no text in the EDT file ( %d ) %S", usQuoteNum, pFilename );
  1486. #ifndef JA2BETAVERSION
  1487. return( FALSE );
  1488. #endif
  1489. }
  1490. }
  1491. else
  1492. {
  1493. swprintf( zDialogueText, L"I have no text in the file ( %d ) %S", usQuoteNum , pFilename );
  1494. #ifndef JA2BETAVERSION
  1495. return( FALSE );
  1496. #endif
  1497. }
  1498. }
  1499. // CHECK IF THE FILE EXISTS, IF NOT, USE DEFAULT!
  1500. pFilename = GetDialogueDataFilename( ubCharacterNum, usQuoteNum, TRUE );
  1501. // Copy
  1502. strcpy( zSoundString, pFilename );
  1503. // Double check it exists....
  1504. //#ifndef JA2TESTVERSION
  1505. /*
  1506. if ( !FileExists( pFilename ) )
  1507. {
  1508. CHAR8 sString[512];
  1509. sprintf( sString, "ERROR: Missing file for character # %d, quote # %d", ubCharacterNum, usQuoteNum );
  1510. ShowCursor(TRUE);
  1511. ShowCursor(TRUE);
  1512. ShutdownWithErrorBox( sString );
  1513. }
  1514. */
  1515. //#endif
  1516. // get speech if applicable
  1517. if ( gGameSettings.fOptions[ TOPTION_SPEECH ] )
  1518. {
  1519. // Load it into memory!
  1520. *puiSoundID = SoundLoadSample( pFilename );
  1521. }
  1522. return(TRUE);
  1523. }
  1524. // Handlers for tactical UI stuff
  1525. void HandleTacticalNPCTextUI( UINT8 ubCharacterNum, INT16 *zQuoteStr )
  1526. {
  1527. INT16 zText[ QUOTE_MESSAGE_SIZE ];
  1528. // Setup dialogue text box
  1529. if ( guiCurrentScreen != MAP_SCREEN )
  1530. {
  1531. gTalkPanel.fRenderSubTitlesNow = TRUE;
  1532. gTalkPanel.fSetupSubTitles = TRUE;
  1533. }
  1534. // post message to mapscreen message system
  1535. #ifdef TAIWANESE
  1536. swprintf( gTalkPanel.zQuoteStr, L"%s", zQuoteStr );
  1537. #else
  1538. swprintf( gTalkPanel.zQuoteStr, L"\"%s\"", zQuoteStr );
  1539. swprintf( zText, L"%s: \"%s\"", gMercProfiles[ ubCharacterNum ].zNickname, zQuoteStr );
  1540. MapScreenMessage( FONT_MCOLOR_WHITE, MSG_DIALOG, L"%s", zText );
  1541. #endif
  1542. }
  1543. // Handlers for tactical UI stuff
  1544. void DisplayTextForExternalNPC( UINT8 ubCharacterNum, STR16 zQuoteStr )
  1545. {
  1546. INT16 zText[ QUOTE_MESSAGE_SIZE ];
  1547. INT16 sLeft;
  1548. // Setup dialogue text box
  1549. if ( guiCurrentScreen != MAP_SCREEN )
  1550. {
  1551. gTalkPanel.fRenderSubTitlesNow = TRUE;
  1552. gTalkPanel.fSetupSubTitles = TRUE;
  1553. }
  1554. // post message to mapscreen message system
  1555. #ifdef TAIWANESE
  1556. swprintf( gTalkPanel.zQuoteStr, L"%s", zQuoteStr );
  1557. #else
  1558. swprintf( gTalkPanel.zQuoteStr, L"\"%s\"", zQuoteStr );
  1559. swprintf( zText, L"%s: \"%s\"", gMercProfiles[ ubCharacterNum ].zNickname, zQuoteStr );
  1560. MapScreenMessage( FONT_MCOLOR_WHITE, MSG_DIALOG, L"%s", zText );
  1561. #endif
  1562. if ( guiCurrentScreen == MAP_SCREEN )
  1563. {
  1564. sLeft = ( gsExternPanelXPosition + 97 );
  1565. gsTopPosition = gsExternPanelYPosition;
  1566. }
  1567. else
  1568. {
  1569. sLeft = ( 110 );
  1570. }
  1571. ExecuteTacticalTextBox( sLeft, gTalkPanel.zQuoteStr );
  1572. return;
  1573. }
  1574. void HandleTacticalTextUI( INT32 iFaceIndex, SOLDIERTYPE *pSoldier, INT16 *zQuoteStr )
  1575. {
  1576. INT16 zText[ QUOTE_MESSAGE_SIZE ];
  1577. INT16 sLeft = 0;
  1578. //BUild text
  1579. // How do we do this with defines?
  1580. //swprintf( zText, L"\xb4\xa2 %s: \xb5 \"%s\"", gMercProfiles[ ubCharacterNum ].zNickname, zQuoteStr );
  1581. #ifdef TAIWANESE
  1582. swprintf( zText, L"%s", zQuoteStr );
  1583. #else
  1584. swprintf( zText, L"\"%s\"", zQuoteStr );
  1585. #endif
  1586. sLeft = 110;
  1587. //previous version
  1588. //sLeft = 110;
  1589. ExecuteTacticalTextBox( sLeft, zText );
  1590. #ifndef TAIWANESE
  1591. swprintf( zText, L"%s: \"%s\"", gMercProfiles[ pSoldier->ubProfile ].zNickname, zQuoteStr );
  1592. MapScreenMessage( FONT_MCOLOR_WHITE, MSG_DIALOG, L"%s", zText );
  1593. #endif
  1594. }
  1595. void ExecuteTacticalTextBoxForLastQuote( INT16 sLeftPosition, STR16 pString )
  1596. {
  1597. UINT32 uiDelay = FindDelayForString( pString );
  1598. fDialogueBoxDueToLastMessage = TRUE;
  1599. guiDialogueLastQuoteTime = GetJA2Clock();
  1600. guiDialogueLastQuoteDelay = ( ( uiDelay < FINAL_TALKING_DURATION ) ? FINAL_TALKING_DURATION : uiDelay );
  1601. // now execute box
  1602. ExecuteTacticalTextBox(sLeftPosition, pString );
  1603. }
  1604. void ExecuteTacticalTextBox( INT16 sLeftPosition, STR16 pString )
  1605. {
  1606. VIDEO_OVERLAY_DESC VideoOverlayDesc;
  1607. // check if mouse region created, if so, do not recreate
  1608. if( fTextBoxMouseRegionCreated == TRUE )
  1609. {
  1610. return;
  1611. }
  1612. memset( &VideoOverlayDesc, 0, sizeof( VIDEO_OVERLAY_DESC ) );
  1613. // Prepare text box
  1614. SET_USE_WINFONTS( TRUE );
  1615. SET_WINFONT( giSubTitleWinFont );
  1616. iDialogueBox = PrepareMercPopupBox( iDialogueBox , BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, pString, DIALOGUE_DEFAULT_SUBTITLE_WIDTH, 0, 0, 0, &gusSubtitleBoxWidth, &gusSubtitleBoxHeight );
  1617. SET_USE_WINFONTS( FALSE );
  1618. VideoOverlayDesc.sLeft = sLeftPosition;
  1619. VideoOverlayDesc.sTop = gsTopPosition;
  1620. VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + gusSubtitleBoxWidth;
  1621. VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + gusSubtitleBoxHeight;
  1622. VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
  1623. VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
  1624. VideoOverlayDesc.BltCallback = RenderSubtitleBoxOverlay;
  1625. giTextBoxOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
  1626. gsTopPosition = 20;
  1627. //Define main region
  1628. MSYS_DefineRegion( &gTextBoxMouseRegion, VideoOverlayDesc.sLeft, VideoOverlayDesc.sTop, VideoOverlayDesc.sRight, VideoOverlayDesc.sBottom, MSYS_PRIORITY_HIGHEST,
  1629. CURSOR_NORMAL, MSYS_NO_CALLBACK, TextOverlayClickCallback );
  1630. // Add region
  1631. MSYS_AddRegion(&(gTextBoxMouseRegion) );
  1632. fTextBoxMouseRegionCreated = TRUE;
  1633. }
  1634. void HandleExternNPCSpeechFace( INT32 iIndex )
  1635. {
  1636. INT32 iFaceIndex;
  1637. VIDEO_OVERLAY_DESC VideoOverlayDesc;
  1638. INT32 iFaceOverlay;
  1639. // grab face index
  1640. iFaceIndex = iIndex;
  1641. // Enable it!
  1642. SetAutoFaceActive( FACE_AUTO_DISPLAY_BUFFER, FACE_AUTO_RESTORE_BUFFER, iFaceIndex , 0, 0 );
  1643. // Set flag to say WE control when to set inactive!
  1644. gFacesData[ iFaceIndex ].uiFlags |= FACE_INACTIVE_HANDLED_ELSEWHERE;
  1645. if ( guiCurrentScreen != MAP_SCREEN )
  1646. {
  1647. // Setup video overlay!
  1648. VideoOverlayDesc.sLeft = 10;
  1649. VideoOverlayDesc.sTop = 20;
  1650. VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + 99;
  1651. VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + 98;
  1652. VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
  1653. VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
  1654. VideoOverlayDesc.BltCallback = RenderFaceOverlay;
  1655. }
  1656. else
  1657. {
  1658. // Setup video overlay!
  1659. VideoOverlayDesc.sLeft = gsExternPanelXPosition;
  1660. VideoOverlayDesc.sTop = gsExternPanelYPosition;
  1661. VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + 99;
  1662. VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + 98;
  1663. VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
  1664. VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
  1665. VideoOverlayDesc.BltCallback = RenderFaceOverlay;
  1666. }
  1667. iFaceOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
  1668. gpCurrentTalkingFace->iVideoOverlay = iFaceOverlay;
  1669. RenderAutoFace( iFaceIndex );
  1670. // ATE: Create mouse region.......
  1671. if ( !fExternFaceBoxRegionCreated )
  1672. {
  1673. fExternFaceBoxRegionCreated = TRUE;
  1674. //Define main region
  1675. MSYS_DefineRegion( &gFacePopupMouseRegion, VideoOverlayDesc.sLeft, VideoOverlayDesc.sTop, VideoOverlayDesc.sRight, VideoOverlayDesc.sBottom, MSYS_PRIORITY_HIGHEST,
  1676. CURSOR_NORMAL, MSYS_NO_CALLBACK, FaceOverlayClickCallback );
  1677. // Add region
  1678. MSYS_AddRegion(&(gFacePopupMouseRegion) );
  1679. }
  1680. gfFacePanelActive = TRUE;
  1681. return;
  1682. }
  1683. void HandleTacticalSpeechUI( UINT8 ubCharacterNum, INT32 iFaceIndex )
  1684. {
  1685. VIDEO_OVERLAY_DESC VideoOverlayDesc;
  1686. INT32 iFaceOverlay;
  1687. SOLDIERTYPE *pSoldier;
  1688. BOOLEAN fDoExternPanel = FALSE;
  1689. memset( &VideoOverlayDesc, 0, sizeof( VIDEO_OVERLAY_DESC ) );
  1690. // Get soldier pointer, if there is one...
  1691. // Try to find soldier...
  1692. pSoldier = FindSoldierByProfileID( ubCharacterNum, FALSE );
  1693. // PLEASE NOTE: pSoldier may legally be NULL (e.g. Skyrider) !!!
  1694. if ( pSoldier == NULL )
  1695. {
  1696. fDoExternPanel = TRUE;
  1697. }
  1698. else
  1699. {
  1700. // If we are not an active face!
  1701. if ( guiCurrentScreen != MAP_SCREEN )
  1702. {
  1703. fDoExternPanel = TRUE;
  1704. }
  1705. }
  1706. if ( fDoExternPanel )
  1707. {
  1708. // Enable it!
  1709. SetAutoFaceActive( FACE_AUTO_DISPLAY_BUFFER, FACE_AUTO_RESTORE_BUFFER, iFaceIndex , 0, 0 );
  1710. // Set flag to say WE control when to set inactive!
  1711. gFacesData[ iFaceIndex ].uiFlags |= ( FACE_INACTIVE_HANDLED_ELSEWHERE | FACE_MAKEACTIVE_ONCE_DONE );
  1712. // IF we are in tactical and this soldier is on the current squad
  1713. if ( ( guiCurrentScreen == GAME_SCREEN ) && ( pSoldier != NULL ) && ( pSoldier->bAssignment == iCurrentTacticalSquad ) )
  1714. {
  1715. // Make the interface panel dirty..
  1716. // This will dirty the panel next frame...
  1717. gfRerenderInterfaceFromHelpText = TRUE;
  1718. }
  1719. // Setup video overlay!
  1720. VideoOverlayDesc.sLeft = 10;
  1721. VideoOverlayDesc.sTop = 20;
  1722. VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + 99;
  1723. VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + 98;
  1724. VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
  1725. VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
  1726. VideoOverlayDesc.BltCallback = RenderFaceOverlay;
  1727. iFaceOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
  1728. gpCurrentTalkingFace->iVideoOverlay = iFaceOverlay;
  1729. RenderAutoFace( iFaceIndex );
  1730. // ATE: Create mouse region.......
  1731. if ( !fExternFaceBoxRegionCreated )
  1732. {
  1733. fExternFaceBoxRegionCreated = TRUE;
  1734. //Define main region
  1735. MSYS_DefineRegion( &gFacePopupMouseRegion, VideoOverlayDesc.sLeft, VideoOverlayDesc.sTop, VideoOverlayDesc.sRight, VideoOverlayDesc.sBottom, MSYS_PRIORITY_HIGHEST,
  1736. CURSOR_NORMAL, MSYS_NO_CALLBACK, FaceOverlayClickCallback );
  1737. // Add region
  1738. MSYS_AddRegion(&(gFacePopupMouseRegion) );
  1739. }
  1740. gfFacePanelActive = TRUE;
  1741. }
  1742. else if ( guiCurrentScreen == MAP_SCREEN )
  1743. {
  1744. // Are we in mapscreen?
  1745. // If so, set current guy active to talk.....
  1746. if ( pSoldier != NULL )
  1747. {
  1748. ContinueDialogue( pSoldier, FALSE );
  1749. }
  1750. }
  1751. }
  1752. void HandleDialogueEnd( FACETYPE *pFace )
  1753. {
  1754. if ( gGameSettings.fOptions[ TOPTION_SPEECH ] )
  1755. {
  1756. if ( pFace != gpCurrentTalkingFace )
  1757. {
  1758. //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"HandleDialogueEnd() face mismatch." );
  1759. return;
  1760. }
  1761. if ( pFace->fTalking )
  1762. {
  1763. ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"HandleDialogueEnd() face still talking." );
  1764. return;
  1765. }
  1766. switch( gbUIHandlerID )
  1767. {
  1768. case DIALOGUE_TACTICAL_UI:
  1769. if ( gfFacePanelActive )
  1770. {
  1771. // Set face inactive!
  1772. pFace->fCanHandleInactiveNow = TRUE;
  1773. SetAutoFaceInActive( pFace->iID );
  1774. gfFacePanelActive = FALSE;
  1775. if ( fExternFaceBoxRegionCreated )
  1776. {
  1777. fExternFaceBoxRegionCreated = FALSE;
  1778. MSYS_RemoveRegion(&(gFacePopupMouseRegion) );
  1779. }
  1780. }
  1781. break;
  1782. case DIALOGUE_NPC_UI:
  1783. break;
  1784. case DIALOGUE_EXTERNAL_NPC_UI:
  1785. pFace->fCanHandleInactiveNow = TRUE;
  1786. SetAutoFaceInActive( pFace->iID );
  1787. gfFacePanelActive = FALSE;
  1788. if ( fExternFaceBoxRegionCreated )
  1789. {
  1790. fExternFaceBoxRegionCreated = FALSE;
  1791. MSYS_RemoveRegion(&(gFacePopupMouseRegion) );
  1792. }
  1793. break;
  1794. }
  1795. }
  1796. if ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] || !pFace->fValidSpeech )
  1797. {
  1798. switch( gbUIHandlerID )
  1799. {
  1800. case DIALOGUE_TACTICAL_UI:
  1801. case DIALOGUE_EXTERNAL_NPC_UI:
  1802. // Remove if created
  1803. if ( giTextBoxOverlay != -1 )
  1804. {
  1805. RemoveVideoOverlay( giTextBoxOverlay );
  1806. giTextBoxOverlay = -1;
  1807. if ( fTextBoxMouseRegionCreated )
  1808. {
  1809. RemoveMercPopupBoxFromIndex( iDialogueBox );
  1810. // reset box id
  1811. iDialogueBox = -1;
  1812. MSYS_RemoveRegion( &gTextBoxMouseRegion );
  1813. fTextBoxMouseRegionCreated = FALSE;
  1814. }
  1815. }
  1816. break;
  1817. case DIALOGUE_NPC_UI:
  1818. // Remove region
  1819. if ( gTalkPanel.fTextRegionOn )
  1820. {
  1821. MSYS_RemoveRegion(&(gTalkPanel.TextRegion) );
  1822. gTalkPanel.fTextRegionOn = FALSE;
  1823. }
  1824. SetRenderFlags( RENDER_FLAG_FULL );
  1825. gTalkPanel.fRenderSubTitlesNow = FALSE;
  1826. // Delete subtitle box
  1827. gTalkPanel.fDirtyLevel = DIRTYLEVEL2;
  1828. RemoveMercPopupBoxFromIndex( iInterfaceDialogueBox );
  1829. iInterfaceDialogueBox = -1;
  1830. break;
  1831. case DIALOGUE_CONTACTPAGE_UI:
  1832. break;
  1833. case DIALOGUE_SPECK_CONTACT_PAGE_UI:
  1834. break;
  1835. }
  1836. }
  1837. TurnOffSectorLocator();
  1838. gsExternPanelXPosition = DEFAULT_EXTERN_PANEL_X_POS;
  1839. gsExternPanelYPosition = DEFAULT_EXTERN_PANEL_Y_POS;
  1840. }
  1841. void RenderFaceOverlay( VIDEO_OVERLAY *pBlitter )
  1842. {
  1843. UINT32 uiDestPitchBYTES, uiSrcPitchBYTES;
  1844. UINT8 *pDestBuf, *pSrcBuf;
  1845. INT16 sFontX, sFontY;
  1846. SOLDIERTYPE *pSoldier;
  1847. INT16 zTownIDString[50];
  1848. if ( gpCurrentTalkingFace == NULL )
  1849. {
  1850. return;
  1851. }
  1852. if ( gfFacePanelActive )
  1853. {
  1854. pSoldier = FindSoldierByProfileID( gpCurrentTalkingFace->ubCharacterNum, FALSE );
  1855. // a living soldier?..or external NPC?..choose panel based on this
  1856. if( pSoldier )
  1857. {
  1858. BltVideoObjectFromIndex( pBlitter->uiDestBuff, guiCOMPANEL, 0, pBlitter->sX, pBlitter->sY, VO_BLT_SRCTRANSPARENCY, NULL );
  1859. }
  1860. else
  1861. {
  1862. BltVideoObjectFromIndex( pBlitter->uiDestBuff, guiCOMPANELB, 0, pBlitter->sX, pBlitter->sY, VO_BLT_SRCTRANSPARENCY, NULL );
  1863. }
  1864. // Display name, location ( if not current )
  1865. SetFont( BLOCKFONT2 );
  1866. SetFontBackground( FONT_MCOLOR_BLACK );
  1867. SetFontForeground( FONT_MCOLOR_LTGRAY );
  1868. if ( pSoldier )
  1869. {
  1870. //reset the font dest buffer
  1871. SetFontDestBuffer( pBlitter->uiDestBuff, 0,0,640,480, FALSE);
  1872. VarFindFontCenterCoordinates( (INT16)( pBlitter->sX + 12 ), (INT16)( pBlitter->sY + 55 ), 73, 9, BLOCKFONT2, &sFontX, &sFontY, L"%s", pSoldier->name );
  1873. mprintf( sFontX, sFontY, L"%s", pSoldier->name );
  1874. // What sector are we in, ( and is it the same as ours? )
  1875. if ( pSoldier->sSectorX != gWorldSectorX || pSoldier->sSectorY != gWorldSectorY || pSoldier->bSectorZ != gbWorldSectorZ || pSoldier->fBetweenSectors )
  1876. {
  1877. GetSectorIDString( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, zTownIDString, FALSE );
  1878. ReduceStringLength( zTownIDString, 64 , BLOCKFONT2 );
  1879. VarFindFontCenterCoordinates( (INT16)( pBlitter->sX + 12 ), (INT16)( pBlitter->sY + 68 ), 73, 9, BLOCKFONT2, &sFontX, &sFontY, L"%s", zTownIDString );
  1880. mprintf( sFontX, sFontY, L"%s", zTownIDString );
  1881. }
  1882. //reset the font dest buffer
  1883. SetFontDestBuffer(FRAME_BUFFER, 0,0,640,480, FALSE);
  1884. // Display bars
  1885. DrawLifeUIBarEx( pSoldier, (INT16)( pBlitter->sX + 69 ), (INT16)( pBlitter->sY + 47 ), 3, 42, FALSE, pBlitter->uiDestBuff );
  1886. DrawBreathUIBarEx( pSoldier, (INT16)( pBlitter->sX + 75 ), (INT16)( pBlitter->sY + 47 ), 3, 42, FALSE, pBlitter->uiDestBuff );
  1887. DrawMoraleUIBarEx( pSoldier, (INT16)( pBlitter->sX + 81 ), (INT16)( pBlitter->sY + 47 ), 3, 42, FALSE, pBlitter->uiDestBuff );
  1888. }
  1889. else
  1890. {
  1891. VarFindFontCenterCoordinates( (INT16)( pBlitter->sX + 9 ), (INT16)( pBlitter->sY + 55 ), 73, 9, BLOCKFONT2, &sFontX, &sFontY, L"%s", gMercProfiles[ gpCurrentTalkingFace->ubCharacterNum ].zNickname );
  1892. mprintf( sFontX, sFontY, L"%s", gMercProfiles[ gpCurrentTalkingFace->ubCharacterNum ].zNickname );
  1893. }
  1894. //RenderAutoFace( gpCurrentTalkingFace->iID );
  1895. //BlinkAutoFace( gpCurrentTalkingFace->iID );
  1896. //MouthAutoFace( gpCurrentTalkingFace->iID );
  1897. pDestBuf = LockVideoSurface( pBlitter->uiDestBuff, &uiDestPitchBYTES);
  1898. pSrcBuf = LockVideoSurface( gpCurrentTalkingFace->uiAutoDisplayBuffer, &uiSrcPitchBYTES);
  1899. Blt16BPPTo16BPP((UINT16 *)pDestBuf, uiDestPitchBYTES,
  1900. (UINT16 *)pSrcBuf, uiSrcPitchBYTES,
  1901. (INT16)( pBlitter->sX + 14 ), (INT16)( pBlitter->sY + 6 ),
  1902. 0 , 0,
  1903. gpCurrentTalkingFace->usFaceWidth, gpCurrentTalkingFace->usFaceHeight );
  1904. UnLockVideoSurface( pBlitter->uiDestBuff );
  1905. UnLockVideoSurface( gpCurrentTalkingFace->uiAutoDisplayBuffer );
  1906. InvalidateRegion( pBlitter->sX, pBlitter->sY, pBlitter->sX + 99, pBlitter->sY + 98 );
  1907. }
  1908. }
  1909. void RenderSubtitleBoxOverlay( VIDEO_OVERLAY *pBlitter )
  1910. {
  1911. if ( giTextBoxOverlay != -1 )
  1912. {
  1913. RenderMercPopUpBoxFromIndex( iDialogueBox, pBlitter->sX, pBlitter->sY, pBlitter->uiDestBuff );
  1914. InvalidateRegion( pBlitter->sX, pBlitter->sY, pBlitter->sX + gusSubtitleBoxWidth, pBlitter->sY + gusSubtitleBoxHeight );
  1915. }
  1916. }
  1917. void SayQuoteFromAnyBodyInSector( UINT16 usQuoteNum )
  1918. {
  1919. UINT8 ubMercsInSector[ 20 ] = { 0 };
  1920. UINT8 ubNumMercs = 0;
  1921. UINT8 ubChosenMerc;
  1922. SOLDIERTYPE *pTeamSoldier;
  1923. INT32 cnt;
  1924. // Loop through all our guys and randomly say one from someone in our sector
  1925. // set up soldier ptr as first element in mercptrs list
  1926. cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
  1927. // run through list
  1928. for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
  1929. {
  1930. // Add guy if he's a candidate...
  1931. if ( OK_INSECTOR_MERC( pTeamSoldier ) && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->fMercAsleep )
  1932. {
  1933. if ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] == 0 )
  1934. {
  1935. // quotes referring to Deidranna's men so we skip quote if there were no army guys fought
  1936. if ( (usQuoteNum == QUOTE_SECTOR_SAFE) && (pTeamSoldier->ubProfile == IRA || pTeamSoldier->ubProfile == MIGUEL || pTeamSoldier->ubProfile == SHANK ) )
  1937. {
  1938. continue;
  1939. }
  1940. if ( (usQuoteNum == QUOTE_ENEMY_PRESENCE ) && (pTeamSoldier->ubProfile == IRA || pTeamSoldier->ubProfile == DIMITRI || pTeamSoldier->ubProfile == DYNAMO || pTeamSoldier->ubProfile == SHANK ) )
  1941. {
  1942. continue;
  1943. }
  1944. }
  1945. ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
  1946. ubNumMercs++;
  1947. }
  1948. }
  1949. // If we are > 0
  1950. if ( ubNumMercs > 0 )
  1951. {
  1952. ubChosenMerc = (UINT8)Random( ubNumMercs );
  1953. // If we are air raid, AND red exists somewhere...
  1954. if ( usQuoteNum == QUOTE_AIR_RAID )
  1955. {
  1956. for ( cnt = 0; cnt < ubNumMercs; cnt++ )
  1957. {
  1958. if ( ubMercsInSector[ cnt ] == 11 )
  1959. {
  1960. ubChosenMerc = (UINT8)cnt;
  1961. break;
  1962. }
  1963. }
  1964. }
  1965. TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
  1966. }
  1967. }
  1968. void SayQuoteFromAnyBodyInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usQuoteNum )
  1969. {
  1970. UINT8 ubMercsInSector[ 20 ] = { 0 };
  1971. UINT8 ubNumMercs = 0;
  1972. UINT8 ubChosenMerc;
  1973. SOLDIERTYPE *pTeamSoldier;
  1974. INT32 cnt;
  1975. // Loop through all our guys and randomly say one from someone in our sector
  1976. // set up soldier ptr as first element in mercptrs list
  1977. cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
  1978. // run through list
  1979. for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
  1980. {
  1981. if ( pTeamSoldier->bActive )
  1982. {
  1983. // Add guy if he's a candidate...
  1984. if( pTeamSoldier->sSectorX == sSectorX && pTeamSoldier->sSectorY == sSectorY && pTeamSoldier -> bSectorZ == bSectorZ && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->fMercAsleep )
  1985. {
  1986. ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
  1987. ubNumMercs++;
  1988. }
  1989. }
  1990. }
  1991. // If we are > 0
  1992. if ( ubNumMercs > 0 )
  1993. {
  1994. ubChosenMerc = (UINT8)Random( ubNumMercs );
  1995. // If we are air raid, AND red exists somewhere...
  1996. if ( usQuoteNum == QUOTE_AIR_RAID )
  1997. {
  1998. for ( cnt = 0; cnt < ubNumMercs; cnt++ )
  1999. {
  2000. if ( ubMercsInSector[ cnt ] == 11 )
  2001. {
  2002. ubChosenMerc = (UINT8)cnt;
  2003. break;
  2004. }
  2005. }
  2006. }
  2007. TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
  2008. }
  2009. }
  2010. void SayQuoteFromNearbyMercInSector( INT16 sGridNo, INT8 bDistance, UINT16 usQuoteNum )
  2011. {
  2012. UINT8 ubMercsInSector[ 20 ] = { 0 };
  2013. UINT8 ubNumMercs = 0;
  2014. UINT8 ubChosenMerc;
  2015. SOLDIERTYPE *pTeamSoldier;
  2016. INT32 cnt;
  2017. // Loop through all our guys and randomly say one from someone in our sector
  2018. // set up soldier ptr as first element in mercptrs list
  2019. cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
  2020. // run through list
  2021. for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
  2022. {
  2023. // Add guy if he's a candidate...
  2024. if ( OK_INSECTOR_MERC( pTeamSoldier ) && PythSpacesAway( sGridNo, pTeamSoldier->sGridNo ) < bDistance && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->fMercAsleep &&
  2025. SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, 0, 0, (UINT8)MaxDistanceVisible(), TRUE ) )
  2026. {
  2027. if ( usQuoteNum == 66 && (INT8) Random( 100 ) > EffectiveWisdom( pTeamSoldier ) )
  2028. {
  2029. continue;
  2030. }
  2031. ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
  2032. ubNumMercs++;
  2033. }
  2034. }
  2035. // If we are > 0
  2036. if ( ubNumMercs > 0 )
  2037. {
  2038. ubChosenMerc = (UINT8)Random( ubNumMercs );
  2039. if (usQuoteNum == 66)
  2040. {
  2041. SetFactTrue( FACT_PLAYER_FOUND_ITEMS_MISSING );
  2042. }
  2043. TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
  2044. }
  2045. }
  2046. void SayQuote58FromNearbyMercInSector( INT16 sGridNo, INT8 bDistance, UINT16 usQuoteNum, INT8 bSex )
  2047. {
  2048. UINT8 ubMercsInSector[ 20 ] = { 0 };
  2049. UINT8 ubNumMercs = 0;
  2050. UINT8 ubChosenMerc;
  2051. SOLDIERTYPE *pTeamSoldier;
  2052. INT32 cnt;
  2053. // Loop through all our guys and randomly say one from someone in our sector
  2054. // set up soldier ptr as first element in mercptrs list
  2055. cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
  2056. // run through list
  2057. for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
  2058. {
  2059. // Add guy if he's a candidate...
  2060. if ( OK_INSECTOR_MERC( pTeamSoldier ) && PythSpacesAway( sGridNo, pTeamSoldier->sGridNo ) < bDistance && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->fMercAsleep &&
  2061. SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, 0, 0, (UINT8)MaxDistanceVisible(), TRUE ) )
  2062. {
  2063. // ATE: This is to check gedner for this quote...
  2064. if ( QuoteExp_GenderCode[ pTeamSoldier->ubProfile ] == 0 && bSex == FEMALE )
  2065. {
  2066. continue;
  2067. }
  2068. if ( QuoteExp_GenderCode[ pTeamSoldier->ubProfile ] == 1 && bSex == MALE )
  2069. {
  2070. continue;
  2071. }
  2072. ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
  2073. ubNumMercs++;
  2074. }
  2075. }
  2076. // If we are > 0
  2077. if ( ubNumMercs > 0 )
  2078. {
  2079. ubChosenMerc = (UINT8)Random( ubNumMercs );
  2080. TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
  2081. }
  2082. }
  2083. void TextOverlayClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
  2084. {
  2085. static BOOLEAN fLButtonDown = FALSE;
  2086. if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
  2087. {
  2088. fLButtonDown = TRUE;
  2089. }
  2090. if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP && fLButtonDown )
  2091. {
  2092. if( gpCurrentTalkingFace != NULL )
  2093. {
  2094. InternalShutupaYoFace( gpCurrentTalkingFace->iID, FALSE );
  2095. // Did we succeed in shutting them up?
  2096. if ( !gpCurrentTalkingFace->fTalking )
  2097. {
  2098. // shut down last quote box
  2099. ShutDownLastQuoteTacticalTextBox( );
  2100. }
  2101. }
  2102. }
  2103. else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
  2104. {
  2105. fLButtonDown = FALSE;
  2106. }
  2107. }
  2108. void FaceOverlayClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
  2109. {
  2110. static BOOLEAN fLButtonDown = FALSE;
  2111. if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
  2112. {
  2113. fLButtonDown = TRUE;
  2114. }
  2115. if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP && fLButtonDown )
  2116. {
  2117. if( gpCurrentTalkingFace != NULL )
  2118. {
  2119. InternalShutupaYoFace( gpCurrentTalkingFace->iID, FALSE );
  2120. }
  2121. }
  2122. else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
  2123. {
  2124. fLButtonDown = FALSE;
  2125. }
  2126. }
  2127. void ShutDownLastQuoteTacticalTextBox( void )
  2128. {
  2129. if( fDialogueBoxDueToLastMessage )
  2130. {
  2131. RemoveVideoOverlay( giTextBoxOverlay );
  2132. giTextBoxOverlay = -1;
  2133. if ( fTextBoxMouseRegionCreated )
  2134. {
  2135. MSYS_RemoveRegion( &gTextBoxMouseRegion );
  2136. fTextBoxMouseRegionCreated = FALSE;
  2137. }
  2138. fDialogueBoxDueToLastMessage = FALSE;
  2139. }
  2140. }
  2141. UINT32 FindDelayForString( STR16 sString )
  2142. {
  2143. return( wcslen( sString ) * TEXT_DELAY_MODIFIER );
  2144. }
  2145. void BeginLoggingForBleedMeToos( BOOLEAN fStart )
  2146. {
  2147. gubLogForMeTooBleeds = fStart;
  2148. }
  2149. void SetEngagedInConvFromPCAction( SOLDIERTYPE *pSoldier )
  2150. {
  2151. // OK, If a good give, set engaged in conv...
  2152. gTacticalStatus.uiFlags |= ENGAGED_IN_CONV;
  2153. gTacticalStatus.ubEngagedInConvFromActionMercID = pSoldier->ubID;
  2154. }
  2155. void UnSetEngagedInConvFromPCAction( SOLDIERTYPE *pSoldier )
  2156. {
  2157. if ( gTacticalStatus.ubEngagedInConvFromActionMercID == pSoldier->ubID )
  2158. {
  2159. // OK, If a good give, set engaged in conv...
  2160. gTacticalStatus.uiFlags &= ( ~ENGAGED_IN_CONV );
  2161. }
  2162. }
  2163. BOOLEAN IsStopTimeQuote( UINT16 usQuoteNum )
  2164. {
  2165. INT32 cnt;
  2166. for ( cnt = 0; cnt < gubNumStopTimeQuotes; cnt++ )
  2167. {
  2168. if ( gusStopTimeQuoteList[ cnt ] == usQuoteNum )
  2169. {
  2170. return( TRUE );
  2171. }
  2172. }
  2173. return( FALSE );
  2174. }
  2175. void CheckForStopTimeQuotes( UINT16 usQuoteNum )
  2176. {
  2177. if ( IsStopTimeQuote( usQuoteNum ) )
  2178. {
  2179. // Stop Time, game
  2180. EnterModalTactical( TACTICAL_MODAL_NOMOUSE );
  2181. gpCurrentTalkingFace->uiFlags |= FACE_MODAL;
  2182. ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Starting Modal Tactical Quote." );
  2183. }
  2184. }
  2185. void SetStopTimeQuoteCallback( MODAL_HOOK pCallBack )
  2186. {
  2187. gModalDoneCallback = pCallBack;
  2188. }
  2189. BOOLEAN IsMercSayingDialogue( UINT8 ubProfileID )
  2190. {
  2191. if ( gpCurrentTalkingFace != NULL && gubCurrentTalkingID == ubProfileID )
  2192. {
  2193. return( TRUE );
  2194. }
  2195. return( FALSE );
  2196. }
  2197. BOOLEAN ShouldMercSayPrecedentToRepeatOneSelf( UINT8 ubMercID, UINT32 uiQuoteID )
  2198. {
  2199. UINT8 ubQuoteBit=0;
  2200. //If the quote is not in the array
  2201. if( !IsQuoteInPrecedentArray( uiQuoteID ) )
  2202. {
  2203. return( FALSE );
  2204. }
  2205. ubQuoteBit = GetQuoteBitNumberFromQuoteID( uiQuoteID );
  2206. if( ubQuoteBit == 0 )
  2207. return( FALSE );
  2208. if( GetMercPrecedentQuoteBitStatus( ubMercID, ubQuoteBit ) )
  2209. {
  2210. return( TRUE );
  2211. }
  2212. else
  2213. {
  2214. SetMercPrecedentQuoteBitStatus( ubMercID, ubQuoteBit );
  2215. }
  2216. return( FALSE );
  2217. }
  2218. BOOLEAN GetMercPrecedentQuoteBitStatus( UINT8 ubMercID, UINT8 ubQuoteBit )
  2219. {
  2220. if( gMercProfiles[ ubMercID ].uiPrecedentQuoteSaid & ( 1 << ( ubQuoteBit - 1 ) ) )
  2221. return( TRUE );
  2222. else
  2223. return( FALSE );
  2224. }
  2225. BOOLEAN SetMercPrecedentQuoteBitStatus( UINT8 ubMercID, UINT8 ubBitToSet )
  2226. {
  2227. //Set the bit
  2228. gMercProfiles[ ubMercID ].uiPrecedentQuoteSaid |= 1 << ( ubBitToSet - 1 );
  2229. return( TRUE );
  2230. }
  2231. BOOLEAN IsQuoteInPrecedentArray( UINT32 uiQuoteID )
  2232. {
  2233. UINT8 ubCnt;
  2234. //If the quote id is above or below the ones in the array
  2235. if( uiQuoteID < gubMercValidPrecedentQuoteID[ 0 ] ||
  2236. uiQuoteID > gubMercValidPrecedentQuoteID[ NUMBER_VALID_MERC_PRECEDENT_QUOTES-1 ] )
  2237. {
  2238. return( FALSE );
  2239. }
  2240. //loop through all the quotes
  2241. for( ubCnt=0; ubCnt<NUMBER_VALID_MERC_PRECEDENT_QUOTES;ubCnt++)
  2242. {
  2243. if( gubMercValidPrecedentQuoteID[ ubCnt ] == uiQuoteID )
  2244. {
  2245. return( TRUE );
  2246. }
  2247. }
  2248. return( FALSE );
  2249. }
  2250. UINT8 GetQuoteBitNumberFromQuoteID( UINT32 uiQuoteID )
  2251. {
  2252. UINT8 ubCnt;
  2253. //loop through all the quotes
  2254. for( ubCnt=0; ubCnt<NUMBER_VALID_MERC_PRECEDENT_QUOTES;ubCnt++)
  2255. {
  2256. if( gubMercValidPrecedentQuoteID[ ubCnt ] == uiQuoteID )
  2257. {
  2258. return( ubCnt );
  2259. }
  2260. }
  2261. return( 0 );
  2262. }
  2263. void HandleShutDownOfMapScreenWhileExternfaceIsTalking( void )
  2264. {
  2265. if ( ( fExternFaceBoxRegionCreated ) && ( gpCurrentTalkingFace) )
  2266. {
  2267. RemoveVideoOverlay( gpCurrentTalkingFace->iVideoOverlay );
  2268. gpCurrentTalkingFace->iVideoOverlay = -1;
  2269. }
  2270. }
  2271. void HandleImportantMercQuote( SOLDIERTYPE * pSoldier, UINT16 usQuoteNumber )
  2272. {
  2273. // wake merc up for THIS quote
  2274. if( pSoldier->fMercAsleep )
  2275. {
  2276. TacticalCharacterDialogueWithSpecialEvent( pSoldier, usQuoteNumber, DIALOGUE_SPECIAL_EVENT_SLEEP, 0,0 );
  2277. TacticalCharacterDialogue( pSoldier, usQuoteNumber );
  2278. TacticalCharacterDialogueWithSpecialEvent( pSoldier, usQuoteNumber, DIALOGUE_SPECIAL_EVENT_SLEEP, 1,0 );
  2279. }
  2280. else
  2281. {
  2282. TacticalCharacterDialogue( pSoldier, usQuoteNumber );
  2283. }
  2284. }
  2285. // handle pausing of the dialogue queue
  2286. void PauseDialogueQueue( void )
  2287. {
  2288. gfDialogueQueuePaused = TRUE;
  2289. return;
  2290. }
  2291. // unpause the dialogue queue
  2292. void UnPauseDialogueQueue( void )
  2293. {
  2294. gfDialogueQueuePaused = FALSE;
  2295. return;
  2296. }
  2297. void SetExternMapscreenSpeechPanelXY( INT16 sXPos, INT16 sYPos )
  2298. {
  2299. gsExternPanelXPosition = sXPos;
  2300. gsExternPanelYPosition = sYPos;
  2301. }