// m32 script test & show-off file // do "include a" in the console include names.h // flag 1: per-block (top-level, event, or state) variable gamevar h 0 1 gamevar i 0 1 gamevar j 0 1 gamevar k 0 1 gamevar l 0 1 gamevar m 0 1 gamevar p 0 1 gamevar q 0 1 gamevar r 0 1 gamearray xx 10 gamearray yy 10 gamevar c 0 0 gamevar d 0 0 gamevar x 0 0 gamevar y 0 0 gamevar x2 0 0 gamevar y2 0 0 gamevar z 0 0 gamevar frac 0 0 gamevar gi 0 0 gamevar gj 0 0 gamevar gk 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 thecount 0 0 gamevar davr 65536 0 gamevar dayx 65536 0 gamevar drawcol 9 0 define TQUOTE 3 definequote 0 OK definequote 1 DAMN definequote 2 BU:%d ABS:%d definequote TQUOTE write on me! definequote 4 ASPECT: VR=%d, YX=%d definequote 5 ALPHA KEY: %d (SCANCODE: %d) definequote 6 time: %d ms definequote 7 door sector not an island sector! definequote 8 door sector has no SE sprite! //light x y z r g b mins maxs definequote 9 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 definequote 10 --PRLIGHTS-- definequote 11 --ENDPRLIGHTS-- definequote 12 RED: definequote 13 GREEN: definequote 14 BLUE: definequote 15 x/yoffset: %d %d definequote 16 RGB color: %d %d %d definequote 17 PICNUM: definequote 18 NUMBER KEY: %d (SCANCODE: %d) // Corruption checker definequote 19 PANIC!!! SECTOR OR WALL LIMIT EXCEEDED!!! definequote 20 SECTOR[%d].WALLPTR=%d out of range: numwalls=%d!!! definequote 21 SECTOR[%d].WALLPTR=%d inconsistent, expected %d!!! definequote 22 SECTOR[%d]: wallptr+wallnum=%d out of range: numwalls=%d!!! definequote 23 WALL[%d].POINT2=%d out of range: sector[%d].wallptr=%d, endwall=%d!!! definequote 24 WALL[%d].NEXTWALL=%d out of range: numwalls=%d!!! definequote 25 WALL[%d].NEXTSECTOR=%d out of range: numsectors=%d!!! definequote 26 FLOAT ACCESS TEST definequote 27 OVERRIDE POLYMER PARALLAX & SPECULAR: OFF definequote 28 OVERRIDE POLYMER PARALLAX & SPECULAR: ON definequote 29 PARALLAX SCALE: %f definequote 30 PARALLAX BIAS: %f definequote 31 SPECULAR FACTOR: %f definequote 32 SPECULAR POWER: %f definequote 33 PAL: %d define PRSCALE 1000 // NOTE: inline constants >=32768 are sometimes broken ATM (when loading a second time?). // This should always work define MAXSPECULAR 100000 gamearray ar 128 gamearray parm 8 // various tests of m32-script features defstate tests // array test getarraysize ar tmp resizearray ar 65536 getticks parm[2] for j range 65536 set ar[j] j set i 0 for j range 65536 add i ar[j] getticks parm[3] resizearray ar tmp ife i 2147450880 quote 0 else quote 1 sub parm[3] parm[2] qsprintf TQUOTE 6 parm[3] quote TQUOTE // iteration and break test for i range 10 { addlogvar i ife i 5 break } ife i 5 quote 0 else quote 1 quote 26 set tmp pr_parallaxscale set gi tmp set gj tmp set gk tmp al gi al gj al gk ftoi gi 20 ftoi gj 200 ftoi gk 2000 al gi al gj al gk mul gk 2 itof gk 2000 ends // prints out maphack light definitions based on SE lights in map defstate printlights print 10 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 l 0 ifand .cstat 2 { ifand .cstat 512 set l 4 else set l 2 } // range r g b qsprintf TQUOTE 9 .sectnum .x .y .z .hitag .xvel .yvel .zvel j k .ang .extra .xoffset .yoffset l .owner // radius fade horiz minshade maxshade prio tile print TQUOTE } print 11 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: // KP/ enable/disable overrides // when overrides are on: // KP 4,7: parallaxscale // KP 8,9: parallaxbias // KP 1,2: specularfactor // KP 3,6: specularpower // // Also try Shift and/or Ctrl modifiers for different increments defstate fiddlewithlights ife searchstat 3 nullop else { ifhitkey KEY_gSLASH { ife pr_overrideparallax 0 { set pr_overrideparallax 1 set pr_overridespecular 1 quote 28 } else { set pr_overrideparallax 0 set pr_overridespecular 0 quote 27 } } } // if aiming at sector or wall ife searchstat 3 nullop else ifn pr_overrideparallax 0 { // polymer override parallaxscale set j 0 set k 0 ifhitkey KEY_KP4 set j -1 ifhitkey KEY_KP7 set j 1 ifn j 0 set k 1 ifhitkey KEY_KP8 set j -1 ifhitkey KEY_KP9 set j 1 ife k 0 ifn j 0 set k 2 ifhitkey KEY_KP1 set j -1 ifhitkey KEY_KP2 set j 1 ife k 0 ifn j 0 set k 3 ifhitkey KEY_KP3 set j -1 ifhitkey KEY_KP6 set j 1 ife k 0 ifn j 0 set k 4 ifeithershift mul j 2 else mul j 10 ifeitherctrl mul j 10 switch k case 0: break; case 1: { set k pr_parallaxscale ftoi k PRSCALE // must convert to scaled integer, scale is 1:PRSCALE add k j, clamp k -10000 10000 itof k PRSCALE // convert back qsprintf TQUOTE 29 k, quote TQUOTE set pr_parallaxscale k break; } case 2: { set k pr_parallaxbias ftoi k PRSCALE, add k j, clamp k -10000 10000, itof k PRSCALE qsprintf TQUOTE 30 k, quote TQUOTE set pr_parallaxbias k break; } case 3: { set k pr_specularfactor ftoi k PRSCALE, add k j, clamp k -10000 MAXSPECULAR, itof k PRSCALE qsprintf TQUOTE 31 k, quote TQUOTE set pr_specularfactor k break; } case 4: { set k pr_specularpower ftoi k PRSCALE, add k j, clamp k -10000 MAXSPECULAR, itof k PRSCALE qsprintf TQUOTE 32 k, quote TQUOTE set pr_specularpower k break; } endswitch } // if aiming at an SE with lotag 49 or 50 ife searchstat 3 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 // 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 // range ifeithershift set j 10 else ifeitherctrl set j 1000 else set j 100 ifhitkey KEY_gPGUP add .hitag j else ifhitkey KEY_gHOME sub .hitag j clamp .hitag 0 16000 // radius ifeitherctrl { ifholdkey KEY_gMINUS add .shade 9 else ifholdkey KEY_gPLUS sub .shade 9 clamp .shade -118 117 } // min/max shade ifeithershift set j -1 else set j 1 ifeitherctrl { ifhitkey KEY_gSLASH { set .xoffset 0 set .yoffset 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 15 .xoffset .yoffset quote TQUOTE } } // color/picnum ifeitheralt { ifhitkey KEY_gEND { getnumber256 .xvel 12 255 getnumber256 .yvel 13 255 getnumber256 .zvel 14 255 } else ifhitkey KEY_gDOWN { getnumber256 .owner 17 -MAXTILES } } else { ifeitherctrl set j 1 else set j 10 ifeithershift inv j set k 0 ifhitkey KEY_gEND { add .xvel j, set k 1 } ifhitkey KEY_gDOWN { add .yvel j, set k 1 } ifhitkey KEY_gPGDN { add .zvel j, set k 1 } ife k 1 { clamp .xvel 1 255 clamp .yvel 1 255 clamp .zvel 1 255 qsprintf TQUOTE 16 .xvel .yvel .zvel quote TQUOTE } } } ends /* defstate testkeyavail for i range 27 { ifholdkey alphakeys[i] { qsprintf TQUOTE 5 i alphakeys[i] quote TQUOTE } } for i range 10 { ifholdkey numberkeys[i] { qsprintf TQUOTE 18 i numberkeys[i] quote TQUOTE } } ends */ // 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 onevent EVENT_PREKEYS2D // 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 onevent EVENT_PREKEYS3D // state testkeyavail state fiddlewithlights endevent defstate setas set j dayx mul j ydim mul j 8 div j xdim div j 5 setaspect davr j ends onevent EVENT_ENTER3DMODE state setas endevent defstate cmp_by_lotag // comparator subroutine for sorting set RETURN sprite[SV2].lotag sub RETURN sprite[SV1].lotag ends onevent EVENT_DRAW2DSCREEN ifl cursectnum 0 return // connect LOCATORS in a sector by 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] drawline16b sprite[j].x sprite[j].y sprite[k].x sprite[k].y drawcol } /* set drawlinepat -1 for i allsprites ifactor LIZTROOP drawcircle16b sprite[i].x sprite[i].y 256 drawcol */ ////////// polymer light 2d projections ////////// set tmp 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 drawline16b x y x2 y2 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 drawline16b x y x2 y2 c drawcircle16b .x .y .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 drawline16b .x .y xx[0] yy[0] c drawline16b .x .y xx[1] yy[1] c } } } set drawlinepat tmp endevent // 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 //////////////////// 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 ifn searchstat 3 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 ifn searchstat 3 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 ifn searchstat 3 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 ifn searchstat 3 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 onevent EVENT_ANALYZESPRITES state tduprot state tduplin /* ife searchstat 3 for i drawnsprites { ife tsprite[i].owner searchwall { qsprintf TQUOTE 33 tsprite[i].pal quote TQUOTE break } // switch sprite[j].picnum // case LIZTROOP spritepal 1 break // case PIGCOP spritepal 2 break // case BOSS1 spritepal 6 break // endswitch } */ endevent onevent EVENT_KEYS3D // door sound tester ife searchstat 0 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 } } } // swinging doors tester -- hit space on a door wall ife searchstat 0 ifhitkey KEY_SPACE // SE11 ST23 up:ccw { set k wall[searchwall].nextsector ifl k 0 return ifn sector[k].lotag 23 return 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 7 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 8 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) ife searchstat 3 ifhitkey 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 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 } else ife sprite[searchwall].extra DUP_LIN_MAGIC2 { state duplin } } ifholdkey KEY_0 // ife 0 1 { ifeithershift sub davr 512 else add davr 512 ifl davr 32768 set davr 32768 ifg davr 256000 set davr 256000 setaspect davr yxaspect qsprintf TQUOTE 4 davr yxaspect 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 jumptosec // (tmp) ifge tmp 0 ifl tmp numsectors nullop else return set j sector[tmp].wallptr set posx wall[j].x set posy wall[j].y updatecursectnum ends // Map corruption checker gamevar ewall 0 0 gamevar endwall 0 0 defstate corruptchk ifle numsectors MAXSECTORS ifle numwalls MAXWALLS nullop else { quote 19 printmessage16 19 return } set ewall 0 // expected wall index for i allsectors { set k 1 ifge sector[i].wallptr 0 ifl sector[i].wallptr numwalls nullop else { qsprintf TQUOTE 20 i sector[i].wallptr numwalls quote TQUOTE printmessage16 TQUOTE set k 0 } ifn ewall sector[i].wallptr { qsprintf TQUOTE 21 i sector[i].wallptr ewall quote TQUOTE printmessage16 TQUOTE set ewall sector[i].wallptr } add ewall sector[i].wallnum set endwall sector[i].wallptr add endwall sector[i].wallnum ifg endwall numwalls { qsprintf TQUOTE 22 i endwall numwalls quote TQUOTE printmessage16 TQUOTE set k 0 } ifn k 0 { for j wallsofsector i { ifge wall[j].point2 sector[i].wallptr ifl wall[i].point2 endwall nullop else { qsprintf TQUOTE 23 j wall[j].point2 i sector[i].wallptr endwall quote TQUOTE printmessage16 TQUOTE } ifge wall[i].nextwall numwalls { qsprintf TQUOTE 24 j wall[j].nextwall numwalls quote TQUOTE printmessage16 TQUOTE } ifge wall[i].nextsector numsectors { qsprintf TQUOTE 25 j wall[j].nextsector numsectors quote TQUOTE printmessage16 TQUOTE } } } } ends