Game.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732
  1. #include "Hunt.h"
  2. bool ShowFaces = true;
  3. void UploadGeometry()
  4. {
  5. int x,y,xx,yy;
  6. byte temp;
  7. AudioFCount = 0;
  8. int MaxView = 20;
  9. int HalfView = (int)(MaxView/2)+1;
  10. for (x = 0; x < MaxView; x++)
  11. for (y = 0; y < MaxView; y++)
  12. {
  13. xx = (x - HalfView)*2;
  14. yy = (y - HalfView)*2;
  15. data[AudioFCount].x1 = (CCX+xx) * 256 - CameraX;
  16. data[AudioFCount].y1 = HMap[CCY+yy][CCX+xx] * ctHScale - CameraY;
  17. data[AudioFCount].z1 = (CCY+yy) * 256 - CameraZ;
  18. xx = ((x+1) - HalfView)*2;
  19. yy = (y - HalfView)*2;
  20. data[AudioFCount].x2 = (CCX+xx) * 256 - CameraX;
  21. data[AudioFCount].y2 = HMap[CCY+yy][CCX+xx] * ctHScale - CameraY;
  22. data[AudioFCount].z2 = (CCY+yy) * 256 - CameraZ;
  23. xx = ((x+1) - HalfView)*2;
  24. yy = ((y+1) - HalfView)*2;
  25. data[AudioFCount].x3 = (CCX+xx) * 256 - CameraX;
  26. data[AudioFCount].y3 = HMap[CCY+yy][CCX+xx] * ctHScale - CameraY;
  27. data[AudioFCount].z3 = (CCY+yy) * 256 - CameraZ;
  28. xx = (x - HalfView)*2;
  29. yy = ((y+1) - HalfView)*2;
  30. data[AudioFCount].x4 = (CCX+xx) * 256 - CameraX;
  31. data[AudioFCount].y4 = HMap[CCY+yy][CCX+xx] * ctHScale - CameraY;
  32. data[AudioFCount].z4 = (CCY+yy) * 256 - CameraZ;
  33. AudioFCount++;
  34. }
  35. if (ShowFaces)
  36. { wsprintf(logt,"Audio_UpdateGeometry: %i faces uploaded\n", AudioFCount); PrintLog(logt);
  37. ShowFaces = false;}
  38. }
  39. void SetupRes()
  40. {
  41. if (!HARD3D)
  42. if (OptRes>5) OptRes=5;
  43. if (OptRes==0) { WinW = 320; WinH=240; }
  44. if (OptRes==1) { WinW = 400; WinH=300; }
  45. if (OptRes==2) { WinW = 512; WinH=384; }
  46. if (OptRes==3) { WinW = 640; WinH=480; }
  47. if (OptRes==4) { WinW = 800; WinH=600; }
  48. if (OptRes==5) { WinW =1024; WinH=768; }
  49. if (OptRes==6) { WinW =1280; WinH=1024; }
  50. if (OptRes==7) { WinW =1600; WinH=1200; }
  51. }
  52. float GetLandOH(int x, int y)
  53. {
  54. return (float)(HMapO[y][x]) * ctHScale;
  55. }
  56. float GetLandOUH(int x, int y)
  57. {
  58. if (FMap[y][x] & fmReverse)
  59. return (float)((int)(HMap[y][x+1]+HMap[y+1][x])/2.f)*ctHScale;
  60. else
  61. return (float)((int)(HMap[y][x]+HMap[y+1][x+1])/2.f)*ctHScale;
  62. }
  63. float GetLandUpH(float x, float y)
  64. {
  65. int CX = (int)x / 256;
  66. int CY = (int)y / 256;
  67. if (!(FMap[CY][CX] & fmWaterA)) return GetLandH(x,y);
  68. return (float)(WaterList[ WMap[CY][CX] ].wlevel * ctHScale);
  69. }
  70. float GetLandH(float x, float y)
  71. {
  72. int CX = (int)x / 256;
  73. int CY = (int)y / 256;
  74. int dx = (int)x % 256;
  75. int dy = (int)y % 256;
  76. int h1 = HMap[CY][CX];
  77. int h2 = HMap[CY][CX+1];
  78. int h3 = HMap[CY+1][CX+1];
  79. int h4 = HMap[CY+1][CX];
  80. if (FMap[CY][CX] & fmReverse) {
  81. if (256-dx>dy) h3 = h2+h4-h1;
  82. else h1 = h2+h4-h3;
  83. } else {
  84. if (dx>dy) h4 = h1+h3-h2;
  85. else h2 = h1+h3-h4;
  86. }
  87. float h = (float)
  88. (h1 * (256-dx) + h2 * dx) * (256-dy) +
  89. (h4 * (256-dx) + h3 * dx) * dy;
  90. return (h / 256.f / 256.f) * ctHScale;
  91. }
  92. float GetLandLt(float x, float y)
  93. {
  94. int CX = (int)x / 256;
  95. int CY = (int)y / 256;
  96. int dx = (int)x % 256;
  97. int dy = (int)y % 256;
  98. int h1 = LMap[CY][CX];
  99. int h2 = LMap[CY][CX+1];
  100. int h3 = LMap[CY+1][CX+1];
  101. int h4 = LMap[CY+1][CX];
  102. float h = (float)
  103. (h1 * (256-dx) + h2 * dx) * (256-dy) +
  104. (h4 * (256-dx) + h3 * dx) * dy;
  105. return (h / 256.f / 256.f);
  106. }
  107. float GetLandLt2(float x, float y)
  108. {
  109. int CX = ((int)x / 512)*2 - CCX;
  110. int CY = ((int)y / 512)*2 - CCY;
  111. int dx = (int)x % 512;
  112. int dy = (int)y % 512;
  113. int h1 = VMap[CY+128][CX+128].Light;
  114. int h2 = VMap[CY+128][CX+2+128].Light;
  115. int h3 = VMap[CY+2+128][CX+2+128].Light;
  116. int h4 = VMap[CY+2+128][CX+128].Light;
  117. float h = (float)
  118. (h1 * (512-dx) + h2 * dx) * (512-dy) +
  119. (h4 * (512-dx) + h3 * dx) * dy;
  120. return (h / 512.f / 512.f);
  121. }
  122. void CalcModelGroundLight(TModel *mptr, float x0, float z0, int FI)
  123. {
  124. float ca = (float)f_cos(FI * pi / 2);
  125. float sa = (float)f_sin(FI * pi / 2);
  126. for (int v=0; v<mptr->VCount; v++) {
  127. float x = mptr->gVertex[v].x * ca + mptr->gVertex[v].z * sa + x0;
  128. float z = mptr->gVertex[v].z * ca - mptr->gVertex[v].x * sa + z0;
  129. mptr->VLight[0][v] = GetLandLt2(x, z) - 128;
  130. }
  131. }
  132. BOOL PointOnBound(float &H, float px, float py, float cx, float cy, float oy, TBound *bound, int angle)
  133. {
  134. px-=cx;
  135. py-=cy;
  136. float ca = (float) f_cos(angle*pi / 2.f);
  137. float sa = (float) f_sin(angle*pi / 2.f);
  138. BOOL _on = FALSE;
  139. H=-10000;
  140. for (int o=0; o<8; o++) {
  141. if (bound[o].a<0) continue;
  142. if (bound[o].y2 + oy > PlayerY + 128) continue;
  143. float a,b;
  144. float ccx = bound[o].cx*ca + bound[o].cy*sa;
  145. float ccy = bound[o].cy*ca - bound[o].cx*sa;
  146. if (angle & 1) {
  147. a = bound[o].b;
  148. b = bound[o].a;
  149. } else {
  150. a = bound[o].a;
  151. b = bound[o].b;
  152. }
  153. if ( ( fabs(px - ccx) < a) && (fabs(py - ccy) < b) )
  154. {
  155. _on=TRUE;
  156. if (H < bound[o].y2) H = bound[o].y2;
  157. }
  158. }
  159. return _on;
  160. }
  161. BOOL PointUnBound(float &H, float px, float py, float cx, float cy, float oy, TBound *bound, int angle)
  162. {
  163. px-=cx;
  164. py-=cy;
  165. float ca = (float) f_cos(angle*pi / 2.f);
  166. float sa = (float) f_sin(angle*pi / 2.f);
  167. BOOL _on = FALSE;
  168. H=+10000;
  169. for (int o=0; o<8; o++) {
  170. if (bound[o].a<0) continue;
  171. if (bound[o].y1 + oy < PlayerY + 128) continue;
  172. float a,b;
  173. float ccx = bound[o].cx*ca + bound[o].cy*sa;
  174. float ccy = bound[o].cy*ca - bound[o].cx*sa;
  175. if (angle & 1) {
  176. a = bound[o].b;
  177. b = bound[o].a;
  178. } else {
  179. a = bound[o].a;
  180. b = bound[o].b;
  181. }
  182. if ( ( fabs(px - ccx) < a) && (fabs(py - ccy) < b) )
  183. {
  184. _on=TRUE;
  185. if (H > bound[o].y1) H = bound[o].y1;
  186. }
  187. }
  188. return _on;
  189. }
  190. float GetLandCeilH(float CameraX, float CameraZ)
  191. {
  192. float h,hh;
  193. h = GetLandH(CameraX, CameraZ) + 20480;
  194. int ccx = (int)CameraX / 256;
  195. int ccz = (int)CameraZ / 256;
  196. for (int z=-4; z<=4; z++)
  197. for (int x=-4; x<=4; x++)
  198. if (OMap[ccz+z][ccx+x]!=255) {
  199. int ob = OMap[ccz+z][ccx+x];
  200. float CR = (float)MObjects[ob].info.Radius - 1.f;
  201. float oz = (ccz+z) * 256.f + 128.f;
  202. float ox = (ccx+x) * 256.f + 128.f;
  203. float LandY = GetLandOH(ccx+x, ccz+z);
  204. if (!(MObjects[ob].info.flags & ofBOUND)) {
  205. if (MObjects[ob].info.YLo + LandY > h) continue;
  206. if (MObjects[ob].info.YLo + LandY < PlayerY+100) continue;
  207. }
  208. float r = CR+1;
  209. if (MObjects[ob].info.flags & ofBOUND)
  210. {
  211. float hh;
  212. if (PointUnBound(hh, CameraX, CameraZ, ox, oz, LandY, MObjects[ob].bound, ((FMap[ccz+z][ccx+x] >> 2) & 3) ) )
  213. if (h > LandY + hh) h = LandY + hh;
  214. } else {
  215. if (MObjects[ob].info.flags & ofCIRCLE)
  216. r = (float) sqrt( (ox-CameraX)*(ox-CameraX) + (oz-CameraZ)*(oz-CameraZ) );
  217. else
  218. r = (float) max( fabs(ox-CameraX) , fabs(oz-CameraZ) );
  219. if (r<CR) h = MObjects[ob].info.YLo + LandY;
  220. }
  221. }
  222. return h;
  223. }
  224. float GetLandQH(float CameraX, float CameraZ)
  225. {
  226. float h,hh;
  227. h = GetLandH(CameraX, CameraZ);
  228. hh = GetLandH(CameraX-90.f, CameraZ-90.f); if (hh>h) h=hh;
  229. hh = GetLandH(CameraX+90.f, CameraZ-90.f); if (hh>h) h=hh;
  230. hh = GetLandH(CameraX-90.f, CameraZ+90.f); if (hh>h) h=hh;
  231. hh = GetLandH(CameraX+90.f, CameraZ+90.f); if (hh>h) h=hh;
  232. hh = GetLandH(CameraX+128.f, CameraZ); if (hh>h) h=hh;
  233. hh = GetLandH(CameraX-128.f, CameraZ); if (hh>h) h=hh;
  234. hh = GetLandH(CameraX, CameraZ+128.f); if (hh>h) h=hh;
  235. hh = GetLandH(CameraX, CameraZ-128.f); if (hh>h) h=hh;
  236. int ccx = (int)CameraX / 256;
  237. int ccz = (int)CameraZ / 256;
  238. for (int z=-4; z<=4; z++)
  239. for (int x=-4; x<=4; x++)
  240. if (OMap[ccz+z][ccx+x]!=255) {
  241. int ob = OMap[ccz+z][ccx+x];
  242. float CR = (float)MObjects[ob].info.Radius - 1.f;
  243. float oz = (ccz+z) * 256.f + 128.f;
  244. float ox = (ccx+x) * 256.f + 128.f;
  245. float LandY = GetLandOH(ccx+x, ccz+z);
  246. if (!(MObjects[ob].info.flags & ofBOUND)) {
  247. if (MObjects[ob].info.YHi + LandY < h) continue;
  248. if (MObjects[ob].info.YHi + LandY > PlayerY+128) continue;
  249. //if (MObjects[ob].info.YLo + LandY > PlayerY+256) continue;
  250. }
  251. float r = CR+1;
  252. if (MObjects[ob].info.flags & ofBOUND)
  253. {
  254. float hh;
  255. if (PointOnBound(hh, CameraX, CameraZ, ox, oz, LandY, MObjects[ob].bound, ((FMap[ccz+z][ccx+x] >> 2) & 3) ) )
  256. if (h < LandY + hh) h = LandY + hh;
  257. } else {
  258. if (MObjects[ob].info.flags & ofCIRCLE)
  259. r = (float) sqrt( (ox-CameraX)*(ox-CameraX) + (oz-CameraZ)*(oz-CameraZ) );
  260. else
  261. r = (float) max( fabs(ox-CameraX) , fabs(oz-CameraZ) );
  262. if (r<CR) h = MObjects[ob].info.YHi + LandY;
  263. }
  264. }
  265. return h;
  266. }
  267. float GetLandHObj(float CameraX, float CameraZ)
  268. {
  269. float h;
  270. h = 0;
  271. int ccx = (int)CameraX / 256;
  272. int ccz = (int)CameraZ / 256;
  273. for (int z=-3; z<=3; z++)
  274. for (int x=-3; x<=3; x++)
  275. if (OMap[ccz+z][ccx+x]!=255) {
  276. int ob = OMap[ccz+z][ccx+x];
  277. float CR = (float)MObjects[ob].info.Radius - 1.f;
  278. float oz = (ccz+z) * 256.f + 128.f;
  279. float ox = (ccx+x) * 256.f + 128.f;
  280. if (MObjects[ob].info.YHi + GetLandOH(ccx+x, ccz+z) < h) continue;
  281. if (MObjects[ob].info.YLo + GetLandOH(ccx+x, ccz+z) > PlayerY+256) continue;
  282. float r;
  283. if (MObjects[ob].info.flags & ofCIRCLE)
  284. r = (float) sqrt( (ox-CameraX)*(ox-CameraX) + (oz-CameraZ)*(oz-CameraZ) );
  285. else
  286. r = (float) max( fabs(ox-CameraX) , fabs(oz-CameraZ) );
  287. if (r<CR)
  288. h = MObjects[ob].info.YHi + GetLandOH(ccx+x, ccz+z);
  289. }
  290. return h;
  291. }
  292. float GetLandQHNoObj(float CameraX, float CameraZ)
  293. {
  294. float h,hh;
  295. h = GetLandH(CameraX, CameraZ);
  296. hh = GetLandH(CameraX-90.f, CameraZ-90.f); if (hh>h) h=hh;
  297. hh = GetLandH(CameraX+90.f, CameraZ-90.f); if (hh>h) h=hh;
  298. hh = GetLandH(CameraX-90.f, CameraZ+90.f); if (hh>h) h=hh;
  299. hh = GetLandH(CameraX+90.f, CameraZ+90.f); if (hh>h) h=hh;
  300. hh = GetLandH(CameraX+128.f, CameraZ); if (hh>h) h=hh;
  301. hh = GetLandH(CameraX-128.f, CameraZ); if (hh>h) h=hh;
  302. hh = GetLandH(CameraX, CameraZ+128.f); if (hh>h) h=hh;
  303. hh = GetLandH(CameraX, CameraZ-128.f); if (hh>h) h=hh;
  304. return h;
  305. }
  306. void ProcessCommandLine()
  307. {
  308. for (int a=0; a<__argc; a++) {
  309. LPSTR s = __argv[a];
  310. if (strstr(s,"x=")) { PlayerX = (float)atof(&s[2])*256.f; LockLanding = TRUE; }
  311. if (strstr(s,"y=")) { PlayerZ = (float)atof(&s[2])*256.f; LockLanding = TRUE; }
  312. if (strstr(s,"reg=")) TrophyRoom.RegNumber = atoi(&s[4]);
  313. if (strstr(s,"prj=")) strcpy(ProjectName, (s+4));
  314. if (strstr(s,"din=")) TargetDino = (atoi(&s[4])*1024);
  315. if (strstr(s,"wep=")) WeaponPres = atoi(&s[4]);
  316. if (strstr(s,"dtm=")) OptDayNight = atoi(&s[4]);
  317. if (strstr(s,"-debug")) DEBUG = TRUE;
  318. if (strstr(s,"-double")) DoubleAmmo = TRUE;
  319. if (strstr(s,"-radar")) RadarMode = TRUE;
  320. if (strstr(s,"-tranq")) Tranq = TRUE;
  321. if (strstr(s,"-observ")) ObservMode = TRUE;
  322. }
  323. }
  324. void AddWCircle(float x, float z, float scale)
  325. {
  326. WCircles[WCCount].pos.x = x;
  327. WCircles[WCCount].pos.z = z;
  328. WCircles[WCCount].pos.y = GetLandUpH(x, z);
  329. WCircles[WCCount].FTime = 0;
  330. WCircles[WCCount].scale = scale;
  331. WCCount++;
  332. }
  333. void AddShipTask(int cindex)
  334. {
  335. TCharacter *cptr = &Characters[cindex];
  336. BOOL TROPHYON = (GetLandUpH(cptr->pos.x, cptr->pos.z) - GetLandH(cptr->pos.x, cptr->pos.z) < 100) &&
  337. (!Tranq);
  338. if (TROPHYON) {
  339. ShipTask.clist[ShipTask.tcount] = cindex;
  340. ShipTask.tcount++;
  341. AddVoicev(ShipModel.SoundFX[3].length,
  342. ShipModel.SoundFX[3].lpData, 256);
  343. }
  344. //===== trophy =======//
  345. SYSTEMTIME st;
  346. GetLocalTime(&st);
  347. int t=0;
  348. for (t=0; t<23; t++)
  349. if (!TrophyRoom.Body[t].ctype) break;
  350. float score = (float)DinoInfo[Characters[cindex].CType].BaseScore;
  351. if (TrophyRoom.Last.success>1)
  352. score*=(1.f + TrophyRoom.Last.success / 10.f);
  353. if (!(TargetDino & (1<<Characters[cindex].AI)) ) score/=2.f;
  354. if (Tranq ) score *= 1.25f;
  355. if (RadarMode) score *= 0.70f;
  356. if (ScentMode) score *= 0.80f;
  357. if (CamoMode ) score *= 0.85f;
  358. TrophyRoom.Score+=(int)score;
  359. if (!Tranq) {
  360. TrophyTime = 20 * 1000;
  361. TrophyBody = t;
  362. TrophyRoom.Body[t].ctype = Characters[cindex].CType;
  363. TrophyRoom.Body[t].scale = Characters[cindex].scale;
  364. TrophyRoom.Body[t].weapon = CurrentWeapon;
  365. TrophyRoom.Body[t].score = (int)score;
  366. TrophyRoom.Body[t].phase = (RealTime & 3);
  367. TrophyRoom.Body[t].time = (st.wHour<<10) + st.wMinute;
  368. TrophyRoom.Body[t].date = (st.wYear<<20) + (st.wMonth<<10) + st.wDay;
  369. TrophyRoom.Body[t].range = VectorLength( SubVectors(Characters[cindex].pos, PlayerPos) ) / 64.f;
  370. PrintLog("Trophy added: ");
  371. PrintLog(DinoInfo[Characters[cindex].CType].Name);
  372. PrintLog("\n");
  373. }
  374. }
  375. void InitShip(int cindex)
  376. {
  377. TCharacter *cptr = &Characters[cindex];
  378. Ship.DeltaY = 2048.f + DinoInfo[cptr->CType].ShDelta * cptr->scale;
  379. Ship.pos.x = PlayerX - 90*256;
  380. if (Ship.pos.x < 256) Ship.pos.x = PlayerX + 90*256;
  381. Ship.pos.z = PlayerZ - 90*256;
  382. if (Ship.pos.z < 256) Ship.pos.z = PlayerZ + 90*256;
  383. Ship.pos.y = GetLandUpH(Ship.pos.x, Ship.pos.z) + Ship.DeltaY + 1024;
  384. Ship.tgpos.x = cptr->pos.x;
  385. Ship.tgpos.z = cptr->pos.z;
  386. Ship.tgpos.y = GetLandUpH(Ship.tgpos.x, Ship.tgpos.z) + Ship.DeltaY;
  387. Ship.State = 0;
  388. Ship.retpos = Ship.pos;
  389. Ship.cindex = cindex;
  390. Ship.FTime = 0;
  391. }
  392. void HideWeapon()
  393. {
  394. TWeapon *wptr = &Weapon;
  395. if (UNDERWATER && !wptr->state) return;
  396. if (ObservMode || TrophyMode) return;
  397. if (wptr->state == 0) {
  398. if (!ShotsLeft[CurrentWeapon]) return;
  399. if (WeapInfo[CurrentWeapon].Optic) OPTICMODE = TRUE;
  400. AddVoicev(wptr->chinfo[CurrentWeapon].SoundFX[0].length,
  401. wptr->chinfo[CurrentWeapon].SoundFX[0].lpData, 256);
  402. wptr->FTime = 0;
  403. wptr->state = 1;
  404. BINMODE = FALSE;
  405. MapMode = FALSE;
  406. wptr->shakel = 0.2f;
  407. return;
  408. }
  409. if (wptr->state!=2 || wptr->FTime!=0) return;
  410. AddVoicev(wptr->chinfo[CurrentWeapon].SoundFX[2].length,
  411. wptr->chinfo[CurrentWeapon].SoundFX[2].lpData, 256);
  412. wptr->state = 3;
  413. wptr->FTime = 0;
  414. OPTICMODE = FALSE;
  415. return ;
  416. }
  417. void InitGameInfo()
  418. {
  419. for (int c=0; c<32; c++) {
  420. DinoInfo[c].Scale0 = 800;
  421. DinoInfo[c].ScaleA = 600;
  422. DinoInfo[c].ShDelta = 0;
  423. }
  424. /*
  425. WeapInfo[0].Name = "Shotgun";
  426. WeapInfo[0].Power = 1.5f;
  427. WeapInfo[0].Prec = 1.1f;
  428. WeapInfo[0].Loud = 0.3f;
  429. WeapInfo[0].Rate = 1.6f;
  430. WeapInfo[0].Shots = 6;
  431. WeapInfo[1].Name = "X-Bow";
  432. WeapInfo[1].Power = 1.1f;
  433. WeapInfo[1].Prec = 0.7f;
  434. WeapInfo[1].Loud = 1.9f;
  435. WeapInfo[1].Rate = 1.2f;
  436. WeapInfo[1].Shots = 8;
  437. WeapInfo[2].Name = "Sniper Rifle";
  438. WeapInfo[2].Power = 1.0f;
  439. WeapInfo[2].Prec = 1.8f;
  440. WeapInfo[2].Loud = 0.6f;
  441. WeapInfo[2].Rate = 1.0f;
  442. WeapInfo[2].Shots = 6;
  443. DinoInfo[ 0].Name = "Moschops";
  444. DinoInfo[ 0].Health0 = 2;
  445. DinoInfo[ 0].Mass = 0.15f;
  446. DinoInfo[ 1].Name = "Galimimus";
  447. DinoInfo[ 1].Health0 = 2;
  448. DinoInfo[ 1].Mass = 0.1f;
  449. DinoInfo[ 2].Name = "Dimorphodon";
  450. DinoInfo[ 2].Health0 = 1;
  451. DinoInfo[ 2].Mass = 0.05f;
  452. DinoInfo[ 3].Name = "Dimetrodon";
  453. DinoInfo[ 3].Health0 = 2;
  454. DinoInfo[ 3].Mass = 0.22f;
  455. DinoInfo[ 5].Name = "Parasaurolophus";
  456. DinoInfo[ 5].Mass = 1.5f;
  457. DinoInfo[ 5].Length = 5.8f;
  458. DinoInfo[ 5].Radius = 320.f;
  459. DinoInfo[ 5].Health0 = 5;
  460. DinoInfo[ 5].BaseScore = 6;
  461. DinoInfo[ 5].SmellK = 0.8f; DinoInfo[ 4].HearK = 1.f; DinoInfo[ 4].LookK = 0.4f;
  462. DinoInfo[ 5].ShDelta = 48;
  463. DinoInfo[ 6].Name = "Pachycephalosaurus";
  464. DinoInfo[ 6].Mass = 0.8f;
  465. DinoInfo[ 6].Length = 4.5f;
  466. DinoInfo[ 6].Radius = 280.f;
  467. DinoInfo[ 6].Health0 = 4;
  468. DinoInfo[ 6].BaseScore = 8;
  469. DinoInfo[ 6].SmellK = 0.4f; DinoInfo[ 5].HearK = 0.8f; DinoInfo[ 5].LookK = 0.6f;
  470. DinoInfo[ 6].ShDelta = 36;
  471. DinoInfo[ 7].Name = "Stegosaurus";
  472. DinoInfo[ 7].Mass = 7.f;
  473. DinoInfo[ 7].Length = 7.f;
  474. DinoInfo[ 7].Radius = 480.f;
  475. DinoInfo[ 7].Health0 = 5;
  476. DinoInfo[ 7].BaseScore = 7;
  477. DinoInfo[ 7].SmellK = 0.4f; DinoInfo[ 6].HearK = 0.8f; DinoInfo[ 6].LookK = 0.6f;
  478. DinoInfo[ 7].ShDelta = 128;
  479. DinoInfo[ 8].Name = "Allosaurus";
  480. DinoInfo[ 8].Mass = 0.5;
  481. DinoInfo[ 8].Length = 4.2f;
  482. DinoInfo[ 8].Radius = 256.f;
  483. DinoInfo[ 8].Health0 = 3;
  484. DinoInfo[ 8].BaseScore = 12;
  485. DinoInfo[ 8].Scale0 = 1000;
  486. DinoInfo[ 8].ScaleA = 600;
  487. DinoInfo[ 8].SmellK = 1.0f; DinoInfo[ 7].HearK = 0.3f; DinoInfo[ 7].LookK = 0.5f;
  488. DinoInfo[ 8].ShDelta = 32;
  489. DinoInfo[ 8].DangerCall = TRUE;
  490. DinoInfo[ 9].Name = "Chasmosaurus";
  491. DinoInfo[ 9].Mass = 3.f;
  492. DinoInfo[ 9].Length = 5.0f;
  493. DinoInfo[ 9].Radius = 400.f;
  494. DinoInfo[ 9].Health0 = 8;
  495. DinoInfo[ 9].BaseScore = 9;
  496. DinoInfo[ 9].SmellK = 0.6f; DinoInfo[ 8].HearK = 0.5f; DinoInfo[ 8].LookK = 0.4f;
  497. //DinoInfo[ 8].ShDelta = 148;
  498. DinoInfo[ 9].ShDelta = 108;
  499. DinoInfo[10].Name = "Velociraptor";
  500. DinoInfo[10].Mass = 0.3f;
  501. DinoInfo[10].Length = 4.0f;
  502. DinoInfo[10].Radius = 256.f;
  503. DinoInfo[10].Health0 = 3;
  504. DinoInfo[10].BaseScore = 16;
  505. DinoInfo[10].ScaleA = 400;
  506. DinoInfo[10].SmellK = 1.0f; DinoInfo[ 9].HearK = 0.5f; DinoInfo[ 9].LookK = 0.4f;
  507. DinoInfo[10].ShDelta =-24;
  508. DinoInfo[10].DangerCall = TRUE;
  509. DinoInfo[11].Name = "T-Rex";
  510. DinoInfo[11].Mass = 6.f;
  511. DinoInfo[11].Length = 12.f;
  512. DinoInfo[11].Radius = 400.f;
  513. DinoInfo[11].Health0 = 1024;
  514. DinoInfo[11].BaseScore = 20;
  515. DinoInfo[11].SmellK = 0.85f; DinoInfo[10].HearK = 0.8f; DinoInfo[10].LookK = 0.8f;
  516. DinoInfo[11].ShDelta = 168;
  517. DinoInfo[11].DangerCall = TRUE;
  518. DinoInfo[ 4].Name = "Brahiosaurus";
  519. DinoInfo[ 4].Mass = 9.f;
  520. DinoInfo[ 4].Length = 12.f;
  521. DinoInfo[ 4].Radius = 400.f;
  522. DinoInfo[ 4].Health0 = 1024;
  523. DinoInfo[ 4].BaseScore = 0;
  524. DinoInfo[ 4].SmellK = 0.85f; DinoInfo[16].HearK = 0.8f; DinoInfo[16].LookK = 0.8f;
  525. DinoInfo[ 4].ShDelta = 168;
  526. DinoInfo[ 4].DangerCall = FALSE;
  527. */
  528. LoadResourcesScript();
  529. }
  530. void InitEngine()
  531. {
  532. //DEBUG = TRUE;
  533. WATERANI = TRUE;
  534. NODARKBACK = TRUE;
  535. LoDetailSky = TRUE;
  536. CORRECTION = TRUE;
  537. FOGON = TRUE;
  538. FOGENABLE = TRUE;
  539. Clouds = TRUE;
  540. SKY = TRUE;
  541. GOURAUD = TRUE;
  542. MODELS = TRUE;
  543. TIMER = DEBUG;
  544. BITMAPP = FALSE;
  545. MIPMAP = TRUE;
  546. NOCLIP = FALSE;
  547. CLIP3D = TRUE;
  548. SLOW = FALSE;
  549. LOWRESTX = FALSE;
  550. MORPHP = TRUE;
  551. MORPHA = TRUE;
  552. _GameState = 0;
  553. RadarMode = FALSE;
  554. fnt_BIG = CreateFont(
  555. 23, 10, 0, 0,
  556. 600, 0,0,0,
  557. #ifdef __rus
  558. RUSSIAN_CHARSET,
  559. #else
  560. ANSI_CHARSET,
  561. #endif
  562. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, NULL);
  563. fnt_Small = CreateFont(
  564. 14, 5, 0, 0,
  565. 100, 0,0,0,
  566. #ifdef __rus
  567. RUSSIAN_CHARSET,
  568. #else
  569. ANSI_CHARSET,
  570. #endif
  571. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, NULL);
  572. fnt_Midd = CreateFont(
  573. 16, 7, 0, 0,
  574. 550, 0,0,0,
  575. #ifdef __rus
  576. RUSSIAN_CHARSET,
  577. #else
  578. ANSI_CHARSET,
  579. #endif
  580. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, NULL);
  581. Heap = HeapCreate( 0, 60000000, 64000000 );
  582. if( Heap == NULL ) {
  583. MessageBox(hwndMain,"Error creating heap.","Error",IDOK);
  584. return; }
  585. Textures[255] = (TEXTURE*) _HeapAlloc(Heap, 0, sizeof(TEXTURE));
  586. WaterR = 10;
  587. WaterG = 38;
  588. WaterB = 46;
  589. WaterA = 10;
  590. TargetDino = 1<<10;
  591. TargetCall = 10;
  592. WeaponPres = 1;
  593. MessageList.timeleft = 0;
  594. InitGameInfo();
  595. CreateVideoDIB();
  596. CreateFadeTab();
  597. CreateDivTable();
  598. InitClips();
  599. TrophyRoom.RegNumber=0;
  600. PlayerX = (ctMapSize / 3) * 256;
  601. PlayerZ = (ctMapSize / 3) * 256;
  602. ProcessCommandLine();
  603. switch (OptDayNight) {
  604. case 0:
  605. SunShadowK = 0.7f;
  606. Sun3dPos.x = - 4048;
  607. Sun3dPos.y = + 2048;
  608. Sun3dPos.z = - 4048;
  609. break;
  610. case 1:
  611. SunShadowK = 0.5f;
  612. Sun3dPos.x = - 2048;
  613. Sun3dPos.y = + 4048;
  614. Sun3dPos.z = - 2048;
  615. break;
  616. case 2:
  617. SunShadowK = -0.7f;
  618. Sun3dPos.x = + 3048;
  619. Sun3dPos.y = + 3048;
  620. Sun3dPos.z = + 3048;
  621. break;
  622. }
  623. LoadTrophy();
  624. ProcessCommandLine();
  625. //ctViewR = 72;
  626. //ctViewR1 = 28;
  627. //ctViewRM = 24;
  628. ctViewR = 42 + (int)(OptViewR / 8)*2;
  629. ctViewR1 = 28;
  630. ctViewRM = 24;
  631. Soft_Persp_K = 1.5f;
  632. HeadY = 220;
  633. FogsList[0].fogRGB = 0x000000;
  634. FogsList[0].YBegin = 0;
  635. FogsList[0].Transp = 000;
  636. FogsList[0].FLimit = 000;
  637. FogsList[127].fogRGB = 0x00504000;
  638. FogsList[127].Mortal = FALSE;
  639. FogsList[127].Transp = 460;
  640. FogsList[127].FLimit = 200;
  641. FillMemory( FogsMap, sizeof(FogsMap), 0);
  642. PrintLog("Init Engine: Ok.\n");
  643. }
  644. void ShutDownEngine()
  645. {
  646. ReleaseDC(hwndMain,hdcMain);
  647. }
  648. void ProcessSyncro()
  649. {
  650. RealTime = timeGetTime();
  651. srand( (unsigned) RealTime );
  652. if (SLOW) RealTime/=4;
  653. TimeDt = RealTime - PrevTime;
  654. if (TimeDt<0) TimeDt = 10;
  655. if (TimeDt>10000) TimeDt = 10;
  656. if (TimeDt>1000) TimeDt = 1000;
  657. PrevTime = RealTime;
  658. Takt++;
  659. if (!PAUSE)
  660. if (MyHealth) MyHealth+=TimeDt*4;
  661. if (MyHealth>MAX_HEALTH) MyHealth = MAX_HEALTH;
  662. }
  663. void AddBloodTrail(TCharacter *cptr)
  664. {
  665. if (BloodTrail.Count>508) {
  666. memcpy(&BloodTrail.Trail[0], &BloodTrail.Trail[1], 510*sizeof(TBloodP));
  667. BloodTrail.Count--;
  668. }
  669. BloodTrail.Trail[BloodTrail.Count].LTime = 210000;
  670. BloodTrail.Trail[BloodTrail.Count].pos = cptr->pos;
  671. BloodTrail.Trail[BloodTrail.Count].pos.x+=siRand(32);
  672. BloodTrail.Trail[BloodTrail.Count].pos.z+=siRand(32);
  673. BloodTrail.Trail[BloodTrail.Count].pos.y =
  674. GetLandH(BloodTrail.Trail[BloodTrail.Count].pos.x,
  675. BloodTrail.Trail[BloodTrail.Count].pos.z)+4;
  676. BloodTrail.Count++;
  677. }
  678. void MakeCall()
  679. {
  680. if (!TargetDino) return;
  681. if (UNDERWATER) return;
  682. if (ObservMode || TrophyMode) return;
  683. if (CallLockTime) return;
  684. CallLockTime=1024*3;
  685. NextCall+=(RealTime % 2)+1;
  686. NextCall%=3;
  687. AddVoicev(fxCall[TargetCall-10][NextCall].length,
  688. fxCall[TargetCall-10][NextCall].lpData, 256);
  689. float dmin = 512*256;
  690. int ai = -1;
  691. for (int c=0; c<ChCount; c++) {
  692. TCharacter *cptr = &Characters[c];
  693. if (DinoInfo[AI_to_CIndex[TargetCall] ].DangerCall)
  694. if (cptr->AI<10) {
  695. cptr->State=2;
  696. cptr->AfraidTime = (10 + rRand(5)) * 1024;
  697. }
  698. if (cptr->AI!=TargetCall) continue;
  699. if (cptr->AfraidTime) continue;
  700. if (cptr->State) continue;
  701. float d = VectorLength(SubVectors(PlayerPos, cptr->pos));
  702. if (d < ctViewR * 400) {
  703. if (rRand(128) > 32)
  704. if (d<dmin) { dmin = d; ai = c; }
  705. cptr->tgx = PlayerX + siRand(1800);
  706. cptr->tgz = PlayerZ + siRand(1800);
  707. }
  708. }
  709. if (ai!=-1) {
  710. answpos = SubVectors(Characters[ai].pos, PlayerPos);
  711. answpos.x/=-3.f; answpos.y/=-3.f; answpos.z/=-3.f;
  712. answpos = SubVectors(PlayerPos, answpos);
  713. answtime = 2000 + rRand(2000);
  714. answcall = TargetCall;
  715. }
  716. }
  717. DWORD ColorSum(DWORD C1, DWORD C2)
  718. {
  719. DWORD R,G,B;
  720. R = min(255, ((C1>> 0) & 0xFF) + ((C2>> 0) & 0xFF));
  721. G = min(255, ((C1>> 8) & 0xFF) + ((C2>> 8) & 0xFF));
  722. B = min(255, ((C1>>16) & 0xFF) + ((C2>>16) & 0xFF));
  723. return R + (G<<8) + (B<<16);
  724. }
  725. #define partBlood 1
  726. #define partWater 2
  727. #define partGround 3
  728. #define partBubble 4
  729. void AddElements(float x, float y, float z, int etype, int cnt)
  730. {
  731. if (ElCount > 30) {
  732. memcpy(&Elements[0], &Elements[1], (ElCount-1) * sizeof(TElements));
  733. ElCount--;
  734. }
  735. Elements[ElCount].EDone = 0;
  736. Elements[ElCount].Type = etype;
  737. Elements[ElCount].ECount = min(30, cnt);
  738. int c;
  739. switch (etype) {
  740. case partBlood:
  741. #ifdef _d3d
  742. Elements[ElCount].RGBA = 0xE0600000;
  743. Elements[ElCount].RGBA2= 0x20300000;
  744. #else
  745. Elements[ElCount].RGBA = 0xE0000060;
  746. Elements[ElCount].RGBA2= 0x20000030;
  747. #endif
  748. break;
  749. case partGround:
  750. #ifdef _d3d
  751. Elements[ElCount].RGBA = 0xF0F09E55;
  752. Elements[ElCount].RGBA2= 0x10F09E55;
  753. #else
  754. Elements[ElCount].RGBA = 0xF0559EF0;
  755. Elements[ElCount].RGBA2= 0x10559EF0;
  756. #endif
  757. break;
  758. case partBubble:
  759. c = WaterList[ WMap[ (int)z / 256][ (int)x / 256] ].fogRGB;
  760. #ifdef _d3d
  761. c = ColorSum( ((c & 0xFEFEFE)>>1) , 0x152020);
  762. #else
  763. c = ColorSum( ((c & 0xFEFEFE)>>1) , 0x202015);
  764. #endif
  765. Elements[ElCount].RGBA = 0x70000000 + (ColorSum(c, ColorSum(c,c)));
  766. Elements[ElCount].RGBA2= 0x40000000 + (ColorSum(c, c));
  767. break;
  768. case partWater:
  769. c = WaterList[ WMap[ (int)z / 256][ (int)x / 256] ].fogRGB;
  770. #ifdef _d3d
  771. c = ColorSum( ((c & 0xFEFEFE)>>1) , 0x152020);
  772. #else
  773. c = ColorSum( ((c & 0xFEFEFE)>>1) , 0x202015);
  774. #endif
  775. Elements[ElCount].RGBA = 0xB0000000 + ( ColorSum(c, ColorSum(c,c)) );
  776. Elements[ElCount].RGBA2 = 0x40000000 + (c);
  777. break;
  778. }
  779. Elements[ElCount].RGBA = conv_xGx(Elements[ElCount].RGBA);
  780. Elements[ElCount].RGBA2 = conv_xGx(Elements[ElCount].RGBA2);
  781. float al = siRand(128) / 128.f * pi / 4.f;
  782. float ss = f_sin(al);
  783. float cc = f_cos(al);
  784. for (int e=0; e<Elements[ElCount].ECount; e++) {
  785. Elements[ElCount].EList[e].pos.x = x;
  786. Elements[ElCount].EList[e].pos.y = y;
  787. Elements[ElCount].EList[e].pos.z = z;
  788. Elements[ElCount].EList[e].R = 6 + rRand(5);
  789. Elements[ElCount].EList[e].Flags = 0;
  790. float v;
  791. switch (etype) {
  792. case partBlood:
  793. v = e * 6 + rRand(96) + 220;
  794. Elements[ElCount].EList[e].speed.x =ss*ca*v + siRand(32);
  795. Elements[ElCount].EList[e].speed.y =cc * (v * 3);
  796. Elements[ElCount].EList[e].speed.z =ss*sa*v + siRand(32);
  797. break;
  798. case partGround:
  799. Elements[ElCount].EList[e].speed.x =siRand(52)-sa*64;
  800. Elements[ElCount].EList[e].speed.y =rRand(100) + 600 + e * 20;
  801. Elements[ElCount].EList[e].speed.z =siRand(52)+ca*64;
  802. break;
  803. case partWater:
  804. Elements[ElCount].EList[e].speed.x =siRand(32);
  805. Elements[ElCount].EList[e].speed.y =rRand(80) + 400 + e * 40;
  806. Elements[ElCount].EList[e].speed.z =siRand(32);
  807. break;
  808. case partBubble:
  809. Elements[ElCount].EList[e].speed.x =siRand(40);
  810. Elements[ElCount].EList[e].speed.y =rRand(140) + 20;
  811. Elements[ElCount].EList[e].speed.z =siRand(40);
  812. break;
  813. }
  814. }
  815. ElCount++;
  816. }
  817. void MakeShot(float ax, float ay, float az,
  818. float bx, float by, float bz)
  819. {
  820. int sres;
  821. if (!WeapInfo[CurrentWeapon].Fall)
  822. sres = TraceShot(ax, ay, az, bx, by, bz);
  823. else {
  824. Vector3d dl;
  825. float dy = 40.f * ctViewR / 36.f;
  826. dl.x = (bx-ax) / 3;
  827. dl.y = (by-ay) / 3;
  828. dl.z = (bz-az) / 3;
  829. bx = ax + dl.x;
  830. by = ay + dl.y - dy / 2;
  831. bz = az + dl.z;
  832. sres = TraceShot(ax, ay, az, bx, by, bz);
  833. if (sres!=-1) goto ENDTRACE;
  834. ax = bx; ay = by; az = bz;
  835. bx = ax + dl.x;
  836. by = ay + dl.y - dy * 3;
  837. bz = az + dl.z;
  838. sres = TraceShot(ax, ay, az, bx, by, bz);
  839. if (sres!=-1) goto ENDTRACE;
  840. ax = bx; ay = by; az = bz;
  841. bx = ax + dl.x;
  842. by = ay + dl.y - dy * 5;
  843. bz = az + dl.z;
  844. sres = TraceShot(ax, ay, az, bx, by, bz);
  845. if (sres!=-1) goto ENDTRACE;
  846. ax = bx; ay = by; az = bz;
  847. }
  848. ENDTRACE:
  849. if (sres==-1) return;
  850. int mort = (sres & 0xFF00) && (Characters[ShotDino].Health);
  851. sres &= 0xFF;
  852. if (sres == tresGround)
  853. AddElements(bx, by, bz, partGround, 6 + WeapInfo[CurrentWeapon].Power*4);
  854. if (sres == tresModel)
  855. AddElements(bx, by, bz, partGround, 6 + WeapInfo[CurrentWeapon].Power*4);
  856. if (sres == tresWater) {
  857. AddElements(bx, by, bz, partWater, 4 + WeapInfo[CurrentWeapon].Power*3);
  858. //AddElements(bx, GetLandH(bx, bz), bz, partBubble);
  859. AddWCircle(bx, bz, 1.2);
  860. AddWCircle(bx, bz, 1.2);
  861. }
  862. if (sres!=tresChar) return;
  863. AddElements(bx, by, bz, partBlood, 4 + WeapInfo[CurrentWeapon].Power*4);
  864. if (!Characters[ShotDino].Health) return;
  865. //======= character damage =========//
  866. if (mort) Characters[ShotDino].Health = 0;
  867. else Characters[ShotDino].Health-=WeapInfo[CurrentWeapon].Power;
  868. if (Characters[ShotDino].Health<0) Characters[ShotDino].Health=0;
  869. if (!Characters[ShotDino].Health) {
  870. if (Characters[ShotDino].AI>=10) {
  871. TrophyRoom.Last.success++;
  872. AddShipTask(ShotDino);
  873. }
  874. if (Characters[ShotDino].AI<10)
  875. Characters_AddSecondaryOne(Characters[ShotDino].CType);
  876. }
  877. else {
  878. Characters[ShotDino].AfraidTime = 60*1000;
  879. if (Characters[ShotDino].State==0)
  880. Characters[ShotDino].State = 2;
  881. Characters[ShotDino].BloodTTime+=90000;
  882. }
  883. }
  884. void RemoveCharacter(int index)
  885. {
  886. if (index==-1) return;
  887. memcpy( &Characters[index], &Characters[index+1], (255 - index) * sizeof(TCharacter) );
  888. ChCount--;
  889. if (DemoPoint.CIndex > index) DemoPoint.CIndex--;
  890. for (int c=0; c<ShipTask.tcount; c++)
  891. if (ShipTask.clist[c]>index) ShipTask.clist[c]--;
  892. }
  893. void AnimateShip()
  894. {
  895. if (Ship.State==-1) {
  896. SetAmbient3d(0,0, 0,0,0);
  897. if (!ShipTask.tcount) return;
  898. InitShip(ShipTask.clist[0]);
  899. memcpy(&ShipTask.clist[0], &ShipTask.clist[1], 250*4);
  900. ShipTask.tcount--;
  901. return;
  902. }
  903. SetAmbient3d(ShipModel.SoundFX[0].length,
  904. ShipModel.SoundFX[0].lpData,
  905. Ship.pos.x, Ship.pos.y, Ship.pos.z);
  906. int _TimeDt = TimeDt;
  907. //====== get up/down time acceleration ===========//
  908. if (Ship.FTime) {
  909. int am = ShipModel.Animation[0].AniTime;
  910. if (Ship.FTime < 500) _TimeDt = TimeDt * (Ship.FTime + 48) / 548;
  911. if (am-Ship.FTime < 500) _TimeDt = TimeDt * (am-Ship.FTime + 48) / 548;
  912. if (_TimeDt<2) _TimeDt=2;
  913. }
  914. //===================================
  915. float L = VectorLength( SubVectors(Ship.tgpos, Ship.pos) );
  916. float L2 = sqrt ( (Ship.tgpos.x - Ship.pos.x) * (Ship.tgpos.x - Ship.pos.x) +
  917. (Ship.tgpos.x - Ship.pos.x) * (Ship.tgpos.x - Ship.pos.x) );
  918. Ship.pos.y+=0.3f*(float)f_cos(RealTime / 256.f);
  919. Ship.tgalpha = FindVectorAlpha(Ship.tgpos.x - Ship.pos.x, Ship.tgpos.z - Ship.pos.z);
  920. float currspeed;
  921. float dalpha = (float)fabs(Ship.tgalpha - Ship.alpha);
  922. float drspd = dalpha; if (drspd>pi) drspd = 2*pi - drspd;
  923. //====== fly more away if I near =============//
  924. if (Ship.State)
  925. if (Ship.speed>1)
  926. if (L<4000)
  927. if (VectorLength(SubVectors(PlayerPos, Ship.pos))<(ctViewR+2)*256) {
  928. Ship.tgpos.x += (float)f_cos(Ship.alpha) * 256*6.f;
  929. Ship.tgpos.z += (float)f_sin(Ship.alpha) * 256*6.f;
  930. Ship.tgpos.y = GetLandUpH(Ship.tgpos.x, Ship.tgpos.z) + Ship.DeltaY;
  931. Ship.tgpos.y = max(Ship.tgpos.y, GetLandUpH(Ship.pos.x, Ship.pos.z) + Ship.DeltaY);
  932. }
  933. //==============================//
  934. //========= animate down ==========//
  935. if (Ship.State==3) {
  936. Ship.FTime+=_TimeDt;
  937. if (Ship.FTime>=ShipModel.Animation[0].AniTime) {
  938. Ship.FTime=ShipModel.Animation[0].AniTime-1;
  939. Ship.State=2;
  940. AddVoicev(ShipModel.SoundFX[4].length,
  941. ShipModel.SoundFX[4].lpData, 256);
  942. AddVoice3d(ShipModel.SoundFX[1].length, ShipModel.SoundFX[1].lpData,
  943. Ship.pos.x, Ship.pos.y, Ship.pos.z);
  944. }
  945. return;
  946. }
  947. //========= get body on board ==========//
  948. if (Ship.State) {
  949. if (Ship.cindex!=-1) {
  950. DeltaFunc(Characters[Ship.cindex].pos.y, Ship.pos.y-650 - (Ship.DeltaY-2048), _TimeDt / 3.f);
  951. DeltaFunc(Characters[Ship.cindex].beta, 0, TimeDt / 4048.f);
  952. DeltaFunc(Characters[Ship.cindex].gamma, 0, TimeDt / 4048.f);
  953. }
  954. if (Ship.State==2) {
  955. Ship.FTime-=_TimeDt;
  956. if (Ship.FTime<0) Ship.FTime=0;
  957. if (Ship.FTime==0)
  958. if (fabs(Characters[Ship.cindex].pos.y - (Ship.pos.y-650 - (Ship.DeltaY-2048))) < 1.f) {
  959. Ship.State = 1;
  960. AddVoicev(ShipModel.SoundFX[5].length,
  961. ShipModel.SoundFX[5].lpData, 256);
  962. AddVoice3d(ShipModel.SoundFX[2].length, ShipModel.SoundFX[2].lpData,
  963. Ship.pos.x, Ship.pos.y, Ship.pos.z);
  964. }
  965. return;
  966. }
  967. }
  968. //=====================================//
  969. //====== speed ===============//
  970. float vspeed = 1.f + L / 128.f;
  971. if (vspeed > 24) vspeed = 24;
  972. if (Ship.State) vspeed = 24;
  973. if (fabs(dalpha) > 0.4) vspeed = 0.f;
  974. float _s = Ship.speed;
  975. if (vspeed>Ship.speed) DeltaFunc(Ship.speed, vspeed, TimeDt / 200.f);
  976. else Ship.speed = vspeed;
  977. if (Ship.speed>0 && _s==0)
  978. AddVoice3d(ShipModel.SoundFX[2].length, ShipModel.SoundFX[2].lpData,
  979. Ship.pos.x, Ship.pos.y, Ship.pos.z);
  980. //====== fly ===========//
  981. float l = TimeDt * Ship.speed / 16.f;
  982. if (fabs(dalpha) < 0.4)
  983. if (l<L) {
  984. if (l>L2) l = L2 * 0.5f;
  985. if (L2<0.1) l = 0;
  986. Ship.pos.x += (float)f_cos(Ship.alpha)*l;
  987. Ship.pos.z += (float)f_sin(Ship.alpha)*l;
  988. } else {
  989. if (Ship.State) {
  990. Ship.State = -1;
  991. RemoveCharacter(Ship.cindex);
  992. return;
  993. } else {
  994. Ship.pos = Ship.tgpos;
  995. Ship.State = 3;
  996. Ship.FTime = 1;
  997. Ship.tgpos = Ship.retpos;
  998. Ship.tgpos.y = GetLandUpH(Ship.tgpos.x, Ship.tgpos.z) + Ship.DeltaY;
  999. Ship.tgpos.y = max(Ship.tgpos.y, GetLandUpH(Ship.pos.x, Ship.pos.z) + Ship.DeltaY);
  1000. Characters[Ship.cindex].StateF = 0xFF;
  1001. AddVoice3d(ShipModel.SoundFX[1].length, ShipModel.SoundFX[1].lpData,
  1002. Ship.pos.x, Ship.pos.y, Ship.pos.z);
  1003. }
  1004. }
  1005. //======= y movement ============//
  1006. float h = GetLandUpH(Ship.pos.x, Ship.pos.z);
  1007. DeltaFunc(Ship.pos.y, Ship.tgpos.y, TimeDt / 4.f);
  1008. if (Ship.pos.y < h + 1024) {
  1009. if (Ship.State)
  1010. if (Ship.cindex!=-1)
  1011. Characters[Ship.cindex].pos.y+= h + 1024 - Ship.pos.y;
  1012. Ship.pos.y = h + 1024;
  1013. }
  1014. //======= rotation ============//
  1015. if (Ship.tgalpha > Ship.alpha) currspeed = 0.1f + (float)fabs(drspd)/2.f;
  1016. else currspeed =-0.1f - (float)fabs(drspd)/2.f;
  1017. if (fabs(dalpha) > pi) currspeed=-currspeed;
  1018. DeltaFunc(Ship.rspeed, currspeed, (float)TimeDt / 420.f);
  1019. float rspd=Ship.rspeed * TimeDt / 1024.f;
  1020. if (fabs(drspd) < fabs(rspd)) { Ship.alpha = Ship.tgalpha; Ship.rspeed/=2; }
  1021. else {
  1022. Ship.alpha+=rspd;
  1023. if (Ship.State)
  1024. if (Ship.cindex!=-1)
  1025. Characters[Ship.cindex].alpha+=rspd;
  1026. }
  1027. if (Ship.alpha<0) Ship.alpha+=pi*2;
  1028. if (Ship.alpha>pi*2) Ship.alpha-=pi*2;
  1029. //======== move body ===========//
  1030. if (Ship.State) {
  1031. if (Ship.cindex!=-1) {
  1032. Characters[Ship.cindex].pos.x = Ship.pos.x;
  1033. Characters[Ship.cindex].pos.z = Ship.pos.z;
  1034. }
  1035. if (L>1000) Ship.tgpos.y+=TimeDt / 12.f;
  1036. } else {
  1037. Ship.tgpos.x = Characters[Ship.cindex].pos.x;
  1038. Ship.tgpos.z = Characters[Ship.cindex].pos.z;
  1039. Ship.tgpos.y = GetLandUpH(Ship.tgpos.x, Ship.tgpos.z) + Ship.DeltaY;
  1040. Ship.tgpos.y = max(Ship.tgpos.y, GetLandUpH(Ship.pos.x, Ship.pos.z) + Ship.DeltaY);
  1041. }
  1042. }
  1043. void ProcessTrophy()
  1044. {
  1045. TrophyBody = -1;
  1046. for (int c=0; c<ChCount; c++) {
  1047. Vector3d p = Characters[c].pos;
  1048. p.x+=Characters[c].lookx * 256*2.5f;
  1049. p.z+=Characters[c].lookz * 256*2.5f;
  1050. if (VectorLength( SubVectors(p, PlayerPos) ) < 148)
  1051. TrophyBody = c;
  1052. }
  1053. if (TrophyBody==-1) return;
  1054. TrophyBody = Characters[TrophyBody].State;
  1055. }
  1056. void RespawnSnow(int s, BOOL rand)
  1057. {
  1058. Snow[s].pos.x = PlayerX + siRand(12*256);
  1059. Snow[s].pos.z = PlayerZ + siRand(12*256);
  1060. Snow[s].hl = GetLandUpH(Snow[s].pos.x, Snow[s].pos.z);
  1061. Snow[s].ftime = 0;
  1062. if (rand) Snow[s].pos.y = Snow[s].hl + 256+rRand(12*256);
  1063. else Snow[s].pos.y = Snow[s].hl + (8+rRand(5))*256;
  1064. }
  1065. void AnimateElements()
  1066. {
  1067. for (int eg=0; eg<ElCount; eg++) {
  1068. if (Elements[eg].Type == partGround) {
  1069. int a1 = Elements[eg].RGBA >> 24; a1-=TimeDt/4; if (a1<0) a1=0; Elements[eg].RGBA = (Elements[eg].RGBA & 0x00FFFFFF) + (a1<<24);
  1070. int a2 = Elements[eg].RGBA2>> 24; a2-=TimeDt/4; if (a2<0) a2=0; Elements[eg].RGBA2= (Elements[eg].RGBA2 & 0x00FFFFFF) + (a2<<24);
  1071. if (a1 == 0 && a2==0) Elements[eg].ECount = 0;
  1072. }
  1073. if (Elements[eg].Type == partWater)
  1074. if (Elements[eg].EDone == Elements[eg].ECount)
  1075. Elements[eg].ECount = 0;
  1076. if (Elements[eg].Type == partBubble)
  1077. if (Elements[eg].EDone == Elements[eg].ECount)
  1078. Elements[eg].ECount = 0;
  1079. if (Elements[eg].Type == partBlood)
  1080. if ((Takt & 3)==0)
  1081. if (Elements[eg].EDone == Elements[eg].ECount) {
  1082. int a1 = Elements[eg].RGBA >> 24; a1--; if (a1<0) a1=0; Elements[eg].RGBA = (Elements[eg].RGBA & 0x00FFFFFF) + (a1<<24);
  1083. int a2 = Elements[eg].RGBA2>> 24; a2--; if (a2<0) a2=0; Elements[eg].RGBA2= (Elements[eg].RGBA2 & 0x00FFFFFF) + (a2<<24);
  1084. if (a1 == 0 && a2==0) Elements[eg].ECount = 0;
  1085. }
  1086. //====== remove finished process =========//
  1087. if (!Elements[eg].ECount) {
  1088. memcpy(&Elements[eg], &Elements[eg+1], (ElCount+1-eg) * sizeof(TElements));
  1089. ElCount--;
  1090. eg--;
  1091. continue;
  1092. }
  1093. for (int e=0; e<Elements[eg].ECount; e++) {
  1094. if (Elements[eg].EList[e].Flags) continue;
  1095. Elements[eg].EList[e].pos.x+=Elements[eg].EList[e].speed.x * TimeDt / 1000.f;
  1096. Elements[eg].EList[e].pos.y+=Elements[eg].EList[e].speed.y * TimeDt / 1000.f;
  1097. Elements[eg].EList[e].pos.z+=Elements[eg].EList[e].speed.z * TimeDt / 1000.f;
  1098. float h;
  1099. h = GetLandUpH(Elements[eg].EList[e].pos.x, Elements[eg].EList[e].pos.z);
  1100. BOOL OnWater = GetLandH(Elements[eg].EList[e].pos.x, Elements[eg].EList[e].pos.z) < h;
  1101. switch (Elements[eg].Type) {
  1102. case partBubble:
  1103. Elements[eg].EList[e].speed.y += 2.0 * 256 * TimeDt / 1000.f;
  1104. if (Elements[eg].EList[e].speed.y > 824) Elements[eg].EList[e].speed.y = 824;
  1105. if (Elements[eg].EList[e].pos.y > h) {
  1106. AddWCircle(Elements[eg].EList[e].pos.x, Elements[eg].EList[e].pos.z, 0.6);
  1107. Elements[eg].EDone++;
  1108. Elements[eg].EList[e].Flags = 1;
  1109. if (OnWater) Elements[eg].EList[e].pos.y-= 10240;
  1110. }
  1111. break;
  1112. default:
  1113. Elements[eg].EList[e].speed.y -= 9.8 * 256 * TimeDt / 1000.f;
  1114. if (Elements[eg].EList[e].pos.y < h) {
  1115. if (OnWater) AddWCircle(Elements[eg].EList[e].pos.x, Elements[eg].EList[e].pos.z, 0.6);
  1116. Elements[eg].EDone++;
  1117. Elements[eg].EList[e].Flags = 1;
  1118. if (OnWater) Elements[eg].EList[e].pos.y-= 10240;
  1119. else Elements[eg].EList[e].pos.y = h + 4;
  1120. }
  1121. break;
  1122. } //== switch ==//
  1123. } // for(e) //
  1124. } // for(eg) //
  1125. for (int b=0; b<BloodTrail.Count; b++) {
  1126. BloodTrail.Trail[b].LTime-=TimeDt;
  1127. if (BloodTrail.Trail[b].LTime<=0) {
  1128. memcpy(&BloodTrail.Trail[b], &BloodTrail.Trail[b+1], (511-b)*sizeof(TBloodP));
  1129. BloodTrail.Count--;
  1130. b--;
  1131. }
  1132. }
  1133. if (!SNOW) return;
  1134. while (SnCount<2000) {
  1135. RespawnSnow(SnCount, TRUE);
  1136. SnCount++;
  1137. }
  1138. nv = Wind.nv;
  1139. NormVector(nv, (4+Wind.speed)*4*TimeDt/1000);
  1140. for (int s=0; s<SnCount; s++) {
  1141. if ( (fabs(Snow[s].pos.x - PlayerX) > 14*256) ||
  1142. (fabs(Snow[s].pos.z - PlayerZ) > 14*256) ) {
  1143. Snow[s].pos.x = PlayerX + siRand(12*256);
  1144. Snow[s].pos.z = PlayerZ + siRand(12*256);
  1145. Snow[s].pos.y = Snow[s].pos.y - Snow[s].hl;
  1146. Snow[s].hl = GetLandUpH(Snow[s].pos.x, Snow[s].pos.z);
  1147. Snow[s].pos.y+=Snow[s].hl;
  1148. }
  1149. if (!Snow[s].ftime) {
  1150. float v = ( ((RealTime + s * 23) % 800) - 400) * TimeDt / 16000;
  1151. Snow[s].pos.x+=ca*v;
  1152. Snow[s].pos.z+=sa*v;
  1153. Snow[s].pos = AddVectors(Snow[s].pos, nv);
  1154. Snow[s].hl = GetLandUpH(Snow[s].pos.x, Snow[s].pos.z);
  1155. Snow[s].pos.y-=TimeDt*192/1000.f;
  1156. if (Snow[s].pos.y < Snow[s].hl+8) {
  1157. Snow[s].pos.y = Snow[s].hl+8;
  1158. Snow[s].ftime = 1;
  1159. }
  1160. } else {
  1161. Snow[s].ftime+=TimeDt;
  1162. Snow[s].pos.y-=TimeDt*3/1000.f;
  1163. if (Snow[s].ftime>2000) RespawnSnow(s, FALSE);
  1164. }
  1165. }
  1166. }
  1167. void AnimateProcesses()
  1168. {
  1169. AnimateElements();
  1170. if ((Takt & 63)==0) {
  1171. float al2 = CameraAlpha + siRand(60) * pi / 180.f;
  1172. float c2 = f_cos(al2);
  1173. float s2 = f_sin(al2);
  1174. float l = 1024 + rRand(3120);
  1175. float xx = CameraX + s2 * l;
  1176. float zz = CameraZ - c2 * l;
  1177. if (GetLandUpH(xx,zz) > GetLandH(xx,zz)+256)
  1178. AddElements(xx, GetLandH(xx,zz), zz, 4, 6 + rRand(6));
  1179. }
  1180. if (Takt & 1) {
  1181. Wind.alpha+=siRand(16) / 4096.f;
  1182. Wind.speed+=siRand(400) / 6400.f;
  1183. }
  1184. if (Wind.speed< 4.f) Wind.speed=4.f;
  1185. if (Wind.speed>18.f) Wind.speed=18.f;
  1186. Wind.nv.x = (float) f_sin(Wind.alpha);
  1187. Wind.nv.z = (float)-f_cos(Wind.alpha);
  1188. Wind.nv.y = 0.f;
  1189. if (answtime) {
  1190. answtime-=TimeDt;
  1191. if (answtime<=0) {
  1192. answtime = 0;
  1193. int r = rRand(128) % 3;
  1194. AddVoice3d(fxCall[answcall-10][r].length, fxCall[answcall-10][r].lpData,
  1195. answpos.x, answpos.y, answpos.z);
  1196. }
  1197. }
  1198. if (CallLockTime) {
  1199. CallLockTime-=TimeDt;
  1200. if (CallLockTime<0) CallLockTime=0;
  1201. }
  1202. CheckAfraid();
  1203. AnimateShip();
  1204. if (TrophyMode)
  1205. ProcessTrophy();
  1206. for (int w=0; w<WCCount; w++) {
  1207. if (WCircles[w].scale > 1)
  1208. WCircles[w].FTime+=(int)(TimeDt*3 / WCircles[w].scale);
  1209. else
  1210. WCircles[w].FTime+=TimeDt*3;
  1211. if (WCircles[w].FTime >= 2000) {
  1212. memcpy(&WCircles[w], &WCircles[w+1], sizeof(TWCircle) * (WCCount+1-w) );
  1213. w--;
  1214. WCCount--;
  1215. }
  1216. }
  1217. if (ExitTime) {
  1218. ExitTime-=TimeDt;
  1219. if (ExitTime<=0) {
  1220. TrophyRoom.Total.time +=TrophyRoom.Last.time;
  1221. TrophyRoom.Total.smade +=TrophyRoom.Last.smade;
  1222. TrophyRoom.Total.success+=TrophyRoom.Last.success;
  1223. TrophyRoom.Total.path +=TrophyRoom.Last.path;
  1224. if (MyHealth) SaveTrophy();
  1225. else LoadTrophy();
  1226. DoHalt("");
  1227. }
  1228. }
  1229. }
  1230. void RemoveCurrentTrophy()
  1231. {
  1232. int p = 0;
  1233. if (!TrophyMode) return;
  1234. if (!TrophyRoom.Body[TrophyBody].ctype) return;
  1235. PrintLog("Trophy removed: ");
  1236. PrintLog(DinoInfo[TrophyRoom.Body[TrophyBody].ctype].Name);
  1237. PrintLog("\n");
  1238. for (int c=0; c<TrophyBody; c++)
  1239. if (TrophyRoom.Body[c].ctype) p++;
  1240. TrophyRoom.Body[TrophyBody].ctype = 0;
  1241. if (TrophyMode) {
  1242. memcpy(&Characters[p],
  1243. &Characters[p+1],
  1244. (250-p) * sizeof(TCharacter) );
  1245. ChCount--;
  1246. }
  1247. TrophyTime = 0;
  1248. TrophyBody = -1;
  1249. }
  1250. void LoadTrophy()
  1251. {
  1252. int pr = TrophyRoom.RegNumber;
  1253. FillMemory(&TrophyRoom, sizeof(TrophyRoom), 0);
  1254. TrophyRoom.RegNumber = pr;
  1255. DWORD l;
  1256. char fname[128];
  1257. int rn = TrophyRoom.RegNumber;
  1258. wsprintf(fname, "trophy0%d.sav", TrophyRoom.RegNumber);
  1259. HANDLE hfile = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1260. if (hfile==INVALID_HANDLE_VALUE) {
  1261. PrintLog("===> Error loading trophy!\n");
  1262. return;
  1263. }
  1264. ReadFile(hfile, &TrophyRoom, sizeof(TrophyRoom), &l, NULL);
  1265. ReadFile(hfile, &OptAgres, 4, &l, NULL);
  1266. ReadFile(hfile, &OptDens , 4, &l, NULL);
  1267. ReadFile(hfile, &OptSens , 4, &l, NULL);
  1268. ReadFile(hfile, &OptRes, 4, &l, NULL);
  1269. ReadFile(hfile, &FOGENABLE, 4, &l, NULL);
  1270. ReadFile(hfile, &OptText , 4, &l, NULL);
  1271. ReadFile(hfile, &OptViewR, 4, &l, NULL);
  1272. ReadFile(hfile, &SHADOWS3D, 4, &l, NULL);
  1273. ReadFile(hfile, &OptMsSens, 4, &l, NULL);
  1274. ReadFile(hfile, &OptBrightness, 4, &l, NULL);
  1275. ReadFile(hfile, &KeyMap, sizeof(KeyMap), &l, NULL);
  1276. ReadFile(hfile, &REVERSEMS, 4, &l, NULL);
  1277. ReadFile(hfile, &ScentMode, 4, &l, NULL);
  1278. ReadFile(hfile, &CamoMode, 4, &l, NULL);
  1279. ReadFile(hfile, &RadarMode, 4, &l, NULL);
  1280. ReadFile(hfile, &Tranq , 4, &l, NULL);
  1281. ReadFile(hfile, &OPT_ALPHA_COLORKEY, 4, &l, NULL);
  1282. ReadFile(hfile, &OptSys , 4, &l, NULL);
  1283. ReadFile(hfile, &OptSound , 4, &l, NULL);
  1284. ReadFile(hfile, &OptRender, 4, &l, NULL);
  1285. SetupRes();
  1286. CloseHandle(hfile);
  1287. TrophyRoom.RegNumber = rn;
  1288. PrintLog("Trophy Loaded.\n");
  1289. // TrophyRoom.Score = 299;
  1290. }
  1291. void SaveTrophy()
  1292. {
  1293. DWORD l;
  1294. char fname[128];
  1295. wsprintf(fname, "trophy0%d.sav", TrophyRoom.RegNumber);
  1296. int r = TrophyRoom.Rank;
  1297. TrophyRoom.Rank = 0;
  1298. if (TrophyRoom.Score >= 100) TrophyRoom.Rank = 1;
  1299. if (TrophyRoom.Score >= 300) TrophyRoom.Rank = 2;
  1300. HANDLE hfile = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1301. if (hfile == INVALID_HANDLE_VALUE) {
  1302. PrintLog("==>> Error saving trophy!\n");
  1303. return;
  1304. }
  1305. WriteFile(hfile, &TrophyRoom, sizeof(TrophyRoom), &l, NULL);
  1306. WriteFile(hfile, &OptAgres, 4, &l, NULL);
  1307. WriteFile(hfile, &OptDens , 4, &l, NULL);
  1308. WriteFile(hfile, &OptSens , 4, &l, NULL);
  1309. WriteFile(hfile, &OptRes, 4, &l, NULL);
  1310. WriteFile(hfile, &FOGENABLE, 4, &l, NULL);
  1311. WriteFile(hfile, &OptText , 4, &l, NULL);
  1312. WriteFile(hfile, &OptViewR, 4, &l, NULL);
  1313. WriteFile(hfile, &SHADOWS3D, 4, &l, NULL);
  1314. WriteFile(hfile, &OptMsSens, 4, &l, NULL);
  1315. WriteFile(hfile, &OptBrightness, 4, &l, NULL);
  1316. WriteFile(hfile, &KeyMap, sizeof(KeyMap), &l, NULL);
  1317. WriteFile(hfile, &REVERSEMS, 4, &l, NULL);
  1318. WriteFile(hfile, &ScentMode, 4, &l, NULL);
  1319. WriteFile(hfile, &CamoMode , 4, &l, NULL);
  1320. WriteFile(hfile, &RadarMode, 4, &l, NULL);
  1321. WriteFile(hfile, &Tranq , 4, &l, NULL);
  1322. WriteFile(hfile, &OPT_ALPHA_COLORKEY, 4, &l, NULL);
  1323. WriteFile(hfile, &OptSys , 4, &l, NULL);
  1324. WriteFile(hfile, &OptSound , 4, &l, NULL);
  1325. WriteFile(hfile, &OptRender, 4, &l, NULL);
  1326. CloseHandle(hfile);
  1327. PrintLog("Trophy Saved.\n");
  1328. }