raze/polymer/eduke32/package/sdk/samples/a.m32
helixhorned b5bb86b8e2 Mapster32: make sprite duplication examples in m32script_ex.map work again.
- Work around a sequencing issue (assignment of searchstat) in
  M32_DrawRoomsAndMasks()
- When having sprites highlighted and changing shade, since r1943 change
  every highlighted sprite's shade if one of them is aimed at. With this
  revision, if SHIFT is pressed while doing that, only change the aimed at
  sprite's shade
- a.m32: Use 'break' from a state instead of 'return'. The former may be
  "sticky" in a way that is not intended. Needs to be debugged later.
- Update instructions in m32script_ex.map

DONT_BUILD.

git-svn-id: https://svn.eduke32.com/eduke32@4880 1a8010ca-5511-0410-912e-c29ae57300e0
2015-01-06 19:56:41 +00:00

1793 lines
45 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
var val
// 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..PSCALESTEPS
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
{
// KP8/KP5: horiz
ifeithershift set j 1 else set j 10
ifhitkey KEY_gUP nullop
else ifhitkey KEY_gKP5 mul j -1
else set j 0
ifvarn j 0
{
// change it
set val .extra
add val j
clamp val -32768 32767
set .extra val
}
// KP4/KP6: 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
// KP+/KP-: 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 return
}
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 yy
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
}
}
set yy 208
for tmp range 16
{
qsprintf TQUOTE "editor color %d" tmp
printext16 TQUOTE 100 yy tmp 0 0
printext16 TQUOTE 260 yy 0 tmp 0
add yy 8
}
}
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
defstate sanitize_underwater_sprites
"Xvel=1 for wall/flr spr."
for i selsprites
{
set j .cstat
and j 49
ife j 17 set .xvel 1
ife j 33 set .xvel 1
}
printmessage16 "Set xvel=1 on highlighted wall/floor sprites"
ends
define BZ_MAX 8388608
defstate uniformceil
var avgz n
for i selsectors
{
ifand sector[i].ceilingstat 2 xor sector[i].ceilingstat 2
add avgz sector[i].ceilingz
add n 1
}
ife n 0 break
div avgz n
and avgz 0xfffffc00 // round to one PGUP/PNDN unit (1024 z units)
ifvarge avgz -BZ_MAX ifvarle avgz BZ_MAX nullop
else quote "ERROR: average z value outside [-8388608 .. 8388608]" // BZ_MAX
for i selsectors
set sector[i].ceilingz avgz
ends
// XXX: CODEDUP
defstate uniformfloor
var avgz n
for i selsectors
{
ifand sector[i].floorstat 2 xor sector[i].floorstat 2
add avgz sector[i].floorz
add n 1
}
ife n 0 break
div avgz n
and avgz 0xfffffc00 // round to one PGUP/PNDN unit (1024 z units)
ifvarge avgz -BZ_MAX ifvarle avgz BZ_MAX nullop
else quote "ERROR: average z value outside [-8388608 .. 8388608]" // BZ_MAX
for i selsectors
set sector[i].floorz avgz
ends
defstate for_sprites_near_picnum
"Ch. lotag for near spr."
var ii dst
var picnumi picnumj maxldist lotag
getnumberfromuser picnumi "picnum i: " MAXTILES 10
ifvarl picnumi 0 break
getnumberfromuser picnumj "picnum j: " MAXTILES 10
ifvarl picnumj 0 break
getnumberfromuser maxldist "max ldist: " 65536 8
ifvarl maxldist 0 break
getnumberfromuser lotag "lotag (unsigned) to change to: " 65536 8
ifvarl lotag 0 break
for i allsprites ife sprite[i].picnum picnumi
for j allsprites ife sprite[j].picnum picnumj
{
ldist dst i j
ifle dst maxldist
set sprite[j].lotag lotag
}
qsprintf TQUOTE "changed lotag of sprites w/ tile %d near those w/ tile %d to %d" picnumj picnumi lotag
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
////////// 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
*/