1 #include "Animation_Data.h"
2 #include "Cursors.h"
3 #include "Font_Control.h"
4 #include "HImage.h"
5 #include "Isometric_Utils.h"
6 #include "TileDef.h"
7 #include "VObject.h"
8 #include "SysUtil.h"
9 #include "RenderWorld.h"
10 #include "Interface.h"
11 #include "Sound_Control.h"
12 #include "WorldDef.h"
13 #include "Interactive_Tiles.h"
14 #include "WorldMan.h"
15 #include "Structure.h"
16 #include "Animation_Control.h"
17 #include "Points.h"
18 #include "Overhead.h"
19 #include "Structure_Wrap.h"
20 #include "Tile_Animation.h"
21 #include "Tile_Cache.h"
22 #include "Handle_Doors.h"
23 #include "StrategicMap.h"
24 #include "Quests.h"
25 #include "Dialogue_Control.h"
26 #include "Random.h"
27 #include "English.h"
28 #include "Handle_Items.h"
29 #include "Message.h"
30 #include "Handle_UI.h"
31 #include "NPC.h"
32 #include "Explosion_Control.h"
33 #include "Text.h"
34 #include "GameSettings.h"
35 #include "Environment.h"
36 #include "Debug.h"
37 #include "UILayout.h"
38
39 #include "Soldier.h"
40 #include "GameInstance.h"
41 #include "ContentManager.h"
42 #include "ShippingDestinationModel.h"
43
44 #define MAX_INTTILE_STACK 10
45
46
47 struct CUR_INTERACTIVE_TILE
48 {
49 INT16 sGridNo;
50 INT16 sTileIndex;
51 INT16 sHeighestScreenY;
52 BOOLEAN fFound;
53 LEVELNODE const* pFoundNode;
54 INT16 sFoundGridNo;
55 UINT16 usStructureID;
56 BOOLEAN fStructure;
57 };
58
59
60 struct INTERACTIVE_TILE_STACK_TYPE
61 {
62 INT8 bNum;
63 CUR_INTERACTIVE_TILE bTiles[MAX_INTTILE_STACK];
64 INT8 bCur;
65 };
66
67
68 static INTERACTIVE_TILE_STACK_TYPE gCurIntTileStack;
69 static BOOLEAN gfCycleIntTile = FALSE;
70
71
72 static CUR_INTERACTIVE_TILE gCurIntTile;
73 static BOOLEAN gfOverIntTile = FALSE;
74
75 // Values to determine if we should check or not
76 static INT16 gsINTOldRenderCenterX = 0;
77 static INT16 gsINTOldRenderCenterY = 0;
78 static UINT16 gusINTOldMousePosX = 0;
79 static UINT16 gusINTOldMousePosY = 0;
80
81
StartInteractiveObject(GridNo const gridno,STRUCTURE const & structure,SOLDIERTYPE & s,UINT8 const direction)82 void StartInteractiveObject(GridNo const gridno, STRUCTURE const& structure, SOLDIERTYPE& s, UINT8 const direction)
83 {
84 // ATE: Patch fix: Don't allow if alreay in animation
85 if (s.usAnimState == OPEN_STRUCT) return;
86 if (s.usAnimState == OPEN_STRUCT_CROUCHED) return;
87 if (s.usAnimState == BEGIN_OPENSTRUCT) return;
88 if (s.usAnimState == BEGIN_OPENSTRUCT_CROUCHED) return;
89
90 SoldierSP soldier = GetSoldier(&s);
91
92 // Add soldier event for opening door/struct
93 soldier->setPendingAction(structure.fFlags & STRUCTURE_ANYDOOR ? MERC_OPENDOOR : MERC_OPENSTRUCT);
94 s.uiPendingActionData1 = structure.usStructureID;
95 s.sPendingActionData2 = gridno;
96 s.bPendingActionData3 = direction;
97 }
98
99
SoldierHandleInteractiveObject(SOLDIERTYPE & s)100 bool SoldierHandleInteractiveObject(SOLDIERTYPE& s)
101 {
102 GridNo const gridno = s.sPendingActionData2;
103 UINT16 const structure_id = (UINT16)s.uiPendingActionData1;
104 STRUCTURE* const structure = FindStructureByID(gridno, structure_id);
105 if (!structure) return false;
106 return HandleOpenableStruct(&s, gridno, structure);
107 }
108
109
HandleStructChangeFromGridNo(SOLDIERTYPE * const s,GridNo const grid_no)110 void HandleStructChangeFromGridNo(SOLDIERTYPE* const s, GridNo const grid_no)
111 {
112 STRUCTURE* const structure = FindStructure(grid_no, STRUCTURE_OPENABLE);
113 if (!structure)
114 {
115 SLOGW("Told to handle struct that does not exist at %d.", grid_no);
116 return;
117 }
118
119 // Do sound...
120 bool const closing = structure->fFlags & STRUCTURE_OPEN;
121 PlayLocationJA2Sample(grid_no, GetStructureOpenSound(structure, closing), HIGHVOLUME, 1);
122
123 // ATE: Don't handle switches!
124 if (!(structure->fFlags & STRUCTURE_SWITCH))
125 {
126 bool did_missing_quote = false;
127 if (s->bTeam == OUR_TEAM)
128 {
129 auto primaryDest = GCM->getPrimaryShippingDestination();
130 if (grid_no == primaryDest->deliverySectorGridNo &&
131 gWorldSectorX == primaryDest->deliverySectorX &&
132 gWorldSectorY == primaryDest->deliverySectorY &&
133 gbWorldSectorZ == primaryDest->deliverySectorZ &&
134 CheckFact(FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT, 0) &&
135 !CheckFact(FACT_PLAYER_FOUND_ITEMS_MISSING, 0))
136 {
137 SayQuoteFromNearbyMercInSector(grid_no, 3, QUOTE_STUFF_MISSING_DRASSEN);
138 did_missing_quote = true;
139 }
140 }
141 else if (s->bTeam == CIV_TEAM)
142 {
143 if (s->ubProfile != NO_PROFILE)
144 {
145 TriggerNPCWithGivenApproach(s->ubProfile, APPROACH_DONE_OPEN_STRUCTURE);
146 }
147 }
148
149 ITEM_POOL* const item_pool = GetItemPool(grid_no, s->bLevel);
150 if (item_pool)
151 {
152 // Update visiblity
153 if (!closing)
154 {
155 bool do_humm = true;
156 bool do_locators = true;
157
158 if (s->bTeam != OUR_TEAM)
159 {
160 do_humm = false;
161 do_locators = false;
162 }
163
164 // Look for ownership here
165 if (GetWorldItem(item_pool->iItemIndex).o.usItem == OWNERSHIP)
166 {
167 do_humm = false;
168 MakeCharacterDialogueEventDoBattleSound(*s, BATTLE_SOUND_NOTHING, 500);
169 }
170
171 // If now open, set visible
172 SetItemsVisibilityOn(grid_no, s->bLevel, ANY_VISIBILITY_VALUE, do_locators);
173
174 // ATE: Check now many things in pool
175 if (!did_missing_quote)
176 {
177 if (item_pool->pNext && item_pool->pNext->pNext)
178 {
179 MakeCharacterDialogueEventDoBattleSound(*s, BATTLE_SOUND_COOL1, 500);
180 }
181 else if (do_humm)
182 {
183 MakeCharacterDialogueEventDoBattleSound(*s, BATTLE_SOUND_HUMM, 500);
184 }
185 }
186 }
187 else
188 {
189 SetItemsVisibilityHidden(grid_no, s->bLevel);
190 }
191 }
192 else
193 {
194 if (!closing)
195 {
196 MakeCharacterDialogueEventDoBattleSound(*s, BATTLE_SOUND_NOTHING, 500);
197 }
198 }
199 }
200
201 STRUCTURE* const new_structure = SwapStructureForPartner(structure);
202 if (new_structure)
203 {
204 RecompileLocalMovementCosts(grid_no);
205 SetRenderFlags(RENDER_FLAG_FULL);
206 if (new_structure->fFlags & STRUCTURE_SWITCH)
207 { // Just turned a switch on!
208 ActivateSwitchInGridNo(s, grid_no);
209 }
210 }
211 }
212
213
GetInteractiveTileCursor(UICursorID const old_cursor,BOOLEAN const confirm)214 UICursorID GetInteractiveTileCursor(UICursorID const old_cursor, BOOLEAN const confirm)
215 {
216 GridNo grid_no;
217 STRUCTURE* structure;
218 LEVELNODE const* const int_node = GetCurInteractiveTileGridNoAndStructure(&grid_no, &structure);
219 if (!int_node || !structure) return old_cursor;
220
221 if (structure->fFlags & STRUCTURE_ANYDOOR)
222 {
223 SetDoorString(grid_no);
224 }
225 else if (structure->fFlags & STRUCTURE_SWITCH)
226 {
227 SetIntTileLocationText(gzLateLocalizedString[STR_LATE_25]);
228 }
229 return confirm ? OKHANDCURSOR_UICURSOR : NORMALHANDCURSOR_UICURSOR;
230 }
231
232
SetActionModeDoorCursorText()233 void SetActionModeDoorCursorText()
234 {
235 // If we are over a merc, don't
236 if (gUIFullTarget) return;
237
238 GridNo grid_no;
239 STRUCTURE* structure;
240 LEVELNODE const* const int_node = GetCurInteractiveTileGridNoAndStructure(&grid_no, &structure);
241 if (!int_node || !structure) return;
242 if (!(structure->fFlags & STRUCTURE_ANYDOOR)) return;
243 SetDoorString(grid_no);
244 }
245
246
GetLevelNodeScreenRect(LEVELNODE const & n,SGPRect & rect,INT16 const x,INT16 const y,GridNo const gridno)247 static void GetLevelNodeScreenRect(LEVELNODE const& n, SGPRect& rect, INT16 const x, INT16 const y, GridNo const gridno)
248 {
249 // Get 'TRUE' merc position
250 INT16 sTempX_S;
251 INT16 sTempY_S;
252 INT16 const offset_x = x - gsRenderCenterX;
253 INT16 const offset_y = y - gsRenderCenterY;
254 FromCellToScreenCoordinates(offset_x, offset_y, &sTempX_S, &sTempY_S);
255
256 ETRLEObject const* pTrav;
257 if (n.uiFlags & LEVELNODE_CACHEDANITILE)
258 {
259 ANITILE const& a = *n.pAniTile;
260 pTrav = &gpTileCache[a.sCachedTileID].pImagery->vo->SubregionProperties(a.sCurrentFrame);
261 }
262 else
263 {
264 TILE_ELEMENT const* te = &gTileDatabase[n.usIndex];
265 // Adjust for current frames and animations
266 if (te->uiFlags & ANIMATED_TILE)
267 {
268 TILE_ANIMATION_DATA const& a = *te->pAnimData;
269 te = &gTileDatabase[a.pusFrames[a.bCurrentFrame]];
270 }
271 else if (n.uiFlags & LEVELNODE_ANIMATION && n.sCurrentFrame != -1)
272 {
273 te = &gTileDatabase[te->pAnimData->pusFrames[n.sCurrentFrame]];
274 }
275 pTrav = &te->hTileSurface->SubregionProperties(te->usRegionIndex);
276 }
277
278 INT16 sScreenX = (g_ui.m_tacticalMapCenterX) + (INT16)sTempX_S;
279 INT16 sScreenY = (g_ui.m_tacticalMapCenterY) + (INT16)sTempY_S;
280
281 // Adjust for offset position on screen
282 sScreenX -= gsRenderWorldOffsetX;
283 sScreenY -= gsRenderWorldOffsetY;
284 sScreenY -= gpWorldLevelData[gridno].sHeight;
285
286 // Adjust based on interface level
287 if (gsInterfaceLevel > 0)
288 {
289 sScreenY += ROOF_LEVEL_HEIGHT;
290 }
291
292 // Adjust for render height
293 sScreenY += gsRenderHeight;
294
295 // Add to start position of dest buffer
296 sScreenX += pTrav->sOffsetX - WORLD_TILE_X / 2;
297 sScreenY += pTrav->sOffsetY - WORLD_TILE_Y / 2;
298
299 // Adjust y offset!
300 sScreenY += WORLD_TILE_Y / 2;
301
302 rect.iLeft = sScreenX;
303 rect.iTop = sScreenY;
304 rect.iRight = sScreenX + pTrav->usWidth;
305 rect.iBottom = sScreenY + pTrav->usHeight;
306 }
307
308
309 static bool RefineLogicOnStruct(GridNo, LEVELNODE const&);
310 static BOOLEAN RefinePointCollisionOnStruct(INT16 sTestX, INT16 sTestY, INT16 sSrcX, INT16 sSrcY, LEVELNODE const&);
311
312
LogMouseOverInteractiveTile(INT16 const sGridNo)313 void LogMouseOverInteractiveTile(INT16 const sGridNo)
314 {
315 // OK, for now, don't allow any interactive tiles on higher interface level!
316 if (gsInterfaceLevel > 0) return;
317
318 // Also, don't allow for mercs who are on upper level
319 SOLDIERTYPE const* const sel = GetSelectedMan();
320 if (sel && sel->bLevel == 1) return;
321
322 // Get World XY From gridno
323 INT16 sXMapPos;
324 INT16 sYMapPos;
325 ConvertGridNoToCellXY(sGridNo, &sXMapPos, &sYMapPos);
326
327 // Set mouse stuff
328 INT16 const sScreenX = gusMouseXPos;
329 INT16 const sScreenY = gusMouseYPos;
330
331 for (LEVELNODE const* n = gpWorldLevelData[sGridNo].pStructHead; n; n = n->pNext)
332 {
333 SGPRect aRect;
334 GetLevelNodeScreenRect(*n, aRect, sXMapPos, sYMapPos, sGridNo);
335
336 // Make sure we are always on guy if we are on same gridno
337 if (!IsPointInScreenRect(sScreenX, sScreenY, aRect)) continue;
338
339 if (!RefinePointCollisionOnStruct(sScreenX, sScreenY, aRect.iLeft, aRect.iBottom, *n)) continue;
340
341 if (!RefineLogicOnStruct(sGridNo, *n)) continue;
342
343 gCurIntTile.fFound = TRUE;
344
345 if (gfCycleIntTile) continue;
346
347 // Accumulate them!
348 gCurIntTileStack.bTiles[gCurIntTileStack.bNum].pFoundNode = n;
349 gCurIntTileStack.bTiles[gCurIntTileStack.bNum].sFoundGridNo = sGridNo;
350 gCurIntTileStack.bNum++;
351
352 // Determine if it's the best one
353 if (aRect.iBottom <= gCurIntTile.sHeighestScreenY) continue;
354
355 gCurIntTile.sHeighestScreenY = aRect.iBottom;
356
357 gCurIntTile.pFoundNode = n;
358 gCurIntTile.sFoundGridNo = sGridNo;
359
360 // Set stack current one
361 gCurIntTileStack.bCur = gCurIntTileStack.bNum - 1;
362 }
363 }
364
365
InternalGetCurInteractiveTile(const BOOLEAN fRejectItemsOnTop)366 static LEVELNODE* InternalGetCurInteractiveTile(const BOOLEAN fRejectItemsOnTop)
367 {
368 if (_KeyDown(SHIFT)) return NULL;
369 if (!gfOverIntTile) return NULL;
370
371 LEVELNODE* n = gpWorldLevelData[gCurIntTile.sGridNo].pStructHead;
372 for (; n != NULL; n = n->pNext)
373 {
374 if (n->usIndex != gCurIntTile.sTileIndex) continue;
375 if (fRejectItemsOnTop && gCurIntTile.fStructure)
376 {
377 // get strucuture here...
378 STRUCTURE* const s = FindStructureByID(gCurIntTile.sGridNo, gCurIntTile.usStructureID);
379 if (s == NULL || s->fFlags & STRUCTURE_HASITEMONTOP) return NULL;
380 }
381 break;
382 }
383 return n;
384 }
385
386
GetCurInteractiveTile(void)387 LEVELNODE* GetCurInteractiveTile(void)
388 {
389 return InternalGetCurInteractiveTile(TRUE);
390 }
391
392
GetCurInteractiveTileGridNo(INT16 * const psGridNo)393 LEVELNODE* GetCurInteractiveTileGridNo(INT16* const psGridNo)
394 {
395 LEVELNODE* const n = GetCurInteractiveTile();
396 *psGridNo = (n != NULL ? gCurIntTile.sGridNo : NOWHERE);
397 return n;
398 }
399
400
ConditionalGetCurInteractiveTileGridNoAndStructure(INT16 * const psGridNo,STRUCTURE ** const ppStructure,const BOOLEAN fRejectOnTopItems)401 LEVELNODE* ConditionalGetCurInteractiveTileGridNoAndStructure(INT16* const psGridNo, STRUCTURE** const ppStructure, const BOOLEAN fRejectOnTopItems)
402 {
403 GridNo g = NOWHERE;
404 STRUCTURE* s = NULL;
405 LEVELNODE* n = InternalGetCurInteractiveTile(fRejectOnTopItems);
406 if (n != NULL)
407 {
408 g = gCurIntTile.sGridNo;
409 if (gCurIntTile.fStructure)
410 {
411 s = FindStructureByID(g, gCurIntTile.usStructureID);
412 if (s == NULL) n = NULL;
413 }
414 }
415 *ppStructure = s;
416 *psGridNo = g;
417 return n;
418 }
419
420
GetCurInteractiveTileGridNoAndStructure(INT16 * const psGridNo,STRUCTURE ** const ppStructure)421 LEVELNODE* GetCurInteractiveTileGridNoAndStructure(INT16* const psGridNo, STRUCTURE** const ppStructure)
422 {
423 return ConditionalGetCurInteractiveTileGridNoAndStructure(psGridNo, ppStructure, TRUE);
424 }
425
426
BeginCurInteractiveTileCheck(void)427 void BeginCurInteractiveTileCheck(void)
428 {
429 gfOverIntTile = FALSE;
430
431 // OK, release our stack, stuff could be different!
432 gfCycleIntTile = FALSE;
433
434 // Reset some highest values
435 gCurIntTile.sHeighestScreenY = 0;
436 gCurIntTile.fFound = FALSE;
437
438 // Reset stack values
439 gCurIntTileStack.bNum = 0;
440
441 }
442
443
EndCurInteractiveTileCheck()444 void EndCurInteractiveTileCheck()
445 {
446 if (gCurIntTile.fFound)
447 { // We are over this cycled node or levelnode
448 CUR_INTERACTIVE_TILE const& cur_int_tile =
449 gfCycleIntTile ? gCurIntTileStack.bTiles[gCurIntTileStack.bCur] :
450 gCurIntTile;
451
452 gCurIntTile.sGridNo = cur_int_tile.sFoundGridNo;
453 gCurIntTile.sTileIndex = cur_int_tile.pFoundNode->usIndex;
454
455 if (cur_int_tile.pFoundNode->pStructureData)
456 {
457 gCurIntTile.usStructureID = cur_int_tile.pFoundNode->pStructureData->usStructureID;
458 gCurIntTile.fStructure = TRUE;
459 }
460 else
461 {
462 gCurIntTile.fStructure = FALSE;
463 }
464
465 gfOverIntTile = TRUE;
466 }
467 else
468 { // If we are in cycle mode, end it
469 gfCycleIntTile = FALSE;
470 }
471 }
472
473
RefineLogicOnStruct(INT16 gridno,LEVELNODE const & n)474 static bool RefineLogicOnStruct(INT16 gridno, LEVELNODE const& n)
475 {
476 if (n.uiFlags & LEVELNODE_CACHEDANITILE) return false;
477
478 // See if we are on an interactable tile!
479 // Try and get struct data from levelnode pointer
480 if (!n.pStructureData) return false; // If no data, quit
481 STRUCTURE const& structure = *n.pStructureData;
482
483 if (!(structure.fFlags & (STRUCTURE_OPENABLE | STRUCTURE_HASITEMONTOP))) return false;
484
485 SOLDIERTYPE const* const sel = GetSelectedMan();
486 if (sel && sel->ubBodyType == ROBOTNOWEAPON) return false;
487
488 if (structure.fFlags & STRUCTURE_ANYDOOR)
489 { // A door, we need a different definition of being visible than other structs
490 if (!IsDoorVisibleAtGridNo(gridno)) return false;
491
492 // For a OPENED door, addition requirements are: need to be in 'HAND CURSOR' mode
493 if (structure.fFlags & STRUCTURE_OPEN &&
494 gCurrentUIMode != HANDCURSOR_MODE &&
495 gCurrentUIMode != ACTION_MODE)
496 {
497 return false;
498 }
499
500 if (!gGameSettings.fOptions[TOPTION_SNAP_CURSOR_TO_DOOR] &&
501 gCurrentUIMode != HANDCURSOR_MODE)
502 {
503 return false;
504 }
505
506 return true;
507 }
508 else if (structure.fFlags & STRUCTURE_SWITCH)
509 { // A switch, reject in another direction
510 // Find a new gridno based on switch's orientation
511 switch (structure.pDBStructureRef->pDBStructure->ubWallOrientation)
512 {
513 case OUTSIDE_TOP_LEFT:
514 case INSIDE_TOP_LEFT:
515 // Move south
516 gridno = NewGridNo(gridno, DirectionInc(SOUTH));
517 break;
518
519 case OUTSIDE_TOP_RIGHT:
520 case INSIDE_TOP_RIGHT:
521 // Move east
522 gridno = NewGridNo(gridno, DirectionInc(EAST));
523 break;
524
525 default: return true; // XXX exception?
526 }
527 }
528
529 // If we are hidden by a roof, reject it!
530 if (!gfBasement && IsRoofVisible(gridno) && !(gTacticalStatus.uiFlags & SHOW_ALL_ITEMS))
531 {
532 return false;
533 }
534
535 return true;
536 }
537
538
RefinePointCollisionOnStruct(INT16 const test_x,INT16 const test_y,INT16 const src_x,INT16 const src_y,LEVELNODE const & n)539 static BOOLEAN RefinePointCollisionOnStruct(INT16 const test_x, INT16 const test_y, INT16 const src_x, INT16 const src_y, LEVELNODE const& n)
540 {
541 HVOBJECT vo;
542 UINT16 idx;
543 if (n.uiFlags & LEVELNODE_CACHEDANITILE)
544 {
545 ANITILE const& a = *n.pAniTile;
546 vo = gpTileCache[a.sCachedTileID].pImagery->vo;
547 idx = a.sCurrentFrame;
548 }
549 else
550 {
551 TILE_ELEMENT const* te = &gTileDatabase[n.usIndex];
552 // Adjust for current frames and animations
553 if (te->uiFlags & ANIMATED_TILE)
554 {
555 TILE_ANIMATION_DATA const& a = *te->pAnimData;
556 te = &gTileDatabase[a.pusFrames[a.bCurrentFrame]];
557 }
558 else if (n.uiFlags & LEVELNODE_ANIMATION && n.sCurrentFrame != -1)
559 {
560 te = &gTileDatabase[te->pAnimData->pusFrames[n.sCurrentFrame]];
561 }
562 vo = te->hTileSurface;
563 idx = te->usRegionIndex;
564 }
565 return CheckVideoObjectScreenCoordinateInData(vo, idx, test_x - src_x, -(test_y - src_y));
566 }
567
568
569 // This function will check the video object at SrcX and SrcY for the lack of transparency
570 // will return true if data found, else false
CheckVideoObjectScreenCoordinateInData(HVOBJECT hSrcVObject,UINT16 usIndex,INT32 iTestX,INT32 iTestY)571 BOOLEAN CheckVideoObjectScreenCoordinateInData(HVOBJECT hSrcVObject, UINT16 usIndex, INT32 iTestX, INT32 iTestY)
572 {
573 BOOLEAN fDataFound = FALSE;
574 INT32 iTestPos, iStartPos;
575
576 // Assertions
577 Assert( hSrcVObject != NULL );
578
579 // Get Offsets from Index into structure
580 ETRLEObject const& pTrav = hSrcVObject->SubregionProperties(usIndex);
581 UINT32 usHeight = pTrav.usHeight;
582 UINT32 const usWidth = pTrav.usWidth;
583
584 // Calculate test position we are looking for!
585 // Calculate from 0, 0 at top left!
586 iTestPos = ( ( usHeight - iTestY ) * usWidth ) + iTestX;
587 iStartPos = 0;
588
589 UINT8 const* SrcPtr = hSrcVObject->PixData(pTrav);
590
591 do
592 {
593 for (;;)
594 {
595 UINT8 PxCount = *SrcPtr++;
596 if (PxCount == 0) break;
597 if (PxCount & 0x80)
598 {
599 PxCount &= 0x7F;
600 }
601 else
602 {
603 if (iStartPos < iTestPos && iTestPos <= iStartPos + PxCount) return TRUE;
604 SrcPtr += PxCount;
605 }
606 iStartPos += PxCount;
607 }
608 if (iStartPos >= iTestPos) break;
609 }
610 while (--usHeight > 0);
611 return(fDataFound);
612
613 }
614
615
ShouldCheckForMouseDetections()616 BOOLEAN ShouldCheckForMouseDetections( )
617 {
618 BOOLEAN fOK = FALSE;
619
620 if (gsINTOldRenderCenterX != gsRenderCenterX || gsINTOldRenderCenterY != gsRenderCenterY ||
621 gusINTOldMousePosX != gusMouseXPos || gusINTOldMousePosY != gusMouseYPos)
622 {
623 fOK = TRUE;
624 }
625
626 // Set old values
627 gsINTOldRenderCenterX = gsRenderCenterX;
628 gsINTOldRenderCenterY = gsRenderCenterY;
629
630 gusINTOldMousePosX = gusMouseXPos;
631 gusINTOldMousePosY = gusMouseYPos;
632
633 return( fOK );
634 }
635
636
CycleIntTileFindStack(UINT16 usMapPos)637 void CycleIntTileFindStack( UINT16 usMapPos )
638 {
639 gfCycleIntTile = TRUE;
640
641 // Cycle around!
642 gCurIntTileStack.bCur++;
643
644 //PLot new movement
645 gfPlotNewMovement = TRUE;
646
647 if ( gCurIntTileStack.bCur == gCurIntTileStack.bNum )
648 {
649 gCurIntTileStack.bCur = 0;
650 }
651 }
652