BSTUB.CPP 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925
  1. /*******************************************************************************
  2. FILE: BSTUB.CPP
  3. DESCRIPTION: This file contains enhancements to the BUILD editor, both
  4. in 3d mode and 2d mode.
  5. AUTHOR: Peter M. Freese
  6. CREATED: 94/11/01
  7. COPYRIGHT: Copyright (c) 1995 Q Studios Corporation
  8. *******************************************************************************/
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdarg.h>
  13. #include <io.h>
  14. #include <fcntl.h>
  15. #include <dos.h>
  16. #include <conio.h>
  17. #include "engine.h"
  18. #include "build.h"
  19. #include "typedefs.h"
  20. #include "bstub.h"
  21. #include "db.h"
  22. #include "screen.h"
  23. #include "misc.h"
  24. #include "gameutil.h"
  25. #include "sectorfx.h"
  26. #include "globals.h"
  27. #include "key.h"
  28. #include "textio.h"
  29. #include "inifile.h"
  30. #include "helix.h"
  31. #include "debug4g.h"
  32. #include "qheap.h"
  33. #include "resource.h"
  34. #include "gui.h"
  35. #include "error.h"
  36. #include "protect.h"
  37. #include "tile.h"
  38. #include "options.h"
  39. #include "gfx.h"
  40. #include "timer.h"
  41. #include "trig.h"
  42. #include "edit2d.h"
  43. #include "mouse.h"
  44. #include "eventq.h"
  45. #include "names.h"
  46. #include <memcheck.h>
  47. /*******************************************************************************
  48. Structures and typedefs
  49. *******************************************************************************/
  50. struct NAMED_TYPE
  51. {
  52. short id;
  53. char *name;
  54. };
  55. /*******************************************************************************
  56. Global Variables
  57. *******************************************************************************/
  58. int gHighlightThreshold;
  59. int gStairHeight;
  60. int gLBIntensity;
  61. int gLBAttenuation;
  62. int gLBReflections;
  63. int gLBMaxBright;
  64. int gLBRampDist;
  65. int gPalette = kPalNormal;
  66. BOOL gBeep;
  67. BOOL gOldKeyMapping;
  68. BOOL gPanning = TRUE;
  69. char *gBoolNames[2];
  70. char *gSpriteNames[1024];
  71. char *gWallNames[1024];
  72. char *gSectorNames[1024];
  73. char *gWaveNames[16];
  74. char *gDepthNames[4];
  75. char *gCommandNames[256];
  76. char *gRespawnNames[4];
  77. int gSaveTime = 0;
  78. int gSaveInterval;
  79. /*******************************************************************************
  80. These were globals that were referenced in other parts of build.c. Ken should
  81. make these non-static.
  82. *******************************************************************************/
  83. short grid = 4, gridlock = 1;
  84. long zoom = 768;
  85. /*******************************************************************************
  86. Local Variables
  87. *******************************************************************************/
  88. static char buffer[256] = "";
  89. static EHF prevErrorHandler;
  90. // options
  91. IniFile MapEditINI("MAPEDIT.INI");
  92. char buildkeys[] =
  93. {
  94. KEY_UP,
  95. KEY_DOWN,
  96. KEY_LEFT,
  97. KEY_RIGHT,
  98. KEY_LSHIFT,
  99. KEY_RCTRL,
  100. KEY_LCTRL,
  101. KEY_SPACE,
  102. KEY_A,
  103. KEY_Z,
  104. KEY_PAGEDN,
  105. KEY_PAGEUP,
  106. KEY_PAD7,
  107. KEY_PAD9,
  108. KEY_PADENTER,
  109. KEY_ENTER,
  110. KEY_PLUS,
  111. KEY_MINUS,
  112. KEY_TAB,
  113. };
  114. static NAMED_TYPE boolNTNames[] =
  115. {
  116. 0, "Off",
  117. 1, "On",
  118. };
  119. static NAMED_TYPE spriteNTNames[] =
  120. {
  121. kNothing, "Decoration",
  122. kMarkerPlayerStart, "Player Start",
  123. kMarkerDeathStart, "Bloodbath Start",
  124. kMarkerOff, "Off marker",
  125. kMarkerOn, "On marker",
  126. kMarkerAxis, "Axis marker",
  127. kMarkerUpperLink, "Upper link",
  128. kMarkerLowerLink, "Lower link",
  129. kMarkerWarpDest, "Teleport target",
  130. kMarkerRaingen, "Rain generator",
  131. kSwitchToggle, "Toggle switch",
  132. kSwitchMomentary, "Momentary switch",
  133. kSwitchCombination, "Combination switch",
  134. kSwitchPadlock, "Padlock (1-shot)",
  135. kMiscTorch, "Torch",
  136. kMiscHangingTorch, "Hanging Torch",
  137. kWeaponItemRandom, gWeaponText[kWeaponItemRandom - kWeaponItemBase],
  138. kWeaponItemShotgun, gWeaponText[kWeaponItemShotgun - kWeaponItemBase],
  139. kWeaponItemTommyGun, gWeaponText[kWeaponItemTommyGun - kWeaponItemBase],
  140. kWeaponItemFlareGun, gWeaponText[kWeaponItemFlareGun - kWeaponItemBase],
  141. kWeaponItemVoodooDoll, gWeaponText[kWeaponItemVoodooDoll - kWeaponItemBase],
  142. kWeaponItemSpearGun, gWeaponText[kWeaponItemSpearGun - kWeaponItemBase],
  143. kWeaponItemShadowGun, gWeaponText[kWeaponItemShadowGun - kWeaponItemBase],
  144. kWeaponItemPitchfork, gWeaponText[kWeaponItemPitchfork - kWeaponItemBase],
  145. kWeaponItemSprayCan, gWeaponText[kWeaponItemSprayCan - kWeaponItemBase],
  146. kWeaponItemTNT, gWeaponText[kWeaponItemTNT - kWeaponItemBase],
  147. kAmmoItemSprayCan, gAmmoText[kAmmoItemSprayCan - kAmmoItemBase],
  148. kAmmoItemTNTStick, gAmmoText[kAmmoItemTNTStick - kAmmoItemBase],
  149. kAmmoItemTNTBundle, gAmmoText[kAmmoItemTNTBundle - kAmmoItemBase],
  150. kAmmoItemTNTCase, gAmmoText[kAmmoItemTNTCase - kAmmoItemBase],
  151. kAmmoItemTNTProximity, gAmmoText[kAmmoItemTNTProximity - kAmmoItemBase],
  152. kAmmoItemTNTRemote, gAmmoText[kAmmoItemTNTRemote - kAmmoItemBase],
  153. kAmmoItemTNTTimer, gAmmoText[kAmmoItemTNTTimer - kAmmoItemBase],
  154. kAmmoItemShells, gAmmoText[kAmmoItemShells - kAmmoItemBase],
  155. kAmmoItemShellBox, gAmmoText[kAmmoItemShellBox - kAmmoItemBase],
  156. kAmmoItemBullets, gAmmoText[kAmmoItemBullets - kAmmoItemBase],
  157. kAmmoItemBulletBox, gAmmoText[kAmmoItemBulletBox - kAmmoItemBase],
  158. kAmmoItemAPBullets, gAmmoText[kAmmoItemAPBullets - kAmmoItemBase],
  159. kAmmoItemTommyDrum, gAmmoText[kAmmoItemTommyDrum - kAmmoItemBase],
  160. kAmmoItemSpear, gAmmoText[kAmmoItemSpear - kAmmoItemBase],
  161. kAmmoItemSpearPack, gAmmoText[kAmmoItemSpearPack - kAmmoItemBase],
  162. kAmmoItemHESpears, gAmmoText[kAmmoItemHESpears - kAmmoItemBase],
  163. kAmmoItemFlares, gAmmoText[kAmmoItemFlares - kAmmoItemBase],
  164. kAmmoItemHEFlares, gAmmoText[kAmmoItemHEFlares - kAmmoItemBase],
  165. kAmmoItemStarFlares, gAmmoText[kAmmoItemStarFlares - kAmmoItemBase],
  166. kAmmoItemRandom, "Random Ammo",
  167. kItemKey1, gItemText[kItemKey1 - kItemBase],
  168. kItemKey2, gItemText[kItemKey2 - kItemBase],
  169. kItemKey3, gItemText[kItemKey3 - kItemBase],
  170. kItemKey4, gItemText[kItemKey4 - kItemBase],
  171. kItemKey5, gItemText[kItemKey5 - kItemBase],
  172. kItemKey6, gItemText[kItemKey6 - kItemBase],
  173. kItemKey7, gItemText[kItemKey7 - kItemBase],
  174. kItemDoctorBag, gItemText[kItemDoctorBag - kItemBase],
  175. kItemMedPouch, gItemText[kItemMedPouch - kItemBase],
  176. kItemLifeEssence, gItemText[kItemLifeEssence - kItemBase],
  177. kItemLifeSeed, gItemText[kItemLifeSeed - kItemBase],
  178. kItemPotion1, gItemText[kItemPotion1 - kItemBase],
  179. kItemFeatherFall, gItemText[kItemFeatherFall - kItemBase],
  180. kItemLtdInvisibility, gItemText[kItemLtdInvisibility - kItemBase],
  181. kItemInvulnerability, gItemText[kItemInvulnerability - kItemBase],
  182. kItemJumpBoots, gItemText[kItemJumpBoots - kItemBase],
  183. kItemRavenFlight, gItemText[kItemRavenFlight - kItemBase],
  184. kItemGunsAkimbo, gItemText[kItemGunsAkimbo - kItemBase],
  185. kItemDivingSuit, gItemText[kItemDivingSuit - kItemBase],
  186. kItemGasMask, gItemText[kItemGasMask - kItemBase],
  187. kItemClone, gItemText[kItemClone - kItemBase],
  188. kItemCrystalBall, gItemText[kItemCrystalBall - kItemBase],
  189. kItemDecoy, gItemText[kItemDecoy - kItemBase],
  190. kItemDoppleganger, gItemText[kItemDoppleganger - kItemBase],
  191. kItemReflectiveShots, gItemText[kItemReflectiveShots - kItemBase],
  192. kItemRoseGlasses, gItemText[kItemRoseGlasses - kItemBase],
  193. kItemShadowCloak, gItemText[kItemShadowCloak - kItemBase],
  194. kItemShroomRage, gItemText[kItemShroomRage - kItemBase],
  195. kItemShroomDelirium, gItemText[kItemShroomDelirium - kItemBase],
  196. kItemShroomGrow, gItemText[kItemShroomGrow - kItemBase],
  197. kItemShroomShrink, gItemText[kItemShroomShrink - kItemBase],
  198. kItemDeathMask, gItemText[kItemDeathMask - kItemBase],
  199. kItemWineGoblet, gItemText[kItemWineGoblet - kItemBase],
  200. kItemWineBottle, gItemText[kItemWineBottle - kItemBase],
  201. kItemSkullGrail, gItemText[kItemSkullGrail - kItemBase],
  202. kItemSilverGrail, gItemText[kItemSilverGrail - kItemBase],
  203. kItemTome, gItemText[kItemTome - kItemBase],
  204. kItemBlackChest, gItemText[kItemBlackChest - kItemBase],
  205. kItemWoodenChest, gItemText[kItemWoodenChest - kItemBase],
  206. kItemAsbestosArmor, gItemText[kItemAsbestosArmor - kItemBase],
  207. kItemRandom, "Random Item",
  208. kDudeRandom, "Random Creature",
  209. kDudeTommyCultist, "Cultist w/Tommy",
  210. kDudeShotgunCultist, "Cultist w/Shotgun",
  211. kDudeAxeZombie, "Axe Zombie",
  212. kDudeFatZombie, "Fat Zombie",
  213. kDudeEarthZombie, "Earth Zombie",
  214. kDudeFleshGargoyle, "Flesh Gargoyle",
  215. kDudeStoneGargoyle, "Stone Gargoyle",
  216. kDudeFleshStatue, "Flesh Statue",
  217. kDudeStoneStatue, "Stone Statue",
  218. kDudePhantasm, "Phantasm",
  219. kDudeHound, "Hound",
  220. kDudeHand, "Hand",
  221. kDudeBrownSpider, "Brown Spider",
  222. kDudeRedSpider, "Red Spider",
  223. kDudeBlackSpider, "Black Spider",
  224. kDudeMotherSpider, "Mother Spider",
  225. kDudeGillBeast, "GillBeast",
  226. kDudeEel, "Eel",
  227. kDudeBat, "Bat",
  228. kDudeRat, "Rat",
  229. kDudeGreenPod, "Green Pod",
  230. kDudeGreenTentacle, "Green Tentacle",
  231. kDudeFirePod, "Fire Pod",
  232. kDudeFireTentacle, "Fire Tentacle",
  233. kDudeMotherPod, "Mother Pod",
  234. kDudeMotherTentacle, "Mother Tentacle",
  235. kDudeCerberus, "Cerberus",
  236. kDudeTchernobog, "Tchernobog",
  237. kDudeRachel, "Rachel",
  238. kThingTNTBarrel, "TNT Barrel",
  239. kThingTNTProxArmed, "Armed Proximity Bomb",
  240. kThingTNTRemArmed, "Armed Remote Bomb",
  241. kThingBlueVase, "Blue Vase",
  242. kThingBrownVase, "Brown Vase",
  243. kThingCrateFace, "Crate Face",
  244. kThingClearGlass, "Clear Glass",
  245. kThingFluorescent, "Fluorescent Light",
  246. kThingWallCrack, "Wall Crack",
  247. kThingWoodBeam, "Wood Beam",
  248. kThingWeb, "Spider's Web",
  249. kThingMetalGrate1, "MetalGrate1",
  250. kThingFlammableTree, "FlammableTree",
  251. kThingMachineGun, "Machine Gun",
  252. kTrapSpiketrap, "Spike Trap",
  253. kTrapRocktrap, "Rock Trap",
  254. kTrapSawBlade, "Saw Blade",
  255. kTrapUnpoweredZap, "Electric Zap",
  256. kTrapPoweredZap, "Switched Zap",
  257. kTrapPendulum, "Pendulum",
  258. kTrapGuillotine, "Guillotine",
  259. kGenTrigger, "Trigger Gen",
  260. kGenWaterDrip, "WaterDrip Gen",
  261. kGenBloodDrip, "BloodDrip Gen",
  262. kGenFireball, "Fireball Gen",
  263. kGenEctoSkull, "EctoSkull Gen",
  264. kGenDart, "Dart Gen",
  265. kGenBubble, "Bubble Gen",
  266. kGenBubbles, "Multi-Bubble Gen",
  267. kGenSound, "Sound Gen",
  268. };
  269. static NAMED_TYPE wallNTNames[] =
  270. {
  271. 0, "Normal",
  272. kSwitchToggle, "Toggle switch",
  273. kSwitchMomentary, "Momentary switch",
  274. kWallForcefield, "Forcefield",
  275. kWallCrushing, "Crushing",
  276. // kWallPendulum, "Pendulum",
  277. kWallSpeartrap, "Speartrap",
  278. kWallFlametrap, "Flametrap",
  279. kWallRazordoor, "Razor Door",
  280. // kWallGuillotine, "Guillotine",
  281. kWallClearGlass, "Clear Glass",
  282. kWallStainedGlass, "Stained Glass",
  283. kWallWoodBeams, "Wood Beams",
  284. kWallWeb, "Spider's Web",
  285. // kWallMetalGrate1, "MetalGrate1"
  286. };
  287. static NAMED_TYPE sectorNTNames[] =
  288. {
  289. 0, "Normal",
  290. kSectorZMotion, "Z Motion",
  291. kSectorZCrusher, "Z Crusher",
  292. kSectorZSprite, "Z Motion SPRITE",
  293. kSectorWarp, "Warp",
  294. kSectorTeleport, "Teleporter",
  295. kSectorUpperwater, "Upper water",
  296. kSectorLowerwater, "Lower water",
  297. kSectorSlideMarked, "Slide Marked",
  298. kSectorRotateMarked, "Rotate Marked",
  299. kSectorSlide, "Slide",
  300. kSectorRotate, "Rotate",
  301. kSectorSlideCrush, "Slide Crush",
  302. kSectorRotateCrush, "Rotate Crush",
  303. };
  304. static NAMED_TYPE waveNTNames[] =
  305. {
  306. kWaveNone, "None",
  307. kWaveSquare, "Square",
  308. kWaveSaw, "Saw",
  309. kWaveRampup, "Ramp up",
  310. kWaveRampdown, "Ramp down",
  311. kWaveSine, "Sine",
  312. kWaveFlicker1, "Flicker1",
  313. kWaveFlicker2, "Flicker2",
  314. kWaveFlicker3, "Flicker3",
  315. kWaveFlicker4, "Flicker4",
  316. kWaveStrobe, "Strobe",
  317. kWaveSearch, "Search",
  318. };
  319. static NAMED_TYPE depthNTNames[] =
  320. {
  321. kDepthWalk, "Walk",
  322. kDepthTread, "Tread",
  323. kDepthWade, "Wade",
  324. kDepthSwim, "Swim*",
  325. };
  326. static NAMED_TYPE commandNTNames[] =
  327. {
  328. kCommandOff, "OFF",
  329. kCommandOn, "ON",
  330. kCommandState, "State",
  331. kCommandToggle, "Toggle",
  332. kCommandNotState, "!State",
  333. kCommandLink, "Link",
  334. kCommandLock, "Lock",
  335. kCommandUnlock, "Unlock",
  336. kCommandToggleLock, "Tog-Lock",
  337. };
  338. static NAMED_TYPE respawnNTNames[] =
  339. {
  340. 0, "Never",
  341. 1, "Optional",
  342. 2, "Always",
  343. 3, "Permanent",
  344. };
  345. /***********************************************************************
  346. * Functions
  347. **********************************************************************/
  348. void ProcessKeys3D( void );
  349. void ProcessKeys2D( void );
  350. /***********************************************************************
  351. * Wait()
  352. *
  353. * Delays for a period of time specified in 1/120th secs
  354. **********************************************************************/
  355. void Wait(long time)
  356. {
  357. long done = gGameClock + time;
  358. while (gGameClock < done);
  359. }
  360. void BeepOkay( void )
  361. {
  362. if (gBeep)
  363. {
  364. sound(6000);
  365. Wait(2);
  366. nosound();
  367. Wait(2);
  368. }
  369. asksave = 1;
  370. }
  371. void BeepError( void )
  372. {
  373. sound(1000);
  374. Wait(4);
  375. sound(800);
  376. Wait(4);
  377. nosound();
  378. }
  379. /***********************************************************************
  380. * CloseBanner()
  381. *
  382. * Display credits when program exits
  383. **********************************************************************/
  384. void CloseBanner( void )
  385. {
  386. setvmode(gOldDisplayMode);
  387. printf("\nBUILD engine by Ken Silverman\n");
  388. printf("MAPEDIT version by Peter Freese\n");
  389. printf("Copyright (c) 1994, 1995 Q Studios\n");
  390. }
  391. /***********************************************************************
  392. * FillNameArray
  393. *
  394. **********************************************************************/
  395. void FillNameArray( char **names, NAMED_TYPE *ntNames, int length )
  396. {
  397. for (int i = 0; i < length; i++)
  398. {
  399. names[ntNames->id] = ntNames->name;
  400. ntNames++;
  401. }
  402. }
  403. void InitializeNames( void )
  404. {
  405. static char numbers[192][4];
  406. FillNameArray(gBoolNames, boolNTNames, LENGTH(boolNTNames));
  407. FillNameArray(gSpriteNames, spriteNTNames, LENGTH(spriteNTNames));
  408. FillNameArray(gWallNames, wallNTNames, LENGTH(wallNTNames));
  409. FillNameArray(gSectorNames, sectorNTNames, LENGTH(sectorNTNames));
  410. FillNameArray(gWaveNames, waveNTNames, LENGTH(waveNTNames));
  411. FillNameArray(gDepthNames, depthNTNames, LENGTH(depthNTNames));
  412. FillNameArray(gCommandNames, commandNTNames, LENGTH(commandNTNames));
  413. for (int i = 0; i < 192; i++)
  414. {
  415. sprintf(numbers[i], "%d", i);
  416. gCommandNames[64 + i] = numbers[i];
  417. }
  418. FillNameArray(gRespawnNames, respawnNTNames, LENGTH(respawnNTNames));
  419. }
  420. /*******************************************************************************
  421. FUNCTION: CleanUp()
  422. DESCRIPTION: Call this function periodically to fix all the problems
  423. Ken causes by rearranging the database with abandon.
  424. *******************************************************************************/
  425. void CleanUp( void )
  426. {
  427. int nSprite, nSector, j;
  428. dbXSectorClean();
  429. dbXWallClean();
  430. dbXSpriteClean();
  431. // make sure proper sectors are on the effect lists
  432. InitSectorFX();
  433. // back propagate marker references
  434. for (nSector = 0; nSector < numsectors; nSector++)
  435. {
  436. int nXSector = sector[nSector].extra;
  437. if (nXSector > 0)
  438. {
  439. switch (sector[nSector].type)
  440. {
  441. case kSectorTeleport:
  442. if (xsector[nXSector].marker0 >= 0)
  443. {
  444. int nSprite = xsector[nXSector].marker0;
  445. if (nSprite < kMaxSprites && sprite[nSprite].statnum == kStatMarker && sprite[nSprite].type == kMarkerWarpDest)
  446. sprite[nSprite].owner = (short)nSector;
  447. else
  448. {
  449. xsector[nXSector].marker0 = -1;
  450. dprintf("Invalid teleport sector -> target marker reference found\n");
  451. }
  452. }
  453. break;
  454. case kSectorSlide:
  455. case kSectorSlideMarked:
  456. case kSectorSlideCrush:
  457. if (xsector[nXSector].marker0 >= 0)
  458. {
  459. int nSprite = xsector[nXSector].marker0;
  460. if (nSprite < kMaxSprites && sprite[nSprite].statnum == kStatMarker && sprite[nSprite].type == kMarkerOff)
  461. sprite[nSprite].owner = (short)nSector;
  462. else
  463. {
  464. xsector[nXSector].marker0 = -1;
  465. dprintf("Invalid slide sector -> off marker reference found\n");
  466. }
  467. }
  468. if (xsector[nXSector].marker1 >= 0)
  469. {
  470. int nSprite = xsector[nXSector].marker1;
  471. if (nSprite < kMaxSprites && sprite[nSprite].statnum == kStatMarker && sprite[nSprite].type == kMarkerOn)
  472. sprite[nSprite].owner = (short)nSector;
  473. else
  474. {
  475. xsector[nXSector].marker1 = -1;
  476. dprintf("Invalid slide sector -> on marker reference found\n");
  477. }
  478. }
  479. break;
  480. case kSectorRotate:
  481. case kSectorRotateMarked:
  482. case kSectorRotateCrush:
  483. if (xsector[nXSector].marker0 >= 0)
  484. {
  485. int nSprite = xsector[nXSector].marker0;
  486. if (nSprite < kMaxSprites && sprite[nSprite].statnum == kStatMarker && sprite[nSprite].type == kMarkerAxis)
  487. sprite[nSprite].owner = (short)nSector;
  488. else
  489. {
  490. xsector[nXSector].marker0 = -1;
  491. dprintf("Invalid rotate sector -> axis marker reference found\n");
  492. }
  493. }
  494. break;
  495. }
  496. }
  497. }
  498. // clear invalid marker references and add new markers as necessary
  499. for (nSector = 0; nSector < numsectors; nSector++)
  500. {
  501. int nXSector = sector[nSector].extra;
  502. if (nXSector > 0)
  503. {
  504. switch (sector[nSector].type)
  505. {
  506. case kSectorTeleport:
  507. if (xsector[nXSector].marker0 >= 0)
  508. {
  509. int nSprite = xsector[nXSector].marker0;
  510. if (sprite[nSprite].owner != (short)nSector)
  511. {
  512. // clone the marker
  513. dprintf("Cloning teleport sector -> target marker\n");
  514. int nSprite2 = insertsprite(sprite[nSprite].sectnum, kStatMarker);
  515. sprite[nSprite2] = sprite[nSprite];
  516. sprite[nSprite2].owner = (short)nSector;
  517. xsector[nXSector].marker0 = nSprite2;
  518. }
  519. }
  520. if (xsector[nXSector].marker0 < 0)
  521. {
  522. dprintf("Creating new teleport sector -> target marker\n");
  523. int nSprite = insertsprite((short)nSector, kStatMarker);
  524. sprite[nSprite].x = wall[sector[nSector].wallptr].x;
  525. sprite[nSprite].y = wall[sector[nSector].wallptr].y;
  526. sprite[nSprite].cstat |= kSpriteInvisible;
  527. sprite[nSprite].owner = (short)nSector;
  528. sprite[nSprite].type = kMarkerWarpDest;
  529. xsector[nXSector].marker0 = nSprite;
  530. }
  531. break;
  532. case kSectorSlide:
  533. case kSectorSlideMarked:
  534. case kSectorSlideCrush:
  535. if (xsector[nXSector].marker0 >= 0)
  536. {
  537. int nSprite = xsector[nXSector].marker0;
  538. if (sprite[nSprite].owner != (short)nSector)
  539. {
  540. // clone the marker
  541. dprintf("Cloning slide sector -> off marker\n");
  542. int nSprite2 = insertsprite(sprite[nSprite].sectnum, kStatMarker);
  543. sprite[nSprite2] = sprite[nSprite];
  544. sprite[nSprite2].owner = (short)nSector;
  545. xsector[nXSector].marker0 = nSprite2;
  546. }
  547. }
  548. if (xsector[nXSector].marker0 < 0)
  549. {
  550. // create a new marker
  551. dprintf("Creating new slide sector -> off marker\n");
  552. int nSprite = insertsprite((short)nSector, kStatMarker);
  553. sprite[nSprite].x = wall[sector[nSector].wallptr].x;
  554. sprite[nSprite].y = wall[sector[nSector].wallptr].y;
  555. sprite[nSprite].cstat |= kSpriteInvisible;
  556. sprite[nSprite].owner = (short)nSector;
  557. sprite[nSprite].type = kMarkerOff;
  558. xsector[nXSector].marker0 = nSprite;
  559. }
  560. if (xsector[nXSector].marker1 >= 0)
  561. {
  562. int nSprite = xsector[nXSector].marker1;
  563. if (sprite[nSprite].owner != (short)nSector)
  564. {
  565. // clone the marker
  566. dprintf("Cloning slide sector -> on marker\n");
  567. int nSprite2 = insertsprite(sprite[nSprite].sectnum, kStatMarker);
  568. sprite[nSprite2] = sprite[nSprite];
  569. sprite[nSprite2].owner = (short)nSector;
  570. xsector[nXSector].marker1 = (short)nSprite2;
  571. }
  572. }
  573. if (xsector[nXSector].marker1 < 0)
  574. {
  575. dprintf("Creating new slide sector -> on marker\n");
  576. int nSprite = insertsprite((short)nSector, kStatMarker);
  577. sprite[nSprite].x = wall[sector[nSector].wallptr].x;
  578. sprite[nSprite].y = wall[sector[nSector].wallptr].y;
  579. sprite[nSprite].cstat |= kSpriteInvisible;
  580. sprite[nSprite].owner = (short)nSector;
  581. sprite[nSprite].type = kMarkerOn;
  582. xsector[nXSector].marker1 = nSprite;
  583. }
  584. break;
  585. case kSectorRotate:
  586. case kSectorRotateMarked:
  587. case kSectorRotateCrush:
  588. if (xsector[nXSector].marker0 >= 0)
  589. {
  590. int nSprite = xsector[nXSector].marker0;
  591. if (sprite[nSprite].owner != (short)nSector)
  592. {
  593. // clone the marker
  594. dprintf("Cloning rotate sector -> axis marker\n");
  595. int nSprite2 = insertsprite(sprite[nSprite].sectnum, kStatMarker);
  596. sprite[nSprite2] = sprite[nSprite];
  597. sprite[nSprite2].owner = (short)nSector;
  598. xsector[nXSector].marker0 = nSprite2;
  599. }
  600. }
  601. if (xsector[nXSector].marker0 < 0)
  602. {
  603. dprintf("Creating new rotate sector -> axis marker\n");
  604. int nSprite = insertsprite((short)nSector, kStatMarker);
  605. sprite[nSprite].x = wall[sector[nSector].wallptr].x;
  606. sprite[nSprite].y = wall[sector[nSector].wallptr].y;
  607. sprite[nSprite].cstat |= kSpriteInvisible;
  608. sprite[nSprite].owner = (short)nSector;
  609. sprite[nSprite].type = kMarkerAxis;
  610. xsector[nXSector].marker0 = nSprite;
  611. }
  612. break;
  613. default:
  614. xsector[nXSector].marker0 = -1;
  615. xsector[nXSector].marker1 = -1;
  616. break;
  617. }
  618. }
  619. }
  620. // delete all invalid marker sprites
  621. for (nSprite = headspritestat[kStatMarker]; nSprite != -1; nSprite = j)
  622. {
  623. j = nextspritestat[nSprite];
  624. sprite[nSprite].extra = -1;
  625. sprite[nSprite].cstat |= kSpriteInvisible;
  626. sprite[nSprite].cstat &= ~kSpriteBlocking;
  627. int nSector = sprite[nSprite].owner;
  628. int nXSector = sector[nSector].extra;
  629. if (nSector >= 0 && nSector < numsectors && nXSector > 0 && nXSector < kMaxXSectors)
  630. {
  631. switch (sprite[nSprite].type)
  632. {
  633. case kMarkerOff:
  634. if ( xsector[nXSector].marker0 == nSprite )
  635. continue;
  636. break;
  637. case kMarkerOn:
  638. if ( xsector[nXSector].marker1 == nSprite)
  639. continue;
  640. break;
  641. case kMarkerAxis:
  642. if ( xsector[nXSector].marker0 == nSprite)
  643. continue;
  644. break;
  645. case kMarkerWarpDest:
  646. if ( xsector[nXSector].marker0 == nSprite)
  647. continue;
  648. break;
  649. }
  650. }
  651. dprintf("Deleting unreferenced marker sprite\n");
  652. deletesprite((short)nSprite);
  653. }
  654. }
  655. /***********************************************************************
  656. * GetXSector()
  657. *
  658. * Returns the index of the xsector structure for a sector index. If
  659. * the xsector structure does not exist, it is created.
  660. **********************************************************************/
  661. int GetXSector( int nSector )
  662. {
  663. dassert(nSector >= 0 && nSector < kMaxSectors);
  664. if (sector[nSector].extra != -1)
  665. return sector[nSector].extra;
  666. return dbInsertXSector(nSector);
  667. }
  668. /***********************************************************************
  669. * GetXWall()
  670. *
  671. * Returns the index of the xwall structure for a wall index. If
  672. * the xwall structure does not exist, it is created.
  673. **********************************************************************/
  674. int GetXWall( int nWall )
  675. {
  676. int nXWall;
  677. dassert(nWall >= 0 && nWall < kMaxWalls);
  678. if (wall[nWall].extra > 0)
  679. return wall[nWall].extra;
  680. nXWall = dbInsertXWall(nWall);
  681. return nXWall;
  682. }
  683. /***********************************************************************
  684. * GetXSprite()
  685. *
  686. * Returns the index of the xsprite structure for a sprite index. If
  687. * the xsprite structure does not exist, it is created.
  688. **********************************************************************/
  689. int GetXSprite( int nSprite )
  690. {
  691. int nXSprite;
  692. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  693. if (sprite[nSprite].extra > 0)
  694. return sprite[nSprite].extra;
  695. nXSprite = dbInsertXSprite(nSprite);
  696. return nXSprite;
  697. }
  698. struct AUTODATA
  699. {
  700. short type;
  701. short picnum;
  702. short xrepeat, yrepeat;
  703. uchar hitBit;
  704. short plu;
  705. };
  706. AUTODATA autoData[] =
  707. {
  708. { kMarkerPlayerStart, -1, -1, -1, 0, kPLUNormal },
  709. { kMarkerDeathStart, -1, -1, -1, 0, kPLUGray },
  710. { kMarkerUpperLink, 2332, 16, 16, 0, -1 },
  711. { kMarkerLowerLink, 2332, 16, 16, 0, -1 },
  712. { kSwitchToggle, -1, -1, -1, 1, -1 },
  713. { kSwitchMomentary, -1, -1, -1, 1, -1 },
  714. { kSwitchCombination, -1, -1, -1, 1, -1 },
  715. { kSwitchPadlock, kPicPadlock, -1, -1, 1, -1 },
  716. { kMiscTorch, kPicTorchPot1, -1, -1, 1, -1 },
  717. { kMiscTorch, kPicTorchPot2, -1, -1, 1, -1 },
  718. { kMiscTorch, kPicTorchStand1, -1, -1, 1, -1 },
  719. { kMiscTorch, kPicTorchStand2, -1, -1, 1, -1 },
  720. { kMiscTorch, kPicTorchSconce1, -1, -1, 1, -1 },
  721. { kMiscTorch, kPicTorchSconce2, -1, -1, 1, -1 },
  722. { kMiscHangingTorch, kPicTorchBowl1, -1, -1, 1, -1 },
  723. { kWeaponItemRandom, kPicRandomUp, 48, 48, 0, kPLUNormal },
  724. { kWeaponItemShotgun, kPicShotgun, 48, 48, 0, kPLUNormal },
  725. { kWeaponItemTommyGun, kPicTommyGun, 48, 48, 0, kPLUNormal },
  726. { kWeaponItemFlareGun, kPicFlareGun, 48, 48, 0, kPLUNormal },
  727. { kWeaponItemVoodooDoll, kPicVoodooDoll, 48, 48, 0, kPLUNormal },
  728. { kWeaponItemSpearGun, kPicSpearGun, 48, 48, 0, kPLUNormal },
  729. { kWeaponItemShadowGun, kPicShadowGun, 48, 48, 0, kPLUNormal },
  730. { kAmmoItemSprayCan, kPicSprayCan, 40, 40, 1, kPLUNormal },
  731. { kAmmoItemTNTStick, kPicTNTStick, 48, 48, 1, kPLUNormal },
  732. { kAmmoItemTNTBundle, kPicTNTPak, 48, 48, 1, kPLUNormal },
  733. { kAmmoItemTNTCase, kPicTNTBox, 48, 48, 1, kPLUNormal },
  734. { kAmmoItemTNTProximity, kPicTNTProx, 48, 48, 0, kPLUNormal },
  735. { kAmmoItemTNTRemote, kPicTNTRemote, 48, 48, 0, kPLUNormal },
  736. { kAmmoItemTNTTimer, kPicTNTTimer, 48, 48, 0, kPLUNormal },
  737. { kAmmoItemShells, kPicShotShells, 48, 48, 0, kPLUNormal },
  738. { kAmmoItemShellBox, kPicShellBox, 48, 48, 0, kPLUNormal },
  739. { kAmmoItemBullets, kPicBullets, 48, 48, 0, kPLUNormal },
  740. { kAmmoItemBulletBox, kPicBulletBox, 48, 48, 0, kPLUNormal },
  741. { kAmmoItemAPBullets, kPicBulletBoxAP, 48, 48, 0, kPLUNormal },
  742. { kAmmoItemTommyDrum, kPicTommyDrum, 48, 48, 0, kPLUNormal },
  743. { kAmmoItemSpear, kPicSpear, 48, 48, 0, kPLUNormal },
  744. { kAmmoItemSpearPack, kPicSpears, 48, 48, 0, kPLUNormal },
  745. { kAmmoItemHESpears, kPicSpearExplode, 48, 48, 1, kPLUNormal },
  746. { kAmmoItemFlares, kPicFlares, 48, 48, 0, kPLUNormal },
  747. { kAmmoItemHEFlares, kPicFlareHE, 48, 48, 1, kPLUNormal },
  748. { kAmmoItemStarFlares, kPicFlareBurst, 48, 48, 0, kPLUNormal },
  749. { kAmmoItemRandom, kPicRandomUp, 40, 40, 0, kPLUNormal },
  750. { kItemKey1, kPicKey1, 32, 32, 0, kPLUNormal },
  751. { kItemKey2, kPicKey2, 32, 32, 0, kPLUNormal },
  752. { kItemKey3, kPicKey3, 32, 32, 0, kPLUNormal },
  753. { kItemKey4, kPicKey4, 32, 32, 0, kPLUNormal },
  754. { kItemKey5, kPicKey5, 32, 32, 0, kPLUNormal },
  755. { kItemKey6, kPicKey6, 32, 32, 0, kPLUNormal },
  756. { kItemKey7, -1, -1, -1, 0, kPLUNormal },
  757. { kItemDoctorBag, kPicDocBag, 48, 48, 0, kPLUNormal },
  758. { kItemMedPouch, kPicMedPouch, 40, 40, 0, kPLUNormal },
  759. { kItemLifeEssence, kPicEssence, 40, 40, 0, kPLUNormal },
  760. { kItemLifeSeed, kAnmLifeSeed, 40, 40, 0, kPLUNormal },
  761. { kItemPotion1, kPicPotion, 40, 40, 0, kPLUNormal },
  762. { kItemFeatherFall, kAnmFeather, 40, 40, 0, kPLUNormal },
  763. { kItemLtdInvisibility,kAnmInviso, 40, 40, 0, kPLUNormal },
  764. { kItemInvulnerability,kPicInvulnerable, 40, 40, 0, kPLUNormal },
  765. { kItemJumpBoots, kPicJumpBoots, 40, 40, 0, kPLUNormal },
  766. { kItemRavenFlight, kPicRavenFlight, 40, 40, 0, kPLUNormal },
  767. { kItemGunsAkimbo, kPicGunsAkimbo, 40, 40, 0, kPLUNormal },
  768. { kItemDivingSuit, kPicDivingSuit, 80, 64, 0, kPLUNormal },
  769. { kItemGasMask, kPicGasMask, 40, 40, 0, kPLUNormal },
  770. { kItemClone, kAnmClone, 40, 40, 0, kPLUNormal },
  771. { kItemCrystalBall, kPicCrystalBall, 40, 40, 0, kPLUNormal },
  772. { kItemDecoy, kPicDecoy, 40, 40, 0, kPLUNormal },
  773. { kItemDoppleganger, kAnmDoppleganger, 40, 40, 0, kPLUNormal },
  774. { kItemReflectiveShots,kAnmReflectShots, 40, 40, 0, kPLUNormal },
  775. { kItemRoseGlasses, kPicRoseGlasses, 40, 40, 0, kPLUNormal },
  776. { kItemShadowCloak, kAnmCloakNDagger, 64, 64, 0, kPLUNormal },
  777. { kItemShroomRage, kPicShroom1, 48, 48, 0, kPLUNormal },
  778. { kItemShroomDelirium,kPicShroom2, 48, 48, 0, kPLUNormal },
  779. { kItemShroomGrow, kPicShroom3, 48, 48, 0, kPLUNormal },
  780. { kItemShroomShrink, kPicShroom4, 48, 48, 0, kPLUNormal },
  781. { kItemDeathMask, kPicDeathMask, 40, 40, 0, kPLUNormal },
  782. { kItemWineGoblet, kPicGoblet, 40, 40, 0, kPLUNormal },
  783. { kItemWineBottle, kPicBottle1, 40, 40, 0, kPLUNormal },
  784. { kItemSkullGrail, kPicSkullGrail, 40, 40, 0, kPLUNormal },
  785. { kItemSilverGrail, kPicSilverGrail, 40, 40, 0, kPLUNormal },
  786. { kItemTome, kPicTome1, 40, 40, 0, kPLUNormal },
  787. { kItemBlackChest, kPicBlackChest, 40, 40, 0, kPLUNormal },
  788. { kItemWoodenChest, kPicWoodChest, 40, 40, 0, kPLUNormal },
  789. { kItemAsbestosArmor, kPicAsbestosSuit, 80, 64, 0, kPLUNormal },
  790. { kItemRandom, kPicRandomUp, 40, 40, 0, kPLUNormal },
  791. { kDudeRandom, kPicRandomUp, 64, 64, 1, kPLUNormal },
  792. { kDudeTommyCultist, kAnmCultistA1, 40, 40, 1, kPLUCultist2 },
  793. { kDudeShotgunCultist,kPicShotgunIdle, 40, 40, 1, kPLUNormal },
  794. { kDudeAxeZombie, kAnmZomb1M1, 38, 38, 1, kPLUNormal },
  795. { kDudeFatZombie, kAnmZomb2M1, 40, 40, 1, kPLUNormal },
  796. { kDudeEarthZombie, kPicEarthIdle, 38, 38, 1, kPLUNormal },
  797. { kDudeFleshGargoyle, kAnmGargoyleM1, 40, 40, 1, kPLUNormal },
  798. { kDudeStoneGargoyle, kAnmGargoyleM1, 40, 40, 1, kPLUGray },
  799. { kDudeFleshStatue, kAnmGargStatue, 40, 40, 1, kPLUNormal },
  800. { kDudeStoneStatue, kAnmGargStatue, 40, 40, 1, kPLUGray },
  801. { kDudePhantasm, kAnmPhantasmM1, 40, 40, 1, kPLUNormal },
  802. { kDudeHound, kAnmHellM2, 40, 40, 1, kPLUNormal },
  803. { kDudeHand, kAnmHandM1, 32, 32, 1, kPLUNormal },
  804. { kDudeBrownSpider, kAnmSpiderM1, 16, 16, 1, kPLUSpider1 },
  805. { kDudeRedSpider, kAnmSpiderM1B, 24, 24, 1, kPLUSpider2 },
  806. { kDudeBlackSpider, kAnmSpiderM1C, 32, 32, 1, kPLUSpider3 },
  807. { kDudeMotherSpider, kAnmSpiderM1D, 40, 40, 1, kPLUNormal },
  808. { kDudeGillBeast, kAnmGillM1, 48, 48, 1, kPLUNormal },
  809. { kDudeEel, kAnmEelM1, 32, 32, 1, kPLUNormal },
  810. { kDudeBat, kAnmBatM2, 32, 32, 1, kPLUNormal },
  811. { kDudeRat, kAnmRatM1, 24, 24, 1, kPLUNormal },
  812. { kDudeGreenPod, kAnmPodM1, 32, 32, 1, kPLUNormal },
  813. { kDudeGreenTentacle, kAnmTentacleM1, 32, 32, 1, kPLUNormal },
  814. { kDudeFirePod, kAnmPodM1, 48, 48, 1, kPLURed },
  815. { kDudeFireTentacle, kAnmTentacleM1, 48, 48, 1, kPLURed },
  816. { kDudeMotherPod, kAnmPodM1, 64, 64, 1, kPLUGrayish },
  817. { kDudeMotherTentacle,kAnmTentacleM1, 64, 64, 1, kPLUGrayish },
  818. { kDudeCerberus, kAnmCerberusM1, 32, 32, 1, kPLUNormal },
  819. { kDudeTchernobog, kAnmTchernobogM1, 40, 40, 1, kPLUNormal },
  820. { kDudeRachel, kAnmRachelM1, 40, 40, 1, kPLUNormal },
  821. { kDudePlayer1, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  822. { kDudePlayer2, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  823. { kDudePlayer3, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  824. { kDudePlayer4, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  825. { kDudePlayer5, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  826. { kDudePlayer6, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  827. { kDudePlayer7, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  828. { kDudePlayer8, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  829. { kDudePlayer_Owned, kAnmCultistM1, 40, 40, 1, kPLUNormal },
  830. { kDudeHound_Owned, kAnmHellM2, 40, 40, 1, kPLUNormal },
  831. { kDudeEel_Owned, kAnmEelM1, 32, 32, 1, kPLUNormal },
  832. { kDudeSpider_Owned, kAnmSpiderM1, 16, 16, 1, kPLUNormal },
  833. { kThingTNTBarrel, kPicTNTBarrel, 64, 64, 1, kPLUNormal },
  834. { kThingTNTProxArmed, kAnmTNTProxArmed, 40, 40, 1, kPLUNormal },
  835. { kThingTNTRemArmed, kAnmTNTRemArmed, 40, 40, 1, kPLUNormal },
  836. { kThingBlueVase, kPicVase1, -1, -1, 1, kPLUNormal },
  837. { kThingBrownVase, kPicVase2, -1, -1, 1, kPLUNormal },
  838. { kThingCrateFace, kPicCrateFace, -1, -1, 1, kPLUNormal },
  839. { kThingClearGlass, kPicGlass, -1, -1, 1, kPLUNormal },
  840. { kThingFluorescent, kPicFluorescent, -1, -1, 1, kPLUNormal },
  841. { kThingWallCrack, kPicWallCrack, -1, -1, 1, kPLUNormal },
  842. { kThingWoodBeam, kPicWoodBeam, -1, -1, 1, kPLUNormal },
  843. { kThingWeb, kPicBlockWeb, -1, -1, 1, kPLUNormal },
  844. { kThingMetalGrate1, kPicMetalGrate1, -1, -1, 1, -1 },
  845. { kThingFlammableTree,-1, -1, -1, 1, -1 },
  846. { kThingMachineGun, -1, 64, 64, 0, kPLUNormal },
  847. { kTrapSpiketrap, kAnmFloorSpike, 64, 64, 0, kPLUNormal },
  848. { kTrapRocktrap, -1, 64, 64, 0, kPLUNormal },
  849. { kTrapSatellite, -1, -1, -1, 0, kPLUNormal },
  850. { kTrapSawBlade, kAnmCircSaw1, 27, 32, 0, kPLUNormal },
  851. { kTrapUnpoweredZap, kAnmElectrify, -1, -1, 0, kPLUNormal },
  852. { kTrapPoweredZap, kAnmElectrify, -1, -1, 0, kPLUNormal },
  853. { kTrapPendulum, kAnmPendulum, -1, -1, 0, kPLUNormal },
  854. { kTrapGuillotine, kPicGuillotine, -1, -1, 0, kPLUNormal },
  855. };
  856. /***********************************************************************
  857. * AutoAdjustSprites()
  858. *
  859. * Adjust sprite x/yrepeat values for oddly sized sprites
  860. **********************************************************************/
  861. void AutoAdjustSprites(void)
  862. {
  863. dprintf("Auto adjusting sprite attributes... ");
  864. for ( short nSprite = 0; nSprite < kMaxSprites; nSprite++ )
  865. {
  866. SPRITE *pSprite = &sprite[nSprite];
  867. if ( pSprite->statnum < kMaxStatus )
  868. {
  869. int i, iPicnum = -1, iType = -1;
  870. // clear out types having no name (probably invalid)
  871. if ( pSprite->type != 0 && gSpriteNames[sprite[nSprite].type] == NULL )
  872. pSprite->type = 0;
  873. // look up by picnum
  874. for ( i = 0; i < LENGTH(autoData); i++)
  875. {
  876. if ( autoData[i].picnum >= 0 && autoData[i].picnum == pSprite->picnum )
  877. {
  878. iPicnum = i;
  879. break;
  880. }
  881. }
  882. // look up by type
  883. for ( i = 0; i < LENGTH(autoData); i++)
  884. {
  885. if ( autoData[i].type == pSprite->type )
  886. {
  887. iType = i;
  888. break;
  889. }
  890. }
  891. i = -1;
  892. // this set of rules determine which row to use from the autoData table
  893. if ( iPicnum >= 0 )
  894. i = iPicnum;
  895. if ( iType >= 0 )
  896. i = iType;
  897. if ( iPicnum >= 0 && autoData[iPicnum].type == pSprite->type )
  898. i = iPicnum;
  899. // if nothing found, ignore this sprite
  900. if ( i < 0 )
  901. continue;
  902. // convert spin sprite flags to face sprites
  903. if ( (pSprite->cstat & kSpriteSpin) == kSpriteSpin )
  904. pSprite->cstat &= ~kSpriteSpin;
  905. short type = autoData[i].type;
  906. if ( type == kMarkerPlayerStart || type == kMarkerDeathStart)
  907. {
  908. pSprite->cstat &= ~kSpriteBlocking;
  909. changespritestat(nSprite, kStatDefault);
  910. int nXSprite = GetXSprite(nSprite);
  911. xsprite[nXSprite].data1 &= 7; // force 0..7 player range
  912. pSprite->picnum = (short)(kPicStart1 + xsprite[nXSprite].data1);
  913. }
  914. else if ( type == kMarkerUpperLink || type == kMarkerLowerLink )
  915. {
  916. pSprite->cstat &= ~kSpriteBlocking;
  917. changespritestat(nSprite, kStatDefault);
  918. int nXSprite = GetXSprite(nSprite);
  919. if (type == kMarkerUpperLink)
  920. pSprite->cstat &= ~kSpriteFlipY;
  921. else
  922. pSprite->cstat |= kSpriteFlipY;
  923. }
  924. else if ( type >= kSwitchBase && type < kSwitchMax )
  925. {
  926. pSprite->cstat &= ~kSpriteBlocking;
  927. changespritestat(nSprite, kStatDefault);
  928. GetXSprite(nSprite);
  929. }
  930. else if ( type >= kWeaponItemBase && type < kWeaponItemMax )
  931. {
  932. if ( (pSprite->cstat & kSpriteRMask) != kSpriteFace )
  933. continue;
  934. pSprite->cstat &= ~kSpriteBlocking;
  935. changespritestat(nSprite, kStatItem);
  936. }
  937. else if ( type >= kAmmoItemBase && type < kAmmoItemMax )
  938. {
  939. if ( (pSprite->cstat & kSpriteRMask) != kSpriteFace )
  940. continue;
  941. pSprite->cstat &= ~kSpriteBlocking;
  942. changespritestat(nSprite, kStatItem);
  943. }
  944. else if ( type >= kItemBase && type < kItemMax )
  945. {
  946. if ( (pSprite->cstat & kSpriteRMask) != kSpriteFace )
  947. continue;
  948. pSprite->cstat &= ~kSpriteBlocking;
  949. changespritestat(nSprite, kStatItem);
  950. }
  951. else if ( type >= kDudeBase && type < kDudeMax )
  952. {
  953. if ( (pSprite->cstat & kSpriteRMask) != kSpriteFace )
  954. continue;
  955. pSprite->cstat &= ~kSpriteBlocking;
  956. changespritestat(nSprite, kStatDude);
  957. GetXSprite(nSprite);
  958. }
  959. else if ( type >= kThingBase && type < kThingMax )
  960. {
  961. // if ( (pSprite->cstat & kSpriteRMask) != kSpriteFace )
  962. // continue;
  963. pSprite->cstat |= kSpriteBlocking;
  964. changespritestat(nSprite, kStatThing);
  965. GetXSprite(nSprite);
  966. }
  967. else if ( type >= kTrapBase && type < kTrapMax )
  968. {
  969. // these get moved onto their appropriate stat lists in trInit()
  970. changespritestat(nSprite, kStatTraps);
  971. GetXSprite(nSprite);
  972. }
  973. else
  974. changespritestat(nSprite, kStatDefault);
  975. pSprite->type = type;
  976. if ( autoData[i].picnum >= 0 )
  977. pSprite->picnum = autoData[i].picnum;
  978. if ( autoData[i].xrepeat >= 0 )
  979. pSprite->xrepeat = (uchar)autoData[i].xrepeat;
  980. if ( autoData[i].yrepeat >= 0 )
  981. pSprite->yrepeat = (uchar)autoData[i].yrepeat;
  982. if ( autoData[i].hitBit )
  983. pSprite->cstat |= kSpriteHitscan;
  984. else
  985. pSprite->cstat &= ~kSpriteHitscan;
  986. if ( autoData[i].plu >= 0 )
  987. pSprite->pal = (uchar)autoData[i].plu;
  988. // make sure Things & Dudes aren't in the floor or ceiling
  989. if ( pSprite->statnum == kStatThing || pSprite->statnum == kStatDude || pSprite->statnum == kStatInactive )
  990. {
  991. int zTop, zBot;
  992. GetSpriteExtents(pSprite, &zTop, &zBot);
  993. if ( !(sector[pSprite->sectnum].ceilingstat & kSectorParallax) )
  994. pSprite->z += ClipLow(sector[pSprite->sectnum].ceilingz - zTop, 0);
  995. if ( !(sector[pSprite->sectnum].floorstat & kSectorParallax) )
  996. pSprite->z += ClipHigh(sector[pSprite->sectnum].floorz - zBot, 0);
  997. }
  998. }
  999. }
  1000. dprintf("done\n");
  1001. }
  1002. /***********************************************************************
  1003. * ShowSpriteStatistics()
  1004. *
  1005. * Generate and display game sprite statistics
  1006. *
  1007. **********************************************************************/
  1008. void ShowSpriteStatistics(short nSprite)
  1009. {
  1010. short spriteCount[ 1024 ];
  1011. memset( spriteCount, 0, sizeof(spriteCount) );
  1012. // ignore nSprite parameter and use as iterator instead
  1013. for (nSprite = 0; nSprite < kMaxSprites; nSprite++)
  1014. {
  1015. if ( sprite[nSprite].statnum < kMaxStatus )
  1016. spriteCount[ sprite[nSprite].type ]++;
  1017. }
  1018. }
  1019. /***********************************************************************
  1020. * ExtGetSectorCaption()
  1021. *
  1022. * Build calls this to generate the sector caption displayed on the
  1023. * 2D map.
  1024. **********************************************************************/
  1025. const char *ExtGetSectorCaption(short nSector)
  1026. {
  1027. dassert(nSector >= 0 && nSector < kMaxSectors);
  1028. int nXSector = sector[nSector].extra;
  1029. buffer[0] = 0;
  1030. if (nXSector > 0)
  1031. {
  1032. char temp[256];
  1033. if ( xsector[nXSector].rxID > 0 )
  1034. {
  1035. sprintf(buffer, "%i:", xsector[nXSector].rxID);
  1036. }
  1037. strcat(buffer, gSectorNames[sector[nSector].type]);
  1038. if ( xsector[nXSector].txID > 0 )
  1039. {
  1040. sprintf(temp, ":%i", xsector[nXSector].txID);
  1041. strcat(buffer, temp);
  1042. }
  1043. if ( xsector[nXSector].panVel != 0 )
  1044. {
  1045. sprintf(temp, " PAN(%i,%i)", xsector[nXSector].panAngle, xsector[nXSector].panVel);
  1046. strcat(buffer, temp);
  1047. }
  1048. strcat(buffer, " ");
  1049. strcat(buffer, gBoolNames[xsector[nXSector].state]);
  1050. }
  1051. else
  1052. {
  1053. if ( sector[nSector].type != 0 || sector[nSector].hitag != 0 )
  1054. sprintf(buffer,"{%i:%i}", sector[nSector].hitag, sector[nSector].type);
  1055. }
  1056. return buffer;
  1057. }
  1058. /***********************************************************************
  1059. * ExtGetWallCaption()
  1060. *
  1061. * Build calls this to generate the wall caption displayed on the
  1062. * 2D map.
  1063. **********************************************************************/
  1064. const char *ExtGetWallCaption(short nWall)
  1065. {
  1066. dassert(nWall >= 0 && nWall < kMaxWalls);
  1067. int nXWall = wall[nWall].extra;
  1068. buffer[0] = 0;
  1069. if (nXWall > 0)
  1070. {
  1071. char temp[256];
  1072. if ( xwall[nXWall].rxID > 0 )
  1073. {
  1074. sprintf(temp, "%i:", xwall[nXWall].rxID);
  1075. strcat(buffer, temp);
  1076. }
  1077. strcat(buffer, gWallNames[wall[nWall].type]);
  1078. if ( xwall[nXWall].txID > 0 )
  1079. {
  1080. sprintf(temp, ":%i", xwall[nXWall].txID);
  1081. strcat(buffer, temp);
  1082. }
  1083. if ( xwall[nXWall].panXVel != 0 || xwall[nXWall].panYVel != 0 )
  1084. {
  1085. sprintf(temp, " PAN(%i,%i)", xwall[nXWall].panXVel, xwall[nXWall].panYVel);
  1086. strcat(buffer, temp);
  1087. }
  1088. strcat(buffer, " ");
  1089. strcat(buffer, gBoolNames[xwall[nXWall].state]);
  1090. }
  1091. else
  1092. {
  1093. if ( wall[nWall].type != 0 || wall[nWall].hitag != 0 )
  1094. sprintf(buffer,"{%i:%i}", wall[nWall].hitag, wall[nWall].type);
  1095. }
  1096. return buffer;
  1097. }
  1098. /***********************************************************************
  1099. * ExtGetSpriteCaption()
  1100. *
  1101. * Build calls this to generate the sprite caption displayed on the
  1102. * 2D map.
  1103. **********************************************************************/
  1104. const char *ExtGetSpriteCaption( short nSprite )
  1105. {
  1106. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  1107. SPRITE *pSprite = &sprite[nSprite];
  1108. if ( pSprite->type == 0 )
  1109. return "";
  1110. if ( pSprite->statnum == kStatMarker )
  1111. return "";
  1112. char *typeName = gSpriteNames[pSprite->type];
  1113. if ( typeName == NULL )
  1114. return "";
  1115. int nXSprite = pSprite->extra;
  1116. if ( nXSprite > 0 )
  1117. {
  1118. XSPRITE *pXSprite = &xsprite[nXSprite];
  1119. if ( pSprite->type == kMarkerUpperLink || pSprite->type == kMarkerLowerLink )
  1120. {
  1121. sprintf(buffer, "%s [%d]", typeName, pXSprite->data1);
  1122. return buffer;
  1123. }
  1124. buffer[0] = 0;
  1125. char temp[256];
  1126. if ( pXSprite->rxID > 0 )
  1127. {
  1128. sprintf(temp, "%i:", pXSprite->rxID);
  1129. strcat(buffer, temp);
  1130. }
  1131. strcat(buffer, typeName);
  1132. if ( pXSprite->txID > 0 )
  1133. {
  1134. sprintf(temp, ":%i", pXSprite->txID);
  1135. strcat(buffer, temp);
  1136. }
  1137. if ( pSprite->type >= kSwitchBase && pSprite->type < kMiscMax )
  1138. {
  1139. strcat(buffer, " ");
  1140. strcat(buffer, gBoolNames[pXSprite->state]);
  1141. }
  1142. return buffer;
  1143. }
  1144. else
  1145. return typeName;
  1146. }
  1147. /***********************************************************************
  1148. * ExtShowSectorData()
  1149. *
  1150. * Build calls this when F5 is pressed.
  1151. **********************************************************************/
  1152. void ExtShowSectorData( short nSector )
  1153. {
  1154. if ( keystatus[KEY_LALT] | keystatus[KEY_RALT] )
  1155. EditSectorData(nSector);
  1156. else
  1157. ShowSectorData(nSector);
  1158. }
  1159. /***********************************************************************
  1160. * ExtShowWallData()
  1161. *
  1162. * Build calls this when F6 is pressed.
  1163. **********************************************************************/
  1164. void ExtShowWallData( short nWall )
  1165. {
  1166. if ( keystatus[KEY_LALT] | keystatus[KEY_RALT] )
  1167. EditWallData(nWall);
  1168. else
  1169. ShowWallData(nWall);
  1170. }
  1171. /***********************************************************************
  1172. * ExtShowSpriteData()
  1173. *
  1174. * Build calls this when F6 is pressed.
  1175. **********************************************************************/
  1176. void ExtShowSpriteData( short nSprite )
  1177. {
  1178. if ( keystatus[KEY_LCTRL] | keystatus[KEY_RCTRL] )
  1179. ShowSpriteStatistics(nSprite);
  1180. else if ( keystatus[KEY_LALT] | keystatus[KEY_RALT] )
  1181. EditSpriteData(nSprite);
  1182. else
  1183. ShowSpriteData(nSprite);
  1184. }
  1185. /***********************************************************************
  1186. * ExtEditSectorData()
  1187. *
  1188. * Build calls this when F7 is pressed.
  1189. **********************************************************************/
  1190. void ExtEditSectorData( short /* nSector */ )
  1191. {
  1192. }
  1193. /***********************************************************************
  1194. * ExtEditWallData()
  1195. *
  1196. * Build calls this when F8 is pressed.
  1197. **********************************************************************/
  1198. void ExtEditWallData(short /* nWall */ )
  1199. {
  1200. }
  1201. /***********************************************************************
  1202. * ExtEditSpriteData()
  1203. *
  1204. * This function allows editing of the game specific sprite data.
  1205. * Build calls this when F8 is pressed.
  1206. **********************************************************************/
  1207. void ExtEditSpriteData( short /* nSprite */ )
  1208. {
  1209. }
  1210. /***********************************************************************
  1211. * ExtLoadMap()
  1212. *
  1213. * Build calls this right after the loadmap() call. Use this opportunity
  1214. * to preload all the necessary tiles.
  1215. **********************************************************************/
  1216. void ExtLoadMap( char * )
  1217. {
  1218. long i;
  1219. for (i = 0; i < numsectors; i++)
  1220. {
  1221. tilePreloadTile(sector[i].ceilingpicnum);
  1222. tilePreloadTile(sector[i].floorpicnum);
  1223. }
  1224. for (i = 0; i < numwalls; i++)
  1225. {
  1226. tilePreloadTile(wall[i].picnum);
  1227. if (wall[i].overpicnum >= 0)
  1228. tilePreloadTile(wall[i].overpicnum);
  1229. }
  1230. for (i = 0; i < kMaxSprites; i++)
  1231. {
  1232. if (sprite[i].statnum < kMaxStatus)
  1233. tilePreloadTile(sprite[i].picnum);
  1234. }
  1235. dprintf("ExtLoadMap: highlightsectorcnt = %d\n", highlightsectorcnt);
  1236. }
  1237. /***********************************************************************
  1238. * Overridden functions
  1239. **********************************************************************/
  1240. #if 0
  1241. short sectorofwall(short nWall)
  1242. {
  1243. int l = 0, r = numsectors - 1, mid = 0;
  1244. if ( nWall < 0 )
  1245. return -1;
  1246. if ( wall[nWall].nextwall >= 0 )
  1247. return wall[wall[nWall].nextwall].nextsector;
  1248. while ( l <= r )
  1249. {
  1250. mid = (l + r) >> 1;
  1251. int nStart = sector[mid].wallptr;
  1252. int nEnd = nStart + sector[mid].wallnum - 1;
  1253. if ( nWall < nStart )
  1254. r = mid - 1;
  1255. else if (nWall > nEnd )
  1256. l = mid + 1;
  1257. else
  1258. break;
  1259. }
  1260. dassert(nWall >= sector[mid].wallptr && nWall < sector[mid].wallptr + sector[mid].wallnum);
  1261. return (short)mid;
  1262. }
  1263. void checksectorpointer(short nWall, short nSector)
  1264. {
  1265. long x1, y1, x2, y2;
  1266. if ( nWall < 0 )
  1267. return;
  1268. if ( nSector < 0 )
  1269. return;
  1270. x1 = wall[nWall].x;
  1271. y1 = wall[nWall].y;
  1272. x2 = wall[wall[nWall].point2].x;
  1273. y2 = wall[wall[nWall].point2].y;
  1274. if (wall[nWall].nextwall >= 0) //Check for early exit
  1275. {
  1276. short k = wall[nWall].nextwall;
  1277. if ((wall[k].x == x2) && (wall[k].y == y2))
  1278. if ((wall[wall[k].point2].x == x1) && (wall[wall[k].point2].y == y1))
  1279. return;
  1280. }
  1281. short startwall, endwall;
  1282. wall[nWall].nextsector = -1;
  1283. wall[nWall].nextwall = -1;
  1284. for (short j = 0; j < numsectors; j++)
  1285. {
  1286. if (j == nSector)
  1287. continue;
  1288. startwall = sector[j].wallptr;
  1289. endwall = (short)(startwall + sector[j].wallnum - 1);
  1290. for (short k = startwall; k <= endwall; k++)
  1291. {
  1292. if ((wall[k].x == x2) && (wall[k].y == y2))
  1293. if ((wall[wall[k].point2].x == x1) && (wall[wall[k].point2].y == y1))
  1294. {
  1295. wall[nWall].nextsector = j;
  1296. wall[nWall].nextwall = k;
  1297. wall[k].nextsector = nSector;
  1298. wall[k].nextwall = nWall;
  1299. }
  1300. }
  1301. }
  1302. }
  1303. #endif
  1304. void setbrightness( char /* brightness */, char * /* pal */ )
  1305. {
  1306. scrSetGamma(gGamma);
  1307. scrSetDac(0);
  1308. }
  1309. int loadboard( char *filename, long *x, long *y, long *z, short *ang, short *sectnum )
  1310. {
  1311. // don't try to load it if it doesn't exist
  1312. if (access(filename, F_OK) == -1)
  1313. return -1;
  1314. dbLoadMap(filename, x, y, z, ang, sectnum);
  1315. CleanUp();
  1316. // fix sprite type attributes
  1317. AutoAdjustSprites();
  1318. if (qsetmode != 200) // in 2D mode
  1319. {
  1320. sprintf( buffer, "Map Revisions: %i", gMapRev );
  1321. printext16(0 * 8 + 4, 0 * 8 + 28, 11, 8, buffer, 0);
  1322. }
  1323. dprintf("loadboard: highlightsectorcnt = %d\n", highlightsectorcnt);
  1324. return 0;
  1325. }
  1326. // this replaces ken's timer handler
  1327. void bstubClockStrobe( void )
  1328. {
  1329. totalclock = ++gGameClock;
  1330. keytimerstuff();
  1331. }
  1332. void inittimer( void )
  1333. {
  1334. timerRegisterClient(bstubClockStrobe, kTimerRate);
  1335. timerInstall();
  1336. }
  1337. void uninittimer( void )
  1338. {
  1339. timerRemove();
  1340. }
  1341. void initkeys( void )
  1342. {
  1343. keyInstall();
  1344. }
  1345. void uninitkeys( void )
  1346. {
  1347. keyRemove();
  1348. }
  1349. void faketimerhandler( void )
  1350. { }
  1351. /***********************************************************************
  1352. * saveboard()
  1353. *
  1354. * Saves the given board from memory into the specified filename. Returns -1
  1355. * if unable to save. If no extension is given, .MAP will be appended to the
  1356. * filename.
  1357. **********************************************************************/
  1358. int saveboard(char *filename, long *x, long *y, long *z, short *ang,
  1359. short *sectnum)
  1360. {
  1361. // fix up floor and ceiling shade values for sectors that have dynamic lighting
  1362. UndoSectorLighting();
  1363. CleanUp();
  1364. // fix sprite type attributes
  1365. AutoAdjustSprites();
  1366. dbSaveMap(filename, *x, *y, *z, *ang, *sectnum);
  1367. asksave = 0;
  1368. return 0;
  1369. }
  1370. /***********************************************************************
  1371. * ExtSaveMap()
  1372. *
  1373. * Build calls this right after the savemap() call. This function saves
  1374. * the game and object specific tag information.
  1375. **********************************************************************/
  1376. void ExtSaveMap( char * )
  1377. {
  1378. }
  1379. /***********************************************************************
  1380. * ExtPreCheckKeys()
  1381. *
  1382. * Called before drawrooms, drawmasks and nextpage in 3D mode.
  1383. *
  1384. **********************************************************************/
  1385. void ExtPreCheckKeys(void)
  1386. {
  1387. if (qsetmode == 200) // in 3D mode
  1388. {
  1389. // animate sector lighting
  1390. DoSectorLighting();
  1391. // we need this because Ken called nextpage() in build.c
  1392. switch ( vidoption )
  1393. {
  1394. case 0: // non-chained
  1395. if (chainnumpages > 1)
  1396. gPageTable[0].begin = (unsigned)chainplace;
  1397. break;
  1398. case 1: // VESA 2.0 linear buffer
  1399. gPageTable[0].begin = (unsigned)frameplace;
  1400. case 2: // memory buffered VESA/13h
  1401. break;
  1402. case 3: // Tseng ET4000
  1403. break;
  1404. case 4: // Paradise
  1405. break;
  1406. case 5: // S3
  1407. break;
  1408. case 6: // Crystal Eyes
  1409. break;
  1410. case 7: // Red/Blue Stereogram
  1411. break;
  1412. }
  1413. }
  1414. }
  1415. /***********************************************************************
  1416. * ExtAnalyzeSprites()
  1417. *
  1418. * Called between drawrooms and drawmasks in 3D mode.
  1419. *
  1420. **********************************************************************/
  1421. void ExtAnalyzeSprites(void)
  1422. {
  1423. int i, nOctant;
  1424. short nSprite, nXSprite;
  1425. long dx, dy;
  1426. for (i = 0; i < spritesortcnt; i++)
  1427. {
  1428. int nTile = tsprite[i].picnum;
  1429. dassert(nTile >= 0 && nTile < kMaxTiles);
  1430. int nFrames = picanm[nTile].frames + 1;
  1431. nSprite = tsprite[i].owner;
  1432. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  1433. int j = nSprite;
  1434. // KEN'S CODE TO SHADE SPRITES
  1435. // Add relative shading code for textures, and possibly sector cstat bit to
  1436. // indicate where shading comes from (i.e. shadows==floorshade, sky==ceilingshade)
  1437. tsprite[i].shade = (schar)ClipRange( tsprite[i].shade + 6, -128, 127 );
  1438. if ( (sector[tsprite[i].sectnum].ceilingstat & kSectorParallax)
  1439. && !(sector[tsprite[i].sectnum].floorstat & kSectorFloorShade) )
  1440. tsprite[i].shade = (schar)ClipRange( tsprite[i].shade + sector[tsprite[i].sectnum].ceilingshade, -128, 127 );
  1441. else
  1442. tsprite[i].shade = (schar)ClipRange( tsprite[i].shade + sector[tsprite[i].sectnum].floorshade, -128, 127 );
  1443. nXSprite = tsprite[i].extra;
  1444. switch ( picanm[nTile].view )
  1445. {
  1446. case kSpriteViewSingle:
  1447. if (nXSprite > 0)
  1448. {
  1449. dassert(nXSprite < kMaxXSprites);
  1450. switch ( sprite[nSprite].type )
  1451. {
  1452. case kSwitchToggle:
  1453. case kSwitchMomentary:
  1454. if ( xsprite[nXSprite].state )
  1455. tsprite[i].picnum = (short)(nTile + nFrames);
  1456. break;
  1457. case kSwitchCombination:
  1458. tsprite[i].picnum = (short)(nTile + xsprite[nXSprite].data1 * nFrames);
  1459. break;
  1460. }
  1461. }
  1462. break;
  1463. case kSpriteView5Full:
  1464. // Calculate which of the 8 angles of the sprite to draw (0-7)
  1465. dx = posx - tsprite[i].x;
  1466. dy = posy - tsprite[i].y;
  1467. RotateVector(&dx, &dy, -tsprite[i].ang + kAngle45 / 2);
  1468. nOctant = GetOctant(dx, dy);
  1469. if (nOctant <= 4)
  1470. {
  1471. tsprite[i].picnum = (short)(nTile + nOctant);
  1472. tsprite[i].cstat &= ~4; // clear x-flipping bit
  1473. }
  1474. else
  1475. {
  1476. tsprite[i].picnum = (short)(nTile + 8 - nOctant);
  1477. tsprite[i].cstat |= 4; // set x-flipping bit
  1478. }
  1479. break;
  1480. case kSpriteView8Full:
  1481. break;
  1482. case kSpriteView5Half:
  1483. break;
  1484. }
  1485. }
  1486. }
  1487. /***********************************************************************
  1488. * ExtCheckKeys()
  1489. *
  1490. * Called just before nextpage in both 2D and 3D modes.
  1491. *
  1492. **********************************************************************/
  1493. void ExtCheckKeys( void )
  1494. {
  1495. gFrameTicks = gGameClock - gFrameClock;
  1496. gFrameClock += gFrameTicks;
  1497. // autosave code
  1498. if ( gFrameClock > gSaveTime + gSaveInterval )
  1499. {
  1500. gSaveTime = gFrameClock;
  1501. if ( asksave )
  1502. {
  1503. // fix up floor and ceiling shade values for sectors that have dynamic lighting
  1504. UndoSectorLighting();
  1505. CleanUp();
  1506. // fix sprite type attributes
  1507. AutoAdjustSprites();
  1508. dbSaveMap("AUTOSAVE.MAP", posx, posy, posz, ang, cursectnum);
  1509. if (qsetmode == 200) // in 3D mode
  1510. scrSetMessage("Map autosaved to AUTOSAVE.MAP");
  1511. else
  1512. printmessage16("Map autosaved to AUTOSAVE.MAP");
  1513. }
  1514. }
  1515. CalcFrameRate();
  1516. if (qsetmode == 200) // in 3D mode
  1517. {
  1518. // animate sector lighting
  1519. UndoSectorLighting();
  1520. ProcessKeys3D();
  1521. sprintf(buffer, "%3i", gFrameRate);
  1522. printext256(xdim - 12, 0, gStdColor[kColorWhite], -1, buffer, 1);
  1523. scrDisplayMessage(gStdColor[kColorWhite]);
  1524. // animate panning sectors
  1525. if ( gPanning )
  1526. DoSectorPanning();
  1527. }
  1528. else // 2D mode
  1529. {
  1530. ProcessKeys2D();
  1531. sprintf(buffer, "%3i", gFrameRate);
  1532. printext16(640 - 24, pageoffset / 640, 15, -1, buffer, 0);
  1533. }
  1534. }
  1535. /***********************************************************************
  1536. * EditorErrorHandler()
  1537. *
  1538. * Terminate from error condition, displaying a message in text mode.
  1539. *
  1540. **********************************************************************/
  1541. ErrorResult EditorErrorHandler( const Error& error )
  1542. {
  1543. timerRemove();
  1544. uninitengine();
  1545. keyRemove();
  1546. setvmode(gOldDisplayMode);
  1547. // chain to the default error handler
  1548. return prevErrorHandler(error);
  1549. };
  1550. #define kAttrTitle (kColorGreen * 16 + kColorWhite)
  1551. /***********************************************************************
  1552. * ExtInit()
  1553. *
  1554. * Called once before BUILD.EXE makes calls to loadpics()/loadboard()
  1555. **********************************************************************/
  1556. void ExtInit(void)
  1557. {
  1558. char title[256];
  1559. int i;
  1560. void *p = NULL;
  1561. atexit(CloseBanner);
  1562. gOldDisplayMode = getvmode();
  1563. sprintf(title, "MapEdit Alpha Build [%s] -- DO NOT DISTRIBUTE", gBuildDate);
  1564. tioInit();
  1565. tioCenterString(0, 0, tioScreenCols - 1, title, kAttrTitle);
  1566. tioCenterString(tioScreenRows - 1, 0, tioScreenCols - 1,
  1567. "Copyright (c) 1994, 1995 Q Studios Corporation", kAttrTitle);
  1568. tioWindow(1, 0, tioScreenRows - 2, tioScreenCols);
  1569. if ( _grow_handles(kRequiredFiles) < kRequiredFiles )
  1570. ThrowError("Not enough file handles available", ES_ERROR);
  1571. InitializeNames();
  1572. tioPrint("Loading preferences");
  1573. gGamma = BloodINI.GetKeyInt("View", "Gamma", 0);
  1574. gBeep = MapEditINI.GetKeyBool("Options", "Beep", TRUE);
  1575. gHighlightThreshold = MapEditINI.GetKeyInt("Options", "HighlightThreshold", 40);
  1576. gStairHeight = MapEditINI.GetKeyInt("Options", "StairHeight", 8);
  1577. gOldKeyMapping = MapEditINI.GetKeyBool("Options", "OldKeyMapping", FALSE);
  1578. gSaveInterval = kTimerRate * MapEditINI.GetKeyBool("Options", "AutoSaveInterval", 5 * 60);
  1579. gLBIntensity = MapEditINI.GetKeyInt("LightBomb", "Intensity", 16);
  1580. gLBAttenuation = MapEditINI.GetKeyInt("LightBomb", "Attenuation", 0x1000);
  1581. gLBReflections = MapEditINI.GetKeyInt("LightBomb", "Reflections", 2);
  1582. gLBMaxBright = MapEditINI.GetKeyInt("LightBomb", "MaxBright", -4);
  1583. gLBRampDist = MapEditINI.GetKeyInt("LightBomb", "RampDist", 0x10000);
  1584. tioPrint("Initializing heap and resource system");
  1585. Resource::heap = new QHeap(dpmiDetermineMaxRealAlloc());
  1586. tioPrint("Initializing resource archive");
  1587. gSysRes.Init("BLOOD.RFF", "*.*");
  1588. gGuiRes.Init("GUI.RFF", NULL);
  1589. tioPrint("Initializing mouse");
  1590. if ( !initmouse() )
  1591. tioPrint("Mouse not detected");
  1592. CheckDemoDate(gSysRes);
  1593. // install our error handler
  1594. prevErrorHandler = errSetHandler(EditorErrorHandler);
  1595. InitEngine();
  1596. Mouse::SetRange(xdim, ydim);
  1597. tioPrint("Loading tiles");
  1598. if (tileInit() == 0)
  1599. ThrowError("ART files not found", ES_ERROR);
  1600. tioPrint("Loading cosine table");
  1601. trigInit(gSysRes);
  1602. scrInit();
  1603. tioPrint("Creating standard color lookups");
  1604. scrCreateStdColors();
  1605. dbInit();
  1606. visibility = 800;
  1607. kensplayerheight = 56 << 8; // eyeHeight
  1608. zmode = 0;
  1609. defaultspritecstat = kSpriteOriginAlign;
  1610. for (i = 0; i < kMaxSectors; i++)
  1611. sector[i].extra = -1;
  1612. for (i = 0; i < kMaxWalls; i++)
  1613. wall[i].extra = -1;
  1614. for (i = 0; i < kMaxSprites; i++)
  1615. sprite[i].extra = -1;
  1616. // qsetmode = 200; // inform the rest of the code that we're in 3D mode
  1617. scrSetGameMode();
  1618. }
  1619. /***********************************************************************
  1620. * ExtUnInit()
  1621. *
  1622. * Called once right before BUILD.EXE uninitengine()
  1623. **********************************************************************/
  1624. void ExtUnInit(void)
  1625. {
  1626. unlink("AUTOSAVE.MAP");
  1627. }