Actor.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. //---------------------------------------------------------------------------
  2. //
  3. // actor.cpp - This file contains the code for the Actor class
  4. //
  5. //---------------------------------------------------------------------------//
  6. // Copyright (C) Microsoft Corporation. All rights reserved. //
  7. //===========================================================================//
  8. //---------------------------------------------------------------------------
  9. // Include files
  10. #ifndef MCLIB_H
  11. #include "mclib.h"
  12. #endif
  13. #ifndef ACTOR_H
  14. #include "actor.h"
  15. #endif
  16. #ifndef CAMERA_H
  17. #include "camera.h"
  18. #endif
  19. #ifndef SPRTMGR_H
  20. #include "sprtmgr.h"
  21. #endif
  22. #ifndef DBASEGUI_H
  23. #include "dbasegui.h"
  24. #endif
  25. //-----------------------------------------------------------------------------
  26. void memclear(void *Dest,int Length);
  27. //-----------------------------------------------------------------------------
  28. // class VFXAppearanceType
  29. void VFXAppearanceType::init (FilePtr apprFile, unsigned long fileSize)
  30. {
  31. loadIniFile(apprFile,fileSize);
  32. //------------------------------------------------------------------------------------
  33. // Once the Ini File is loaded, we need to create the Shape set for this type.
  34. numPackets = spriteManager->getShapePackets(getAppearanceFileNum());
  35. textureList = (TGATexturePtr *)spriteManager->mallocDataRAM(sizeof(TGATexture *)*numPackets);
  36. gosASSERT(textureList != NULL);
  37. memclear(textureList,sizeof(TGATexture *)*numPackets);
  38. }
  39. //---------------------------------------------------------------------------
  40. void VFXAppearanceType::removeTexture (TGATexturePtr texture) //Cache texture out
  41. {
  42. for (long i=0;i<numPackets;i++)
  43. {
  44. if (textureList[i] == texture)
  45. {
  46. textureList[i] = NULL;
  47. }
  48. }
  49. AppearanceRecord *ourUsers = users;
  50. while (ourUsers)
  51. {
  52. VFXAppearance *thisAppearance = (VFXAppearance *)ourUsers->appear;
  53. if (thisAppearance->currentTexture == texture)
  54. {
  55. thisAppearance->currentTexture = NULL;
  56. }
  57. ourUsers = ourUsers->next;
  58. }
  59. }
  60. //---------------------------------------------------------------------------
  61. long VFXAppearanceType::loadIniFile (FilePtr apprFile, unsigned long fileSize)
  62. {
  63. FitIniFile VFXAppearanceFile;
  64. long result = VFXAppearanceFile.open(apprFile,fileSize);
  65. gosASSERT(result == NO_ERR);
  66. //-----------------
  67. // States section
  68. result = VFXAppearanceFile.seekBlock("States");
  69. gosASSERT(result == NO_ERR);
  70. result = VFXAppearanceFile.readIdUChar("NumStates", numStates);
  71. gosASSERT(result == NO_ERR);
  72. actorStateData = (ActorData *)spriteManager->mallocDataRAM(sizeof(ActorData)*numStates);
  73. gosASSERT(actorStateData != NULL);
  74. memclear(actorStateData,sizeof(ActorData)*MAX_ACTOR_STATES);
  75. for (long curState = 0; curState < numStates; curState++)
  76. {
  77. char stateBlockName[20];
  78. sprintf(stateBlockName,"State%d",curState);
  79. result = VFXAppearanceFile.seekBlock(stateBlockName);
  80. gosASSERT(result == NO_ERR);
  81. unsigned char tempState;
  82. result = VFXAppearanceFile.readIdUChar("State", tempState);
  83. gosASSERT(result == NO_ERR);
  84. actorStateData[curState].state = (ActorState)tempState;
  85. result = VFXAppearanceFile.readIdULong("NumFrames", actorStateData[curState].numFrames);
  86. gosASSERT(result == NO_ERR);
  87. result = VFXAppearanceFile.readIdFloat("FrameRate", actorStateData[curState].frameRate);
  88. gosASSERT(result == NO_ERR);
  89. result = VFXAppearanceFile.readIdULong("BasePacketNumber", actorStateData[curState].basePacketNumber);
  90. gosASSERT(result == NO_ERR);
  91. result = VFXAppearanceFile.readIdUChar("NumRotations", actorStateData[curState].numRotations);
  92. gosASSERT(result == NO_ERR);
  93. result = VFXAppearanceFile.readIdUChar("Symmetrical", actorStateData[curState].symmetrical);
  94. gosASSERT(result == NO_ERR);
  95. result = VFXAppearanceFile.readIdLong("TextureSize", actorStateData[curState].textureSize);
  96. gosASSERT(result == NO_ERR);
  97. result = VFXAppearanceFile.readIdLong("TextureHS", actorStateData[curState].textureHS);
  98. gosASSERT(result == NO_ERR);
  99. }
  100. VFXAppearanceFile.close();
  101. return(NO_ERR);
  102. }
  103. //-----------------------------------------------------------------------------
  104. // This function is the meat and potatoes of this class. The Mech actor class
  105. // will use this function to find the gesture it is currently interested in
  106. // drawing. This function will handle ALL caching.
  107. TGATexturePtr VFXAppearanceType::getTexture (ActorState shapeId, long rot, long currFrame, float &frameRate, bool &mirror)
  108. {
  109. bool mirrorOn = FALSE;
  110. mirror = FALSE;
  111. //---------------------------------------------------------------------------------
  112. // If the NewShape does not exist for this sprite, it's frame count should be set to
  113. // zero. This is probably bad, since the sprite will disappear from the screen.
  114. if (actorStateData[shapeId].numFrames == 0)
  115. return(NULL);
  116. if (rot < 0.0 && actorStateData[shapeId].symmetrical)
  117. {
  118. rot = -rot;
  119. mirrorOn = TRUE;
  120. }
  121. else if (rot < 0.0 && !actorStateData[shapeId].symmetrical)
  122. {
  123. rot += 360;
  124. }
  125. mirror = mirrorOn;
  126. frameRate = actorStateData[shapeId].frameRate;
  127. //---------------------------------------------------------------------------------------
  128. // Remember: sprites use 0 degrees as facing camera, and degrees rotate counter-clockwise
  129. // long rotation = (long)(rot / (360.0 / (actorStateData[shapeId].numRotations)));
  130. long rotation = float2short( (1.0/360.0) * (rot * (actorStateData[shapeId].numRotations) ));
  131. //-------------------------------------------------------------------
  132. // Using the information provided, figure out which packet we really
  133. // want and check to see if the Gesture is cached. If it is, return it
  134. // If not, check if there is still room in the cache. If so, load the
  135. // gesture. At this point, depending on processor/game load and available
  136. // memory, we may load some other gestures to help offset a future load.
  137. // If no memory is left in this Sprite's cache, mark as free any block not
  138. // used recently. LRU cache.
  139. long packetNum = actorStateData[shapeId].basePacketNumber;
  140. packetNum += rotation * actorStateData[shapeId].numFrames; //Each frame is its own packet NOW!
  141. packetNum += currFrame;
  142. //-------------------------------------------------------------------
  143. // There weren't enough packets in the shape file. Give em nothing.
  144. if (packetNum >= numPackets)
  145. return(NULL);
  146. if (textureList[packetNum])
  147. {
  148. ((TGATexturePtr)textureList[packetNum])->lastTurnUsed = turn;
  149. return((TGATexturePtr)textureList[packetNum]);
  150. }
  151. //-------------------------------------------------
  152. // We have to cache something in at this point.
  153. // Be sure the frame length knows about it.
  154. dynamicFrameTiming = FALSE;
  155. textureList[packetNum] = spriteManager->getTextureData(getAppearanceFileNum(),packetNum,turn,this);
  156. return((TGATexturePtr)(textureList[packetNum]));
  157. }
  158. //----------------------------------------------------------------------------
  159. void VFXAppearanceType::destroy (void)
  160. {
  161. //---------------------------------------------------------------------------------------------
  162. //-- If we are going away, inform ALL of the shapes in the cache that their owner is NULL now.
  163. //-- Next dumpLRU will purge these FIRST!!
  164. for (long i=0;i<numPackets;i++)
  165. {
  166. if (textureList[i])
  167. {
  168. textureList[i]->owner = NULL;
  169. }
  170. }
  171. spriteManager->freeDataRAM(users);
  172. users = NULL;
  173. spriteManager->freeDataRAM(textureList);
  174. textureList = NULL;
  175. spriteManager->freeDataRAM(actorStateData);
  176. actorStateData = NULL;
  177. }
  178. //-----------------------------------------------------------------------------
  179. //-----------------------------------------------------------------------------
  180. // class VFXAppearance
  181. void VFXAppearance::init (AppearanceTypePtr tree, GameObjectPtr obj)
  182. {
  183. Appearance::init(tree,obj);
  184. appearType = (VFXAppearanceType *)tree;
  185. if (appearType)
  186. appearType->addUsers(this);
  187. currentTexture = NULL;
  188. currentFrame = -1;
  189. currentRotation = 0;
  190. inView = FALSE;
  191. lastInView = 0.0;
  192. timeInFrame = 0.0;
  193. lastWholeFrame = 0;
  194. fadeTable = NULL;
  195. currentShapeTypeId = ACTOR_STATE_NORMAL;
  196. startFrame = endFrame = -1;
  197. shapeMin.x = shapeMin.y = -15.0;
  198. shapeMax.x = shapeMax.y = 15.0;
  199. changedTypeId = TRUE;
  200. }
  201. //-----------------------------------------------------------------------------
  202. bool VFXAppearance::isMouseOver (float px, float py)
  203. {
  204. if (inView)
  205. {
  206. if ((px <= lowerRight.x) && (py <= lowerRight.y) &&
  207. (px >= upperLeft.x) &&
  208. (py >= upperLeft.y))
  209. {
  210. return inView;
  211. }
  212. else
  213. {
  214. return FALSE;
  215. }
  216. }
  217. return(inView);
  218. }
  219. #define SELECTED_COLOR 225
  220. #define TARGET_COLOR 207
  221. extern float currentScaleFactor;
  222. //-----------------------------------------------------------------------------
  223. bool VFXAppearance::recalcBounds (void)
  224. {
  225. Stuff::Vector4D tempPos;
  226. inView = FALSE;
  227. if (eye)
  228. {
  229. Stuff::Vector3D topPosition(position);
  230. topPosition.z += appearType->actorStateData[currentShapeTypeId].textureSize;
  231. eye->projectZ(topPosition,tempPos);
  232. topZ = tempPos.z;
  233. eye->projectZ(position,screenPos);
  234. tempPos = screenPos;
  235. float scale = eye->getScaleFactor();
  236. upperLeft.x = tempPos.x;
  237. upperLeft.y = tempPos.y;
  238. lowerRight.x = upperLeft.x;
  239. lowerRight.y = upperLeft.y;
  240. if (currentTexture && currentTexture->textureHandle != 0xffffffff)
  241. {
  242. if (!appearType->typeBoundExists())
  243. {
  244. //------------------------------------------------------------------------
  245. // Now, figure out what the upperLeft and lowerRight coordinates are and
  246. // draw these as extents if we are selected.
  247. shapeMin.x = -(appearType->actorStateData[currentShapeTypeId].textureSize >> 1);
  248. shapeMin.y = shapeMin.x;
  249. shapeMax.x = -(shapeMin.x);
  250. shapeMax.y = shapeMax.x;
  251. upperLeft.x = tempPos.x + (shapeMin.x * scale);
  252. upperLeft.y = tempPos.y + (shapeMin.y * scale);
  253. lowerRight.x = upperLeft.x + (shapeMax.x * scale);
  254. lowerRight.y = upperLeft.y + (shapeMax.y * scale);
  255. }
  256. else
  257. {
  258. upperLeft.x = tempPos.x + (appearType->typeUpperLeftX * scale);
  259. upperLeft.y = tempPos.y + (appearType->typeUpperLeftY * scale);
  260. lowerRight.x = tempPos.x + (appearType->typeLowerRightX * scale);
  261. lowerRight.y = tempPos.y + (appearType->typeLowerRightY * scale);
  262. }
  263. }
  264. if ((lowerRight.x >= 0) && (lowerRight.y >= 0) &&
  265. (upperLeft.x <= eye->getScreenResX()) &&
  266. (upperLeft.y <= eye->getScreenResY()))
  267. {
  268. inView = TRUE;
  269. }
  270. }
  271. return(inView);
  272. }
  273. //-----------------------------------------------------------------------------
  274. void VFXAppearance::setObjectParameters (Stuff::Vector3D &pos, float rot, long sel)
  275. {
  276. position = pos;
  277. rotation = rot;
  278. selected = sel;
  279. }
  280. extern long mechCmdr1PaletteLookup[];
  281. //-----------------------------------------------------------------------------
  282. long VFXAppearance::render (long depthFixup)
  283. {
  284. //-------------------------------------------------------------------------
  285. // First step is figure out where we are and cache the appropriate shapes
  286. bool oldMirror = FALSE;
  287. float tFrameRate = 0.0;
  288. currentTexture = appearType->getTexture(currentShapeTypeId,rotation,currentFrame,tFrameRate,oldMirror);
  289. if (currentFrame < 0)
  290. currentFrame = 0;
  291. TextureElement newElement;
  292. bool shapesOK = FALSE;
  293. if (currentTexture && currentTexture->textureHandle != 0xffffffff)
  294. {
  295. //------------------------------------------------------------------------
  296. // Add this shape to element list for sorting.
  297. newElement.init(currentTexture->textureHandle,screenPos.x,screenPos.y,
  298. (appearType->actorStateData[currentShapeTypeId].textureHS>>16),
  299. (appearType->actorStateData[currentShapeTypeId].textureHS & 0x0000ffff),
  300. appearType->actorStateData[currentShapeTypeId].textureSize,topZ,screenPos.z);
  301. unsigned char lightr,lightg,lightb, visible, seen;
  302. lightIntensity = land->getTerrainLight(position, visible, seen);
  303. lightr = eye->getLightRed(lightIntensity,visible,seen);
  304. lightg = eye->getLightGreen(lightIntensity,visible,seen);
  305. lightb = eye->getLightBlue(lightIntensity,visible,seen);
  306. DWORD lightRGB = lightb + (lightr<<16) + (lightg << 8) + (0xff << 24);
  307. newElement.setLight(lightRGB);
  308. newElement.draw();
  309. shapesOK = TRUE;
  310. }
  311. gosASSERT(shapesOK);
  312. if (selected)
  313. drawBars();
  314. //------------------------------------------------------------------------
  315. if (selected)
  316. {
  317. drawSelectBox(SB_BLUE);
  318. }
  319. selected = FALSE;
  320. return NO_ERR;
  321. }
  322. //-----------------------------------------------------------------------------
  323. void VFXAppearance::setDamageLvl (unsigned long dmg)
  324. {
  325. realBuildingDamage = TRUE;
  326. if (dmg)
  327. {
  328. unsigned long totalFrames1 = appearType->actorStateData[ACTOR_STATE_BLOWING_UP1].numFrames;
  329. unsigned long totalFrames2 = appearType->actorStateData[ACTOR_STATE_BLOWING_UP2].numFrames;
  330. if ((dmg >= (totalFrames1 + totalFrames2)))
  331. {
  332. setTypeId(ACTOR_STATE_DESTROYED);
  333. }
  334. else if ((dmg >= totalFrames1) && (dmg < (totalFrames1 + totalFrames2)))
  335. {
  336. setTypeId(ACTOR_STATE_BLOWING_UP2);
  337. currentFrame = dmg - totalFrames1;
  338. }
  339. else if (dmg < totalFrames1)
  340. {
  341. setTypeId(ACTOR_STATE_BLOWING_UP1);
  342. currentFrame = dmg;
  343. }
  344. }
  345. else
  346. {
  347. setTypeId(ACTOR_STATE_NORMAL);
  348. }
  349. }
  350. //-----------------------------------------------------------------------------
  351. void VFXAppearance::debugUpdate (void)
  352. {
  353. update();
  354. recalcBounds();
  355. }
  356. //-----------------------------------------------------------------------------
  357. long VFXAppearance::update (void)
  358. {
  359. //--------------------------------------------------------
  360. // Check if we are just starting out. If so, set
  361. // the current frame to zero.
  362. bool startingAnimation = FALSE;
  363. if (currentFrame == -1)
  364. {
  365. currentFrame = 0;
  366. startingAnimation = TRUE;
  367. }
  368. //--------------------------------------------------------------
  369. // Must update animation frame numbers, even if not visible!!
  370. // Make sure animation runs no faster than frameRate fps.
  371. // Moved to here to make game work.
  372. unsigned long anyFrames = appearType->actorStateData[currentShapeTypeId].numFrames;
  373. if (anyFrames > 1)
  374. {
  375. long frameInc = 0;
  376. float frameRate = appearType->actorStateData[currentShapeTypeId].frameRate;
  377. //------------------------------------------------------
  378. // Make sure animation runs no faster than frameRate fps.
  379. float frameRateOverOne = (1.0 / frameRate);
  380. timeInFrame += frameLength;
  381. if (timeInFrame >= frameRateOverOne)
  382. {
  383. frameInc = timeInFrame * frameRate;
  384. float remainder = timeInFrame/frameInc - frameRateOverOne;
  385. timeInFrame = remainder;
  386. }
  387. if (frameInc)
  388. {
  389. currentFrame += frameInc;
  390. unsigned long totalFrames = appearType->actorStateData[currentShapeTypeId].numFrames;
  391. unsigned char loop = 1;
  392. if ((currentFrame >= totalFrames) && (loop) && (endFrame == -1))
  393. {
  394. currentFrame %= totalFrames;
  395. return(FALSE); //Let the object know we have completed a cycle.
  396. }
  397. else if ((currentFrame >= totalFrames) && (!loop))
  398. {
  399. currentFrame = totalFrames-1;
  400. }
  401. else if (currentFrame >= endFrame)
  402. {
  403. currentFrame = startFrame;
  404. return(FALSE); //Let the object know we have completed a cycle.
  405. }
  406. }
  407. }
  408. return TRUE;
  409. }
  410. //-----------------------------------------------------------------------------
  411. void VFXAppearance::destroy (void)
  412. {
  413. appearType->removeUsers(this);
  414. appearanceTypeList->removeAppearance(appearType);
  415. }
  416. //-----------------------------------------------------------------------------
  417. long VFXAppearance::stateExists (ActorState typeId)
  418. {
  419. if ((typeId < appearType->numStates) && (typeId >= 0))
  420. return (appearType->actorStateData[typeId].numFrames);
  421. return 0;
  422. }
  423. //*****************************************************************************