Faces.c 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252
  1. #ifdef PRECOMPILEDHEADERS
  2. #include "Tactical All.h"
  3. #else
  4. #include "math.h"
  5. #include <stdio.h>
  6. #include <errno.h>
  7. #include "worlddef.h"
  8. #include "renderworld.h"
  9. #include "vsurface.h"
  10. #include "Render Dirty.h"
  11. #include "sysutil.h"
  12. #include "container.h"
  13. #include "wcheck.h"
  14. #include "video.h"
  15. #include "vobject_blitters.h"
  16. #include "faces.h"
  17. #include "utilities.h"
  18. #include "overhead.h"
  19. #include "gap.h"
  20. #include "Soldier Profile.h"
  21. #include "sound control.h"
  22. #include "teamturns.h"
  23. #include "soldier macros.h"
  24. #include "dialogue control.h"
  25. #include "font control.h"
  26. #include "Assignments.h"
  27. #include "Random.h"
  28. #include "line.h"
  29. #include "GameSettings.h"
  30. #include "squads.h"
  31. #include "interface.h"
  32. #include "Quests.h"
  33. #include "animation control.h"
  34. #endif
  35. // Defines
  36. #define NUM_FACE_SLOTS 50
  37. #define END_FACE_OVERLAY_DELAY 2000
  38. // GLOBAL FOR FACES LISTING
  39. FACETYPE gFacesData[ NUM_FACE_SLOTS ];
  40. UINT32 guiNumFaces = 0;
  41. // LOCAL FUNCTIONS
  42. void NewEye( FACETYPE *pFace );
  43. void NewMouth( FACETYPE *pFace );
  44. INT32 GetFreeFace(void);
  45. void RecountFaces(void);
  46. void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLEAN fUseExternBuffer, UINT32 uiBuffer, INT16 sFaceX, INT16 sFaceY, UINT16 usEyesX, UINT16 usEyesY );
  47. extern BOOLEAN gfInItemPickupMenu;
  48. typedef struct
  49. {
  50. INT8 bEyesX;
  51. INT8 bEyesY;
  52. INT8 bMouthX;
  53. INT8 bMouthY;
  54. } RPC_SMALL_FACE_VALUES;
  55. RPC_SMALL_FACE_VALUES gRPCSmallFaceValues[ ] =
  56. {
  57. 9, 8, 8, 24, // MIGUEL ( 57 )
  58. 8, 8, 7, 24, // CARLOS ( 58 )
  59. 10, 8, 8, 26, // IRA ( 59 )
  60. 7, 8, 7, 26, // DIMITRI ( 60 )
  61. 6, 7, 7, 23, // DEVIN ( 61 )
  62. 0, 0, 0, 0, // THE RAT ( 62 )
  63. 8, 7, 8, 23, // ( 63 )
  64. 8, 8, 8, 22, // SLAY ( 64 )
  65. 0, 0, 0, 0, // ( 65 )
  66. 9, 4, 7, 22, // DYNAMO ( 66 )
  67. 8, 8, 8, 25, // SHANK ( 67 )
  68. 4, 6, 5, 22, // IGGY ( 68 )
  69. 8, 9, 7, 25, // VINCE ( 69 )
  70. 4, 7, 5, 25, // CONRAD ( 70 )
  71. 9, 7, 8, 22, // CARL ( 71 )
  72. 9, 7, 9, 25, // MADDOG ( 72 )
  73. 0, 0, 0, 0, // ( 73 )
  74. 0, 0, 0, 0, // ( 74 )
  75. 9, 3, 8, 23, // MARIA ( 88 )
  76. 9, 3, 8, 25, // JOEY ( 90 )
  77. 11, 7, 9, 24, // SKYRIDER ( 97 )
  78. 9, 5, 7, 23, // Miner ( 106 )
  79. 6, 4, 6, 24, // JOHN ( 118 )
  80. 12,4, 10, 24, // ( 119 )
  81. 8, 6, 8, 23, // Miner ( 148 )
  82. 6, 5, 6, 23, // Miner ( 156 )
  83. 13, 7, 11, 24, // Miner ( 157 )
  84. 9, 7, 8, 22, // Miner ( 158 )
  85. };
  86. UINT8 gubRPCSmallFaceProfileNum[] =
  87. {
  88. 57, // entry 0
  89. 58,
  90. 59,
  91. 60,
  92. 61,
  93. 62,
  94. 63,
  95. 64,
  96. 65,
  97. 66, // entry 9
  98. 67,
  99. 68,
  100. 69,
  101. 70,
  102. 71,
  103. 72,
  104. 73,
  105. 74,
  106. 88,
  107. 90, // entry 19
  108. 97,
  109. 106,
  110. 118,
  111. 119,
  112. 148, // entry 24
  113. 156,
  114. 157,
  115. 158,
  116. };
  117. UINT8 ubRPCNumSmallFaceValues = 28;
  118. extern BOOLEAN gfSMDisableForItems;
  119. extern INT16 gsCurInterfacePanel;
  120. extern UINT16 gusSMCurrentMerc;
  121. extern BOOLEAN gfRerenderInterfaceFromHelpText;
  122. extern BOOLEAN gfInItemPickupMenu;
  123. BOOLEAN FaceRestoreSavedBackgroundRect( INT32 iFaceIndex, INT16 sDestLeft, INT16 sDestTop, INT16 sSrcLeft, INT16 sSrcTop, INT16 sWidth, INT16 sHeight );
  124. void SetupFinalTalkingDelay( FACETYPE *pFace );
  125. INT32 GetFreeFace(void)
  126. {
  127. UINT32 uiCount;
  128. for(uiCount=0; uiCount < guiNumFaces; uiCount++)
  129. {
  130. if((gFacesData[uiCount].fAllocated==FALSE) )
  131. return((INT32)uiCount);
  132. }
  133. if(guiNumFaces < NUM_FACE_SLOTS )
  134. return((INT32)guiNumFaces++);
  135. return(-1);
  136. }
  137. void RecountFaces(void)
  138. {
  139. INT32 uiCount;
  140. for(uiCount=guiNumFaces-1; (uiCount >=0) ; uiCount--)
  141. {
  142. if( ( gFacesData[uiCount].fAllocated ) )
  143. {
  144. guiNumFaces=(UINT32)(uiCount+1);
  145. break;
  146. }
  147. }
  148. }
  149. INT32 InitSoldierFace( SOLDIERTYPE *pSoldier )
  150. {
  151. INT32 iFaceIndex;
  152. // Check if we have a face init already
  153. iFaceIndex = pSoldier->iFaceIndex;
  154. if ( iFaceIndex != -1 )
  155. {
  156. return( iFaceIndex );
  157. }
  158. return( InitFace( pSoldier->ubProfile, pSoldier->ubID, 0) );
  159. }
  160. INT32 InitFace( UINT8 usMercProfileID, UINT8 ubSoldierID, UINT32 uiInitFlags )
  161. {
  162. UINT32 uiBlinkFrequency;
  163. UINT32 uiExpressionFrequency;
  164. if ( usMercProfileID == NO_PROFILE )
  165. {
  166. return( -1 );
  167. }
  168. uiBlinkFrequency = gMercProfiles[ usMercProfileID ].uiBlinkFrequency;
  169. uiExpressionFrequency = gMercProfiles[ usMercProfileID ].uiExpressionFrequency;
  170. if ( Random( 2 ) )
  171. {
  172. uiBlinkFrequency += Random( 2000 );
  173. }
  174. else
  175. {
  176. uiBlinkFrequency -= Random( 2000 );
  177. }
  178. return( InternalInitFace( usMercProfileID, ubSoldierID, uiInitFlags, gMercProfiles[ usMercProfileID ].ubFaceIndex, uiBlinkFrequency, uiExpressionFrequency ) );
  179. }
  180. INT32 InternalInitFace( UINT8 usMercProfileID, UINT8 ubSoldierID, UINT32 uiInitFlags, INT32 iFaceFileID, UINT32 uiBlinkFrequency, UINT32 uiExpressionFrequency )
  181. {
  182. FACETYPE *pFace;
  183. VOBJECT_DESC VObjectDesc;
  184. UINT32 uiVideoObject;
  185. INT32 iFaceIndex;
  186. ETRLEObject ETRLEObject;
  187. HVOBJECT hVObject;
  188. UINT32 uiCount;
  189. SGPPaletteEntry Pal[256];
  190. if( ( iFaceIndex = GetFreeFace() )==(-1) )
  191. return(-1);
  192. // Load face file
  193. VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
  194. // ATE: If we are merc profile ID #151-154, all use 151's protrait....
  195. if ( usMercProfileID >= 151 && usMercProfileID <= 154 )
  196. {
  197. iFaceFileID = 151;
  198. }
  199. // Check if we are a big-face....
  200. if ( uiInitFlags & FACE_BIGFACE )
  201. {
  202. // The filename is the profile ID!
  203. if( iFaceFileID < 100 )
  204. {
  205. sprintf( VObjectDesc.ImageFile, "FACES\\b%02d.sti", iFaceFileID );
  206. }
  207. else
  208. {
  209. sprintf( VObjectDesc.ImageFile, "FACES\\b%03d.sti", iFaceFileID );
  210. }
  211. // ATE: Check for profile - if elliot , use special face :)
  212. if ( usMercProfileID == ELLIOT )
  213. {
  214. if ( gMercProfiles[ ELLIOT ].bNPCData > 3 && gMercProfiles[ ELLIOT ].bNPCData < 7 )
  215. {
  216. sprintf( VObjectDesc.ImageFile, "FACES\\b%02da.sti", iFaceFileID );
  217. }
  218. else if ( gMercProfiles[ ELLIOT ].bNPCData > 6 && gMercProfiles[ ELLIOT ].bNPCData < 10 )
  219. {
  220. sprintf( VObjectDesc.ImageFile, "FACES\\b%02db.sti", iFaceFileID );
  221. }
  222. else if ( gMercProfiles[ ELLIOT ].bNPCData > 9 && gMercProfiles[ ELLIOT ].bNPCData < 13 )
  223. {
  224. sprintf( VObjectDesc.ImageFile, "FACES\\b%02dc.sti", iFaceFileID );
  225. }
  226. else if ( gMercProfiles[ ELLIOT ].bNPCData > 12 && gMercProfiles[ ELLIOT ].bNPCData < 16 )
  227. {
  228. sprintf( VObjectDesc.ImageFile, "FACES\\b%02dd.sti", iFaceFileID );
  229. }
  230. else if ( gMercProfiles[ ELLIOT ].bNPCData == 17 )
  231. {
  232. sprintf( VObjectDesc.ImageFile, "FACES\\b%02de.sti", iFaceFileID );
  233. }
  234. }
  235. }
  236. else
  237. {
  238. if( iFaceFileID < 100 )
  239. {
  240. // The filename is the profile ID!
  241. sprintf( VObjectDesc.ImageFile, "FACES\\%02d.sti", iFaceFileID );
  242. }
  243. else
  244. {
  245. sprintf( VObjectDesc.ImageFile, "FACES\\%03d.sti", iFaceFileID );
  246. }
  247. }
  248. // Load
  249. if( AddVideoObject( &VObjectDesc, &uiVideoObject ) == FALSE )
  250. {
  251. // If we are a big face, use placeholder...
  252. if ( uiInitFlags & FACE_BIGFACE )
  253. {
  254. sprintf( VObjectDesc.ImageFile, "FACES\\placeholder.sti" );
  255. if( AddVideoObject( &VObjectDesc, &uiVideoObject ) == FALSE )
  256. {
  257. return( -1 );
  258. }
  259. }
  260. else
  261. {
  262. return( -1 );
  263. }
  264. }
  265. memset(&gFacesData[ iFaceIndex ], 0, sizeof( FACETYPE ) );
  266. pFace = &gFacesData[ iFaceIndex ];
  267. // Get profile data and set into face data
  268. pFace->ubSoldierID = ubSoldierID;
  269. pFace->iID = iFaceIndex;
  270. pFace->fAllocated = TRUE;
  271. //Default to off!
  272. pFace->fDisabled = TRUE;
  273. pFace->iVideoOverlay = -1;
  274. //pFace->uiEyeDelay = gMercProfiles[ usMercProfileID ].uiEyeDelay;
  275. //pFace->uiMouthDelay = gMercProfiles[ usMercProfileID ].uiMouthDelay;
  276. pFace->uiEyeDelay = 50 + Random( 30 );
  277. pFace->uiMouthDelay = 120;
  278. pFace->ubCharacterNum = usMercProfileID;
  279. pFace->uiBlinkFrequency = uiBlinkFrequency;
  280. pFace->uiExpressionFrequency = uiExpressionFrequency;
  281. pFace->sEyeFrame = 0;
  282. pFace->sMouthFrame = 0;
  283. pFace->uiFlags = uiInitFlags;
  284. // Set palette
  285. if( GetVideoObject( &hVObject, uiVideoObject ) )
  286. {
  287. // Build a grayscale palette! ( for testing different looks )
  288. for(uiCount=0; uiCount < 256; uiCount++)
  289. {
  290. Pal[uiCount].peRed=255;
  291. Pal[uiCount].peGreen=255;
  292. Pal[uiCount].peBlue=255;
  293. }
  294. hVObject->pShades[ FLASH_PORTRAIT_NOSHADE ] = Create16BPPPaletteShaded( hVObject->pPaletteEntry, 255, 255, 255, FALSE );
  295. hVObject->pShades[ FLASH_PORTRAIT_STARTSHADE ] = Create16BPPPaletteShaded( Pal, 255, 255, 255, FALSE );
  296. hVObject->pShades[ FLASH_PORTRAIT_ENDSHADE ] = Create16BPPPaletteShaded( hVObject->pPaletteEntry, 250, 25, 25, TRUE );
  297. hVObject->pShades[ FLASH_PORTRAIT_DARKSHADE ] = Create16BPPPaletteShaded( hVObject->pPaletteEntry, 100, 100, 100, TRUE );
  298. hVObject->pShades[ FLASH_PORTRAIT_LITESHADE ] = Create16BPPPaletteShaded( hVObject->pPaletteEntry, 100, 100, 100, FALSE );
  299. for(uiCount=0; uiCount < 256; uiCount++)
  300. {
  301. Pal[uiCount].peRed=(UINT8)(uiCount%128)+128;
  302. Pal[uiCount].peGreen=(UINT8)(uiCount%128)+128;
  303. Pal[uiCount].peBlue=(UINT8)(uiCount%128)+128;
  304. }
  305. hVObject->pShades[ FLASH_PORTRAIT_GRAYSHADE ] = Create16BPPPaletteShaded( Pal, 255, 255, 255, FALSE );
  306. }
  307. // Get FACE height, width
  308. if( GetVideoObjectETRLEPropertiesFromIndex( uiVideoObject, &ETRLEObject, 0 ) == FALSE )
  309. {
  310. return( -1 );
  311. }
  312. pFace->usFaceWidth = ETRLEObject.usWidth;
  313. pFace->usFaceHeight = ETRLEObject.usHeight;
  314. // OK, check # of items
  315. if ( hVObject->usNumberOfObjects == 8 )
  316. {
  317. pFace->fInvalidAnim = FALSE;
  318. // Get EYE height, width
  319. if( GetVideoObjectETRLEPropertiesFromIndex( uiVideoObject, &ETRLEObject, 1 ) == FALSE )
  320. {
  321. return( -1 );
  322. }
  323. pFace->usEyesWidth = ETRLEObject.usWidth;
  324. pFace->usEyesHeight = ETRLEObject.usHeight;
  325. // Get Mouth height, width
  326. if( GetVideoObjectETRLEPropertiesFromIndex( uiVideoObject, &ETRLEObject, 5 ) == FALSE )
  327. {
  328. return( -1 );
  329. }
  330. pFace->usMouthWidth = ETRLEObject.usWidth;
  331. pFace->usMouthHeight = ETRLEObject.usHeight;
  332. }
  333. else
  334. {
  335. pFace->fInvalidAnim = TRUE;
  336. }
  337. // Set id
  338. pFace->uiVideoObject = uiVideoObject;
  339. return( iFaceIndex );
  340. }
  341. void DeleteSoldierFace( SOLDIERTYPE *pSoldier )
  342. {
  343. DeleteFace( pSoldier->iFaceIndex );
  344. pSoldier->iFaceIndex = -1;
  345. }
  346. void DeleteFace( INT32 iFaceIndex )
  347. {
  348. FACETYPE *pFace;
  349. // Check face index
  350. CHECKV( iFaceIndex != -1 );
  351. pFace = &gFacesData[ iFaceIndex ];
  352. // Check for a valid slot!
  353. CHECKV( pFace->fAllocated != FALSE );
  354. pFace->fCanHandleInactiveNow = TRUE;
  355. if ( !pFace->fDisabled )
  356. {
  357. SetAutoFaceInActive( iFaceIndex );
  358. }
  359. // If we are still talking, stop!
  360. if ( pFace->fTalking )
  361. {
  362. // Call dialogue handler function
  363. pFace->fTalking = FALSE;
  364. HandleDialogueEnd( pFace );
  365. }
  366. // Delete vo
  367. DeleteVideoObjectFromIndex( pFace->uiVideoObject );
  368. // Set uncallocated
  369. pFace->fAllocated = FALSE;
  370. RecountFaces( );
  371. }
  372. void SetAutoFaceActiveFromSoldier( UINT32 uiDisplayBuffer, UINT32 uiRestoreBuffer, UINT8 ubSoldierID , UINT16 usFaceX, UINT16 usFaceY )
  373. {
  374. if( ubSoldierID == NOBODY )
  375. {
  376. return;
  377. }
  378. SetAutoFaceActive( uiDisplayBuffer, uiRestoreBuffer, MercPtrs[ ubSoldierID ]->iFaceIndex, usFaceX, usFaceY );
  379. }
  380. void GetFaceRelativeCoordinates( FACETYPE *pFace, UINT16 *pusEyesX, UINT16 *pusEyesY, UINT16 *pusMouthX, UINT16 *pusMouthY )
  381. {
  382. UINT16 usMercProfileID;
  383. UINT16 usEyesX;
  384. UINT16 usEyesY;
  385. UINT16 usMouthX;
  386. UINT16 usMouthY;
  387. INT32 cnt;
  388. usMercProfileID = pFace->ubCharacterNum;
  389. //Take eyes x,y from profile unless we are an RPC and we are small faced.....
  390. usEyesX = gMercProfiles[ usMercProfileID ].usEyesX;
  391. usEyesY = gMercProfiles[ usMercProfileID ].usEyesY;
  392. usMouthY = gMercProfiles[ usMercProfileID ].usMouthY;
  393. usMouthX = gMercProfiles[ usMercProfileID ].usMouthX;
  394. // Use some other values for x,y, base on if we are a RPC!
  395. if ( !( pFace->uiFlags & FACE_BIGFACE ) ||( pFace->uiFlags & FACE_FORCE_SMALL ))
  396. {
  397. // Are we a recruited merc? .. or small?
  398. if( ( gMercProfiles[ usMercProfileID ].ubMiscFlags & ( PROFILE_MISC_FLAG_RECRUITED | PROFILE_MISC_FLAG_EPCACTIVE ) ) ||( pFace->uiFlags & FACE_FORCE_SMALL ) )
  399. {
  400. // Loop through all values of availible merc IDs to find ours!
  401. for ( cnt = 0; cnt < ubRPCNumSmallFaceValues; cnt++ )
  402. {
  403. // We've found one!
  404. if ( gubRPCSmallFaceProfileNum[ cnt ] == usMercProfileID )
  405. {
  406. usEyesX = gRPCSmallFaceValues[ cnt ].bEyesX;
  407. usEyesY = gRPCSmallFaceValues[ cnt ].bEyesY;
  408. usMouthY = gRPCSmallFaceValues[ cnt ].bMouthY;
  409. usMouthX = gRPCSmallFaceValues[ cnt ].bMouthX;
  410. }
  411. }
  412. }
  413. }
  414. (*pusEyesX) = usEyesX;
  415. (*pusEyesY) = usEyesY;
  416. (*pusMouthX) = usMouthX;
  417. (*pusMouthY) = usMouthY;
  418. }
  419. void SetAutoFaceActive( UINT32 uiDisplayBuffer, UINT32 uiRestoreBuffer, INT32 iFaceIndex , UINT16 usFaceX, UINT16 usFaceY )
  420. {
  421. UINT16 usEyesX;
  422. UINT16 usEyesY;
  423. UINT16 usMouthX;
  424. UINT16 usMouthY;
  425. FACETYPE *pFace;
  426. // Check face index
  427. CHECKV( iFaceIndex != -1 );
  428. pFace = &gFacesData[ iFaceIndex ];
  429. GetFaceRelativeCoordinates( pFace, &usEyesX, &usEyesY, &usMouthX, &usMouthY );
  430. InternalSetAutoFaceActive( uiDisplayBuffer, uiRestoreBuffer, iFaceIndex , usFaceX, usFaceY, usEyesX, usEyesY, usMouthX, usMouthY );
  431. }
  432. void InternalSetAutoFaceActive( UINT32 uiDisplayBuffer, UINT32 uiRestoreBuffer, INT32 iFaceIndex , UINT16 usFaceX, UINT16 usFaceY, UINT16 usEyesX, UINT16 usEyesY, UINT16 usMouthX, UINT16 usMouthY )
  433. {
  434. UINT16 usMercProfileID;
  435. FACETYPE *pFace;
  436. VSURFACE_DESC vs_desc;
  437. UINT16 usWidth;
  438. UINT16 usHeight;
  439. UINT8 ubBitDepth;
  440. // Check face index
  441. CHECKV( iFaceIndex != -1 );
  442. pFace = &gFacesData[ iFaceIndex ];
  443. // IF we are already being contained elsewhere, return without doing anything!
  444. // ATE: Don't allow another activity from setting active....
  445. if ( pFace->uiFlags & FACE_INACTIVE_HANDLED_ELSEWHERE )
  446. {
  447. return;
  448. }
  449. // Check if we are active already, remove if so!
  450. if ( pFace->fDisabled )
  451. {
  452. SetAutoFaceInActive( iFaceIndex );
  453. }
  454. if ( uiRestoreBuffer == FACE_AUTO_RESTORE_BUFFER )
  455. {
  456. // BUILD A BUFFER
  457. GetCurrentVideoSettings( &usWidth, &usHeight, &ubBitDepth );
  458. // OK, ignore screen widths, height, only use BPP
  459. vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
  460. vs_desc.usWidth = pFace->usFaceWidth;
  461. vs_desc.usHeight = pFace->usFaceHeight;
  462. vs_desc.ubBitDepth = ubBitDepth;
  463. pFace->fAutoRestoreBuffer = TRUE;
  464. CHECKV( AddVideoSurface( &vs_desc, &(pFace->uiAutoRestoreBuffer) ) );
  465. }
  466. else
  467. {
  468. pFace->fAutoRestoreBuffer = FALSE;
  469. pFace->uiAutoRestoreBuffer = uiRestoreBuffer;
  470. }
  471. if ( uiDisplayBuffer == FACE_AUTO_DISPLAY_BUFFER )
  472. {
  473. // BUILD A BUFFER
  474. GetCurrentVideoSettings( &usWidth, &usHeight, &ubBitDepth );
  475. // OK, ignore screen widths, height, only use BPP
  476. vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
  477. vs_desc.usWidth = pFace->usFaceWidth;
  478. vs_desc.usHeight = pFace->usFaceHeight;
  479. vs_desc.ubBitDepth = ubBitDepth;
  480. pFace->fAutoDisplayBuffer = TRUE;
  481. CHECKV( AddVideoSurface( &vs_desc, &(pFace->uiAutoDisplayBuffer) ) );
  482. }
  483. else
  484. {
  485. pFace->fAutoDisplayBuffer = FALSE;
  486. pFace->uiAutoDisplayBuffer = uiDisplayBuffer;
  487. }
  488. usMercProfileID = pFace->ubCharacterNum;
  489. pFace->usFaceX = usFaceX;
  490. pFace->usFaceY = usFaceY;
  491. pFace->fCanHandleInactiveNow = FALSE;
  492. //Take eyes x,y from profile unless we are an RPC and we are small faced.....
  493. pFace->usEyesX = usEyesX + usFaceX;
  494. pFace->usEyesY = usEyesY + usFaceY;
  495. pFace->usMouthY = usMouthY + usFaceY;
  496. pFace->usMouthX = usMouthX + usFaceX;
  497. // Save offset values
  498. pFace->usEyesOffsetX = usEyesX;
  499. pFace->usEyesOffsetY = usEyesY;
  500. pFace->usMouthOffsetY = usMouthY;
  501. pFace->usMouthOffsetX = usMouthX;
  502. if ( pFace->usEyesY == usFaceY || pFace->usMouthY == usFaceY )
  503. {
  504. pFace->fInvalidAnim = TRUE;
  505. }
  506. pFace->fDisabled = FALSE;
  507. pFace->uiLastBlink = GetJA2Clock();
  508. pFace->uiLastExpression = GetJA2Clock();
  509. pFace->uiEyelast = GetJA2Clock();
  510. pFace->fStartFrame = TRUE;
  511. // Are we a soldier?
  512. if ( pFace->ubSoldierID != NOBODY )
  513. {
  514. pFace->bOldSoldierLife = MercPtrs[ pFace->ubSoldierID ]->bLife;
  515. }
  516. }
  517. void SetAutoFaceInActiveFromSoldier( UINT8 ubSoldierID )
  518. {
  519. // Check for valid soldier
  520. CHECKV( ubSoldierID != NOBODY );
  521. SetAutoFaceInActive( MercPtrs[ ubSoldierID ]->iFaceIndex );
  522. }
  523. void SetAutoFaceInActive(INT32 iFaceIndex )
  524. {
  525. FACETYPE *pFace;
  526. SOLDIERTYPE *pSoldier;
  527. // Check face index
  528. CHECKV( iFaceIndex != -1 );
  529. pFace = &gFacesData[ iFaceIndex ];
  530. // Check for a valid slot!
  531. CHECKV( pFace->fAllocated != FALSE );
  532. // Turn off some flags
  533. if ( pFace->uiFlags & FACE_INACTIVE_HANDLED_ELSEWHERE )
  534. {
  535. if ( !pFace->fCanHandleInactiveNow )
  536. {
  537. return;
  538. }
  539. }
  540. if ( pFace->uiFlags & FACE_MAKEACTIVE_ONCE_DONE )
  541. {
  542. //
  543. if ( pFace->ubSoldierID != NOBODY )
  544. {
  545. pSoldier = MercPtrs[ pFace->ubSoldierID ];
  546. // IF we are in tactical
  547. if ( pSoldier->bAssignment == iCurrentTacticalSquad && guiCurrentScreen == GAME_SCREEN )
  548. {
  549. // Make the interfac panel dirty..
  550. // This will dirty the panel next frame...
  551. gfRerenderInterfaceFromHelpText = TRUE;
  552. }
  553. }
  554. }
  555. if ( pFace->fAutoRestoreBuffer )
  556. {
  557. DeleteVideoSurfaceFromIndex( pFace->uiAutoRestoreBuffer );
  558. }
  559. if ( pFace->fAutoDisplayBuffer )
  560. {
  561. DeleteVideoSurfaceFromIndex( pFace->uiAutoDisplayBuffer );
  562. }
  563. if ( pFace->iVideoOverlay != -1 )
  564. {
  565. RemoveVideoOverlay( pFace->iVideoOverlay );
  566. pFace->iVideoOverlay = -1;
  567. }
  568. // Turn off some flags
  569. pFace->uiFlags &= ( ~FACE_INACTIVE_HANDLED_ELSEWHERE );
  570. // Disable!
  571. pFace->fDisabled = TRUE;
  572. }
  573. void SetAllAutoFacesInactive( )
  574. {
  575. UINT32 uiCount;
  576. FACETYPE *pFace;
  577. for ( uiCount = 0; uiCount < guiNumFaces; uiCount++ )
  578. {
  579. if ( gFacesData[ uiCount ].fAllocated )
  580. {
  581. pFace = &gFacesData[ uiCount ];
  582. SetAutoFaceInActive( uiCount );
  583. }
  584. }
  585. }
  586. void BlinkAutoFace( INT32 iFaceIndex )
  587. {
  588. FACETYPE *pFace;
  589. INT16 sFrame;
  590. BOOLEAN fDoBlink = FALSE;
  591. if ( gFacesData[ iFaceIndex ].fAllocated && !gFacesData[ iFaceIndex ].fDisabled && !gFacesData[ iFaceIndex ].fInvalidAnim )
  592. {
  593. pFace = &gFacesData[ iFaceIndex ];
  594. // CHECK IF BUDDY IS DEAD, UNCONSCIOUS, ASLEEP, OR POW!
  595. if ( pFace->ubSoldierID != NOBODY )
  596. {
  597. if ( ( MercPtrs[ pFace->ubSoldierID ]->bLife < OKLIFE ) ||
  598. ( MercPtrs[ pFace->ubSoldierID ]->fMercAsleep == TRUE ) ||
  599. ( MercPtrs[ pFace->ubSoldierID ]->bAssignment == ASSIGNMENT_POW ) )
  600. {
  601. return;
  602. }
  603. }
  604. if ( pFace->ubExpression == NO_EXPRESSION )
  605. {
  606. // Get Delay time, if the first frame, use a different delay
  607. if ( ( GetJA2Clock() - pFace->uiLastBlink ) > pFace->uiBlinkFrequency )
  608. {
  609. pFace->uiLastBlink = GetJA2Clock();
  610. pFace->ubExpression = BLINKING;
  611. pFace->uiEyelast = GetJA2Clock();
  612. }
  613. if ( pFace->fAnimatingTalking )
  614. {
  615. if ( ( GetJA2Clock() - pFace->uiLastExpression ) > pFace->uiExpressionFrequency )
  616. {
  617. pFace->uiLastExpression = GetJA2Clock();
  618. if ( Random( 2 ) == 0 )
  619. {
  620. pFace->ubExpression = ANGRY;
  621. }
  622. else
  623. {
  624. pFace->ubExpression = SURPRISED;
  625. }
  626. }
  627. }
  628. }
  629. if ( pFace->ubExpression != NO_EXPRESSION )
  630. {
  631. if ( pFace->fStartFrame )
  632. {
  633. if ( ( GetJA2Clock() - pFace->uiEyelast ) > pFace->uiEyeDelay ) //> Random( 10000 ) )
  634. {
  635. fDoBlink = TRUE;
  636. pFace->fStartFrame = FALSE;
  637. }
  638. }
  639. else
  640. {
  641. if ( ( GetJA2Clock() - pFace->uiEyelast ) > pFace->uiEyeDelay )
  642. {
  643. fDoBlink = TRUE;
  644. }
  645. }
  646. // Are we going to blink?
  647. if ( fDoBlink )
  648. {
  649. pFace->uiEyelast = GetJA2Clock();
  650. // Adjust
  651. NewEye( pFace );
  652. sFrame = pFace->sEyeFrame;
  653. if ( sFrame >= 5 )
  654. {
  655. sFrame = 4;
  656. }
  657. if ( sFrame > 0 )
  658. {
  659. // Blit Accordingly!
  660. BltVideoObjectFromIndex( pFace->uiAutoDisplayBuffer, pFace->uiVideoObject, (INT16)( sFrame ), pFace->usEyesX, pFace->usEyesY, VO_BLT_SRCTRANSPARENCY, NULL );
  661. if ( pFace->uiAutoDisplayBuffer == FRAME_BUFFER )
  662. {
  663. InvalidateRegion( pFace->usEyesX, pFace->usEyesY, pFace->usEyesX + pFace->usEyesWidth, pFace->usEyesY + pFace->usEyesHeight );
  664. }
  665. }
  666. else
  667. {
  668. //RenderFace( uiDestBuffer , uiCount );
  669. pFace->ubExpression = NO_EXPRESSION;
  670. // Update rects just for eyes
  671. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  672. {
  673. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usEyesX, pFace->usEyesY, pFace->usEyesX, pFace->usEyesY, pFace->usEyesWidth, pFace->usEyesHeight );
  674. }
  675. else
  676. {
  677. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usEyesX, pFace->usEyesY, pFace->usEyesOffsetX, pFace->usEyesOffsetY, pFace->usEyesWidth, pFace->usEyesHeight );
  678. }
  679. }
  680. HandleRenderFaceAdjustments( pFace, TRUE, FALSE, 0, pFace->usFaceX, pFace->usFaceY, pFace->usEyesX, pFace->usEyesY );
  681. }
  682. }
  683. }
  684. }
  685. void HandleFaceHilights( FACETYPE *pFace, UINT32 uiBuffer, INT16 sFaceX, INT16 sFaceY )
  686. {
  687. UINT32 uiDestPitchBYTES;
  688. UINT8 *pDestBuf;
  689. UINT16 usLineColor;
  690. INT32 iFaceIndex;
  691. iFaceIndex = pFace->iID;
  692. if ( !gFacesData[ iFaceIndex ].fDisabled )
  693. {
  694. if ( pFace->uiAutoDisplayBuffer == FRAME_BUFFER && guiCurrentScreen == GAME_SCREEN )
  695. {
  696. // If we are highlighted, do this now!
  697. if ( ( pFace->uiFlags & FACE_SHOW_WHITE_HILIGHT ) )
  698. {
  699. // Lock buffer
  700. pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
  701. SetClippingRegionAndImageWidth( uiDestPitchBYTES, sFaceX-2, sFaceY-1, sFaceX + pFace->usFaceWidth + 4, sFaceY + pFace->usFaceHeight + 4 );
  702. usLineColor = Get16BPPColor( FROMRGB( 255, 255, 255 ) );
  703. RectangleDraw( TRUE, (sFaceX - 2 ), (sFaceY - 1),sFaceX + pFace->usFaceWidth + 1, sFaceY + pFace->usFaceHeight , usLineColor, pDestBuf );
  704. SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
  705. UnLockVideoSurface( uiBuffer );
  706. }
  707. else if ( ( pFace->uiFlags & FACE_SHOW_MOVING_HILIGHT ) )
  708. {
  709. if ( pFace->ubSoldierID != NOBODY )
  710. {
  711. if ( MercPtrs[ pFace->ubSoldierID ]->bLife >= OKLIFE )
  712. {
  713. // Lock buffer
  714. pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
  715. SetClippingRegionAndImageWidth( uiDestPitchBYTES, sFaceX-2, sFaceY-1, sFaceX + pFace->usFaceWidth + 4, sFaceY + pFace->usFaceHeight + 4 );
  716. if ( MercPtrs[ pFace->ubSoldierID ]->bStealthMode )
  717. {
  718. usLineColor = Get16BPPColor( FROMRGB( 158, 158, 12 ) );
  719. }
  720. else
  721. {
  722. usLineColor = Get16BPPColor( FROMRGB( 8, 12, 118 ) );
  723. }
  724. RectangleDraw( TRUE, (sFaceX - 2 ), (sFaceY - 1),sFaceX + pFace->usFaceWidth + 1, sFaceY + pFace->usFaceHeight , usLineColor, pDestBuf );
  725. SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
  726. UnLockVideoSurface( uiBuffer );
  727. }
  728. }
  729. }
  730. else
  731. {
  732. // ATE: Zero out any highlight boxzes....
  733. // Lock buffer
  734. pDestBuf = LockVideoSurface( pFace->uiAutoDisplayBuffer, &uiDestPitchBYTES );
  735. SetClippingRegionAndImageWidth( uiDestPitchBYTES, pFace->usFaceX-2, pFace->usFaceY-1, pFace->usFaceX + pFace->usFaceWidth + 4, pFace->usFaceY + pFace->usFaceHeight + 4 );
  736. usLineColor = Get16BPPColor( FROMRGB( 0, 0, 0 ) );
  737. RectangleDraw( TRUE, (pFace->usFaceX - 2 ), (pFace->usFaceY - 1), pFace->usFaceX + pFace->usFaceWidth + 1, pFace->usFaceY + pFace->usFaceHeight , usLineColor, pDestBuf );
  738. SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
  739. UnLockVideoSurface( pFace->uiAutoDisplayBuffer );
  740. }
  741. }
  742. }
  743. if ( ( pFace->fCompatibleItems && !gFacesData[ iFaceIndex ].fDisabled ) )
  744. {
  745. // Lock buffer
  746. pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
  747. SetClippingRegionAndImageWidth( uiDestPitchBYTES, sFaceX-2, sFaceY-1, sFaceX + pFace->usFaceWidth+ 4, sFaceY + pFace->usFaceHeight + 4 );
  748. usLineColor = Get16BPPColor( FROMRGB( 255, 0, 0 ) );
  749. RectangleDraw( TRUE, (sFaceX - 2), (sFaceY - 1), sFaceX + pFace->usFaceWidth + 1, sFaceY + pFace->usFaceHeight , usLineColor, pDestBuf );
  750. SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
  751. UnLockVideoSurface( uiBuffer );
  752. }
  753. }
  754. void MouthAutoFace( INT32 iFaceIndex )
  755. {
  756. FACETYPE *pFace;
  757. INT16 sFrame;
  758. if ( gFacesData[ iFaceIndex ].fAllocated )
  759. {
  760. pFace = &gFacesData[ iFaceIndex ];
  761. // Remove video overlay is present....
  762. if ( pFace->uiFlags & FACE_DESTROY_OVERLAY )
  763. {
  764. //if ( pFace->iVideoOverlay != -1 )
  765. //{
  766. // if ( pFace->uiStopOverlayTimer != 0 )
  767. // {
  768. // if ( ( GetJA2Clock( ) - pFace->uiStopOverlayTimer ) > END_FACE_OVERLAY_DELAY )
  769. // {
  770. // RemoveVideoOverlay( pFace->iVideoOverlay );
  771. // pFace->iVideoOverlay = -1;
  772. // }
  773. // }
  774. //}
  775. }
  776. if ( pFace->fTalking )
  777. {
  778. if ( !gFacesData[ iFaceIndex ].fDisabled && !gFacesData[ iFaceIndex ].fInvalidAnim )
  779. {
  780. if ( pFace->fAnimatingTalking )
  781. {
  782. PollAudioGap( pFace->uiSoundID, &(pFace->GapList ) );
  783. // Check if we have an audio gap
  784. if ( pFace->GapList.audio_gap_active )
  785. {
  786. pFace->sMouthFrame = 0;
  787. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  788. {
  789. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usMouthX, pFace->usMouthY, pFace->usMouthX, pFace->usMouthY, pFace->usMouthWidth, pFace->usMouthHeight );
  790. }
  791. else
  792. {
  793. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usMouthX, pFace->usMouthY, pFace->usMouthOffsetX, pFace->usMouthOffsetY, pFace->usMouthWidth, pFace->usMouthHeight );
  794. }
  795. }
  796. else
  797. {
  798. // Get Delay time
  799. if ( ( GetJA2Clock() - pFace->uiMouthlast ) > pFace->uiMouthDelay )
  800. {
  801. pFace->uiMouthlast = GetJA2Clock();
  802. // Adjust
  803. NewMouth( pFace );
  804. sFrame = pFace->sMouthFrame;
  805. if ( sFrame > 0 )
  806. {
  807. // Blit Accordingly!
  808. BltVideoObjectFromIndex( pFace->uiAutoDisplayBuffer, pFace->uiVideoObject, (INT16)( sFrame + 4 ), pFace->usMouthX, pFace->usMouthY, VO_BLT_SRCTRANSPARENCY, NULL );
  809. // Update rects
  810. if ( pFace->uiAutoDisplayBuffer == FRAME_BUFFER )
  811. {
  812. InvalidateRegion( pFace->usMouthX, pFace->usMouthY, pFace->usMouthX + pFace->usMouthWidth, pFace->usMouthY + pFace->usMouthHeight );
  813. }
  814. }
  815. else
  816. {
  817. //RenderFace( uiDestBuffer , uiCount );
  818. //pFace->fTaking = FALSE;
  819. // Update rects just for Mouth
  820. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  821. {
  822. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usMouthX, pFace->usMouthY, pFace->usMouthX, pFace->usMouthY, pFace->usMouthWidth, pFace->usMouthHeight );
  823. }
  824. else
  825. {
  826. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usMouthX, pFace->usMouthY, pFace->usMouthOffsetX, pFace->usMouthOffsetY, pFace->usMouthWidth, pFace->usMouthHeight );
  827. }
  828. }
  829. HandleRenderFaceAdjustments( pFace, TRUE, FALSE, 0, pFace->usFaceX, pFace->usFaceY, pFace->usEyesX, pFace->usEyesY );
  830. }
  831. }
  832. }
  833. }
  834. }
  835. if ( !( pFace->uiFlags & FACE_INACTIVE_HANDLED_ELSEWHERE ) )
  836. {
  837. HandleFaceHilights( pFace, pFace->uiAutoDisplayBuffer, pFace->usFaceX, pFace->usFaceY );
  838. }
  839. }
  840. }
  841. void HandleTalkingAutoFace( INT32 iFaceIndex )
  842. {
  843. FACETYPE *pFace;
  844. if ( gFacesData[ iFaceIndex ].fAllocated )
  845. {
  846. pFace = &gFacesData[ iFaceIndex ];
  847. if ( pFace->fTalking )
  848. {
  849. // Check if we are done! ( Check this first! )
  850. if ( pFace->fValidSpeech )
  851. {
  852. // Check if we have finished, set some flags for the final delay down if so!
  853. if ( !SoundIsPlaying( pFace->uiSoundID ) && !pFace->fFinishTalking )
  854. {
  855. SetupFinalTalkingDelay( pFace );
  856. }
  857. }
  858. else
  859. {
  860. // Check if our delay is over
  861. if ( !pFace->fFinishTalking )
  862. {
  863. if ( ( GetJA2Clock() - pFace->uiTalkingTimer ) > pFace->uiTalkingDuration )
  864. {
  865. // If here, setup for last delay!
  866. SetupFinalTalkingDelay( pFace );
  867. }
  868. }
  869. }
  870. // Now check for end of talking
  871. if ( pFace->fFinishTalking )
  872. {
  873. if ( ( GetJA2Clock() - pFace->uiTalkingTimer ) > pFace->uiTalkingDuration )
  874. {
  875. pFace->fTalking = FALSE;
  876. pFace->fAnimatingTalking = FALSE;
  877. // Remove gap info
  878. AudioGapListDone( &(pFace->GapList) );
  879. // Remove video overlay is present....
  880. if ( pFace->iVideoOverlay != -1 )
  881. {
  882. //if ( pFace->uiStopOverlayTimer == 0 )
  883. //{
  884. // pFace->uiStopOverlayTimer = GetJA2Clock();
  885. //}
  886. }
  887. // Call dialogue handler function
  888. HandleDialogueEnd( pFace );
  889. }
  890. }
  891. }
  892. }
  893. }
  894. // Local function - uses these variables because they have already been validated
  895. void SetFaceShade( SOLDIERTYPE *pSoldier, FACETYPE *pFace, BOOLEAN fExternBlit )
  896. {
  897. // Set to default
  898. SetObjectHandleShade( pFace->uiVideoObject, FLASH_PORTRAIT_NOSHADE );
  899. if ( pFace->iVideoOverlay == -1 && !fExternBlit )
  900. {
  901. if ( ( pSoldier->bActionPoints == 0 ) && !( gTacticalStatus.uiFlags & REALTIME ) && (gTacticalStatus.uiFlags & INCOMBAT ) )
  902. {
  903. SetObjectHandleShade( pFace->uiVideoObject, FLASH_PORTRAIT_LITESHADE );
  904. }
  905. }
  906. if ( pSoldier->bLife < OKLIFE )
  907. {
  908. SetObjectHandleShade( pFace->uiVideoObject, FLASH_PORTRAIT_DARKSHADE );
  909. }
  910. // ATE: Don't shade for damage if blitting extern face...
  911. if ( !fExternBlit )
  912. {
  913. if ( pSoldier->fFlashPortrait == FLASH_PORTRAIT_START )
  914. {
  915. SetObjectHandleShade( pFace->uiVideoObject, pSoldier->bFlashPortraitFrame );
  916. }
  917. }
  918. }
  919. BOOLEAN RenderAutoFaceFromSoldier( UINT8 ubSoldierID )
  920. {
  921. // Check for valid soldier
  922. CHECKF( ubSoldierID != NOBODY );
  923. return( RenderAutoFace( MercPtrs[ ubSoldierID ]->iFaceIndex ) );
  924. }
  925. void GetXYForIconPlacement( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY )
  926. {
  927. INT16 sX, sY;
  928. UINT16 usWidth, usHeight;
  929. ETRLEObject *pTrav;
  930. HVOBJECT hVObject;
  931. // Get height, width of icon...
  932. GetVideoObject( &hVObject, guiPORTRAITICONS );
  933. pTrav = &(hVObject->pETRLEObject[ ubIndex ] );
  934. usHeight = pTrav->usHeight;
  935. usWidth = pTrav->usWidth;
  936. sX = sFaceX + pFace->usFaceWidth - usWidth - 1;
  937. sY = sFaceY + pFace->usFaceHeight - usHeight - 1;
  938. *psX = sX;
  939. *psY = sY;
  940. }
  941. void GetXYForRightIconPlacement( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY, INT8 bNumIcons )
  942. {
  943. INT16 sX, sY;
  944. UINT16 usWidth, usHeight;
  945. ETRLEObject *pTrav;
  946. HVOBJECT hVObject;
  947. // Get height, width of icon...
  948. GetVideoObject( &hVObject, guiPORTRAITICONS );
  949. pTrav = &(hVObject->pETRLEObject[ ubIndex ] );
  950. usHeight = pTrav->usHeight;
  951. usWidth = pTrav->usWidth;
  952. sX = sFaceX + ( usWidth * bNumIcons ) + 1;
  953. sY = sFaceY + pFace->usFaceHeight - usHeight - 1;
  954. *psX = sX;
  955. *psY = sY;
  956. }
  957. void DoRightIcon( UINT32 uiRenderBuffer, FACETYPE *pFace, INT16 sFaceX, INT16 sFaceY, INT8 bNumIcons, INT8 sIconIndex )
  958. {
  959. INT16 sIconX, sIconY;
  960. // Find X, y for placement
  961. GetXYForRightIconPlacement( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons );
  962. BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
  963. }
  964. void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLEAN fUseExternBuffer, UINT32 uiBuffer, INT16 sFaceX, INT16 sFaceY, UINT16 usEyesX, UINT16 usEyesY )
  965. {
  966. INT16 sIconX, sIconY;
  967. INT16 sIconIndex=-1;
  968. BOOLEAN fDoIcon = FALSE;
  969. UINT32 uiRenderBuffer;
  970. INT16 sPtsAvailable = 0;
  971. UINT16 usMaximumPts = 0;
  972. CHAR16 sString[ 32 ];
  973. UINT16 usTextWidth;
  974. BOOLEAN fAtGunRange = FALSE;
  975. BOOLEAN fShowNumber = FALSE;
  976. BOOLEAN fShowMaximum = FALSE;
  977. SOLDIERTYPE *pSoldier;
  978. INT16 sFontX, sFontY;
  979. INT16 sX1, sY1, sY2, sX2;
  980. UINT32 uiDestPitchBYTES;
  981. UINT8 *pDestBuf;
  982. UINT16 usLineColor;
  983. INT8 bNumRightIcons = 0;
  984. // If we are using an extern buffer...
  985. if ( fUseExternBuffer )
  986. {
  987. uiRenderBuffer = uiBuffer;
  988. }
  989. else
  990. {
  991. if ( fDisplayBuffer )
  992. {
  993. uiRenderBuffer = pFace->uiAutoDisplayBuffer;
  994. }
  995. else
  996. {
  997. uiRenderBuffer = pFace->uiAutoRestoreBuffer;
  998. if ( pFace->uiAutoRestoreBuffer == FACE_NO_RESTORE_BUFFER )
  999. {
  1000. return;
  1001. }
  1002. }
  1003. }
  1004. // BLIT HATCH
  1005. if ( pFace->ubSoldierID != NOBODY )
  1006. {
  1007. pSoldier = MercPtrs[ pFace->ubSoldierID ];
  1008. if ( ( MercPtrs[ pFace->ubSoldierID ]->bLife < CONSCIOUSNESS || MercPtrs[ pFace->ubSoldierID ]->fDeadPanel ) )
  1009. {
  1010. // Blit Closed eyes here!
  1011. BltVideoObjectFromIndex( uiRenderBuffer, pFace->uiVideoObject, 1, usEyesX, usEyesY, VO_BLT_SRCTRANSPARENCY, NULL );
  1012. // Blit hatch!
  1013. BltVideoObjectFromIndex( uiRenderBuffer, guiHATCH, 0, sFaceX, sFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
  1014. }
  1015. if( MercPtrs[ pFace->ubSoldierID ]->fMercAsleep == TRUE )
  1016. {
  1017. // blit eyes closed
  1018. BltVideoObjectFromIndex( uiRenderBuffer, pFace->uiVideoObject, 1, usEyesX, usEyesY, VO_BLT_SRCTRANSPARENCY, NULL );
  1019. }
  1020. if ( ( pSoldier->uiStatusFlags & SOLDIER_DEAD ) )
  1021. {
  1022. // IF we are in the process of doing any deal/close animations, show face, not skill...
  1023. if ( !pSoldier->fClosePanel && !pSoldier->fDeadPanel && !pSoldier->fUIdeadMerc && !pSoldier->fUICloseMerc )
  1024. {
  1025. // Put close panel there
  1026. BltVideoObjectFromIndex( uiRenderBuffer, guiDEAD, 5, sFaceX, sFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
  1027. // Blit hatch!
  1028. BltVideoObjectFromIndex( uiRenderBuffer, guiHATCH, 0, sFaceX, sFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
  1029. }
  1030. }
  1031. // ATE: If talking in popup, don't do the other things.....
  1032. if ( pFace->fTalking && gTacticalStatus.uiFlags & IN_ENDGAME_SEQUENCE )
  1033. {
  1034. return;
  1035. }
  1036. // ATE: Only do this, because we can be talking during an interrupt....
  1037. if ( ( pFace->uiFlags & FACE_INACTIVE_HANDLED_ELSEWHERE ) && !fUseExternBuffer )
  1038. {
  1039. // Don't do this if we are being handled elsewhere and it's not an extern buffer...
  1040. }
  1041. else
  1042. {
  1043. HandleFaceHilights( pFace, uiRenderBuffer, sFaceX, sFaceY );
  1044. #ifdef JA2BETAVERSION
  1045. if ( pSoldier->bOppCnt != 0 )
  1046. #else
  1047. if ( pSoldier->bOppCnt > 0 )
  1048. #endif
  1049. {
  1050. SetFontDestBuffer( uiRenderBuffer, 0, 0, 640, 480, FALSE );
  1051. swprintf( sString, L"%d", pSoldier->bOppCnt );
  1052. SetFont( TINYFONT1 );
  1053. SetFontForeground( FONT_DKRED );
  1054. SetFontBackground( FONT_NEARBLACK );
  1055. sX1 = (INT16)( sFaceX );
  1056. sY1 = (INT16)( sFaceY );
  1057. sX2 = sX1 + StringPixLength( sString, TINYFONT1 ) + 1;
  1058. sY2 = sY1 + GetFontHeight( TINYFONT1 ) - 1;
  1059. mprintf( (INT16)( sX1 + 1), (INT16)( sY1 - 1 ), sString );
  1060. SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE );
  1061. // Draw box
  1062. pDestBuf = LockVideoSurface( uiRenderBuffer, &uiDestPitchBYTES );
  1063. SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
  1064. usLineColor = Get16BPPColor( FROMRGB( 105, 8, 9 ) );
  1065. RectangleDraw( TRUE, sX1, sY1, sX2, sY2, usLineColor, pDestBuf );
  1066. UnLockVideoSurface( uiRenderBuffer );
  1067. }
  1068. if ( MercPtrs[ pFace->ubSoldierID ]->bInSector && ( ( ( gTacticalStatus.ubCurrentTeam != OUR_TEAM ) || !OK_INTERRUPT_MERC( MercPtrs[ pFace->ubSoldierID ] ) ) && !gfHiddenInterrupt ) || ( ( gfSMDisableForItems && !gfInItemPickupMenu ) && gusSMCurrentMerc == pFace->ubSoldierID && gsCurInterfacePanel == SM_PANEL ) )
  1069. {
  1070. // Blit hatch!
  1071. BltVideoObjectFromIndex( uiRenderBuffer, guiHATCH, 0, sFaceX, sFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
  1072. }
  1073. if ( !pFace->fDisabled && !pFace->fInvalidAnim )
  1074. {
  1075. // Render text above here if that's what was asked for
  1076. if ( pFace->fDisplayTextOver != FACE_NO_TEXT_OVER )
  1077. {
  1078. SetFont( TINYFONT1 );
  1079. SetFontBackground( FONT_MCOLOR_BLACK );
  1080. SetFontForeground( FONT_MCOLOR_WHITE );
  1081. SetFontDestBuffer( uiRenderBuffer, 0, 0, 640, 480, FALSE );
  1082. VarFindFontCenterCoordinates( sFaceX, sFaceY, pFace->usFaceWidth, pFace->usFaceHeight, TINYFONT1, &sFontX, &sFontY, pFace->zDisplayText );
  1083. if ( pFace->fDisplayTextOver == FACE_DRAW_TEXT_OVER )
  1084. {
  1085. gprintfinvalidate( sFontX, sFontY, pFace->zDisplayText );
  1086. mprintf( sFontX, sFontY, pFace->zDisplayText );
  1087. }
  1088. else if ( pFace->fDisplayTextOver == FACE_ERASE_TEXT_OVER )
  1089. {
  1090. gprintfRestore( sFontX, sFontY, pFace->zDisplayText );
  1091. pFace->fDisplayTextOver = FACE_NO_TEXT_OVER;
  1092. }
  1093. SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE );
  1094. }
  1095. }
  1096. }
  1097. // Check if a robot and is not controlled....
  1098. if ( MercPtrs[ pFace->ubSoldierID ]->uiStatusFlags & SOLDIER_ROBOT )
  1099. {
  1100. if ( !CanRobotBeControlled( MercPtrs[ pFace->ubSoldierID ] ) )
  1101. {
  1102. // Not controlled robot
  1103. sIconIndex = 5;
  1104. fDoIcon = TRUE;
  1105. }
  1106. }
  1107. if ( ControllingRobot( MercPtrs[ pFace->ubSoldierID ] ) )
  1108. {
  1109. // controlling robot
  1110. sIconIndex = 4;
  1111. fDoIcon = TRUE;
  1112. }
  1113. // If blind...
  1114. if ( MercPtrs[ pFace->ubSoldierID ]->bBlindedCounter > 0 )
  1115. {
  1116. DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 6 );
  1117. bNumRightIcons++;
  1118. }
  1119. if ( MercPtrs[ pFace->ubSoldierID ]->bDrugEffect[ DRUG_TYPE_ADRENALINE ] )
  1120. {
  1121. DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 7 );
  1122. bNumRightIcons++;
  1123. }
  1124. if ( GetDrunkLevel( MercPtrs[ pFace->ubSoldierID ] ) != SOBER )
  1125. {
  1126. DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 8 );
  1127. bNumRightIcons++;
  1128. }
  1129. switch( pSoldier->bAssignment )
  1130. {
  1131. case DOCTOR:
  1132. sIconIndex = 1;
  1133. fDoIcon = TRUE;
  1134. sPtsAvailable = CalculateHealingPointsForDoctor( MercPtrs[ pFace->ubSoldierID ], &usMaximumPts, FALSE );
  1135. fShowNumber = TRUE;
  1136. fShowMaximum = TRUE;
  1137. // divide both amounts by 10 to make the displayed numbers a little more user-palatable (smaller)
  1138. sPtsAvailable = ( sPtsAvailable + 5 ) / 10;
  1139. usMaximumPts = ( usMaximumPts + 5 ) / 10;
  1140. break;
  1141. case PATIENT:
  1142. sIconIndex = 2;
  1143. fDoIcon = TRUE;
  1144. // show current health / maximum health
  1145. sPtsAvailable = MercPtrs[ pFace->ubSoldierID ]->bLife;
  1146. usMaximumPts = MercPtrs[ pFace->ubSoldierID ]->bLifeMax;
  1147. fShowNumber = TRUE;
  1148. fShowMaximum = TRUE;
  1149. break;
  1150. case TRAIN_SELF:
  1151. case TRAIN_TOWN:
  1152. case TRAIN_TEAMMATE:
  1153. case TRAIN_BY_OTHER:
  1154. sIconIndex = 3;
  1155. fDoIcon = TRUE;
  1156. fShowNumber = TRUE;
  1157. fShowMaximum = TRUE;
  1158. // there could be bonus pts for training at gun range
  1159. if ( ( MercPtrs[ pFace->ubSoldierID ]->sSectorX == 13) && (MercPtrs[ pFace->ubSoldierID ]->sSectorY == MAP_ROW_H) && (MercPtrs[ pFace->ubSoldierID ]->bSectorZ == 0) )
  1160. {
  1161. fAtGunRange = TRUE;
  1162. }
  1163. switch( MercPtrs[ pFace->ubSoldierID ]->bAssignment )
  1164. {
  1165. case( TRAIN_SELF ):
  1166. sPtsAvailable = GetSoldierTrainingPts( MercPtrs[ pFace->ubSoldierID ], MercPtrs[ pFace->ubSoldierID ]->bTrainStat, fAtGunRange, &usMaximumPts );
  1167. break;
  1168. case( TRAIN_BY_OTHER ):
  1169. sPtsAvailable = GetSoldierStudentPts( MercPtrs[ pFace->ubSoldierID ], MercPtrs[ pFace->ubSoldierID ]->bTrainStat, fAtGunRange, &usMaximumPts );
  1170. break;
  1171. case( TRAIN_TOWN ):
  1172. sPtsAvailable = GetTownTrainPtsForCharacter( MercPtrs[ pFace->ubSoldierID ], &usMaximumPts );
  1173. // divide both amounts by 10 to make the displayed numbers a little more user-palatable (smaller)
  1174. sPtsAvailable = ( sPtsAvailable + 5 ) / 10;
  1175. usMaximumPts = ( usMaximumPts + 5 ) / 10;
  1176. break;
  1177. case( TRAIN_TEAMMATE ):
  1178. sPtsAvailable = GetBonusTrainingPtsDueToInstructor( MercPtrs[ pFace->ubSoldierID ], NULL , MercPtrs[ pFace->ubSoldierID ]->bTrainStat, fAtGunRange, &usMaximumPts );
  1179. break;
  1180. }
  1181. break;
  1182. case REPAIR:
  1183. sIconIndex = 0;
  1184. fDoIcon = TRUE;
  1185. sPtsAvailable = CalculateRepairPointsForRepairman( MercPtrs[ pFace->ubSoldierID ], &usMaximumPts, FALSE );
  1186. fShowNumber = TRUE;
  1187. fShowMaximum = TRUE;
  1188. // check if we are repairing a vehicle
  1189. if ( Menptr[ pFace->ubSoldierID ].bVehicleUnderRepairID != -1 )
  1190. {
  1191. // reduce to a multiple of VEHICLE_REPAIR_POINTS_DIVISOR. This way skill too low will show up as 0 repair pts.
  1192. sPtsAvailable -= ( sPtsAvailable % VEHICLE_REPAIR_POINTS_DIVISOR );
  1193. usMaximumPts -= ( usMaximumPts % VEHICLE_REPAIR_POINTS_DIVISOR );
  1194. }
  1195. break;
  1196. }
  1197. // Check for being serviced...
  1198. if ( MercPtrs[ pFace->ubSoldierID ]->ubServicePartner != NOBODY )
  1199. {
  1200. // Doctor...
  1201. sIconIndex = 1;
  1202. fDoIcon = TRUE;
  1203. }
  1204. if ( MercPtrs[ pFace->ubSoldierID ]->ubServiceCount != 0 )
  1205. {
  1206. // Patient
  1207. sIconIndex = 2;
  1208. fDoIcon = TRUE;
  1209. }
  1210. if ( fDoIcon )
  1211. {
  1212. // Find X, y for placement
  1213. GetXYForIconPlacement( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY );
  1214. BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
  1215. // ATE: Show numbers only in mapscreen
  1216. if( fShowNumber )
  1217. {
  1218. SetFontDestBuffer( uiRenderBuffer, 0, 0, 640, 480, FALSE );
  1219. if ( fShowMaximum )
  1220. {
  1221. swprintf( sString, L"%d/%d", sPtsAvailable, usMaximumPts );
  1222. }
  1223. else
  1224. {
  1225. swprintf( sString, L"%d", sPtsAvailable );
  1226. }
  1227. usTextWidth = StringPixLength( sString, FONT10ARIAL );
  1228. usTextWidth += 1;
  1229. SetFont( FONT10ARIAL );
  1230. SetFontForeground( FONT_YELLOW );
  1231. SetFontBackground( FONT_BLACK );
  1232. mprintf( sFaceX + pFace->usFaceWidth - usTextWidth, ( INT16 )( sFaceY + 3 ), sString );
  1233. SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE );
  1234. }
  1235. }
  1236. }
  1237. else
  1238. {
  1239. if ( pFace->ubCharacterNum == FATHER || pFace->ubCharacterNum == MICKY )
  1240. {
  1241. if ( gMercProfiles[ pFace->ubCharacterNum ].bNPCData >= 5 )
  1242. {
  1243. DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, 0, 8 );
  1244. }
  1245. }
  1246. }
  1247. }
  1248. BOOLEAN RenderAutoFace( INT32 iFaceIndex )
  1249. {
  1250. FACETYPE *pFace;
  1251. // Check face index
  1252. CHECKF( iFaceIndex != -1 );
  1253. pFace = &gFacesData[ iFaceIndex ];
  1254. // Check for a valid slot!
  1255. CHECKF( pFace->fAllocated != FALSE );
  1256. // Check for disabled guy!
  1257. CHECKF( pFace->fDisabled != TRUE );
  1258. // Set shade
  1259. if ( pFace->ubSoldierID != NOBODY )
  1260. {
  1261. SetFaceShade( MercPtrs[ pFace->ubSoldierID ], pFace, FALSE );
  1262. }
  1263. // Blit face to save buffer!
  1264. if ( pFace->uiAutoRestoreBuffer != FACE_NO_RESTORE_BUFFER )
  1265. {
  1266. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  1267. {
  1268. BltVideoObjectFromIndex( pFace->uiAutoRestoreBuffer, pFace->uiVideoObject, 0, pFace->usFaceX, pFace->usFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
  1269. }
  1270. else
  1271. {
  1272. BltVideoObjectFromIndex( pFace->uiAutoRestoreBuffer, pFace->uiVideoObject, 0, 0, 0, VO_BLT_SRCTRANSPARENCY, NULL );
  1273. }
  1274. }
  1275. HandleRenderFaceAdjustments( pFace, FALSE, FALSE, 0, pFace->usFaceX, pFace->usFaceY, pFace->usEyesX, pFace->usEyesY );
  1276. // Restore extern rect
  1277. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  1278. {
  1279. FaceRestoreSavedBackgroundRect( iFaceIndex, (INT16)( pFace->usFaceX ), (INT16)( pFace->usFaceY ), (INT16)( pFace->usFaceX ), (INT16)( pFace->usFaceY ), ( INT16)( pFace->usFaceWidth ), (INT16)( pFace->usFaceHeight ) );
  1280. }
  1281. else
  1282. {
  1283. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usFaceX, pFace->usFaceY, 0, 0, pFace->usFaceWidth, pFace->usFaceHeight );
  1284. }
  1285. return( TRUE );
  1286. }
  1287. BOOLEAN ExternRenderFaceFromSoldier( UINT32 uiBuffer, UINT8 ubSoldierID, INT16 sX, INT16 sY )
  1288. {
  1289. // Check for valid soldier
  1290. CHECKF( ubSoldierID != NOBODY );
  1291. return( ExternRenderFace( uiBuffer, MercPtrs[ ubSoldierID ]->iFaceIndex, sX, sY ) );
  1292. }
  1293. BOOLEAN ExternRenderFace( UINT32 uiBuffer, INT32 iFaceIndex, INT16 sX, INT16 sY )
  1294. {
  1295. UINT16 usEyesX;
  1296. UINT16 usEyesY;
  1297. UINT16 usMouthX;
  1298. UINT16 usMouthY;
  1299. FACETYPE *pFace;
  1300. // Check face index
  1301. CHECKF( iFaceIndex != -1 );
  1302. pFace = &gFacesData[ iFaceIndex ];
  1303. // Check for a valid slot!
  1304. CHECKF( pFace->fAllocated != FALSE );
  1305. // Here, any face can be rendered, even if disabled
  1306. // Set shade
  1307. if ( pFace->ubSoldierID != NOBODY )
  1308. {
  1309. SetFaceShade( MercPtrs[ pFace->ubSoldierID ], pFace , TRUE );
  1310. }
  1311. // Blit face to save buffer!
  1312. BltVideoObjectFromIndex( uiBuffer, pFace->uiVideoObject, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL );
  1313. GetFaceRelativeCoordinates( pFace, &usEyesX, &usEyesY, &usMouthX, &usMouthY );
  1314. HandleRenderFaceAdjustments( pFace, FALSE, TRUE, uiBuffer, sX, sY, ( UINT16)( sX + usEyesX ), ( UINT16)( sY + usEyesY ) );
  1315. // Restore extern rect
  1316. if ( uiBuffer == guiSAVEBUFFER )
  1317. {
  1318. RestoreExternBackgroundRect( sX, sY, pFace->usFaceWidth, pFace->usFaceWidth );
  1319. }
  1320. return( TRUE );
  1321. }
  1322. void NewEye( FACETYPE *pFace )
  1323. {
  1324. switch(pFace->sEyeFrame)
  1325. {
  1326. case 0 : //pFace->sEyeFrame = (INT16)Random(2); // normal - can blink or frown
  1327. if ( pFace->ubExpression == ANGRY )
  1328. {
  1329. pFace->ubEyeWait = 0;
  1330. pFace->sEyeFrame = 3;
  1331. }
  1332. else if ( pFace->ubExpression == SURPRISED )
  1333. {
  1334. pFace->ubEyeWait = 0;
  1335. pFace->sEyeFrame = 4;
  1336. }
  1337. else
  1338. //if (pFace->sEyeFrame && Talk.talking && Talk.expression != DYING)
  1339. /// pFace->sEyeFrame = 3;
  1340. //else
  1341. pFace->sEyeFrame = 1;
  1342. break;
  1343. case 1 : // starting to blink - has to finish unless dying
  1344. //if (Talk.expression == DYING)
  1345. // pFace->sEyeFrame = 1;
  1346. //else
  1347. pFace->sEyeFrame = 2;
  1348. break;
  1349. case 2 : //pFace->sEyeFrame = (INT16)Random(2); // finishing blink - can go normal or frown
  1350. //if (pFace->sEyeFrame && Talk.talking)
  1351. // pFace->sEyeFrame = 3;
  1352. //else
  1353. // if (Talk.expression == ANGRY)
  1354. // pFace->sEyeFrame = 3;
  1355. // else
  1356. pFace->sEyeFrame = 0;
  1357. break;
  1358. case 3 : //pFace->sEyeFrame = 4; break; // frown
  1359. pFace->ubEyeWait++;
  1360. if ( pFace->ubEyeWait > 6 )
  1361. {
  1362. pFace->sEyeFrame = 0;
  1363. }
  1364. break;
  1365. case 4 :
  1366. pFace->ubEyeWait++;
  1367. if ( pFace->ubEyeWait > 6 )
  1368. {
  1369. pFace->sEyeFrame = 0;
  1370. }
  1371. break;
  1372. case 5 : pFace->sEyeFrame = 6;
  1373. pFace->sEyeFrame = 0;
  1374. break;
  1375. case 6 : pFace->sEyeFrame = 7; break;
  1376. case 7 : pFace->sEyeFrame = (INT16)Random(2); // can stop frowning or continue
  1377. //if (pFace->sEyeFrame && Talk.expression != DYING)
  1378. // pFace->sEyeFrame = 8;
  1379. //else
  1380. // pFace->sEyeFrame = 0;
  1381. //break;
  1382. case 8 : pFace->sEyeFrame = 9; break;
  1383. case 9 : pFace->sEyeFrame = 10; break;
  1384. case 10: pFace->sEyeFrame = 11; break;
  1385. case 11: pFace->sEyeFrame = 12; break;
  1386. case 12: pFace->sEyeFrame = 0; break;
  1387. }
  1388. }
  1389. void NewMouth( FACETYPE *pFace )
  1390. {
  1391. BOOLEAN OK = FALSE;
  1392. UINT16 sOld = pFace->sMouthFrame;
  1393. // if (audio_gap_active == 1)
  1394. // {
  1395. // Talk.mouth = 0;
  1396. // return;
  1397. // }
  1398. do
  1399. {
  1400. //Talk.mouth = random(4);
  1401. pFace->sMouthFrame = (INT16)Random(6);
  1402. if ( pFace->sMouthFrame > 3)
  1403. {
  1404. pFace->sMouthFrame = 0;
  1405. }
  1406. switch( sOld)
  1407. {
  1408. case 0 : if ( pFace->sMouthFrame != 0 )
  1409. OK = TRUE;
  1410. break;
  1411. case 1 : if ( pFace->sMouthFrame != 1 )
  1412. OK = TRUE;
  1413. break;
  1414. case 2 : if ( pFace->sMouthFrame != 2 )
  1415. OK = TRUE;
  1416. break;
  1417. case 3 : if ( pFace->sMouthFrame != 3 )
  1418. OK = TRUE;
  1419. break;
  1420. }
  1421. } while (!OK);
  1422. }
  1423. void HandleAutoFaces( )
  1424. {
  1425. UINT32 uiCount;
  1426. FACETYPE *pFace;
  1427. INT8 bLife;
  1428. INT8 bInSector;
  1429. INT8 bAPs;
  1430. BOOLEAN fRerender = FALSE;
  1431. BOOLEAN fHandleFace;
  1432. BOOLEAN fHandleUIHatch;
  1433. SOLDIERTYPE *pSoldier;
  1434. for ( uiCount = 0; uiCount < guiNumFaces; uiCount++ )
  1435. {
  1436. fRerender = FALSE;
  1437. fHandleFace = TRUE;
  1438. fHandleUIHatch = FALSE;
  1439. // OK, NOW, check if our bLife status has changed, re-render if so!
  1440. if ( gFacesData[ uiCount ].fAllocated )
  1441. {
  1442. pFace = &gFacesData[ uiCount ];
  1443. // Are we a soldier?
  1444. if ( pFace->ubSoldierID != NOBODY )
  1445. {
  1446. // Get Life now
  1447. pSoldier = MercPtrs[ pFace->ubSoldierID ];
  1448. bLife = pSoldier->bLife;
  1449. bInSector = pSoldier->bInSector;
  1450. bAPs = pSoldier->bActionPoints;
  1451. if ( pSoldier->ubID == gsSelectedGuy && gfUIHandleSelectionAboveGuy )
  1452. {
  1453. pFace->uiFlags |= FACE_SHOW_WHITE_HILIGHT;
  1454. }
  1455. else
  1456. {
  1457. pFace->uiFlags &= ( ~FACE_SHOW_WHITE_HILIGHT );
  1458. }
  1459. if ( pSoldier->sGridNo != pSoldier->sFinalDestination && pSoldier->sGridNo != NOWHERE )
  1460. {
  1461. pFace->uiFlags |= FACE_SHOW_MOVING_HILIGHT;
  1462. }
  1463. else
  1464. {
  1465. pFace->uiFlags &= ( ~FACE_SHOW_MOVING_HILIGHT );
  1466. }
  1467. if ( pSoldier->bStealthMode != pFace->bOldStealthMode )
  1468. {
  1469. fRerender = TRUE;
  1470. }
  1471. // Check if we have fallen below OKLIFE...
  1472. if ( bLife < OKLIFE && pFace->bOldSoldierLife >= OKLIFE )
  1473. {
  1474. fRerender = TRUE;
  1475. }
  1476. if ( bLife >= OKLIFE && pFace->bOldSoldierLife < OKLIFE )
  1477. {
  1478. fRerender = TRUE;
  1479. }
  1480. // Check if we have fallen below CONSCIOUSNESS
  1481. if ( bLife < CONSCIOUSNESS && pFace->bOldSoldierLife >= CONSCIOUSNESS )
  1482. {
  1483. fRerender = TRUE;
  1484. }
  1485. if ( bLife >= CONSCIOUSNESS && pFace->bOldSoldierLife < CONSCIOUSNESS )
  1486. {
  1487. fRerender = TRUE;
  1488. }
  1489. if ( pSoldier->bOppCnt != pFace->bOldOppCnt )
  1490. {
  1491. fRerender = TRUE;
  1492. }
  1493. // Check if assignment is idfferent....
  1494. if ( pSoldier->bAssignment != pFace->bOldAssignment )
  1495. {
  1496. pFace->bOldAssignment = pSoldier->bAssignment;
  1497. fRerender = TRUE;
  1498. }
  1499. // Check if we have fallen below CONSCIOUSNESS
  1500. if ( bAPs == 0 && pFace->bOldActionPoints > 0 )
  1501. {
  1502. fRerender = TRUE;
  1503. }
  1504. if ( bAPs > 0 && pFace->bOldActionPoints == 0 )
  1505. {
  1506. fRerender = TRUE;
  1507. }
  1508. if ( !( pFace->uiFlags & FACE_SHOW_WHITE_HILIGHT ) && pFace->fOldShowHighlight )
  1509. {
  1510. fRerender = TRUE;
  1511. }
  1512. if ( ( pFace->uiFlags & FACE_SHOW_WHITE_HILIGHT ) && !( pFace->fOldShowHighlight ) )
  1513. {
  1514. fRerender = TRUE;
  1515. }
  1516. if ( !( pFace->uiFlags & FACE_SHOW_MOVING_HILIGHT ) && pFace->fOldShowMoveHilight )
  1517. {
  1518. fRerender = TRUE;
  1519. }
  1520. if ( ( pFace->uiFlags & FACE_SHOW_MOVING_HILIGHT ) && !( pFace->fOldShowMoveHilight ) )
  1521. {
  1522. fRerender = TRUE;
  1523. }
  1524. if ( pFace->ubOldServiceCount != pSoldier->ubServiceCount )
  1525. {
  1526. fRerender = TRUE;
  1527. pFace->ubOldServiceCount = pSoldier->ubServiceCount;
  1528. }
  1529. if ( pFace->fOldCompatibleItems != pFace->fCompatibleItems || gfInItemPickupMenu || gpItemPointer != NULL )
  1530. {
  1531. fRerender = TRUE;
  1532. pFace->fOldCompatibleItems = pFace->fCompatibleItems;
  1533. }
  1534. if ( pFace->ubOldServicePartner != pSoldier->ubServicePartner )
  1535. {
  1536. fRerender = TRUE;
  1537. pFace->ubOldServicePartner = pSoldier->ubServicePartner;
  1538. }
  1539. pFace->fOldHandleUIHatch = fHandleUIHatch;
  1540. pFace->bOldSoldierLife = bLife;
  1541. pFace->bOldActionPoints = bAPs;
  1542. pFace->bOldStealthMode = pSoldier->bStealthMode;
  1543. pFace->bOldOppCnt = pSoldier->bOppCnt;
  1544. if ( pFace->uiFlags & FACE_SHOW_WHITE_HILIGHT )
  1545. {
  1546. pFace->fOldShowHighlight = TRUE;
  1547. }
  1548. else
  1549. {
  1550. pFace->fOldShowHighlight = FALSE;
  1551. }
  1552. if ( pFace->uiFlags & FACE_SHOW_MOVING_HILIGHT )
  1553. {
  1554. pFace->fOldShowMoveHilight = TRUE;
  1555. }
  1556. else
  1557. {
  1558. pFace->fOldShowMoveHilight = FALSE;
  1559. }
  1560. if ( pSoldier->fGettingHit && pSoldier->fFlashPortrait == FLASH_PORTRAIT_STOP )
  1561. {
  1562. pSoldier->fFlashPortrait = TRUE;
  1563. pSoldier->bFlashPortraitFrame = FLASH_PORTRAIT_STARTSHADE;
  1564. RESETTIMECOUNTER( pSoldier->PortraitFlashCounter, FLASH_PORTRAIT_DELAY );
  1565. fRerender = TRUE;
  1566. }
  1567. if ( pSoldier->fFlashPortrait == FLASH_PORTRAIT_START )
  1568. {
  1569. // Loop through flash values
  1570. if ( TIMECOUNTERDONE( pSoldier->PortraitFlashCounter, FLASH_PORTRAIT_DELAY ) )
  1571. {
  1572. RESETTIMECOUNTER( pSoldier->PortraitFlashCounter, FLASH_PORTRAIT_DELAY );
  1573. pSoldier->bFlashPortraitFrame++;
  1574. if ( pSoldier->bFlashPortraitFrame > FLASH_PORTRAIT_ENDSHADE )
  1575. {
  1576. pSoldier->bFlashPortraitFrame = FLASH_PORTRAIT_ENDSHADE;
  1577. if ( pSoldier->fGettingHit )
  1578. {
  1579. pSoldier->fFlashPortrait = FLASH_PORTRAIT_WAITING;
  1580. }
  1581. else
  1582. {
  1583. // Render face again!
  1584. pSoldier->fFlashPortrait = FLASH_PORTRAIT_STOP;
  1585. }
  1586. fRerender = TRUE;
  1587. }
  1588. }
  1589. }
  1590. // CHECK IF WE WERE WAITING FOR GETTING HIT TO FINISH!
  1591. if ( !pSoldier->fGettingHit && pSoldier->fFlashPortrait == FLASH_PORTRAIT_WAITING )
  1592. {
  1593. pSoldier->fFlashPortrait = FALSE;
  1594. fRerender = TRUE;
  1595. }
  1596. if ( pSoldier->fFlashPortrait == FLASH_PORTRAIT_START )
  1597. {
  1598. fRerender = TRUE;
  1599. }
  1600. if( pFace->uiFlags & FACE_REDRAW_WHOLE_FACE_NEXT_FRAME )
  1601. {
  1602. pFace->uiFlags &= ~FACE_REDRAW_WHOLE_FACE_NEXT_FRAME;
  1603. fRerender = TRUE;
  1604. }
  1605. if ( fInterfacePanelDirty == DIRTYLEVEL2 && guiCurrentScreen == GAME_SCREEN )
  1606. {
  1607. fRerender = TRUE;
  1608. }
  1609. if ( fRerender )
  1610. {
  1611. RenderAutoFace( uiCount );
  1612. }
  1613. if ( bLife < CONSCIOUSNESS )
  1614. {
  1615. fHandleFace = FALSE;
  1616. }
  1617. }
  1618. if ( fHandleFace )
  1619. {
  1620. BlinkAutoFace( uiCount );
  1621. }
  1622. MouthAutoFace( uiCount );
  1623. }
  1624. }
  1625. }
  1626. void HandleTalkingAutoFaces( )
  1627. {
  1628. UINT32 uiCount;
  1629. FACETYPE *pFace;
  1630. for ( uiCount = 0; uiCount < guiNumFaces; uiCount++ )
  1631. {
  1632. // OK, NOW, check if our bLife status has changed, re-render if so!
  1633. if ( gFacesData[ uiCount ].fAllocated )
  1634. {
  1635. pFace = &gFacesData[ uiCount ];
  1636. HandleTalkingAutoFace( uiCount );
  1637. }
  1638. }
  1639. }
  1640. BOOLEAN FaceRestoreSavedBackgroundRect( INT32 iFaceIndex, INT16 sDestLeft, INT16 sDestTop, INT16 sSrcLeft, INT16 sSrcTop, INT16 sWidth, INT16 sHeight )
  1641. {
  1642. FACETYPE *pFace;
  1643. UINT32 uiDestPitchBYTES, uiSrcPitchBYTES;
  1644. UINT8 *pDestBuf, *pSrcBuf;
  1645. // Check face index
  1646. CHECKF( iFaceIndex != -1 );
  1647. pFace = &gFacesData[ iFaceIndex ];
  1648. // DOn't continue if we do not want the resotre to happen ( ei blitting entrie thing every frame...
  1649. if ( pFace->uiAutoRestoreBuffer == FACE_NO_RESTORE_BUFFER )
  1650. {
  1651. return( FALSE );
  1652. }
  1653. pDestBuf = LockVideoSurface(pFace->uiAutoDisplayBuffer, &uiDestPitchBYTES);
  1654. pSrcBuf = LockVideoSurface( pFace->uiAutoRestoreBuffer, &uiSrcPitchBYTES);
  1655. Blt16BPPTo16BPP((UINT16 *)pDestBuf, uiDestPitchBYTES,
  1656. (UINT16 *)pSrcBuf, uiSrcPitchBYTES,
  1657. sDestLeft , sDestTop,
  1658. sSrcLeft , sSrcTop,
  1659. sWidth, sHeight);
  1660. UnLockVideoSurface(pFace->uiAutoDisplayBuffer);
  1661. UnLockVideoSurface(pFace->uiAutoRestoreBuffer);
  1662. // Add rect to frame buffer queue
  1663. if ( pFace->uiAutoDisplayBuffer == FRAME_BUFFER )
  1664. {
  1665. InvalidateRegionEx( sDestLeft - 2, sDestTop - 2, (sDestLeft + sWidth + 3), ( sDestTop + sHeight + 2 ), 0 );
  1666. }
  1667. return(TRUE);
  1668. }
  1669. BOOLEAN SetFaceTalking( INT32 iFaceIndex, CHAR8 *zSoundFile, STR16 zTextString, UINT32 usRate, UINT32 ubVolume, UINT32 ubLoops, UINT32 uiPan )
  1670. {
  1671. FACETYPE *pFace;
  1672. pFace = &gFacesData[ iFaceIndex ];
  1673. // Set face to talking
  1674. pFace->fTalking = TRUE;
  1675. pFace->fAnimatingTalking = TRUE;
  1676. pFace->fFinishTalking = FALSE;
  1677. if ( !AreInMeanwhile( ) )
  1678. {
  1679. TurnOnSectorLocator( pFace->ubCharacterNum );
  1680. }
  1681. // Play sample
  1682. if( gGameSettings.fOptions[ TOPTION_SPEECH ] )
  1683. pFace->uiSoundID = PlayJA2GapSample( zSoundFile, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN, &(pFace->GapList ) );
  1684. else
  1685. pFace->uiSoundID = SOUND_ERROR;
  1686. if ( pFace->uiSoundID != SOUND_ERROR )
  1687. {
  1688. pFace->fValidSpeech = TRUE;
  1689. pFace->uiTalkingFromVeryBeginningTimer = GetJA2Clock( );
  1690. }
  1691. else
  1692. {
  1693. pFace->fValidSpeech = FALSE;
  1694. // Set delay based on sound...
  1695. pFace->uiTalkingTimer = pFace->uiTalkingFromVeryBeginningTimer = GetJA2Clock( );
  1696. pFace->uiTalkingDuration = FindDelayForString( zTextString );
  1697. }
  1698. return( TRUE );
  1699. }
  1700. BOOLEAN ExternSetFaceTalking( INT32 iFaceIndex, UINT32 uiSoundID )
  1701. {
  1702. FACETYPE *pFace;
  1703. pFace = &gFacesData[ iFaceIndex ];
  1704. // Set face to talki ng
  1705. pFace->fTalking = TRUE;
  1706. pFace->fAnimatingTalking = TRUE;
  1707. pFace->fFinishTalking = FALSE;
  1708. pFace->fValidSpeech = TRUE;
  1709. pFace->uiSoundID = uiSoundID;
  1710. return( TRUE );
  1711. }
  1712. void InternalShutupaYoFace( INT32 iFaceIndex, BOOLEAN fForce )
  1713. {
  1714. FACETYPE *pFace;
  1715. // Check face index
  1716. CHECKV( iFaceIndex != -1 );
  1717. pFace = &gFacesData[ iFaceIndex ];
  1718. if ( pFace->fTalking )
  1719. {
  1720. // OK, only do this if we have been talking for a min. amount fo time...
  1721. if ( ( GetJA2Clock( ) - pFace->uiTalkingFromVeryBeginningTimer ) < 500 && !fForce )
  1722. {
  1723. return;
  1724. }
  1725. if ( pFace->uiSoundID != SOUND_ERROR )
  1726. {
  1727. SoundStop( pFace->uiSoundID );
  1728. }
  1729. // Remove gap info
  1730. AudioGapListDone( &(pFace->GapList) );
  1731. // Shutup mouth!
  1732. pFace->sMouthFrame = 0;
  1733. // ATE: Only change if active!
  1734. if ( !pFace->fDisabled )
  1735. {
  1736. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  1737. {
  1738. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usMouthX, pFace->usMouthY, pFace->usMouthX, pFace->usMouthY, pFace->usMouthWidth, pFace->usMouthHeight );
  1739. }
  1740. else
  1741. {
  1742. FaceRestoreSavedBackgroundRect( iFaceIndex, pFace->usMouthX, pFace->usMouthY, pFace->usMouthOffsetX, pFace->usMouthOffsetY, pFace->usMouthWidth, pFace->usMouthHeight );
  1743. }
  1744. }
  1745. // OK, smart guy, make sure this guy has finished talking,
  1746. // before attempting to end dialogue UI.
  1747. pFace->fTalking = FALSE;
  1748. // Call dialogue handler function
  1749. HandleDialogueEnd( pFace );
  1750. pFace->fTalking = FALSE;
  1751. pFace->fAnimatingTalking = FALSE;
  1752. gfUIWaitingForUserSpeechAdvance = FALSE;
  1753. }
  1754. }
  1755. void ShutupaYoFace( INT32 iFaceIndex )
  1756. {
  1757. InternalShutupaYoFace( iFaceIndex, TRUE );
  1758. }
  1759. void SetupFinalTalkingDelay( FACETYPE *pFace )
  1760. {
  1761. pFace->fFinishTalking = TRUE;
  1762. pFace->fAnimatingTalking = FALSE;
  1763. pFace->uiTalkingTimer = GetJA2Clock( );
  1764. if ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] )
  1765. {
  1766. //pFace->uiTalkingDuration = FINAL_TALKING_DURATION;
  1767. pFace->uiTalkingDuration = 300;
  1768. }
  1769. else
  1770. {
  1771. pFace->uiTalkingDuration = 300;
  1772. }
  1773. pFace->sMouthFrame = 0;
  1774. // Close mouth!
  1775. if ( !pFace->fDisabled )
  1776. {
  1777. if ( pFace->uiAutoRestoreBuffer == guiSAVEBUFFER )
  1778. {
  1779. FaceRestoreSavedBackgroundRect( pFace->iID, pFace->usMouthX, pFace->usMouthY, pFace->usMouthX, pFace->usMouthY, pFace->usMouthWidth, pFace->usMouthHeight );
  1780. }
  1781. else
  1782. {
  1783. FaceRestoreSavedBackgroundRect( pFace->iID, pFace->usMouthX, pFace->usMouthY, pFace->usMouthOffsetX, pFace->usMouthOffsetY, pFace->usMouthWidth, pFace->usMouthHeight );
  1784. }
  1785. }
  1786. // Setup flag to wait for advance ( because we have no text! )
  1787. if ( gGameSettings.fOptions[ TOPTION_KEY_ADVANCE_SPEECH ] && ( pFace->uiFlags & FACE_POTENTIAL_KEYWAIT ) )
  1788. {
  1789. // Check if we have had valid speech!
  1790. if ( !pFace->fValidSpeech || gGameSettings.fOptions[ TOPTION_SUBTITLES ] )
  1791. {
  1792. // Set false!
  1793. pFace->fFinishTalking = FALSE;
  1794. // Set waiting for advance to true!
  1795. gfUIWaitingForUserSpeechAdvance = TRUE;
  1796. }
  1797. }
  1798. // Set final delay!
  1799. pFace->fValidSpeech = FALSE;
  1800. }