// m32 script editor extensions. // to load, enter "include samples/a" (without quotes) in the console // or into a file named m32_autoexec.cfg for automatic loading on startup. // to enable all events, "enableevent all" ////////// USER SETTINGS ////////// // settings for the tweaking of Polymer pr_override*-variables with the keypad keys define MINPARALLAXSCALE -10 // minimum pr_parallaxscale value define MAXPARALLAXSCALE 10 define MINPARALLAXBIAS -10 define MAXPARALLAXBIAS 10 define PSCALESTEPS 1000 // 0..1 is mapped to 0..PSCALESTEPS define PBIASSTEPS 1000 define MINSPECULARPOWER -10 define MAXSPECULARPOWER 1000 define MINSPECULARFACTOR -10 define MAXSPECULARFACTOR 1000 define SPOWERSTEPS 100 define SFACTORSTEPS 100 // color of various drawing enhancements define PREVIEW_DRAW_COLOR 11 gamevar showpal 0 0 // whether to use overridden aspect/range values when entering 3d mode (software/Polymost). // tweak with keys 7,8,9,0 on the top row gamevar use_custom_aspect 0 0 // this is now the same as r_usenewaspect gamevar davr 65536 0 gamevar dayx 65536 0 // whether to remap certain widely-available keys to rare ones // (notebook/netbook convenience, see EVENT_KEYPRESS for details) gamevar use_notebook_keys 0 0 // Whether RESPAWN sprites show the respawned sprite picnum unconditionally instead of // only when aimed at (and locked onto) the RESPAWN sprite in 3D mode. gamevar showrespawn_always 0 0 // When set to 1, previewed sprites are 66% translucent instead of 33%: gamevar showrespawn_fulltrans 0 0 gamevar move_by_one 0 0 // Polymer "head" light gamevar headlight_enabled 0 0 gamevar headlight_range 4000 0 // see end of file for more user settings and examples ////////// END USER SETTINGS ////////// include names.h // flag 1: per-block (top-level, event, or state) variable gamevar i 0 1 gamevar j 0 1 gamevar k 0 1 gamevar p 0 1 gamevar r 0 1 gamevar x 0 0 gamevar y 0 0 gamevar z 0 0 gamevar dx 0 0 gamevar dy 0 0 gamevar dz 0 0 gamevar dang 0 0 gamevar tmp 0 0 gamevar cnt 0 0 gamevar sec 0 0 gamevar wal 0 0 gamevar drawcol 9 0 define TQUOTE 0 definequote TQUOTE >>> write on me! <<< //light define LIGHTQUOTE 1 // x y z r g b mins maxs definequote LIGHTQUOTE light %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d // sec range radius fade ang horiz prio tile define PRSCALE 1000 define MAXSPECULAR 100000 define TMPARLEN 128 gamearray ar TMPARLEN gamearray xx TMPARLEN gamearray yy TMPARLEN gamearray parm 8 // prints out maphack light definitions based on SE lights in map defstate printlights "Print Polymer lights" var flags print "--PRLIGHTS--" for i allsprites, ifactor SECTOREFFECTOR, ifge .lotag 49, ifle .lotag 50 { ife .lotag 50 { set j 128, sub j .shade, shiftl j 1 set k j, mul k 3, div k 4 } else { set j 0, set k 0 } set flags 0 ifand .cstat 2 { ifand .cstat 512 set flags 4 else set flags 2 } // range r g b qsprintf TQUOTE LIGHTQUOTE .sectnum .x .y .z .hitag .xvel .yvel .zvel j k .ang .extra .xoffset .yoffset flags .owner // radius fade horiz minshade maxshade prio tile print TQUOTE } print "--ENDPRLIGHTS--" ends defstate insertlights "Insert active SE lights" var sectnum set k 0 for i activelights { insertsprite light[i].sector // I is the inserted sprites' index now set .picnum 1 set .x light[i].x set .y light[i].y set .z light[i].z set .hitag light[i].range set .xvel light[i].r set .yvel light[i].g set .zvel light[i].b set .extra light[i].horiz set .xoffset light[i].minshade set .yoffset light[i].maxshade set .owner light[i].tilenum set .xrepeat 48 set .yrepeat 48 // now those that are calculated ifge light[i].priority 4 or .cstat 512 ifge light[i].priority 2 or .cstat 2 ife light[i].radius 0 { set .lotag 49 } else { set .lotag 50 set j light[i].radius, shiftr j 1, sub j 128, inv j clamp j -128 127 set .shade j } add k 1 } qsprintf TQUOTE "* Inserted %d SE sprites based on active lights." k print TQUOTE ends // convenient polymer SE light manipulation with keypad keys // when aiming at light SE (49 or 50): // KP 4,5,6,8: angle/horiz // KP 7,9: range // KP+/-: radius // KP 1,2,3: RGB color (Shift inverts) // // when aiming at wall or sector and the respective overrides are on: // KP 5,8: parallaxscale // KP 4,6: parallaxbias // KP /,*: specularfactor // KP 7,9: specularpower // // Also try Shift and/or Ctrl modifiers for different increments defstate fiddlewithlights var minval maxval // if aiming at sector or wall ifaimingsprite nullop else ifn pr_overrideparallax 0 { set j 0 set k 0 ifhitkey KEY_KP5 set j -1, ifhitkey KEY_KP8 set j 1 ifn j 0 set k 1 ifhitkey KEY_KP4 set j -1, ifhitkey KEY_KP6 set j 1 ife k 0 ifn j 0 set k 2 ifeitheralt mul j 10 ifeitherctrl mul j 10 switch k case 0: break; case 1: { set k pr_parallaxscale ftoi k PSCALESTEPS // must convert to scaled integer, maps 0..1 to 0..PARALLAXSTEPS set minval MINPARALLAXSCALE, mul minval PSCALESTEPS set maxval MAXPARALLAXSCALE, mul maxval PSCALESTEPS add k j, clamp k minval maxval itof k PSCALESTEPS // convert back qsprintf TQUOTE "PARALLAX SCALE: %f" k, quote TQUOTE set pr_parallaxscale k break; } case 2: { set k pr_parallaxbias ftoi k PBIASSTEPS set minval MINPARALLAXBIAS, mul minval PBIASSTEPS set maxval MAXPARALLAXBIAS, mul maxval PBIASSTEPS add k j, clamp k minval maxval itof k PBIASSTEPS qsprintf TQUOTE "PARALLAX BIAS: %f" k, quote TQUOTE set pr_parallaxbias k break; } endswitch //quote "zxczxc" } //quote "asdasd" // if aiming at sector or wall ifaimingsprite nullop else ifn pr_overridespecular 0 { set j 0 set k 0 ifhitkey KEY_gSLASH set j -1, ifhitkey KEY_gSTAR set j 1 ifn j 0 set k 3 ifhitkey KEY_KP7 set j -1, ifhitkey KEY_KP9 set j 1 ife k 0 ifn j 0 set k 4 ifeitheralt mul j 10 ifeitherctrl mul j 10 switch k case 0: break; case 3: { set k pr_specularfactor ftoi k SFACTORSTEPS set minval MINSPECULARFACTOR, mul minval SFACTORSTEPS set maxval MAXSPECULARFACTOR, mul maxval SFACTORSTEPS add k j, clamp k minval maxval itof k SFACTORSTEPS qsprintf TQUOTE "SPECULAR FACTOR: %f" k, quote TQUOTE set pr_specularfactor k break; } case 4: { set k pr_specularpower ftoi k SPOWERSTEPS set minval MINSPECULARPOWER, mul minval SPOWERSTEPS set maxval MAXSPECULARPOWER, mul maxval SPOWERSTEPS add k j, clamp k minval maxval itof k SPOWERSTEPS qsprintf TQUOTE "SPECULAR POWER: %f" k, quote TQUOTE set pr_specularpower k break; } endswitch } //quote "qweqwe" // if aiming at a sprite that's not a Polymer light ifaimingsprite set k 1 else set k 0 ife k 1 ife sprite[searchwall].picnum SECTOREFFECTOR ifge sprite[searchwall].lotag 49 ifle sprite[searchwall].lotag 50 set k 0 ife k 1 { seti searchwall // [xyz]vel / owner ifeitheralt { ifhitkey KEY_KP1 { getnumber256 .xvel "XVEL: " 0 getnumber256 .yvel "YVEL: " 0 getnumber256 .zvel "ZVEL: " 0 } else ifeithershift ifhitkey KEY_KP2 // alt-kp2 collides with KP* replacement { getnumber256 .owner "OWNER: " 0 ifl .owner 0 set .owner -1 } } } // if aiming at an SE with lotag 49 or 50 (Polymer light) ifaimingsprite ife sprite[searchwall].picnum SECTOREFFECTOR ifge sprite[searchwall].lotag 49 ifle sprite[searchwall].lotag 50 { set i searchwall, seti i // set current sprite = targeted sprite ife .lotag 50 { // horiz ifeithershift set j 1 else set j 10 ifhitkey KEY_gUP add .extra j else ifhitkey KEY_gKP5 sub .extra j clamp .extra -500 500 // angle set j 128 ifeitherctrl set j 4 ifeithershift { ifeitherctrl set j 1 else set j 32 } ifhitkey KEY_gLEFT sub .ang j else ifhitkey KEY_gRIGHT add .ang j // radius ifeitherctrl { ifholdkey KEY_gMINUS add .shade 9 else ifholdkey KEY_gPLUS sub .shade 9 clamp .shade -118 117 } } // range ifeithershift set j 10 else ifeitherctrl set j 1000 else set j 100 set k .hitag ifhitkey KEY_KP9 add k j else ifhitkey KEY_KP7 sub k j clamp k 0 32767 set .hitag k // min/max shade ifeithershift set j -1 else set j 1 ifeitherctrl { ifhitkey KEY_gSLASH { set .xoffset 0 set .yoffset 0 quote "Reset X and Y OFFSET (min/max shade) to 0" } } else { set k 0 ifhitkey KEY_gSLASH { add .xoffset j, set k 1 } else ifhitkey KEY_gSTAR { add .yoffset j, set k 1 } ife k 1 { qsprintf TQUOTE "XY OFFSET (min/max shade): %d %d" .xoffset .yoffset quote TQUOTE } } // color/picnum ifeitheralt { ifhitkey KEY_KP1 { getnumber256 .xvel "XVEL (red): " 255 getnumber256 .yvel "YVEL (green): " 255 getnumber256 .zvel "ZVEL (blue): " 255 } else ifhitkey KEY_KP2 { getnumber256 .owner "OWNER (projection picnum): " -MAXTILES ifl .owner 0 set .owner -1 } } else { ifeitherctrl set j 1 else set j 10 ifeithershift inv j set k 0 ifhitkey KEY_B { add .xvel j, set k 1 } ifhitkey KEY_N { add .yvel j, set k 1 } ifhitkey KEY_M { add .zvel j, set k 1 } ifhitkey KEY_KP1 { add .xvel j, set k 1 } ifhitkey KEY_KP2 { add .yvel j, set k 1 } ifhitkey KEY_KP3 { add .zvel j, set k 1 } ife k 1 { clamp .xvel 1 255 clamp .yvel 1 255 clamp .zvel 1 255 qsprintf TQUOTE "XYZ VEL (RGB color): %d %d %d" .xvel .yvel .zvel quote TQUOTE } } } else { // not aiming at sprite ifeitherctrl ifeithershift ifhitkey KEY_gMINUS { ife headlight_enabled 0 { set headlight_enabled 1 quote "head light enabled" } else { set headlight_enabled 0 quote "head light disabled" } } } ends defstate do_move_by_one ifeithershift { ifhitkey KEY_UP sub horiz 1 ifhitkey KEY_DOWN add horiz 1 ifhitkey KEY_LEFT sub ang 1 ifhitkey KEY_RIGHT add ang 1 and ang 2047 } else { // absolute x/y/z navigation ifhitkey KEY_LEFT sub posx 1 ifhitkey KEY_RIGHT add posx 1 ifhitkey KEY_DOWN sub posy 1 ifhitkey KEY_UP add posy 1 ifhitkey KEY_A sub posz 1 ifhitkey KEY_Z add posz 1 } ends defstate check_move_by_one ifn move_by_one 0 set hardcoded_movement 0 else set hardcoded_movement 1 ends // forward refs defstate userkeys_3d ends defstate userdrawlabel ends onevent EVENT_PREKEYS3D // state testkeyavail state check_move_by_one ifn move_by_one 0 state do_move_by_one state fiddlewithlights state userkeys_3d endevent // rotate highlighted sprites around selected (closest to mouse) sprite // global parameter: dang defstate rotselspr ifg highlightcnt 0 ifge pointhighlight 16384, ifl pointhighlight 32768 { ife dang 0 return set p pointhighlight, and p 16383 add sprite[p].ang dang for i selsprites, ifn i p { rotatepoint sprite[p].x sprite[p].y .x .y dang (x y) add .ang dang bsetsprite I x y .z } } ends gamevar do_batch_extension 0 0 gamevar batch_ohl_i -1 0 gamevar batch_tmp 0 0 ////// sector collecting stuff gamearray collectedsectors MAXSECTORS // shared with 'old-highlighted sectors' gamevar ohlsecs 0 0 // save or restore highlighted sectors defstate save_restore_hlsectors "Save/restore hl. sectors" ifge highlightsectorcnt 0 { // save for i range highlightsectorcnt set collectedsectors[i] highlightsector[i] set ohlsecs highlightsectorcnt quote "Highlighted sectors saved" } else ifl highlightcnt 0 { for i range ohlsecs sethighlightsector collectedsectors[i] 1 quote "Highlighted sectors restored" } ends defstate extendhlsectors "Extend all hl. sectors" ifvarle highlightsectorcnt 0 return state save_restore_hlsectors // will save them for i range highlightsectorcnt sethighlightsector highlightsector[i] 0 set do_batch_extension 1 set batch_ohl_i 0 ends onevent EVENT_PREKEYS2D state check_move_by_one ifn move_by_one 0 state do_move_by_one ifvare do_batch_extension 1 set do_batch_extension 2 else ifvare do_batch_extension 2 { ifge batch_ohl_i ohlsecs { // done! set do_batch_extension 0 set batch_ohl_i -1 set keystatus[0x1d] 0 set keystatus[0x12] 0 } else { ifvare batch_tmp 0 { // highlight that sector sethighlightsector collectedsectors[batch_ohl_i] 1 set batch_tmp 1 } else // ... skip a mainloop iteration so that a frame can be displayed { set batch_tmp 0 add batch_ohl_i 1 // fake a Ctrl-E set keystatus[0x1d] 1 set keystatus[0x12] 1 } } break } // state testkeyavail set j 0 ifeitherctrl { ifhitkey KEY_COMMA set j -1 ifhitkey KEY_PERIOD set j 1 } ifn j 0 { mul j 512 set dang j state rotselspr } endevent gamevar fyx 0 0 gamevar fvr 0 0 defstate setas set fyx dayx mul fyx 4 mul fyx 100 // the correction factor 100/107 has been found div fyx 3 div fyx 107 // out experimentally. squares ftw! set fvr davr mul fvr xdim mul fvr 3 div fvr ydim div fvr 4 setaspect fvr fyx //davr dayx ends onevent EVENT_ENTER3DMODE ifn use_custom_aspect 0 state setas endevent defstate try_nextsector_teleporting var nexts set nexts RETURN set RETURN 0 for i spritesofsector nexts { ife .picnum SECTOREFFECTOR ife .lotag 7 { set RETURN 1 break } } ends defstate try_nextsector_ceilingsky ifand sector[RETURN].ceilingstat 1 set RETURN 1 else set RETURN 0 ends defstate collect_teleporting_sectors // (sec) "Collect telep. sectors" var numsects set numsects numsectors, sub numsects 1 ifinteractive { set sec searchsector getnumberfromuser sec "starting sectnum: " numsects 8 ifl sec 0, return } set ohlsecs 0 // reset old hl'd sectors collectsectors collectedsectors sec numsects try_nextsector_teleporting for i range numsects sethighlightsector collectedsectors[i] 1 ends // XXX: CODEDUP defstate collect_ceilsky_sectors // (sec) "Collect sky ceilings" var numsects set numsects numsectors, sub numsects 1 ifinteractive { set sec searchsector getnumberfromuser sec "starting sectnum: " numsects 8 ifl sec 0, return } set ohlsecs 0 // reset old hl'd sectors collectsectors collectedsectors sec numsects try_nextsector_ceilingsky for i range numsects sethighlightsector collectedsectors[i] 1 ends ////// show LOCATORS defstate cmp_by_lotag // comparator subroutine for sorting set RETURN sprite[SV2].lotag sub RETURN sprite[SV1].lotag ends defstate connectlocators // connect LOCATORS in a sector with lines getarraysize ar tmp set j 0 for i spritesofsector cursectnum { ifge j tmp nullop else ifactor LOCATORS { set ar[j] i add j 1 } } set tmp j sort ar tmp cmp_by_lotag sub tmp 1 for i range tmp { set j ar[i] set k i, add k 1, set k ar[k] drawline16z sprite[j].x sprite[j].y sprite[j].z sprite[k].x sprite[k].y sprite[k].z drawcol } ends defstate draw_prlightprojections ////////// polymer light 2d projections ////////// var c d h r x2 y2 oldpat array xx 2 array yy 2 set oldpat drawlinepat set drawlinepat 0x11111111 for i spritesofsector cursectnum { ifactor SECTOREFFECTOR { ife .lotag 49 // point light { set d .hitag // light distance mul d d, mul d 2, sqrt d d, div d 2 getclosestcol .xvel .yvel .zvel c // light color inv c set x .x, set x2 .x, set y .y, set y2 .y add x d, add y d, sub x2 d, sub y2 d drawline16z x y .z x2 y2 .z c set x .x, set x2 .x, set y .y, set y2 .y add x d, sub y d, sub x2 d, add y2 d drawline16z x y .z x2 y2 .z c drawcircle16z .x .y .z .hitag c } else ife .lotag 50 // spot light { set d .hitag // light distance and d 65535 set r 128, sub r .shade, shiftl r 1 // light cone radius (BUILD angles) getclosestcol .xvel .yvel .zvel c // light color inv c set x .x, set y .y, add x d rotatepoint .x .y x y .ang x y set h .extra // horiz sub h 100 set tmp h, mul tmp tmp, add tmp 40000 sqrt tmp tmp divscale h 200 tmp 15 // h: horizontal distance fraction set dx .x, sub dx x set dy .y, sub dy y set tmp 32768, sub tmp h mulscale dx dx tmp 15 mulscale dy dy tmp 15 set tmp 0, sub tmp r rotatepoint .x .y x y tmp xx[0] yy[0] set tmp 0, add tmp r rotatepoint .x .y x y tmp xx[1] yy[1] add xx[0] dx, add yy[0] dy add xx[1] dx, add yy[1] dy drawline16z .x .y .z xx[0] yy[0] .z c drawline16z .x .y .z xx[1] yy[1] .z c } } } set drawlinepat oldpat ends defstate previewdoors2d // preview swinging and sliding doors in 2d mode var valid sect lo var i j w numw ang trange dx dy set valid 0 set sect searchsector ifge sect 0 ifl sect numsectors { set lo sector[sect].lotag ife lo 23 set valid 1 else ife lo 25 set valid 1 } ife valid 1 { set valid 0 for i spritesofsector sect ifactor SECTOREFFECTOR { ife .lotag 11 ife lo 23 set valid 1 // swinging door ife .lotag 15 ife lo 25 set valid 1 // slide door ife valid 1 { set j i, break } } ife valid 1 seti j else return ife .lotag 15 { set trange 256 for i spritesofsector sect ifactor GPSPEED { set trange .lotag, break } mul trange 2 // now equals distance of sliding door to travel } set i 0 for w loopofwall sector[sect].wallptr { ifge i TMPARLEN break set xx[i] wall[w].x set yy[i] wall[w].y add i 1 } ifl i TMPARLEN { set xx[i] xx[0] set yy[i] yy[0] add i 1 } set numw i ife .lotag 11 { ifg .ang 1024 set ang -512 else set ang 512 for i range numw rotatepoint .x .y xx[i] yy[i] ang xx[i] yy[i] } else // if .lotag 15 { set ang .ang, add ang 1024 a2xy ang dx dy mulscale dx trange dx 14 mulscale dy trange dy 14 for i range numw { add xx[i] dx add yy[i] dy } } set drawlinepat 0x33333333 sub numw 1 for i range numw { set j i, add j 1 drawline16z xx[i] yy[i] sector[sect].floorz xx[j] yy[j] sector[sect].floorz PREVIEW_DRAW_COLOR } set drawlinepat 0xffffffff } ends // LOCATORS auto-incrementer onevent EVENT_INSERTSPRITE2D set k I set j -1 for i spritesofsector .sectnum { ifn i k, ifactor LOCATORS, ifg .lotag j set j .lotag } ifg j -1 { add j 1 set .lotag j } endevent defstate print_parallel_midpts // print the midpoints of parallel wall-lines var p0 p1 p2 s1dx s1dy s2dx s2dy tmp nw quote "----------------" for p1 allwalls { lastwall p1 p0 // get the 'inverse point2' set p2 wall[p1].point2 // ... and the forward one set tmp 0 // both white: OK (may be false positive due to TROR) ifl wall[p0].nextwall 0 ifl wall[p1].nextwall 0 set tmp 1 // both red and no wall originating from midpoint on the other side: OK ifge wall[p0].nextwall 0 ifge wall[p1].nextwall 0 { set nw wall[p1].nextwall ifl p1 nw, ife wall[p0].nextwall wall[nw].point2, set tmp 1 } ife tmp 1 { set s1dx wall[p1].x, sub s1dx wall[p0].x set s1dy wall[p1].y, sub s1dy wall[p0].y set s2dx wall[p2].x, sub s2dx wall[p1].x set s2dy wall[p2].y, sub s2dy wall[p1].y // now have segment dx/dy's mul s1dx -s2dy mul s1dy s2dx set tmp s1dx, add tmp s1dy // tmp = (s1dx, s1dy) . (-s2dy, s2dx) ife tmp 0 { qsprintf TQUOTE "%d" p1 quote TQUOTE } } } ends //////////////////// SPRITE DUPLICATORS //////////////////// defstate transcnt ifle cnt 0 { inv cnt, add cnt 128 } ends define DUP_ROT_MAGIC 123 // duplicates and rotates selected sprites around // pivot sprite with fields // .extra=123 (magic) // .ang: angle delta // .yrepeat*32: z delta (positive if pal!=0, i.e. going down) // .shade: count (-128 to 0 -> 255 to 128) defstate duprot ifaimingsprite nullop else return ifn sprite[searchwall].extra DUP_ROT_MAGIC return set p searchwall // pivot sprite set cnt sprite[p].shade, state transcnt set sprite[p].extra -1 for i range cnt { for j selsprites, ifn j p { dupsprite j // duplicate sprite j, I becomes index of newly created sprite set dang i, add dang 1, mul dang sprite[p].ang rotatepoint sprite[p].x sprite[p].y .x .y dang (x y) add .ang dang set z i, add z 1, mul z sprite[p].yrepeat, shiftl z 5 ife sprite[p].pal 0, inv z add z .z bsetsprite I x y z } } ends // same as above but with tsprite[], as a kind of preview defstate tduprot ifaimingsprite nullop else return ifl searchwall 0 return ifn sprite[searchwall].extra DUP_ROT_MAGIC return set p searchwall // pivot sprite set cnt sprite[p].shade, state transcnt for i range cnt { for j selsprites, ifn j p { set k spritesortcnt tdupsprite j set dang i, add dang 1, mul dang sprite[p].ang rotatepoint sprite[p].x sprite[p].y tsprite[k].x tsprite[k].y dang (x y) add tsprite[k].ang dang set z i, add z 1, mul z sprite[p].yrepeat, shiftl z 5 ife sprite[p].pal 0 inv z add z tsprite[k].z set tsprite[k].x x set tsprite[k].y y set tsprite[k].z z or tsprite[k].cstat 514 } } ends define DUP_LIN_MAGIC 234 define DUP_LIN_MAGIC2 345 // duplicates and translates selected sprites in the direction between two // reference sprites with fields // .extra=234 (1st sprite), =345 (2nd, aimed at sprite) // .shade: count (-128 to 0 -> 255 to 128) defstate duplin ifaimingsprite nullop else return ifn sprite[searchwall].extra DUP_LIN_MAGIC2 return set r searchwall // 2nd reference point set cnt sprite[r].shade, state transcnt set p -1 // 1st reference point for i selsprites, ifn i r { ife .extra DUP_LIN_MAGIC { set p i, break } } ifl p 0 return set sprite[p].extra -1 set sprite[r].extra -1 set dx sprite[r].x, sub dx sprite[p].x set dy sprite[r].y, sub dy sprite[p].y set dz sprite[r].z, sub dz sprite[p].z for i range cnt { for j selsprites, ifn j r { dupsprite j set x i, add x 1, mul x dx, add x .x set y i, add y 1, mul y dy, add y .y set z i, add z 1, mul z dz, add z .z bsetsprite I x y z } } ends defstate tduplin ifaimingsprite nullop else return ifn sprite[searchwall].extra DUP_LIN_MAGIC2 return set r searchwall // 2nd reference point set cnt sprite[r].shade, state transcnt set p -1 // 1st reference point for i selsprites, ifn i r { ife .extra DUP_LIN_MAGIC { set p i, break } } ifl p 0 return set dx sprite[r].x, sub dx sprite[p].x set dy sprite[r].y, sub dy sprite[p].y set dz sprite[r].z, sub dz sprite[p].z for i range cnt { for j selsprites, ifn j r { set k spritesortcnt tdupsprite j set tmp i, add tmp 1, mul tmp dx add tsprite[k].x tmp set tmp i, add tmp 1, mul tmp dy add tsprite[k].y tmp set tmp i, add tmp 1, mul tmp dz add tsprite[k].z tmp or tsprite[k].cstat 514 // bsetsprite I x y z } } ends defstate respawnpreview var ts ow pic z var k onumtspr ife showrespawn_always 0 { ifaimingsprite ife sprite[searchwall].picnum RESPAWN nullop else break } set onumtspr spritesortcnt for ts range onumtspr { set ow tsprite[ts].owner ife showrespawn_always 0 ifn ow searchwall nullop else { ife sprite[ow].picnum RESPAWN { set k spritesortcnt tdupsprite ow // XXX: doesn't work with E1L5 boss RESPAWN... // Something's wrong with setting tsprite[] members. sub tsprite[k].z 4096 set tsprite[k].xrepeat 16 set tsprite[k].yrepeat 16 set pic sprite[ow].hitag ifge pic 0 ifl pic MAXTILES set tsprite[k].picnum pic and tsprite[k].cstat 0xfffffdff // clear bit 512 (reverse translucency) or tsprite[k].cstat 2 // set bit 2 (33% translucency) ifvarn showrespawn_fulltrans 0 or tsprite[k].cstat 512 } } } ends onevent EVENT_ANALYZESPRITES state respawnpreview state tduprot state tduplin endevent defstate update_headlight var li hrz set li 0 ifvare headlight_enabled 0 break ifvarl cursectnum 0 break ifvarn light[li].active 1 break set light[li].x posx set light[li].y posy set light[li].z posz set light[li].sector cursectnum set hrz horiz set light[li].horiz hrz set light[li].angle ang set light[li].range headlight_range set light[li].radius 256 set light[li].faderadius 128 set light[li].r 255 set light[li].g 255 set light[li].b 255 set light[li].priority 0 set light[li].tilenum 0 ends onevent EVENT_PREDRAW3DSCREEN state update_headlight endevent onevent EVENT_KEYS3D var l m // door sound tester ifeitherctrl ifeithershift ifaimingwall ifholdkey KEY_SPACE { set k wall[searchwall].nextsector ifl k 0 set k searchsector ife sector[k].lotag 0 return for i spritesofsector k { ifactor MUSICANDSFX ifge .lotag 0 ifl .lotag MAXSOUNDS { getsoundflags .lotag m ifand m 1 nullop else soundonce .lotag resetkey KEY_SPACE } } } // swinging doors tester -- hit Ctrl-Shift-SPACE on a door wall ifeitherctrl ifeithershift ifaimingwall ifholdkey KEY_SPACE // SE11 ST23 up:ccw { set k wall[searchwall].nextsector ifl k 0 return ifn sector[k].lotag 23 return resetkey KEY_SPACE set tmp 0 for i loopofwall searchwall { ifl wall[i].nextsector 0 set tmp 1 else ifn wall[i].nextsector k set tmp 1 } // a weaker condition // for i loopofwall wall[searchwall].nextwall // { // ifl wall[i].nextsector 0 set tmp 1 else // ifn wall[i].nextsector searchsector set tmp 1 // } ifn tmp 0 { quote "door sector not an island sector!" return } set l -1 for i spritesofsector k { ifactor SECTOREFFECTOR ife sprite[i].lotag 11 { set l i ifn sprite[i].ang 512 ifn sprite[i].ang 1024 ifn sprite[i].ang 1536 set l -1 } } ifl l 0 { quote "door sector has no SE sprite!" return } for tmp wallsofsector k { rotatepoint (sprite[l].x sprite[l].y) (wall[tmp].x wall[tmp].y) sprite[l].ang (i j) dragpoint tmp i j } for tmp spritesofsector k { ifn tmp l { rotatepoint (sprite[l].x sprite[l].y) (sprite[tmp].x sprite[tmp].y) sprite[l].ang (i j) bsetsprite tmp i j sprite[tmp].z } } inv sprite[l].ang } // teleporter -- works on SE7 and SE17 (elevator) ifeitheralt ifaimingsprite ifholdkey KEY_SPACE { ife sprite[searchwall].picnum SECTOREFFECTOR { set tmp 0 ife sprite[searchwall].lotag 7 set tmp 1 ife sprite[searchwall].lotag 17 set tmp 1 ife tmp 0 return resetkey KEY_SPACE for i allsprites { ifn i searchwall, ifactor SECTOREFFECTOR, ife sprite[i].lotag sprite[searchwall].lotag ife sprite[i].hitag sprite[searchwall].hitag { add posx sprite[i].x, sub posx sprite[searchwall].x add posy sprite[i].y, sub posy sprite[searchwall].y add posz sprite[i].z, sub posz sprite[searchwall].z updatecursectnum return } } } else ife sprite[searchwall].extra DUP_ROT_MAGIC { state duprot resetkey KEY_SPACE } else ife sprite[searchwall].extra DUP_LIN_MAGIC2 { state duplin resetkey KEY_SPACE } } set j 0 set k 0 ifholdkey KEY_7 set k -1 ifholdkey KEY_0 set k 1 ifn k 0 { set j 1 ifeithershift nullop else mul k 256 add davr k ifl davr 32768 set davr 32768 ifg davr 256000 set davr 256000 } set k 0 ifholdkey KEY_8 set k -1 ifholdkey KEY_9 set k 1 ifn k 0 { set j 1 ifeithershift nullop else mul k 256 add dayx k ifl dayx 32768 set dayx 32768 ifg dayx 256000 set dayx 256000 } ife j 1 { // setaspect davr dayx state setas qsprintf TQUOTE "ASPECT: davr=%d, dayx=%d | FVR=%d, FYX=%d" davr dayx fvr fyx quote TQUOTE } endevent defstate replacestuff for i spritesofsector searchsector // ife sprite[i].picnum AMMO set sprite[i].picnum BATTERYAMMO ifactor parm[0] cactor parm[1] ends defstate convlights // convert (0,0,0) lights to (255,255,255)-ones for i allsprites ifactor 1 ifge .lotag 49 ifle .lotag 50 ife .xvel 0 ife .yvel 0 ife .zvel 0 { set .xvel 255 set .yvel 255 set .zvel 255 } ends defstate resetallws // reset all sprites and walls to default repeat/panning for i allsprites { set .xrepeat 64 set .yrepeat 64 } for i allwalls { set wall[i].cstat 0 set wall[i].xpanning 0 set wall[i].ypanning 0 set wall[i].yrepeat 8 fixrepeats i } ends defstate js // jump to current sprite set posx .x set posy .y set posz .z updatecursectnum ends defstate jumptowal // (wal) ifge wal 0 ifl wal numwalls nullop else return set posx wall[wal].x set posy wall[wal].y updatecursectnum ends defstate jumptosec // (sec) ifge sec 0 ifl sec numsectors nullop else return set wal sector[sec].wallptr state jumptowal ends onevent EVENT_DRAW2DSCREEN var tmp var xx state userdrawlabel ifge cursectnum 0 { state connectlocators state draw_prlightprojections } state previewdoors2d ifn showpal 0 { set xx 100 for tmp range 256 { drawline16 xx 100 xx 200 -tmp add xx 1 drawline16 xx 100 xx 200 -tmp add xx 1 ifge tmp 240 { drawline16 xx 100 xx 200 -tmp add xx 1 drawline16 xx 100 xx 200 -tmp add xx 1 } } } endevent defstate mkterrain var w2 w3 idx bit tmp sec var warned set warned 0 for i selwalls { sectorofwall j i set tmp 0, ifand sector[j].floorstat 2, set tmp 1 // already handled ife tmp 0 ife sector[j].wallnum 3 { set w2 wall[i].point2 set idx w2, shiftr idx 3 set tmp w2, and tmp 7, set bit 1, shiftl bit tmp ifand show2dwall[idx] bit { setfirstwall j i set z 0x7ffffff ifin3dmode { ife searchstat 2 // floor set z sector[searchsector].floorz } else { for k allsectors { ifinside mousxplc mousyplc k { set z sector[k].floorz break } } } ife z 0x7ffffff { ife warned 0 { quote "Mouse pointer must be aiming at sector floor." set warned 1 } } else { set w3 wall[w2].point2 set sec wall[i].nextsector ifge sec 0 set sector[j].floorz sector[sec].floorz alignflorslope j wall[w3].x wall[w3].y z } } } } ends defstate chselshade for i selsectors { set sector[i].floorshade tempshade set sector[i].ceilingshade tempshade for j spritesofsector i set .shade tempshade for j wallsofsector i set wall[j].shade tempshade } ends defstate listusedtags for i allsprites { getspritelinktype i k ifn k 0 { ife k 1 qsprintf TQUOTE "sprite %d lotag %d" i sprite[i].lotag else ife k 2 qsprintf TQUOTE "sprite %d hitag %d" i sprite[i].hitag quote TQUOTE } } ends // This must be *compiled* with script_expertmode /* defstate setstartpos "Set start pos. from spr." var spr getnumberfromuser spr "sprite number: " MAXSPRITES 8 seti spr set startposx .x set startposy .y set startposz .z set startsector .sectnum set startang .ang ends */ ////////// USER AREA ////////// // key settings defstate userkeys_3d /* ifge searchwall 0 ifl searchwall MAXWALLS ifholdkey KEY_KP5 { add wall[searchwall].ypanning 1 set DOSCRSHOT 1 } */ ifholdkey KEY_SEMI ifhitkey KEY_C state chselshade ends gamevar scrshot 0 1 onevent EVENT_DRAW3DSCREEN ifn move_by_one 0 { qsprintf TQUOTE "x,y,z = %d, %d, %d" posx posy posz printext256 TQUOTE 30 30 -15 0 0 qsprintf TQUOTE "horiz,ang = %d, %d" horiz ang printext256 TQUOTE 30 40 -15 0 0 } /* ifge searchwall 0, ifl searchwall MAXWALLS { // Which wall is considered targeted? qsprintf TQUOTE "searchwall = %d" searchwall printext256 TQUOTE 30 30 -15 0 0 qsprintf TQUOTE "y panning = %d" wall[searchwall].ypanning printext256 TQUOTE 30 40 -15 0 0 } */ endevent // convenience rebindings for notebooks: // Alt-F11 --> SCROLL LOCK (set first position) // Alt-arrows --> KP arrows (change pan/repeat in 3D mode) onevent EVENT_KEYPRESS var thekey set thekey RETURN ifvare use_notebook_keys 0, return /* ifholdkey thekey qsprintf TQUOTE "pressed %d" thekey else qsprintf TQUOTE "released %d" thekey print TQUOTE */ ifholdkey thekey // if the callback key was pressed (and not released) { ifholdkey KEY_LALT { ifhitkey KEY_F11, setkey KEY_SCROLL ifhitkey KEY_UP, setkey KEY_KP8 ifhitkey KEY_DOWN, setkey KEY_KP2 ifhitkey KEY_LEFT, setkey KEY_KP4 ifhitkey KEY_RIGHT, setkey KEY_KP6 // would be 'cleaner' (only checking cb key) but is too much code for my taste: /* switch (thekey) { case KEY_F11: setkey KEY_SCROLL; resetkey thekey; break; // and so on with the rest... } endswitch */ } } else // cb key was released { switch (thekey) { case KEY_LALT: { resetkey KEY_KP8; resetkey KEY_KP2; resetkey KEY_KP4; resetkey KEY_KP6; break; } case KEY_UP: resetkey KEY_KP8; break; case KEY_DOWN: resetkey KEY_KP2; break; case KEY_LEFT: resetkey KEY_KP4; break; case KEY_RIGHT: resetkey KEY_KP6; break; } endswitch } endevent /* // example for custom labels defstate userdrawlabel for i allsprites { ifactor 2978 { qsprintf TQUOTE "MOVABLE EX:%d OW:%d", sprite[i].owner, sprite[i].extra drawlabel TQUOTE .x .y .z 0 31 } } ends */