EDIT2D.CPP 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "engine.h"
  4. #include "bstub.h"
  5. #include "build.h"
  6. #include "misc.h"
  7. #include "trig.h"
  8. #include "globals.h"
  9. #include "textio.h"
  10. #include "gameutil.h"
  11. #include "db.h"
  12. #include "debug4g.h"
  13. #include "key.h"
  14. #include "edit2d.h"
  15. enum controlType
  16. {
  17. TEXT,
  18. NUMBER,
  19. CHECKBOX,
  20. RADIOBUTTON,
  21. LIST,
  22. DIALOG
  23. };
  24. typedef struct DIALOG_ITEM *ITEM_PTR;
  25. typedef BYTE ( *ITEM_PROC )( ITEM_PTR, BYTE key );
  26. struct DIALOG_ITEM
  27. {
  28. int x, y;
  29. int tabGroup;
  30. enum controlType type;
  31. char *label;
  32. int minValue;
  33. int maxValue;
  34. char **names;
  35. ITEM_PROC fieldHelpProc;
  36. int value;
  37. };
  38. // dialog helper function prototypes
  39. BYTE GetNextUnusedID( DIALOG_ITEM *control, BYTE key );
  40. BYTE DoSectorFXDialog( DIALOG_ITEM *control, BYTE key );
  41. /*******************************************************************************
  42. Local Variables
  43. *******************************************************************************/
  44. static char buffer[256] = "";
  45. short sectorhighlight; // which sector mouse is inside in 2d mode
  46. DIALOG_ITEM dlgSprite[] =
  47. {
  48. { 0, 0, 1, LIST, "Type %4d: %-18.18s", 0, 1023, gSpriteNames }, // 0
  49. { 0, 1, 2, NUMBER, "RX ID: %4d", 0, 1023, NULL, GetNextUnusedID }, // 1
  50. { 0, 2, 3, NUMBER, "TX ID: %4d", 0, 1023, NULL, GetNextUnusedID }, // 2
  51. { 0, 3, 4, LIST, "State %1d: %-3.3s", 0, 1, gBoolNames }, // 3
  52. { 0, 4, 5, LIST, "Cmd: %3d: %-6.6s", 0, 255, gCommandNames }, // 4
  53. { 0, 5, 0, TEXT, "Send when:" }, // 5
  54. { 0, 6, 6, CHECKBOX, "going ON" }, // 6
  55. { 0, 7, 7, CHECKBOX, "going OFF" }, // 7
  56. { 0, 8, 8, NUMBER, "busyTime = %4d", 0, 4095 }, // 8
  57. { 0, 9, 9, NUMBER, "waitTime = %4d", 0, 4095 }, // 9
  58. { 0, 10, 10, LIST, "restState %1d: %-3.3s", 0, 1, gBoolNames }, // 10
  59. { 30, 0, 0, TEXT, "Trigger On:" }, // 11
  60. { 30, 1, 11, CHECKBOX, "Push" }, // 12
  61. { 30, 2, 12, CHECKBOX, "Impact" }, // 13
  62. { 30, 3, 13, CHECKBOX, "Reserved" }, // 14
  63. { 30, 4, 14, CHECKBOX, "Pickup" }, // 15
  64. { 30, 5, 15, CHECKBOX, "Touch" }, // 16
  65. { 30, 6, 16, CHECKBOX, "Sight" }, // 17
  66. { 30, 7, 17, CHECKBOX, "Proximity" }, // 18
  67. { 46, 0, 0, TEXT, "Trigger Flags:" }, // 19
  68. { 46, 1, 18, CHECKBOX, "Decoupled" }, // 20
  69. { 46, 2, 19, CHECKBOX, "1-shot" }, // 21
  70. { 46, 3, 20, CHECKBOX, "Locked" }, // 22
  71. { 46, 4, 21, CHECKBOX, "Interruptable" }, // 23
  72. { 46, 5, 22, NUMBER, "Data1: %5d", 0, 65535 }, // 24
  73. { 46, 6, 23, NUMBER, "Data2: %5d", 0, 65535 }, // 25
  74. { 46, 7, 24, NUMBER, "Data3: %5d", 0, 65535 }, // 26
  75. { 46, 8, 25, NUMBER, "Key: %1d", 0, 7 }, // 27
  76. { 46, 9, 26, NUMBER, "Sound: %3d", 0, 255 }, // 28
  77. { 46, 10, 27, NUMBER, "Difficulty: %1d", 0, 3 }, // 29
  78. { 62, 0, 0, TEXT, "Respawn:" }, // 30
  79. { 62, 1, 28, LIST, "When %1d: %-6.6s", 0, 3, gRespawnNames }, // 31
  80. { 62, 2, 29, NUMBER, "Time = %4d", 0, 4095 }, // 32
  81. { 62, 4, 0, TEXT, "Dude Flags:" }, // 33
  82. { 62, 5, 30, CHECKBOX, "dudeDeaf" }, // 34
  83. { 62, 6, 31, CHECKBOX, "dudeAmbush" }, // 35
  84. { 62, 7, 32, CHECKBOX, "dudeGuard" }, // 36
  85. { 62, 8, 33, CHECKBOX, "reserved" }, // 37
  86. };
  87. DIALOG_ITEM dlgWall[] =
  88. {
  89. { 0, 0, 1, LIST, "Type %4d: %-18.18s", 0, 1023, gWallNames }, // 0
  90. { 0, 1, 2, NUMBER, "RX ID: %4d", 0, 1023, NULL, GetNextUnusedID }, // 1
  91. { 0, 2, 3, NUMBER, "TX ID: %4d", 0, 1023, NULL, GetNextUnusedID }, // 2
  92. { 0, 3, 4, LIST, "State %1d: %-3.3s", 0, 1, gBoolNames }, // 3
  93. { 0, 4, 5, LIST, "Cmd: %3d: %-6.6s", 0, 255, gCommandNames }, // 4
  94. { 0, 5, 0, TEXT, "Send when:" }, // 5
  95. { 0, 6, 6, CHECKBOX, "going ON" }, // 6
  96. { 0, 7, 7, CHECKBOX, "going OFF" }, // 7
  97. { 0, 8, 8, NUMBER, "busyTime = %4d", 0, 4095 }, // 8
  98. { 0, 9, 9, NUMBER, "waitTime = %4d", 0, 4095 }, // 9
  99. { 0, 10, 10, LIST, "restState %1d: %-3.3s", 0, 1, gBoolNames }, // 10
  100. { 30, 0, 0, TEXT, "Trigger On:" }, // 11
  101. { 30, 1, 11, CHECKBOX, "Push" }, // 12
  102. { 30, 2, 12, CHECKBOX, "Impact" }, // 13
  103. { 30, 3, 13, CHECKBOX, "Reserved" }, // 14
  104. { 46, 0, 0, TEXT, "Trigger Flags:" }, // 15
  105. { 46, 1, 14, CHECKBOX, "Decoupled" }, // 16
  106. { 46, 2, 15, CHECKBOX, "1-shot" }, // 17
  107. { 46, 3, 16, CHECKBOX, "Locked" }, // 18
  108. { 46, 4, 17, CHECKBOX, "Interruptable" }, // 19
  109. { 46, 6, 18, NUMBER, "Data: %5d", 0, 65535 }, // 20
  110. { 46, 7, 19, NUMBER, "Key: %1d", 0, 7 }, // 21
  111. { 46, 8, 20, NUMBER, "panX = %4d", -128, 127 }, // 22
  112. { 46, 9, 21, NUMBER, "panY = %4d", -128, 127 }, // 23
  113. { 46, 10, 22, CHECKBOX, "panAlways" }, // 24
  114. };
  115. DIALOG_ITEM dlgSectorFX[] =
  116. {
  117. { 0, 0, 0, TEXT, "Lighting:" }, // 0
  118. { 0, 1, 1, LIST, "Wave: %1d %-9.9s", 0, 15, gWaveNames }, // 1
  119. { 0, 2, 2, NUMBER, "Amplitude: %+4d", -128, 127 }, // 2
  120. { 0, 3, 3, NUMBER, "Freq: %3d", 0, 255 }, // 3
  121. { 0, 4, 4, NUMBER, "Phase: %3d", 0, 255 }, // 4
  122. { 0, 5, 5, CHECKBOX, "floor" }, // 5
  123. { 0, 6, 6, CHECKBOX, "ceiling" }, // 6
  124. { 0, 7, 7, CHECKBOX, "walls" }, // 7
  125. { 0, 8, 8, CHECKBOX, "shadeAlways" }, // 8
  126. { 20, 0, 0, TEXT, "Motion FX:" }, // 9
  127. { 20, 1, 9, NUMBER, "Speed = %4d", 0, 255 }, // 10
  128. { 20, 2, 10, NUMBER, "Angle = %4d", 0, kAngle360-1 }, // 11
  129. { 20, 3, 11, CHECKBOX, "pan floor" }, // 12
  130. { 20, 4, 12, CHECKBOX, "pan ceiling" }, // 13
  131. { 20, 5, 13, CHECKBOX, "panAlways" }, // 14
  132. { 20, 6, 14, CHECKBOX, "drag" }, // 15
  133. { 35, 2, 15, LIST, "Depth = %1d: %-5.5s", 0, 3, gDepthNames }, // 16
  134. { 35, 3, 16, LIST, "Under = %1d: %-3.3s", 0, 1, gBoolNames }, // 17
  135. { 35, 4, 17, LIST, "Wind = %1d: %-3.3s", 0, 1, gBoolNames}, // 18
  136. };
  137. DIALOG_ITEM dlgSector[] =
  138. {
  139. { 0, 0, 1, LIST, "Type %4d: %-18.18s", 0, 1023, gSectorNames }, // 0
  140. { 0, 1, 2, NUMBER, "RX ID: %4d", 0, 1023, NULL, GetNextUnusedID }, // 1
  141. { 0, 2, 3, NUMBER, "TX ID: %4d", 0, 1023, NULL, GetNextUnusedID }, // 2
  142. { 0, 3, 4, LIST, "State %1d: %-3.3s", 0, 1, gBoolNames }, // 3
  143. { 0, 4, 5, LIST, "Cmd: %3d: %-6.6s", 0, 255, gCommandNames }, // 4
  144. { 0, 5, 0, TEXT, "Send when:" }, // 5
  145. { 0, 6, 6, CHECKBOX, "going ON" }, // 6
  146. { 0, 7, 7, CHECKBOX, "going OFF" }, // 7
  147. { 0, 8, 8, NUMBER, "busyTime = %3d", 0, 255 }, // 8
  148. { 0, 9, 9, NUMBER, "waitTime = %3d", 0, 255 }, // 9
  149. { 0, 10, 10, LIST, "restState %1d: %-3.3s", 0, 1, gBoolNames }, // 10
  150. { 30, 0, 0, TEXT, "Trigger On:" }, // 11
  151. { 30, 1, 11, CHECKBOX, "Push" }, // 12
  152. { 30, 2, 12, CHECKBOX, "Impact" }, // 13
  153. { 30, 3, 13, CHECKBOX, "Reserved" }, // 14
  154. { 30, 4, 14, CHECKBOX, "Enter" }, // 15
  155. { 30, 5, 15, CHECKBOX, "Exit" }, // 16
  156. { 30, 6, 16, CHECKBOX, "WallPush" }, // 17
  157. { 46, 0, 0, TEXT, "Trigger Flags:" }, // 18
  158. { 46, 1, 17, CHECKBOX, "Decoupled" }, // 19
  159. { 46, 2, 18, CHECKBOX, "1-shot" }, // 20
  160. { 46, 3, 19, CHECKBOX, "Locked" }, // 21
  161. { 46, 4, 20, CHECKBOX, "Interruptable" }, // 22
  162. { 46, 6, 21, NUMBER, "Data: %5d", 0, 65535 }, // 23
  163. { 46, 7, 22, NUMBER, "Key: %1d", 0, 7 }, // 24
  164. { 65, 10, 23, DIALOG, "EFFECTS...", 0, 0, NULL, DoSectorFXDialog }, // 25
  165. };
  166. void DialogText( int x, int y, short nFore, short nBack, char *string)
  167. {
  168. printext16(x * 8 + 4, y * 8 + 28, nFore, nBack, string, 0);
  169. }
  170. /***********************************************************************
  171. * PaintDialogItem()
  172. *
  173. **********************************************************************/
  174. void PaintDialogItem(DIALOG_ITEM *control, int focus)
  175. {
  176. short foreColor = 11, backColor = 8;
  177. if ( focus )
  178. {
  179. foreColor = 14;
  180. backColor = 0;
  181. }
  182. if (control->tabGroup == 0)
  183. {
  184. foreColor = 15;
  185. backColor = 2;
  186. }
  187. switch ( control->type )
  188. {
  189. case TEXT:
  190. case DIALOG:
  191. DialogText(control->x, control->y, foreColor, backColor, control->label);
  192. break;
  193. case NUMBER:
  194. sprintf(buffer, control->label, control->value);
  195. DialogText(control->x, control->y, foreColor, backColor, buffer);
  196. break;
  197. case LIST:
  198. dassert(control->names != NULL);
  199. sprintf(buffer, control->label, control->value, control->names[control->value]);
  200. DialogText(control->x, control->y, foreColor, backColor, buffer);
  201. break;
  202. case CHECKBOX:
  203. sprintf(buffer, "%c %s", control->value ? 3 : 2, control->label);
  204. DialogText(control->x, control->y, foreColor, backColor, buffer);
  205. break;
  206. case RADIOBUTTON:
  207. sprintf(buffer, "%c %s", control->value ? 5 : 4, control->label);
  208. DialogText(control->x, control->y, foreColor, backColor, buffer);
  209. break;
  210. }
  211. }
  212. /***********************************************************************
  213. * PaintDialog()
  214. *
  215. **********************************************************************/
  216. void PaintDialog(DIALOG_ITEM *dialog, int count)
  217. {
  218. int i;
  219. clearmidstatbar16();
  220. for ( i = 0; i < count; i++ )
  221. {
  222. PaintDialogItem(&dialog[i], kFalse);
  223. }
  224. }
  225. /***********************************************************************
  226. * FindGroup()
  227. *
  228. **********************************************************************/
  229. DIALOG_ITEM *FindGroup(DIALOG_ITEM *dialog, int count, int group)
  230. {
  231. DIALOG_ITEM *control;
  232. for ( control = dialog; control < &dialog[count]; control++)
  233. {
  234. if ( control->tabGroup == group )
  235. break;
  236. }
  237. dassert(control < &dialog[count]);
  238. if ( control->type == RADIOBUTTON )
  239. {
  240. while ( control->value == kFalse )
  241. {
  242. control++;
  243. dassert(control < &dialog[count]);
  244. dassert(control->type == RADIOBUTTON);
  245. }
  246. }
  247. return control;
  248. }
  249. /***********************************************************************
  250. * SetControlValue()
  251. *
  252. **********************************************************************/
  253. void SetControlValue(DIALOG_ITEM *dialog, int count, int group, int value )
  254. {
  255. int i;
  256. for ( i = 0; i < count; i++)
  257. {
  258. if ( dialog[i].tabGroup == group )
  259. break;
  260. }
  261. dassert(i < count);
  262. dialog[i].value = value;
  263. }
  264. /***********************************************************************
  265. * GetControlValue()
  266. *
  267. **********************************************************************/
  268. int GetControlValue(DIALOG_ITEM *dialog, int count, int group )
  269. {
  270. int i;
  271. int value = 0;
  272. for ( i = 0; i < count; i++)
  273. {
  274. if ( dialog[i].tabGroup == group )
  275. break;
  276. }
  277. dassert(i < count);
  278. return dialog[i].value;
  279. }
  280. /***********************************************************************
  281. * SetRadioButton()
  282. *
  283. **********************************************************************/
  284. void SetRadioButton(DIALOG_ITEM *dialog, int count, int group, int value )
  285. {
  286. int i;
  287. for ( i = 0; i < count; i++)
  288. {
  289. if ( dialog[i].tabGroup == group )
  290. break;
  291. }
  292. dassert(i < count);
  293. while ( i < count && dialog[i].tabGroup == group )
  294. {
  295. dialog[i].value = (value == 0);
  296. i++;
  297. value--;
  298. }
  299. dassert(value < 0);
  300. }
  301. /***********************************************************************
  302. * GetRadioButton()
  303. *
  304. **********************************************************************/
  305. int GetRadioButton(DIALOG_ITEM *dialog, int count, int group )
  306. {
  307. int i;
  308. int value = 0;
  309. for ( i = 0; i < count; i++)
  310. {
  311. if ( dialog[i].tabGroup == group )
  312. break;
  313. }
  314. dassert(i < count);
  315. while ( i < count )
  316. {
  317. dassert(dialog[i].type == RADIOBUTTON);
  318. if ( dialog[i].value )
  319. break;
  320. i++;
  321. value++;
  322. }
  323. dassert(i < count);
  324. return value;
  325. }
  326. /*******************************************************************************
  327. FUNCTION: EditDialog()
  328. DESCRIPTION: This is the editing event loop for dialogs.
  329. PARAMETERS: dialog is a pointer to the first control, count is the
  330. number of controls within the dialog.
  331. RETURNS: 1 if exited via Enter, 0 if exited with Esc
  332. *******************************************************************************/
  333. int EditDialog(DIALOG_ITEM *dialog, int count)
  334. {
  335. int group = 1, lastGroup = 0;
  336. int i, value, oldValue;
  337. DIALOG_ITEM *control;
  338. BYTE key = 0;
  339. keyFlushStream();
  340. PaintDialog(dialog, count);
  341. for ( i = 0; i < count; i++ )
  342. {
  343. if ( dialog[i].tabGroup > lastGroup )
  344. lastGroup = dialog[i].tabGroup;
  345. }
  346. control = FindGroup(dialog, count, group);
  347. while ( 1 )
  348. {
  349. PaintDialogItem(control, kTrue);
  350. do
  351. {
  352. key = keyGet();
  353. } while ( key == 0 );
  354. if ( control->fieldHelpProc )
  355. {
  356. key = control->fieldHelpProc(control, key);
  357. // may need to repaint all in case of subdialogs
  358. PaintDialog(dialog, count);
  359. }
  360. switch ( key )
  361. {
  362. case KEY_ENTER:
  363. case KEY_PADENTER:
  364. keystatus[key] = 0; // need to clear in 2D mode, got it?
  365. BeepOkay();
  366. return 1;
  367. case KEY_ESC:
  368. keystatus[key] = 0;
  369. return 0;
  370. case KEY_LEFT:
  371. if ( --group == 0 )
  372. group = lastGroup;
  373. PaintDialogItem(control, kFalse);
  374. control = FindGroup(dialog, count, group);
  375. break;
  376. case KEY_RIGHT:
  377. if ( ++group > lastGroup )
  378. group = 1;
  379. PaintDialogItem(control, kFalse);
  380. control = FindGroup(dialog, count, group);
  381. break;
  382. case KEY_TAB:
  383. if ( keystatus[KEY_LSHIFT] || keystatus[KEY_RSHIFT] )
  384. {
  385. if ( --group == 0 )
  386. group = lastGroup;
  387. PaintDialogItem(control, kFalse);
  388. control = FindGroup(dialog, count, group);
  389. break;
  390. }
  391. else
  392. {
  393. if ( ++group > lastGroup )
  394. group = 1;
  395. PaintDialogItem(control, kFalse);
  396. control = FindGroup(dialog, count, group);
  397. break;
  398. }
  399. default:
  400. switch ( control->type )
  401. {
  402. case NUMBER:
  403. oldValue = control->value;
  404. switch ( key )
  405. {
  406. case KEY_BACKSPACE:
  407. control->value /= 10;
  408. break;
  409. case KEY_PADPLUS:
  410. case KEY_UP:
  411. control->value++;
  412. break;
  413. case KEY_PADMINUS:
  414. case KEY_DOWN:
  415. control->value--;
  416. break;
  417. case KEY_PAGEUP:
  418. control->value = IncBy(control->value, 10);
  419. break;
  420. case KEY_PAGEDN:
  421. control->value = DecBy(control->value, 10);
  422. break;
  423. default:
  424. key = ScanToAscii[key];
  425. if ( key >= '0' && key <= '9' )
  426. control->value = control->value * 10 + key - '0';
  427. }
  428. if ( control->value > control->maxValue )
  429. control->value = control->maxValue;
  430. if ( control->value < control->minValue )
  431. control->value = control->minValue;
  432. break;
  433. case CHECKBOX:
  434. switch ( key )
  435. {
  436. case KEY_SPACE:
  437. control->value = !control->value;
  438. break;
  439. }
  440. break;
  441. case RADIOBUTTON:
  442. PaintDialogItem(control, kFalse);
  443. switch ( key )
  444. {
  445. case KEY_UP:
  446. control->value = kFalse;
  447. PaintDialogItem(control, kFalse);
  448. do
  449. {
  450. if (--control < dialog)
  451. control = &dialog[count - 1];
  452. } while ( control->tabGroup != group );
  453. control->value = kTrue;
  454. break;
  455. case KEY_DOWN:
  456. control->value = kFalse;
  457. PaintDialogItem(control, kFalse);
  458. do
  459. {
  460. if (++control == &dialog[count])
  461. control = dialog;
  462. } while ( control->tabGroup != group );
  463. control->value = kTrue;
  464. break;
  465. }
  466. break;
  467. case LIST:
  468. oldValue = control->value;
  469. value = control->value;
  470. switch ( key )
  471. {
  472. case KEY_PADPLUS:
  473. case KEY_UP:
  474. do
  475. {
  476. value++;
  477. } while ( value <= control->maxValue && control->names[value] == NULL );
  478. break;
  479. case KEY_PADMINUS:
  480. case KEY_DOWN:
  481. do
  482. {
  483. value--;
  484. } while ( value >= control->minValue && control->names[value] == NULL );
  485. break;
  486. case KEY_PAGEUP:
  487. do
  488. {
  489. value = IncBy(value, 10);
  490. } while ( value <= control->maxValue && control->names[value] == NULL );
  491. break;
  492. case KEY_PAGEDN:
  493. do
  494. {
  495. value = DecBy(value, 10);
  496. } while ( value >= control->minValue && control->names[value] == NULL );
  497. break;
  498. }
  499. if ( value >= control->minValue && value <= control->maxValue && control->names[value] != NULL )
  500. control->value = value;
  501. break;
  502. }
  503. }
  504. }
  505. }
  506. BYTE GetNextUnusedID( DIALOG_ITEM *control, BYTE key )
  507. {
  508. BOOL used[1024];
  509. int i;
  510. switch ( key )
  511. {
  512. case KEY_F10:
  513. memset(used, FALSE, sizeof(used));
  514. for (i = 0; i < numsectors; i++)
  515. {
  516. int nXSector = sector[i].extra;
  517. if ( nXSector > 0 )
  518. {
  519. used[xsector[nXSector].txID] = TRUE;
  520. used[xsector[nXSector].rxID] = TRUE;
  521. }
  522. }
  523. for (i = 0; i < numwalls; i++)
  524. {
  525. int nXWall = wall[i].extra;
  526. if ( nXWall > 0 )
  527. {
  528. used[xwall[nXWall].txID] = TRUE;
  529. used[xwall[nXWall].rxID] = TRUE;
  530. }
  531. }
  532. for (i = 0; i < kMaxSprites; i++)
  533. {
  534. if ( sprite[i].statnum < kMaxStatus )
  535. {
  536. int nXSprite = sprite[i].extra;
  537. if ( nXSprite > 0 )
  538. {
  539. used[xsprite[nXSprite].txID] = TRUE;
  540. used[xsprite[nXSprite].rxID] = TRUE;
  541. }
  542. }
  543. }
  544. // find the first unused id
  545. for (i = 100; i < 1024; i++)
  546. if ( !used[i] )
  547. break;
  548. control->value = i;
  549. return 0;
  550. }
  551. return key;
  552. }
  553. BYTE DoSectorFXDialog( DIALOG_ITEM * /* control */, BYTE key )
  554. {
  555. switch ( key )
  556. {
  557. case KEY_ENTER:
  558. if ( EditDialog(dlgSectorFX, LENGTH(dlgSectorFX)) )
  559. return KEY_ENTER;
  560. return 0;
  561. }
  562. return key;
  563. }
  564. /***********************************************************************
  565. * XWallToDialog()
  566. *
  567. **********************************************************************/
  568. void XWallToDialog( int nWall )
  569. {
  570. int nXWall = wall[nWall].extra;
  571. dassert(nXWall > 0 && nXWall < kMaxXWalls);
  572. dlgWall[0].value = wall[nWall].type;
  573. dlgWall[1].value = xwall[nXWall].rxID;
  574. dlgWall[2].value = xwall[nXWall].txID;
  575. dlgWall[3].value = xwall[nXWall].state;
  576. dlgWall[4].value = xwall[nXWall].command;
  577. dlgWall[6].value = xwall[nXWall].triggerOn;
  578. dlgWall[7].value = xwall[nXWall].triggerOff;
  579. dlgWall[8].value = xwall[nXWall].busyTime;
  580. dlgWall[9].value = xwall[nXWall].waitTime;
  581. dlgWall[10].value = xwall[nXWall].restState;
  582. dlgWall[12].value = xwall[nXWall].triggerPush;
  583. dlgWall[13].value = xwall[nXWall].triggerImpact;
  584. dlgWall[14].value = xwall[nXWall].triggerReserved0;
  585. dlgWall[16].value = xwall[nXWall].decoupled;
  586. dlgWall[17].value = xwall[nXWall].triggerOnce;
  587. dlgWall[18].value = xwall[nXWall].locked;
  588. dlgWall[19].value = xwall[nXWall].interruptable;
  589. dlgWall[20].value = xwall[nXWall].data;
  590. dlgWall[21].value = xwall[nXWall].key;
  591. dlgWall[22].value = xwall[nXWall].panXVel;
  592. dlgWall[23].value = xwall[nXWall].panYVel;
  593. dlgWall[24].value = xwall[nXWall].panAlways;
  594. }
  595. /***********************************************************************
  596. * DialogToXWall()
  597. *
  598. **********************************************************************/
  599. void DialogToXWall( int nWall )
  600. {
  601. int nXWall = wall[nWall].extra;
  602. dassert(nXWall > 0 && nXWall < kMaxXWalls);
  603. wall[nWall].type= (short)dlgWall[0].value;
  604. xwall[nXWall].rxID= dlgWall[1].value;
  605. xwall[nXWall].txID= dlgWall[2].value;
  606. xwall[nXWall].state= dlgWall[3].value;
  607. xwall[nXWall].command= dlgWall[4].value;
  608. xwall[nXWall].triggerOn= dlgWall[6].value;
  609. xwall[nXWall].triggerOff= dlgWall[7].value;
  610. xwall[nXWall].busyTime= dlgWall[8].value;
  611. xwall[nXWall].waitTime= dlgWall[9].value;
  612. xwall[nXWall].restState= dlgWall[10].value;
  613. xwall[nXWall].triggerPush= dlgWall[12].value;
  614. xwall[nXWall].triggerImpact= dlgWall[13].value;
  615. xwall[nXWall].triggerReserved0= dlgWall[14].value;
  616. xwall[nXWall].decoupled= dlgWall[16].value;
  617. xwall[nXWall].triggerOnce= dlgWall[17].value;
  618. xwall[nXWall].locked= dlgWall[18].value;
  619. xwall[nXWall].interruptable= dlgWall[19].value;
  620. xwall[nXWall].data= dlgWall[20].value;
  621. xwall[nXWall].key= dlgWall[21].value;
  622. xwall[nXWall].panXVel= dlgWall[22].value;
  623. xwall[nXWall].panYVel= dlgWall[23].value;
  624. xwall[nXWall].panAlways= dlgWall[24].value;
  625. }
  626. /***********************************************************************
  627. * XSpriteToDialog()
  628. *
  629. **********************************************************************/
  630. void XSpriteToDialog( int nSprite )
  631. {
  632. int nXSprite = sprite[nSprite].extra;
  633. dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
  634. dlgSprite[0].value = sprite[nSprite].type;
  635. dlgSprite[1].value = xsprite[nXSprite].rxID;
  636. dlgSprite[2].value = xsprite[nXSprite].txID;
  637. dlgSprite[3].value = xsprite[nXSprite].state;
  638. dlgSprite[4].value = xsprite[nXSprite].command;
  639. dlgSprite[6].value = xsprite[nXSprite].triggerOn;
  640. dlgSprite[7].value = xsprite[nXSprite].triggerOff;
  641. dlgSprite[8].value = xsprite[nXSprite].busyTime;
  642. dlgSprite[9].value = xsprite[nXSprite].waitTime;
  643. dlgSprite[10].value = xsprite[nXSprite].restState;
  644. dlgSprite[12].value = xsprite[nXSprite].triggerPush;
  645. dlgSprite[13].value = xsprite[nXSprite].triggerImpact;
  646. dlgSprite[14].value = xsprite[nXSprite].triggerReserved0;
  647. dlgSprite[15].value = xsprite[nXSprite].triggerPickup;
  648. dlgSprite[16].value = xsprite[nXSprite].triggerTouch;
  649. dlgSprite[17].value = xsprite[nXSprite].triggerSight;
  650. dlgSprite[18].value = xsprite[nXSprite].triggerProximity;
  651. dlgSprite[20].value = xsprite[nXSprite].decoupled;
  652. dlgSprite[21].value = xsprite[nXSprite].triggerOnce;
  653. dlgSprite[22].value = xsprite[nXSprite].locked;
  654. dlgSprite[23].value = xsprite[nXSprite].interruptable;
  655. dlgSprite[24].value = xsprite[nXSprite].data1;
  656. dlgSprite[25].value = xsprite[nXSprite].data2;
  657. dlgSprite[26].value = xsprite[nXSprite].data3;
  658. dlgSprite[27].value = xsprite[nXSprite].key;
  659. dlgSprite[28].value = xsprite[nXSprite].soundId;
  660. dlgSprite[29].value = xsprite[nXSprite].difficulty;
  661. dlgSprite[31].value = xsprite[nXSprite].respawn;
  662. dlgSprite[32].value = xsprite[nXSprite].respawnTime;
  663. dlgSprite[34].value = xsprite[nXSprite].dudeDeaf;
  664. dlgSprite[35].value = xsprite[nXSprite].dudeAmbush;
  665. dlgSprite[36].value = xsprite[nXSprite].dudeGuard;
  666. dlgSprite[37].value = xsprite[nXSprite].dudeFlag4;
  667. }
  668. /***********************************************************************
  669. * DialogToXSprite()
  670. *
  671. **********************************************************************/
  672. void DialogToXSprite( int nSprite )
  673. {
  674. int nXSprite = sprite[nSprite].extra;
  675. dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
  676. sprite[nSprite].type = (short)dlgSprite[0].value;
  677. xsprite[nXSprite].rxID = dlgSprite[1].value;
  678. xsprite[nXSprite].txID = dlgSprite[2].value;
  679. xsprite[nXSprite].state = dlgSprite[3].value;
  680. xsprite[nXSprite].command = dlgSprite[4].value;
  681. xsprite[nXSprite].triggerOn = dlgSprite[6].value;
  682. xsprite[nXSprite].triggerOff = dlgSprite[7].value;
  683. xsprite[nXSprite].busyTime = dlgSprite[8].value;
  684. xsprite[nXSprite].waitTime = dlgSprite[9].value;
  685. xsprite[nXSprite].restState = dlgSprite[10].value;
  686. xsprite[nXSprite].triggerPush = dlgSprite[12].value;
  687. xsprite[nXSprite].triggerImpact = dlgSprite[13].value;
  688. xsprite[nXSprite].triggerReserved0 = dlgSprite[14].value;
  689. xsprite[nXSprite].triggerPickup = dlgSprite[15].value;
  690. xsprite[nXSprite].triggerTouch = dlgSprite[16].value;
  691. xsprite[nXSprite].triggerSight = dlgSprite[17].value;
  692. xsprite[nXSprite].triggerProximity = dlgSprite[18].value;
  693. xsprite[nXSprite].decoupled = dlgSprite[20].value;
  694. xsprite[nXSprite].triggerOnce = dlgSprite[21].value;
  695. xsprite[nXSprite].locked = dlgSprite[22].value;
  696. xsprite[nXSprite].interruptable = dlgSprite[23].value;
  697. xsprite[nXSprite].data1 = dlgSprite[24].value;
  698. xsprite[nXSprite].data2 = dlgSprite[25].value;
  699. xsprite[nXSprite].data3 = dlgSprite[26].value;
  700. xsprite[nXSprite].key = dlgSprite[27].value;
  701. xsprite[nXSprite].soundId = dlgSprite[28].value;
  702. xsprite[nXSprite].difficulty = dlgSprite[29].value;
  703. xsprite[nXSprite].respawn = dlgSprite[31].value;
  704. xsprite[nXSprite].respawnTime = dlgSprite[32].value;
  705. xsprite[nXSprite].dudeDeaf= dlgSprite[34].value;
  706. xsprite[nXSprite].dudeAmbush= dlgSprite[35].value;
  707. xsprite[nXSprite].dudeGuard= dlgSprite[36].value;
  708. xsprite[nXSprite].dudeFlag4= dlgSprite[37].value;
  709. }
  710. /***********************************************************************
  711. * XSectorToDialog()
  712. *
  713. **********************************************************************/
  714. void XSectorToDialog( int nSector )
  715. {
  716. int nXSector = sector[nSector].extra;
  717. dassert(nXSector > 0 && nXSector < kMaxXSectors);
  718. dlgSector[0].value = (short)sector[nSector].type;
  719. dlgSector[1].value = xsector[nXSector].rxID;
  720. dlgSector[2].value = xsector[nXSector].txID;
  721. dlgSector[3].value = xsector[nXSector].state;
  722. dlgSector[4].value = xsector[nXSector].command;
  723. dlgSector[6].value = xsector[nXSector].triggerOn;
  724. dlgSector[7].value = xsector[nXSector].triggerOff;
  725. dlgSector[8].value = xsector[nXSector].busyTime;
  726. dlgSector[9].value = xsector[nXSector].waitTime;
  727. dlgSector[10].value = xsector[nXSector].restState;
  728. dlgSector[12].value = xsector[nXSector].triggerPush;
  729. dlgSector[13].value = xsector[nXSector].triggerImpact;
  730. dlgSector[14].value = xsector[nXSector].triggerReserved0;
  731. dlgSector[15].value = xsector[nXSector].triggerEnter;
  732. dlgSector[16].value = xsector[nXSector].triggerExit;
  733. dlgSector[17].value = xsector[nXSector].triggerWPush;
  734. dlgSector[19].value = xsector[nXSector].decoupled;
  735. dlgSector[20].value = xsector[nXSector].triggerOnce;
  736. dlgSector[21].value = xsector[nXSector].locked;
  737. dlgSector[22].value = xsector[nXSector].interruptable;
  738. dlgSector[23].value = xsector[nXSector].data;
  739. dlgSector[24].value = xsector[nXSector].key;
  740. dlgSectorFX[1].value = xsector[nXSector].wave;
  741. dlgSectorFX[2].value = xsector[nXSector].amplitude;
  742. dlgSectorFX[3].value = xsector[nXSector].freq;
  743. dlgSectorFX[4].value = xsector[nXSector].phase;
  744. dlgSectorFX[5].value = xsector[nXSector].shadeFloor;
  745. dlgSectorFX[6].value = xsector[nXSector].shadeCeiling;
  746. dlgSectorFX[7].value = xsector[nXSector].shadeWalls;
  747. dlgSectorFX[8].value = xsector[nXSector].shadeAlways;
  748. dlgSectorFX[10].value = xsector[nXSector].panVel;
  749. dlgSectorFX[11].value = xsector[nXSector].panAngle;
  750. dlgSectorFX[12].value = xsector[nXSector].panFloor;
  751. dlgSectorFX[13].value = xsector[nXSector].panCeiling;
  752. dlgSectorFX[14].value = xsector[nXSector].panAlways;
  753. dlgSectorFX[15].value = xsector[nXSector].drag;
  754. dlgSectorFX[16].value = xsector[nXSector].depth;
  755. dlgSectorFX[17].value = xsector[nXSector].underwater;
  756. dlgSectorFX[18].value = xsector[nXSector].wind;
  757. }
  758. /***********************************************************************
  759. * DialogToXSector()
  760. *
  761. **********************************************************************/
  762. void DialogToXSector( int nSector )
  763. {
  764. int nXSector = sector[nSector].extra;
  765. dassert(nXSector > 0 && nXSector < kMaxXSectors);
  766. sector[nSector].type = (short)dlgSector[0].value;
  767. xsector[nXSector].rxID = dlgSector[1].value;
  768. xsector[nXSector].txID = dlgSector[2].value;
  769. xsector[nXSector].state = dlgSector[3].value;
  770. xsector[nXSector].command = dlgSector[4].value;
  771. xsector[nXSector].triggerOn = dlgSector[6].value;
  772. xsector[nXSector].triggerOff = dlgSector[7].value;
  773. xsector[nXSector].busyTime = dlgSector[8].value;
  774. xsector[nXSector].waitTime = dlgSector[9].value;
  775. xsector[nXSector].restState = dlgSector[10].value;
  776. xsector[nXSector].triggerPush = dlgSector[12].value;
  777. xsector[nXSector].triggerImpact = dlgSector[13].value;
  778. xsector[nXSector].triggerReserved0 = dlgSector[14].value;
  779. xsector[nXSector].triggerEnter = dlgSector[15].value;
  780. xsector[nXSector].triggerExit = dlgSector[16].value;
  781. xsector[nXSector].triggerWPush = dlgSector[17].value;
  782. xsector[nXSector].decoupled = dlgSector[19].value;
  783. xsector[nXSector].triggerOnce = dlgSector[20].value;
  784. xsector[nXSector].locked = dlgSector[21].value;
  785. xsector[nXSector].interruptable = dlgSector[22].value;
  786. xsector[nXSector].data = dlgSector[23].value;
  787. xsector[nXSector].key = dlgSector[24].value;
  788. xsector[nXSector].wave = dlgSectorFX[1].value;
  789. xsector[nXSector].amplitude = dlgSectorFX[2].value;
  790. xsector[nXSector].freq = dlgSectorFX[3].value;
  791. xsector[nXSector].phase = dlgSectorFX[4].value;
  792. xsector[nXSector].shadeFloor = dlgSectorFX[5].value;
  793. xsector[nXSector].shadeCeiling = dlgSectorFX[6].value;
  794. xsector[nXSector].shadeWalls = dlgSectorFX[7].value;
  795. xsector[nXSector].shadeAlways = dlgSectorFX[8].value;
  796. xsector[nXSector].panVel = dlgSectorFX[10].value;
  797. xsector[nXSector].panAngle = dlgSectorFX[11].value;
  798. xsector[nXSector].panFloor = dlgSectorFX[12].value;
  799. xsector[nXSector].panCeiling = dlgSectorFX[13].value;
  800. xsector[nXSector].panAlways = dlgSectorFX[14].value;
  801. xsector[nXSector].drag = dlgSectorFX[15].value;
  802. xsector[nXSector].depth = dlgSectorFX[16].value;
  803. xsector[nXSector].underwater = dlgSectorFX[17].value;
  804. xsector[nXSector].wind = dlgSectorFX[18].value;
  805. }
  806. int getpointhighlight(int x, int y)
  807. {
  808. long i, d, closest, n;
  809. closest = divscale(gHighlightThreshold, zoom, 14);
  810. n = -1;
  811. for (i = 0; i < kMaxSprites; i++)
  812. {
  813. if (sprite[i].statnum < kMaxStatus)
  814. {
  815. d = qdist(x - sprite[i].x, y - sprite[i].y);
  816. if (d < closest)
  817. {
  818. closest = d;
  819. n = i | 0x4000;
  820. }
  821. }
  822. }
  823. for (i = 0; i < numwalls; i++)
  824. {
  825. d = qdist(x - wall[i].x, y - wall[i].y);
  826. if (d < closest)
  827. {
  828. closest = d;
  829. n = i;
  830. }
  831. }
  832. return n;
  833. }
  834. /***********************************************************************
  835. * ShowSectorData()
  836. *
  837. * This function displays the game specific sector data in the status
  838. * area.
  839. **********************************************************************/
  840. void ShowSectorData( int nSector )
  841. {
  842. int nXSector;
  843. dassert(nSector >= 0 && nSector < kMaxSectors);
  844. sprintf(buffer, "Sector %d", nSector);
  845. printmessage16(buffer);
  846. if (sector[nSector].extra != -1)
  847. {
  848. nXSector = sector[nSector].extra;
  849. dassert(nXSector < kMaxXSectors);
  850. XSectorToDialog(nSector);
  851. PaintDialog(dlgSector, LENGTH(dlgSector));
  852. }
  853. else
  854. clearmidstatbar16();
  855. }
  856. /***********************************************************************
  857. * EditSectorData()
  858. *
  859. * This function allows editing of the game specific sector data.
  860. **********************************************************************/
  861. void EditSectorData( int nSector )
  862. {
  863. int nXSector;
  864. dassert(nSector >= 0 && nSector < kMaxSectors);
  865. CleanUp();
  866. sprintf(buffer, "Sector %d", nSector);
  867. printmessage16(buffer);
  868. nXSector = GetXSector(nSector);
  869. XSectorToDialog(nSector);
  870. if ( EditDialog(dlgSector, LENGTH(dlgSector)) )
  871. DialogToXSector(nSector);
  872. ShowSectorData(nSector);
  873. vel = svel = angvel = 0;
  874. CleanUp();
  875. }
  876. /***********************************************************************
  877. * ShowWallData()
  878. *
  879. * This function displays the game specific wall data in the status
  880. * area.
  881. **********************************************************************/
  882. void ShowWallData( int nWall )
  883. {
  884. int nXWall;
  885. dassert(nWall >= 0 && nWall < kMaxWalls);
  886. int nWall2 = wall[nWall].point2;
  887. int length = qdist(wall[nWall2].x - wall[nWall].x, wall[nWall2].y - wall[nWall].y);
  888. sprintf(buffer, "Wall %d: Length = %d", nWall, length);
  889. printmessage16(buffer);
  890. if (wall[nWall].extra != -1)
  891. {
  892. nXWall = wall[nWall].extra;
  893. dassert(nXWall < kMaxXWalls);
  894. XWallToDialog(nWall);
  895. PaintDialog(dlgWall, LENGTH(dlgWall));
  896. }
  897. else
  898. {
  899. clearmidstatbar16();
  900. }
  901. }
  902. /***********************************************************************
  903. * EditWallData()
  904. *
  905. * This function allows editing of the game specific wall data.
  906. **********************************************************************/
  907. void EditWallData( int nWall )
  908. {
  909. int nXWall;
  910. dassert(nWall >= 0 && nWall < kMaxWalls);
  911. CleanUp();
  912. sprintf(buffer, "Wall %d", nWall);
  913. printmessage16(buffer);
  914. nXWall = GetXWall(nWall);
  915. XWallToDialog(nWall);
  916. if ( EditDialog(dlgWall, LENGTH(dlgWall)) )
  917. DialogToXWall(nWall);
  918. ShowWallData(nWall);
  919. vel = svel = angvel = 0;
  920. CleanUp();
  921. }
  922. /***********************************************************************
  923. * ShowSpriteData()
  924. *
  925. * This function displays the game specific sprite data in the status
  926. * area.
  927. **********************************************************************/
  928. void ShowSpriteData( int nSprite )
  929. {
  930. int nXSprite;
  931. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  932. if (sprite[nSprite].extra > 0)
  933. {
  934. nXSprite = sprite[nSprite].extra;
  935. sprintf(buffer, "Sprite %d Extra %d XRef %d",
  936. nSprite, nXSprite, xsprite[nXSprite].reference);
  937. }
  938. else
  939. {
  940. sprintf(buffer, "Sprite %d", nSprite);
  941. }
  942. printmessage16(buffer);
  943. if ( sprite[nSprite].extra > 0 )
  944. {
  945. nXSprite = sprite[nSprite].extra;
  946. dassert(nXSprite < kMaxXSprites);
  947. XSpriteToDialog(nSprite);
  948. PaintDialog(dlgSprite, LENGTH(dlgSprite));
  949. }
  950. else
  951. clearmidstatbar16();
  952. }
  953. /***********************************************************************
  954. * EditSpriteData()
  955. *
  956. * This function allows editing of the game specific sprite data.
  957. **********************************************************************/
  958. void EditSpriteData( int nSprite )
  959. {
  960. int nXSprite;
  961. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  962. CleanUp();
  963. sprintf(buffer, "Sprite %d", nSprite);
  964. printmessage16(buffer);
  965. nXSprite = GetXSprite(nSprite);
  966. XSpriteToDialog(nSprite);
  967. if ( EditDialog(dlgSprite, LENGTH(dlgSprite)) )
  968. DialogToXSprite(nSprite);
  969. ShowSpriteData(nSprite);
  970. vel = svel = angvel = 0;
  971. CleanUp();
  972. // fix sprite type attributes
  973. AutoAdjustSprites();
  974. }
  975. int getlinehighlight(int x, int y)
  976. {
  977. long i, dst, dist, closest, xi, yi;
  978. dist = divscale(gHighlightThreshold, zoom, 14);
  979. closest = -1;
  980. for (i = 0; i < numwalls; i++)
  981. {
  982. int lx = wall[wall[i].point2].x - wall[i].x;
  983. int ly = wall[wall[i].point2].y - wall[i].y;
  984. int qx = x - wall[i].x;
  985. int qy = y - wall[i].y;
  986. // is point on wrong side of wall?
  987. if ( qx * ly > qy * lx )
  988. continue;
  989. int num = dmulscale(qx, lx, qy, ly, 4);
  990. int den = dmulscale(lx, lx, ly, ly, 4);
  991. if (num <= 0 || num >= den)
  992. continue;
  993. xi = wall[i].x + muldiv(lx, num, den);
  994. yi = wall[i].y + muldiv(ly, num, den);
  995. dst = qdist(xi - x, yi - y);
  996. if (dst <= dist)
  997. {
  998. dist = dst;
  999. closest = i;
  1000. }
  1001. }
  1002. return closest;
  1003. }
  1004. void setcolor16(int color);
  1005. #pragma aux setcolor16 =\
  1006. "mov dx, 0x3ce",\
  1007. "shl ax, 8",\
  1008. "out dx, ax",\
  1009. parm [eax]\
  1010. void drawpixel16(int offset);
  1011. #pragma aux drawpixel16 =\
  1012. "mov ecx, edi",\
  1013. "and cl, 7",\
  1014. "xor cl, 7",\
  1015. "mov ah, 1",\
  1016. "shl ah, cl",\
  1017. "mov dx, 0x3ce",\
  1018. "mov al, 0x8",\
  1019. "out dx, ax",\
  1020. "shr edi, 3",\
  1021. "or byte ptr [edi+0xA0000], al",\
  1022. parm [edi]\
  1023. modify [eax ecx edx]\
  1024. void Draw2dWall( int x0, int y0, int x1, int y1, char color, int thick )
  1025. {
  1026. if ( x0 < 0 && x1 < 0 ) return;
  1027. if ( x0 >= 640 && x1 >= 640 ) return;
  1028. if ( y0 < 0 && y1 < 0 ) return;
  1029. if ( y0 >= ydim16 && y1 >= ydim16 ) return;
  1030. drawline16(x0, y0, x1, y1, color);
  1031. if (thick)
  1032. {
  1033. long dx = x1 - x0;
  1034. long dy = y1 - y0;
  1035. RotateVector(&dx, &dy, kAngle45 / 2);
  1036. switch (GetOctant(dx, dy))
  1037. {
  1038. case 0:
  1039. case 4:
  1040. drawline16(x0, y0-1, x1, y1-1, color);
  1041. drawline16(x0, y0+1, x1, y1+1, color);
  1042. break;
  1043. case 1:
  1044. case 5:
  1045. if (qabs(dx) < qabs(dy) )
  1046. {
  1047. drawline16(x0-1, y0+1, x1-1, y1+1, color);
  1048. drawline16(x0-1, y0, x1, y1+1, color);
  1049. drawline16(x0+1, y0, x1+1, y1, color);
  1050. }
  1051. else
  1052. {
  1053. drawline16(x0-1, y0+1, x1-1, y1+1, color);
  1054. drawline16(x0, y0+1, x1, y1+1, color);
  1055. drawline16(x0, y0+1, x1, y1+1, color);
  1056. }
  1057. break;
  1058. case 2:
  1059. case 6:
  1060. drawline16(x0-1, y0, x1-1, y1, color);
  1061. drawline16(x0+1, y0, x1+1, y1, color);
  1062. break;
  1063. case 3:
  1064. case 7:
  1065. if (qabs(dx) < qabs(dy) )
  1066. {
  1067. drawline16(x0-1, y0-1, x1-1, y1-1, color);
  1068. drawline16(x0-1, y0, x1-1, y1, color);
  1069. drawline16(x0+1, y0, x1+1, y1, color);
  1070. }
  1071. else
  1072. {
  1073. drawline16(x0-1, y0-1, x1-1, y1-1, color);
  1074. drawline16(x0, y0-1, x1, y1-1, color);
  1075. drawline16(x0, y0+1, x1, y1+1, color);
  1076. }
  1077. break;
  1078. }
  1079. }
  1080. }
  1081. void Draw2dVertex( int x, int y, int color )
  1082. {
  1083. long templong = y * 640 + x + pageoffset;
  1084. setcolor16(color);
  1085. drawpixel16(templong-2-1280);
  1086. drawpixel16(templong-1-1280);
  1087. drawpixel16(templong+0-1280);
  1088. drawpixel16(templong+1-1280);
  1089. drawpixel16(templong+2-1280);
  1090. drawpixel16(templong-2-640);
  1091. drawpixel16(templong-2+0);
  1092. drawpixel16(templong-2+640);
  1093. drawpixel16(templong+2-640);
  1094. drawpixel16(templong+2+0);
  1095. drawpixel16(templong+2+640);
  1096. drawpixel16(templong-2+1280);
  1097. drawpixel16(templong-1+1280);
  1098. drawpixel16(templong+0+1280);
  1099. drawpixel16(templong+1+1280);
  1100. drawpixel16(templong+2+1280);
  1101. }
  1102. void Draw2dFaceSprite( int x, int y, int color)
  1103. {
  1104. long templong = y * 640 + x + pageoffset;
  1105. setcolor16(color);
  1106. drawpixel16(templong - 1 - 1920);
  1107. drawpixel16(templong + 0 - 1920);
  1108. drawpixel16(templong + 1 - 1920);
  1109. drawpixel16(templong - 2 - 1280);
  1110. drawpixel16(templong + 2 - 1280);
  1111. drawpixel16(templong - 3 - 640);
  1112. drawpixel16(templong + 3 - 640);
  1113. drawpixel16(templong - 3 + 0);
  1114. drawpixel16(templong + 3 + 0);
  1115. drawpixel16(templong - 3 + 640);
  1116. drawpixel16(templong + 3 + 640);
  1117. drawpixel16(templong - 2 + 1280);
  1118. drawpixel16(templong + 2 + 1280);
  1119. drawpixel16(templong - 1 + 1920);
  1120. drawpixel16(templong + 0 + 1920);
  1121. drawpixel16(templong + 1 + 1920);
  1122. }
  1123. void Draw2dFloorSprite( int x, int y, char color)
  1124. {
  1125. drawline16(x - 3, y - 3, x + 3, y - 3, color);
  1126. drawline16(x - 3, y + 3, x + 3, y + 3, color);
  1127. drawline16(x - 3, y - 3, x - 3, y + 3, color);
  1128. drawline16(x + 3, y - 3, x + 3, y + 3, color);
  1129. }
  1130. void Draw2dMarker( int x, int y, int color)
  1131. {
  1132. long templong = y * 640 + x + pageoffset;
  1133. setcolor16(color);
  1134. drawpixel16(templong - 1 - 2560);
  1135. drawpixel16(templong + 0 - 2560);
  1136. drawpixel16(templong + 1 - 2560);
  1137. drawpixel16(templong - 3 - 1920);
  1138. drawpixel16(templong - 2 - 1920);
  1139. drawpixel16(templong + 2 - 1920);
  1140. drawpixel16(templong + 3 - 1920);
  1141. drawpixel16(templong - 3 - 1280);
  1142. drawpixel16(templong - 2 - 1280);
  1143. drawpixel16(templong + 2 - 1280);
  1144. drawpixel16(templong + 3 - 1280);
  1145. drawpixel16(templong - 4 - 640);
  1146. drawpixel16(templong - 1 - 640);
  1147. drawpixel16(templong + 1 - 640);
  1148. drawpixel16(templong + 4 - 640);
  1149. drawpixel16(templong - 4);
  1150. drawpixel16(templong + 0);
  1151. drawpixel16(templong + 4);
  1152. drawpixel16(templong - 4 + 640);
  1153. drawpixel16(templong - 1 + 640);
  1154. drawpixel16(templong + 1 + 640);
  1155. drawpixel16(templong + 4 + 640);
  1156. drawpixel16(templong - 3 + 1280);
  1157. drawpixel16(templong - 2 + 1280);
  1158. drawpixel16(templong + 2 + 1280);
  1159. drawpixel16(templong + 3 + 1280);
  1160. drawpixel16(templong - 3 + 1920);
  1161. drawpixel16(templong - 2 + 1920);
  1162. drawpixel16(templong + 2 + 1920);
  1163. drawpixel16(templong + 3 + 1920);
  1164. drawpixel16(templong - 1 + 2560);
  1165. drawpixel16(templong + 0 + 2560);
  1166. drawpixel16(templong + 1 + 2560);
  1167. }
  1168. void draw2dscreen(long x, long y, short nAngle, long nZoom, short nGrid )
  1169. {
  1170. int i, j, x0, y0, x1, y1;
  1171. char nColor;
  1172. char h = (gFrameClock & 0x08) ? 8 : 0;
  1173. int thick;
  1174. short flags;
  1175. // steal a copy of these variables, because Ken made them static!
  1176. grid = nGrid;
  1177. zoom = nZoom;
  1178. if (qsetmode == 200)
  1179. return;
  1180. for (i = 0; i < numwalls; i++)
  1181. {
  1182. // only draw one side of walls
  1183. if ( wall[i].nextwall > i)
  1184. continue;
  1185. if (wall[i].nextwall == -1)
  1186. {
  1187. nColor = kColorWhite;
  1188. flags = wall[i].cstat;
  1189. thick = 0;
  1190. }
  1191. else
  1192. {
  1193. nColor = kColorRed;
  1194. thick = 0;
  1195. flags = wall[i].cstat | wall[wall[i].nextwall].cstat;
  1196. // if one side is highlighted, only show that side's flags
  1197. if (i == linehighlight)
  1198. flags = wall[i].cstat;
  1199. else if (wall[i].nextwall == linehighlight)
  1200. flags = wall[wall[i].nextwall].cstat;
  1201. if ( flags & kWallHitscan)
  1202. nColor = kColorMagenta;
  1203. if ( flags & kWallBlocking)
  1204. thick = 1;
  1205. }
  1206. if ( flags & kWallMoveForward )
  1207. nColor = kColorLightBlue;
  1208. if ( flags & kWallMoveBackward )
  1209. nColor = kColorLightGreen;
  1210. if ( linehighlight >= 0 && (i == linehighlight || wall[i].nextwall == linehighlight) )
  1211. nColor ^= h;
  1212. x0 = 320 + mulscale(wall[i].x - x, nZoom, 14);
  1213. y0 = 200 + mulscale(wall[i].y - y, nZoom, 14);
  1214. x1 = 320 + mulscale(wall[wall[i].point2].x - x, nZoom, 14);
  1215. y1 = 200 + mulscale(wall[wall[i].point2].y - y, nZoom, 14);
  1216. Draw2dWall( x0, y0, x1, y1, nColor, thick);
  1217. if (nZoom >= 256 && x0 > 4 && x0 < 635 && y0 > 4 && y0 < ydim16-5 )
  1218. Draw2dVertex(x0, y0, kColorBrown);
  1219. }
  1220. // redraw highlighted vertices
  1221. if (nZoom >= 256)
  1222. {
  1223. for (i = 0; i < numwalls; i++)
  1224. {
  1225. if ( i == pointhighlight || (highlightcnt > 0 && TestBitString(show2dwall, i)) )
  1226. {
  1227. x0 = 320 + mulscale(wall[i].x - x, nZoom, 14);
  1228. y0 = 200 + mulscale(wall[i].y - y, nZoom, 14);
  1229. if ( x0 > 4 && x0 < 635 && y0 > 4 && y0 < ydim16-5 )
  1230. Draw2dVertex(x0, y0, kColorBrown ^ h);
  1231. }
  1232. }
  1233. }
  1234. if (nZoom >= 256)
  1235. {
  1236. for (i = 0; i < numsectors; i++)
  1237. {
  1238. j = headspritesect[i];
  1239. while (j != -1)
  1240. {
  1241. x0 = 320 + mulscale(sprite[j].x - x, nZoom, 14);
  1242. y0 = 200 + mulscale(sprite[j].y - y, nZoom, 14);
  1243. if ( sprite[j].statnum == kStatMarker )
  1244. {
  1245. nColor = kColorYellow;
  1246. if ( sprite[j].owner == sectorhighlight )
  1247. nColor = kColorWhite;
  1248. if ((j | 0x4000) == pointhighlight || (highlightcnt > 0 && TestBitString(show2dsprite, j)) )
  1249. nColor ^= h;
  1250. if (x0 > 4 && x0 < 635 && y0 > 4 && y0 < ydim16-5)
  1251. switch( sprite[j].type )
  1252. {
  1253. case kMarkerOff:
  1254. case kMarkerOn:
  1255. Draw2dMarker(x0, y0, nColor);
  1256. break;
  1257. case kMarkerWarpDest:
  1258. case kMarkerAxis:
  1259. Draw2dMarker(x0, y0, nColor);
  1260. x1 = mulscale30(nZoom / 128, Cos(sprite[j].ang));
  1261. y1 = mulscale30(nZoom / 128, Sin(sprite[j].ang));
  1262. Draw2dWall(x0, y0, x0 + x1, y0 + y1, nColor, thick);
  1263. break;
  1264. }
  1265. if ( sprite[j].type == kMarkerOff )
  1266. {
  1267. // draw movement arrow
  1268. int nSector = sprite[j].owner;
  1269. int nXSector = sector[nSector].extra;
  1270. dassert(nXSector > 0 && nXSector < kMaxXSectors);
  1271. int nSprite2 = xsector[nXSector].marker1;
  1272. x1 = 320 + mulscale(sprite[nSprite2].x - x, nZoom, 14);
  1273. y1 = 200 + mulscale(sprite[nSprite2].y - y, nZoom, 14);
  1274. drawline16(x0, y0, x1, y1, kColorLightBlue);
  1275. int nAngle = getangle(x0 - x1, y0 - y1);
  1276. x0 = mulscale30(nZoom / 64, Cos(nAngle + kAngle30));
  1277. y0 = mulscale30(nZoom / 64, Sin(nAngle + kAngle30));
  1278. drawline16(x1, y1, x1 + x0, y1 + y0, kColorLightBlue);
  1279. x0 = mulscale30(nZoom / 64, Cos(nAngle - kAngle30));
  1280. y0 = mulscale30(nZoom / 64, Sin(nAngle - kAngle30));
  1281. drawline16(x1, y1, x1 + x0, y1 + y0, kColorLightBlue);
  1282. }
  1283. }
  1284. else
  1285. {
  1286. nColor = kColorCyan;
  1287. thick = 0;
  1288. if ( sprite[j].cstat & kSpriteHitscan )
  1289. nColor = kColorMagenta;
  1290. if ( sprite[j].cstat & kSpriteMoveForward )
  1291. nColor = kColorLightBlue;
  1292. if ( sprite[j].cstat & kSpriteMoveReverse )
  1293. nColor = kColorLightGreen;
  1294. if ( sprite[j].cstat & kSpriteBlocking )
  1295. thick = 1;
  1296. if ((j | 0x4000) == pointhighlight || (highlightcnt > 0 && TestBitString(show2dsprite, j)) )
  1297. nColor ^= h;
  1298. if (x0 > 4 && x0 < 635 && y0 > 4 && y0 < ydim16-5)
  1299. {
  1300. switch (sprite[j].cstat & kSpriteRMask)
  1301. {
  1302. case kSpriteFace:
  1303. case kSpriteSpin:
  1304. Draw2dFaceSprite(x0, y0, nColor);
  1305. x1 = mulscale30(nZoom / 128, Cos(sprite[j].ang));
  1306. y1 = mulscale30(nZoom / 128, Sin(sprite[j].ang));
  1307. Draw2dWall(x0, y0, x0 + x1, y0 + y1, nColor, thick);
  1308. break;
  1309. case kSpriteWall:
  1310. Draw2dFaceSprite(x0, y0, nColor);
  1311. x1 = mulscale30(nZoom / 128, Cos(sprite[j].ang + kAngle90));
  1312. y1 = mulscale30(nZoom / 128, Sin(sprite[j].ang + kAngle90));
  1313. Draw2dWall(x0 - x1, y0 - y1, x0 + x1, y0 + y1, nColor, thick);
  1314. x1 = mulscale30(nZoom / 256, Cos(sprite[j].ang));
  1315. y1 = mulscale30(nZoom / 256, Sin(sprite[j].ang));
  1316. if (sprite[j].cstat & kSpriteOneSided)
  1317. Draw2dWall(x0, y0, x0 + x1, y0 + y1, nColor, thick);
  1318. else
  1319. Draw2dWall(x0 - x1, y0 - y1, x0 + x1, y0 + y1, nColor, thick);
  1320. break;
  1321. case kSpriteFloor:
  1322. Draw2dFloorSprite(x0, y0, nColor);
  1323. x1 = mulscale30(nZoom / 256, Cos(sprite[j].ang));
  1324. y1 = mulscale30(nZoom / 256, Sin(sprite[j].ang));
  1325. Draw2dWall(x0, y0, x0 + x1, y0 + y1, nColor, thick);
  1326. break;
  1327. }
  1328. }
  1329. }
  1330. j = nextspritesect[j];
  1331. }
  1332. }
  1333. }
  1334. x0 = 320 + mulscale30(nZoom / 128, Cos(nAngle)); //Draw white arrow
  1335. y0 = 200 + mulscale30(nZoom / 128, Sin(nAngle));
  1336. drawline16(x0, y0, 640-x0,400-y0,kColorWhite);
  1337. drawline16(x0, y0, 120+y0,520-x0,kColorWhite);
  1338. drawline16(x0, y0, 520-y0,-120+x0,kColorWhite);
  1339. }
  1340. void ProcessKeys2D( void )
  1341. {
  1342. BYTE key;
  1343. BYTE shift, ctrl, alt;
  1344. int x, y;
  1345. static int nPointLast = -1, nLineLast = -1, nSectorLast = -1;
  1346. static int oldnumwalls, oldnumsectors, oldnumsprites;
  1347. int numsprites = 0;
  1348. // redetermine numsprites (build.c version is static!)
  1349. numsprites = 0;
  1350. for (int i = 0; i < kMaxSprites; i++)
  1351. if ( sprite[i].statnum < kMaxStatus )
  1352. numsprites++;
  1353. // did anything important happen?
  1354. if (numwalls != oldnumwalls || numsectors != oldnumsectors || numsprites != oldnumsprites)
  1355. {
  1356. CleanUp();
  1357. // fix sprite type attributes
  1358. AutoAdjustSprites();
  1359. oldnumwalls = numwalls;
  1360. oldnumsectors = numsectors;
  1361. oldnumsprites = numsprites;
  1362. }
  1363. shift = keystatus[KEY_LSHIFT] | keystatus[KEY_RSHIFT];
  1364. ctrl = keystatus[KEY_LCTRL] | keystatus[KEY_RCTRL];
  1365. alt = keystatus[KEY_LALT] | keystatus[KEY_RALT];
  1366. getpoint(searchx, searchy, &x, &y);
  1367. updatesector(x, y, &sectorhighlight);
  1368. if (pointhighlight != nPointLast || linehighlight != nLineLast || sectorhighlight != nSectorLast)
  1369. {
  1370. nPointLast = pointhighlight;
  1371. nLineLast = linehighlight;
  1372. nSectorLast = sectorhighlight;
  1373. if ((pointhighlight & 0xC000) == 0x4000)
  1374. ShowSpriteData(pointhighlight & 0x3FFF);
  1375. else if (linehighlight >= 0)
  1376. ShowWallData(linehighlight);
  1377. else if (sectorhighlight >= 0)
  1378. ShowSectorData(sectorhighlight);
  1379. else
  1380. clearmidstatbar16();
  1381. }
  1382. key = keyGet();
  1383. switch (key)
  1384. {
  1385. case KEY_HOME:
  1386. if (ctrl)
  1387. {
  1388. short nSprite = getnumber16("Locate sprite #: ",0,kMaxSprites);
  1389. clearmidstatbar16();
  1390. if (nSprite >= 0 && nSprite < kMaxSprites && sprite[nSprite].statnum < kMaxStatus)
  1391. {
  1392. posx = sprite[nSprite].x;
  1393. posy = sprite[nSprite].y;
  1394. posz = sprite[nSprite].z;
  1395. ang = sprite[nSprite].ang;
  1396. cursectnum = sprite[nSprite].sectnum;
  1397. }
  1398. else
  1399. printmessage16("Sir Not Appearing In This Film");
  1400. }
  1401. break;
  1402. case KEY_K: // Kinetic sprites/walls
  1403. if ( (pointhighlight & 0xC000) == 0x4000 ) // is a sprite highlighted
  1404. {
  1405. short flags = (short)(sprite[pointhighlight & 0x3FFF].cstat & kSpriteMoveMask);
  1406. switch (flags)
  1407. {
  1408. case kSpriteMoveNone:
  1409. flags = kSpriteMoveForward;
  1410. break;
  1411. case kSpriteMoveForward:
  1412. flags = kSpriteMoveReverse;
  1413. break;
  1414. case kSpriteMoveReverse:
  1415. flags = kSpriteMoveNone;
  1416. break;
  1417. default:
  1418. flags = kSpriteMoveNone;
  1419. }
  1420. sprite[pointhighlight & 0x3FFF].cstat &= ~kSpriteMoveMask;
  1421. sprite[pointhighlight & 0x3FFF].cstat |= flags;
  1422. BeepOkay();
  1423. }
  1424. else if ( linehighlight >=0 )
  1425. {
  1426. short flags = (short)(wall[linehighlight].cstat & kWallMoveMask);
  1427. switch (flags)
  1428. {
  1429. case kWallMoveNone:
  1430. flags = kWallMoveForward;
  1431. break;
  1432. case kWallMoveForward:
  1433. flags = kWallMoveBackward;
  1434. break;
  1435. case kWallMoveBackward:
  1436. flags = kWallMoveNone;
  1437. break;
  1438. default:
  1439. flags = kWallMoveNone;
  1440. }
  1441. wall[linehighlight].cstat &= ~kWallMoveMask;
  1442. wall[linehighlight].cstat |= flags;
  1443. BeepOkay();
  1444. }
  1445. else
  1446. BeepError();
  1447. break;
  1448. case KEY_M: // Masked walls
  1449. if ( linehighlight >=0 )
  1450. {
  1451. int nWall = linehighlight;
  1452. int nWall2 = wall[nWall].nextwall;
  1453. if (nWall2 < 0)
  1454. {
  1455. BeepError();
  1456. break;
  1457. }
  1458. wall[nWall].cstat |= kWallMasked;
  1459. wall[nWall].cstat &= ~kWallFlipX;
  1460. wall[nWall2].cstat |= kWallFlipX; //auto other-side flip
  1461. wall[nWall2].cstat |= kWallMasked;
  1462. if (wall[nWall].overpicnum < 0)
  1463. wall[nWall].overpicnum = 0;
  1464. wall[nWall2].overpicnum = wall[nWall].overpicnum;
  1465. wall[nWall].cstat &= ~kWallOneWay;
  1466. wall[nWall2].cstat &= ~kWallOneWay;
  1467. sprintf(buffer, "wall[%i] %s masked", searchwall,
  1468. (wall[searchwall].cstat & kWallMasked) ? "is" : "not");
  1469. printmessage16(buffer);
  1470. BeepOkay();
  1471. break;
  1472. }
  1473. else
  1474. BeepError();
  1475. break;
  1476. case KEY_LBRACE:
  1477. if ( (pointhighlight & 0xC000) == 0x4000 ) // is a sprite highlighted
  1478. {
  1479. int nSprite = pointhighlight & 0x3FFF;
  1480. // rotate sprite ccw
  1481. int step = shift ? 16 : 256;
  1482. sprite[nSprite].ang = (short)DecNext(sprite[nSprite].ang, step);
  1483. sprintf(buffer, "sprite[%i].ang: %i", nSprite, sprite[nSprite].ang);
  1484. printmessage16(buffer);
  1485. BeepOkay();
  1486. }
  1487. break;
  1488. case KEY_RBRACE:
  1489. if ( (pointhighlight & 0xC000) == 0x4000 ) // is a sprite highlighted
  1490. {
  1491. int nSprite = pointhighlight & 0x3FFF;
  1492. // rotate sprite ccw
  1493. int step = shift ? 16 : 256;
  1494. sprite[nSprite].ang = (short)IncNext(sprite[nSprite].ang, step);
  1495. sprintf(buffer, "sprite[%i].ang: %i", nSprite, sprite[nSprite].ang);
  1496. printmessage16(buffer);
  1497. BeepOkay();
  1498. }
  1499. break;
  1500. }
  1501. // let's see if this fixes the input buffering problem
  1502. if (key != 0)
  1503. keyFlushStream();
  1504. }