raze/polymer/eduke32/package/samples/a.m32
2013-09-05 17:37:31 +00:00

1685 lines
42 KiB
Text

// 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
// Set to basepal index to override
gamevar override_basepal -1 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
ifvarge override_basepal 0
setgamepalette override_basepal
// 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
defstate moveselsects
var p1 dx dy
for i selsectors
{
set p1 sector[i].wallptr
set dx wall[p1].x, set dy wall[p1].y
for j wallsofsector i
{
sub wall[j].x dx
sub wall[j].y dy
}
for j spritesofsector i
{
sub .x dx
sub .y dy
}
}
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
////////// DRAW TILE (ROTATESPRITE) TESTING //////////
gamevar dt_t -1 0 // tilenum
gamevar dt_x 160 0 // x
gamevar dt_y 100 0 // y
gamevar dt_z 65536 0 // zoom
gamevar dt_a 0 0 // angle
gamevar dt_s 0 0 // shade
gamevar dt_p 0 0 // pal
gamevar dt_o 0 0 // orientation
gamevar dt_A 0 0 // alpha
onevent EVENT_DRAW3DSCREEN
ifge dt_t 0
rotatespritea dt_x dt_y dt_z dt_a dt_t dt_s dt_p dt_o dt_A 0 0 xdim ydim
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
*/