include, plotscr.hsd include, scancode.hsi #----------------------------------------------------------------------- # Increment these to invalidate old saves and old hiscores define constant(2, save version) define constant(1, hiscore version) global variable(100, game board) global variable(101, mouse cursor) global variable(102, ticks) global variable(103, void) global variable(104, dragging) global variable(105, gravity direction) global variable(106, play mode) global variable(108, attacker) global variable(109, effect layer) global variable(110, battle number) global variable(111, round number) global variable(112, paladin max hp) global variable(113, paladin hp) global variable(114, damage bonus) global variable(115, matched tiles) global variable(116, hits dealt) global variable(117, last matched) global variable(118, last hits) global variable(119, damage dealt) global variable(120, total matches) global variable(121, total hits) global variable(122, mid victory save) global variable(123, current save version) global variable(124, current hiscore version) global variable(125, scores done already) global variable(126, victory animate radius) global variable(127, cumulative damage) global variable(128, cumulative rounds) global variable(1000, tcache) global variable(2000, hiscore table) define constant(7, slicol:board) define constant(6, slicol:unit) define constant(8, slicol:victory) define constant(9, slicol:detail) define constant(11, slicol:name entry prompt) define constant(12, slicol:hiscore plank) define constant(13, slicol:hiscore screen) define constant(14, slicol:alert) define constant(15, slicol:menu) define constant(16, slicol:confirm) define constant(17, slicol:credits) define constant(18, slicol:title) define constant(19, slicol:flame plank) define constant(20, slicol:hiscore index) define constant(21, slicol:hiscore index plank) define constant(32, second) define constant(8, lastrow) define constant(22, tilesize) define constant(9, last battle) define constant(10, first base color sprite) define constant(0, str:display) define constant(1, str:sprintf) define constant(3, str:player name) define constant(4, str:tmp name) define constant(0, mode:player) define constant(1, mode:check) define constant(2, mode:attack) define constant(3, mode:dissolve) define constant(4, mode:falling) # Each hiscore entry takes up 46 globals. They are stored in an un-sorted order # 1 global indicates whether the slot is used # 5 globals scores # 40 globals name # # The top 6 scores for each battle are stored grouped together. define constant(46, globals per battle) define constant(6, hiscore slots per battle) #----------------------------------------------------------------------- plotscript, new game script, begin if(save slot used(1)) then(load from slot(1)) init mouse unhide mouse cursor init game title screen name entry prompt main loop end plotscript, load game script, begin init mouse unhide mouse cursor if(current save version <> save version) then( show alert(string sprintf(0, $1="Your saved game is stored in a format (%d) that is incompatible with the save format (%d) of the current update of Paladin Traducer. Sadly, this means you must start again from battle #1", current save version, save version)) delete save(1) reset game ) if(mid victory save) then( next battle ) play song(((battle number -- 1) ,mod, 10)) main loop end script, init game, begin ticks := 0 suspend player init score create void create board create mouse cursor update score display end script, main loop, begin while(true) do( update removals update play mode update display wait(1) ticks += 1 ) end script, save game, begin current save version := save version save in slot(1) end script, update removals, begin variable(tile, unit, tnext) tile := first child(game board) while(tile) do( tnext := next sibling(tile) if(get slice lookup(tile) == sli:tile) then( unit := get tile unit(tile) if(unit) then( if(get remove me(unit) && not(unit is dissolving(unit))) then( if(unit is paladin(unit) && get charmed(unit)) then( set charmed(unit, false) set remove me(unit, false) set unit color(unit, -1) )else( clear tile(tile) ) ) ) ) tile := tnext ) end script, update play mode, begin if(keyval(key:ESC) > 1) then(show pause menu) switch(play mode) do( case(mode:player) do(handle input) case(mode:attack) do(handle special attacks) case(mode:check) do(handle match checking) case(mode:dissolve) do(handle wait for dissolve) case(mode:falling) do(handle falling tiles) ) end script, handle special attacks, begin if(any tiles are moving) then(exit script) if(update special attack(attacker)) then( exit script )else( attacker := 0 ) if(trigger next charm attack) then( apply delayed charm if(trigger next special attack) then( play mode := mode:check ) ) end script, handle match checking, begin clear unit preview if(any tiles are moving) then(exit script) if(complete all matches) then( play mode := mode:player next round save game )else( play mode := mode:dissolve ) end script, handle wait for dissolve, begin if(any tiles are moving) then(exit script) play mode := mode:falling end script, handle falling tiles, begin if(any tiles are moving) then(exit script) if(make tiles fall(gravity direction)) then( play mode := mode:attack ) end script, apply delayed charm, begin variable(unit) unit := get paladin if(unit) then( if(unit is paladin(unit) && get charmed(unit) && get alt color(unit) <> -1) then( set unit color(unit, get alt color(unit)) set alt color(unit, -1) ) ) end script, handle input, begin if(keyval(key:Ctrl) > 0) then( if(keyval(key:X) > 1) then(delete save(1), reset game) if(keyval(key:R) > 1) then(regenerate board) if(keyval(key:B) > 1) then(create blood splash(get paladin)) if(keyval(key:H) > 1) then(paladin hp := 1, update score display) if(keyval(key:N) > 1) then(next battle) ) if(dragging) then( preview unit(dragging, true) if(not(mouse button(left button))) then( release dragging ) )else( variable(win) win := lookup slice(sli:score window) if(click button(sli:detail button, win)) then( show unit detail exit script ) if(click button(sli:menu button, win)) then( show pause menu ) if(mouse button(left button)) then( try to start dragging exit script ) ) end script, click button, button code, holder, begin # Returns true if button was clicked # Expects a button lookup code and a holder slice handle variable(button) button := lookup slice(button code, holder) exit returning(click button handle(button)) end script, click button handle, button, begin # Returns true if button was clicked # Expects a button handle if(button) then( if(slice collide point(button, mouse pixel x, mouse pixel y)) then( if(mouse click(left button)) then( exit returning(true) ) ) ) exit returning(false) end script, try to start dragging, begin for each tile(@try to start dragging tile) end script, try to start dragging tile, tile, begin if(slice collide point(tile, mouse pixel x, mouse pixel y)) then( start dragging tile(tile) exit returning(true) ) end script, release dragging, begin if(not(dragging)) then(exit script) variable(swaptile, dragtile) swaptile := swapping with if(swaptile) then( dragtile := get unit tile(dragging) if(swap can match(swaptile, dragtile)) then( gravity direction := get tile pair direction(dragtile, swaptile) swap tiles(swaptile, dragtile) play mode := mode:attack )else( cancel dragging animation(dragging) ) )else( cancel dragging animation(dragging) ) dragging := false end script, update display, begin update charm flicker update dragging display(dragging) update potential match preview update effects layer update mouse display end script, update charm flicker, begin variable(unit) unit := get paladin if(unit) then( if(get charmed(unit)) then( if((ticks ,mod, (second / 2)) < second / 6) then( apply unit color(unit, -1) )else( apply unit color(unit, get unit color(unit)) ) ) ) end script, update mouse display, begin put slice(mouse cursor, mouse pixel x, mouse pixel y) variable(ring) ring := lookup slice(sli:mouse ring, mouse cursor) if(ring) then( variable(drag) drag := mouse button(left button) set slice visible(ring, drag) if(drag) then( loop frame(ring, 0, 2) ) ) end script, update potential match preview, begin if(not(dragging)) then( if(keyval(key:tilde) > 0) then( for each tile(@update possible match preview) exit script ) if(play mode == mode:attack && attacker) then( for each tile(@update tile attack match preview) )else( for each tile(@clear tile match animation) ) exit script ) variable(swaptile, dragtile) dragtile := get unit tile(dragging) swaptile := swapping with if(dragtile && swaptile) then( quick swap tiles(swaptile, dragtile) ) for each tile(@update tile potential match preview) if(dragtile && swaptile) then( quick swap tiles(swaptile, dragtile) ) end #----------------------------------------------------------------------- # ALERT script, show alert, str id, begin variable(col, txt, i, fuzz) fuzz := create fuzzy layer(100) col := load slice collection(slicol:alert) txt := lookup slice(sli:alert txt, col) set slice text(txt, str id) fuzz in(fuzz) while(true) do( if(mouse click(left button)) then( break ) wait(1) ) free slice(col) free slice(fuzz) end #----------------------------------------------------------------------- # BOARD script, create board, begin variable(col) col := load slice collection(slicol:board) game board := lookup slice(sli:game board, col) effect layer := lookup slice(sli:effect layer, col) variable(tile, tx, ty) for(ty, 0, lastrow) do( for(tx, 0, lastrow) do( tile := create container(tilesize, tilesize) set slice lookup(tile, sli:tile) set parent(tile, game board) put slice(tile, tx * slice width(tile), ty * slice height(tile)) write global(@tcache + ty * (lastrow + 1) + tx, tile) add tile debug slice(tile) ) ) regenerate board end script, regenerate board, begin clear board #for each tile(@create random unit on tile) for each tile(@create random non matching unit on tile) variable(center tile, paladin) center tile := tile at pos(lastrow / 2, lastrow / 2) paladin := create paladin set tile unit(center tile, paladin) reset battle end script, clear board, begin for each tile(@clear tile) end script, for each tile, callback, begin # Callback takes the tile slice as an argument, and can return true to break the loop # Returns true if the loop was broken early variable(tile, result) tile := first child(game board) while(tile) do( if(get slice lookup(tile) == sli:tile) then( result := run script by id(callback, tile) if(result) then(exit returning(true)) ) tile := next sibling(tile) ) exit returning(false) end script, create void, begin void := create container(0, 0) set slice lookup(void, sli:the void) set slice visible(void, false) end script, tile at pos, tx, ty, begin if(tx < 0 || ty < 0 || tx > lastrow || ty > lastrow) then( exit returning(0) ) exit returning(read global(@tcache + ty * (lastrow + 1) + tx)) end script, clear tile match animation, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( animate not a match(unit) ) end script, any tiles are moving, begin variable(tile, unit) tile := first child(game board) while(tile) do( if(get slice lookup(tile) == sli:tile) then( unit := get tile unit(tile) if(unit) then( if(slice is moving(unit) || unit is dissolving(unit)) then(exit returning(true)) ) ) tile := next sibling(tile) ) exit returning(false) end script, trigger next special attack, begin # Returns true if there are no special attacks left to trigger if(for each tile(@trigger special attack)) then( exit returning(false) ) exit returning(true) end script, trigger next charm attack, begin # Returns true if there are no charm attacks left to trigger if(for each tile(@trigger charm attack)) then( exit returning(false) ) exit returning(true) end script, complete all matches, begin # Returns true if there are no matches left to complete variable(tile, match) tile := first child(game board) while(tile) do( if(get slice lookup(tile) == sli:tile) then( if(tile can match(tile)) then( if(not(get remove me(tile))) then( matched tiles += 1 total matches += 1 update score display set remove me(tile, true) dissolve tile(tile) ) match := true ) ) tile := next sibling(tile) ) # Return true if there were any matches exit returning(not(match)) end script, make tiles fall, d, begin # Return true if there are no tiles that need to fall variable(isfalling, sx, ex, sy, ey, xd, yd, fxd, fyd, axis) sx := 0 ex := lastrow xd := 1 sy := 0 ey := lastrow yd := 1 switch(d) do( case(north) do( axis := 1 fyd := 1 ) case(east) do( axis := 0 fxd := -1 sx := lastrow ex := 0 xd := -1 ) case(south) do( axis := 1 fyd := -1 sy := lastrow ey := 0 yd := -1 ) case(west) do( axis := 0 fxd := 1 ) ) variable(tx, ty, tile, unit, falltile, fallunit, i) i := 0 for(ty, sy, ey, yd) do( for(tx, sx, ex, xd) do( tile := tile at pos(tx, ty) #string sprintf(0, $1="%d", i) #tile debug(tile, 0) #i += 1 unit := get tile unit(tile) if(not(unit)) then( # Found an empty tile, units need to fall into it isfalling := true if(axis val(tx, ty, axis) == axis val(ex, ey, axis)) then( # Final row, create a new unit create random non matching unit on tile(tile) )else( falltile := tile at pos(tx + fxd , ty + fyd) fallunit := get tile unit(falltile) if(fallunit) then( set parent(fallunit, tile) ) ) animate tile fall(tile, fxd * -1, fyd * -1) ) ) ) exit returning(not(isfalling)) end #----------------------------------------------------------------------- # TILES script, clear tile, tile, begin variable(unit) unit := get tile unit(tile) if(unit && unit == dragging) then( dragging := 0 ) free slice children(tile) add tile debug slice(tile) end script, dissolve tile, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( dissolve unit(unit) ) play sound(sfx:crumble02) end script, add tile debug slice, tile, begin variable(ds) ds := create text set slice lookup(ds, sli:tile debug) set parent(ds, tile) end script, create random unit on tile, tile, begin variable(unit) unit := create random unit set tile unit(tile, unit) end script, create random non matching unit on tile, tile, begin variable(unit, i) for(i, 0, 19) do( # Make 20 attempts to avoid s unit := create random unit set tile unit(tile, unit) if(not(tile can match(tile))) then( break ) ) end script, set tile unit, tile, unit, begin clear tile(tile) set parent(unit, tile) end script, get tile unit, tile, begin variable(unit) unit := lookup slice(sli:unit box, tile) exit returning(unit) end script, start dragging tile, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( start dragging unit(unit) ) play sound(sfx:chuff01) end script, get tile x, tile, begin exit returning(slice x(tile) / slice width(tile)) end script, get tile y, tile, begin exit returning(slice y(tile) / slice height(tile)) end script, update tile attack match preview, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( if(attacker == unit || unit is paladin(unit)) then( animate potential match(unit) )else( animate not a match(unit) ) ) end script, update possible match preview, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( if(tile has possible match(tile)) then( animate potential match(unit) )else( animate not a match(unit) ) ) end script, update tile potential match preview, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( if(tile can match(tile)) then( animate potential match(unit) )else( animate not a match(unit) ) ) end script, match allowed, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( if(unit is paladin(unit)) then( if(get charmed(unit)) then(exit returning(true)) exit returning(false) ) exit returning(true) ) exit returning(false) end script, swap can match, t1, t2, begin if(not(match allowed(t1))) then(exit returning(false)) if(not(match allowed(t2))) then(exit returning(false)) variable(result) quick swap tiles(t1, t2) if(tile can match(t1)) then(result := true) if(tile can match(t2)) then(result := true) quick swap tiles(t1, t2) exit returning(result) end script, tile can match, tile, begin if(check match(tile, -2, -1, 0, 0)) then(exit returning(true)) if(check match(tile, -1, 1, 0, 0)) then(exit returning(true)) if(check match(tile, 1, 2, 0, 0)) then(exit returning(true)) if(check match(tile, 0, 0, -2, -1)) then(exit returning(true)) if(check match(tile, 0, 0, -1, 1)) then(exit returning(true)) if(check match(tile, 0, 0, 1, 2)) then(exit returning(true)) exit returning(false) end script, tile has possible match, tile, begin # X # XX if(check match(tile, 1, 2, 1, 1)) then(exit returning(true)) if(check match(tile, -1, 1, -1, 0)) then(exit returning(true)) if(check match(tile, -2, -1, -1, 0)) then(exit returning(true)) # X X # X if(check match(tile, 1, 2, 1, 0)) then(exit returning(true)) if(check match(tile, -1, 1, 1, 1)) then(exit returning(true)) if(check match(tile, -2, -1, 0, 1)) then(exit returning(true)) # X # XX if(check match(tile, 1, 2, 0, -1)) then(exit returning(true)) if(check match(tile, -1, 1, 0, -1)) then(exit returning(true)) if(check match(tile, -2, -1, 1, 1)) then(exit returning(true)) # XX # X if(check match(tile, 1, 2, -1, -1)) then(exit returning(true)) if(check match(tile, -1, 1, 1, 0)) then(exit returning(true)) if(check match(tile, -2, -1, 1, 0)) then(exit returning(true)) # X # X X if(check match(tile, 1, 2, -1, 0)) then(exit returning(true)) if(check match(tile, -1, 1, 1, 1)) then(exit returning(true)) if(check match(tile, -2, -1, 0, -1)) then(exit returning(true)) # XX # X if(check match(tile, 1, 2, 0, 1)) then(exit returning(true)) if(check match(tile, -1, 1, 0, 1)) then(exit returning(true)) if(check match(tile, -2, -1, -1, -1)) then(exit returning(true)) # X # X # X if(check match(tile, 1, 1, 1, 2)) then(exit returning(true)) if(check match(tile, -1, 0, -1, 1)) then(exit returning(true)) if(check match(tile, -1, 0, -2, -1)) then(exit returning(true)) # X # X # X if(check match(tile, -1, -1, 1, 2)) then(exit returning(true)) if(check match(tile, 1, 0, -1, 1)) then(exit returning(true)) if(check match(tile, 1, 0, -2, -1)) then(exit returning(true)) # X # X # X if(check match(tile, 1, 0, 1, 2)) then(exit returning(true)) if(check match(tile, -1, -1, -1, 1)) then(exit returning(true)) if(check match(tile, 0, 1, -2, -1)) then(exit returning(true)) # X # X # X if(check match(tile, -1, 0, 1, 2)) then(exit returning(true)) if(check match(tile, 1, 1, -1, 1)) then(exit returning(true)) if(check match(tile, 0, -1, -2, -1)) then(exit returning(true)) # X # X # X if(check match(tile, 0, -1, 1, 2)) then(exit returning(true)) if(check match(tile, 0, -1, -1, 1)) then(exit returning(true)) if(check match(tile, 1, 1, -2, -1)) then(exit returning(true)) # X # X # X if(check match(tile, 0, 1, 1, 2)) then(exit returning(true)) if(check match(tile, 0, 1, -1, 1)) then(exit returning(true)) if(check match(tile, -1, -1, -2, -1)) then(exit returning(true)) # XX X if(check match(tile, 1, 3, 0, 0)) then(exit returning(true)) if(check match(tile, -1, 2, 0, 0)) then(exit returning(true)) if(check match(tile, -3, -2, 0, 0)) then(exit returning(true)) # X XX if(check match(tile, 2, 3, 0, 0)) then(exit returning(true)) if(check match(tile, -2, 1, 0, 0)) then(exit returning(true)) if(check match(tile, -3, -1, 0, 0)) then(exit returning(true)) # X # X # # X if(check match(tile, 0, 0, 1, 3)) then(exit returning(true)) if(check match(tile, 0, 0, -1, 2)) then(exit returning(true)) if(check match(tile, 0, 0, -3, -2)) then(exit returning(true)) # X # # X # X if(check match(tile, 0, 0, 2, 3)) then(exit returning(true)) if(check match(tile, 0, 0, -2, 1)) then(exit returning(true)) if(check match(tile, 0, 0, -3, -1)) then(exit returning(true)) exit returning(false) end script, check match, tile, xA, xB, yA, yB, begin variable(tx, ty, t2, u, u2, c, c2) tx := get tile x(tile) ty := get tile y(tile) u := get tile unit(tile) if(not(u)) then(exit returning(false)) c := get unit color(u) # Check other tile A t2 := tile at pos(tx + xA, ty + yA) if(not(t2)) then(exit returning(false)) u2 := get tile unit(t2) if(not(u2)) then(exit returning(false)) c2 := get unit color(u2) if(c <> c2) then(exit returning(false)) # Check other tile B t2 := tile at pos(tx + xB, ty + yB) if(not(t2)) then(exit returning(false)) u2 := get tile unit(t2) if(not(u2)) then(exit returning(false)) c2 := get unit color(u2) if(c <> c2) then(exit returning(false)) exit returning(true) end script, swapping with, begin if(not(dragging)) then(exit returning(0)) variable(tile, xd, yd) tile := get unit tile(dragging) xd := mouse pixel x -- slice screen x(tile) -- slice width(tile) / 2 yd := mouse pixel y -- slice screen y(tile) -- slice height(tile) / 2 if(abs(xd) < slice width(tile) / 2) then(xd := 0) if(abs(yd) < slice height(tile) / 2) then(yd := 0) if(abs(yd) <= abs(xd)) then(yd := 0) if(abs(xd) <= abs(yd)) then(xd := 0) variable(sx, sy) sx := get tile x(tile) + sign(xd) sy := get tile y(tile) + sign(yd) exit returning(tile at pos(sx, sy)) end script, swap tiles, t1, t2, begin if(not(t1) || not(t2)) then( string sprintf(0, $1="swap tiles: null tile %d %d", t1, t2) script error(0) ) slice to front(t1) variable(u1, u2) u1 := get tile unit(t1) u2 := get tile unit(t2) if(not(u1) || not(u2)) then( string sprintf(0, $1="swap tiles: can't swap empty tiles %d:%d %d:%d", t1, u1, t2, u2) script error(0) ) set parent preserve pos(u1, t2) set parent preserve pos(u2, t1) move slice to(u1, 0, 0, second / 4) move slice to(u2, 0, 0, second / 4) play sound(sfx:petalpop) end script, quick swap tiles, t1, t2, begin if(not(t1) || not(t2)) then( string sprintf(0, $1="quick swap tiles: null tile %d %d", t1, t2) script error(0) ) variable(u1, u2) u1 := get tile unit(t1) u2 := get tile unit(t2) if(not(u1) || not(u2)) then( string sprintf(0, $1="quick swap tiles: null unit %d:%d %d:%d", t1, u1, t2, u2) script error(0) ) set parent(u1, t2) set parent(u2, t1) end script, tile debug, tile, str id, begin variable(ds) ds := lookup slice(sli:tile debug, tile) set slice text(ds, str id) slice to front(ds) end script, get tile pair direction, from tile, to tile, begin variable(xd, yd) xd := get tile x(to tile) -- get tile x(from tile) yd := get tile y(to tile) -- get tile y(from tile) if(abs(xd) > 1 || abs(yd) > 1 || (abs(xd) == 1 && abs(yd) == 1)) then( string sprintf(0, $1="get tile pair direction: tiles should be adjacent %d %d", from tile, to tile) script error(0) ) if(xd == 0 && yd == 0) then( string sprintf(0, $1="get tile pair direction: tiles are the same %d %d", from tile, to tile) script error(0) ) if(yd == -1 && xd == 0) then(exit returning(north)) if(yd == 0 && xd == 1) then(exit returning(east)) if(yd == 1 && xd == 0) then(exit returning(south)) if(yd == 0 && xd == -1) then(exit returning(west)) end script, animate tile fall, tile, xd, yd, begin variable(unit) unit := get tile unit(tile) if(unit) then( put slice(unit, xd * slice width(unit) * -1, yd * slice height(unit) * -1) move slice to(unit, 0, 0, second / 3) ) end script, tile is paladin, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( exit returning(unit is paladin(unit)) ) exit returning(false) end script, trigger special attack, tile, begin if(tile can match(tile)) then( variable(unit) unit := get tile unit(tile) if(unit) then( if(trigger unit special attack(unit)) then( attacker := unit exit returning(true) ) ) ) exit returning(false) end script, trigger charm attack, tile, begin if(tile can match(tile)) then( variable(unit) unit := get tile unit(tile) if(unit) then( if(trigger unit charm attack(unit)) then( attacker := unit exit returning(true) ) ) ) exit returning(false) end #----------------------------------------------------------------------- # UNITS (GENERAL) script, create random unit, begin variable(unit, c) c := random unit color switch(random(0, 3)) do( case(0) do(unit := create warrior(c)) case(1) do(unit := create assassin(c)) case(2) do(unit := create succubus(c)) case(3) do(unit := create mage(c)) ) exit returning(unit) end script, random unit color, begin exit returning(random(0, 4)) end script, palette for color, c, begin variable(pal) switch(c) do( case(-1) do(pal := 11) case(0) do(pal := 1) case(1) do(pal := 2) case(2) do(pal := 3) case(3) do(pal := 4) case(4) do(pal := 5) ) exit returning(pal) end script, c for pal, pal, begin variable(c) for(c, -1, 4) do( if(palette for color(c) == pal) then(exit returning(c)) ) string sprintf(0, $1="c for pal: unable to find palette match for pal %d", pal) script error(0) end script, apply unit color, unit, c, begin variable(spr, pal) pal := palette for color(c) spr := lookup slice(sli:unit base, unit) set sprite set number(spr, first base color sprite + c + 1) set sprite palette(spr, pal) spr := lookup slice(sli:unit body, unit) set sprite palette(spr, pal) end script, create unit, spr, c, begin variable(col, sl, body, holder) col := load slice collection(slicol:unit) holder := lookup slice(sli:unit holder, col) sl := slice child(holder, spr) set parent(sl, void) add metadata(sl) center slice(sl) set unit color(sl, c) free slice(col) exit returning(sl) end script, get unit tile, unit, begin if(not(unit)) then(exit returning(0)) variable(p) p := parent slice(unit) while(p) do( if(get slice lookup(p) == sli:tile) then( exit returning(p) ) p := parent slice(p) ) exit returning(0) end script, start dragging unit, unit, begin cancel dragging animation(dragging) dragging := unit slice to front(get unit tile(unit)) end script, cancel dragging animation, unit, begin if(not(unit)) then(exit script) move slice to(unit, 0, 0, second / 4) end script, update dragging display, unit, begin if(not(unit)) then(exit script) variable(tile, xd, yd) tile := get unit tile(unit) xd := mouse pixel x -- slice screen x(tile) -- slice width(tile) / 2 yd := mouse pixel y -- slice screen y(tile) -- slice height(tile) / 2 if(abs(xd) < slice width(tile) / 2) then(xd := 0) if(abs(yd) < slice height(tile) / 2) then(yd := 0) if(abs(yd) <= abs(xd)) then(yd := 0) if(abs(xd) <= abs(yd)) then(xd := 0) update dragging animation(dragging, sign(xd), sign(yd)) end script, update dragging animation, unit, xd, yd, begin variable(mx, my) mx := xd * slice width(unit) / 2 my := yd * slice height(unit) / 2 if(not(slice is moving(unit))) then( move slice to(unit, mx, my, second / 6) ) end script, animate potential match, unit, begin variable(spr) spr := lookup slice(sli:unit base, unit) loop frame(spr, 1, 4) end script, animate not a match, unit, begin variable(spr) spr := lookup slice(sli:unit base, unit) set sprite frame(spr, 0) end script, unit is dissolving, unit, begin variable(spr) spr := lookup slice(sli:unit base, unit) if(sprite is dissolving(spr)) then(exit returning(true)) spr := lookup slice(sli:unit body, unit) if(sprite is dissolving(spr)) then(exit returning(true)) exit returning(false) end script, dissolve unit, unit, speed=-1, begin if(speed == -1) then(speed := second / 2) variable(spr) spr := lookup slice(sli:unit base, unit) dissolve sprite(spr, dissolve:vapourise, speed) spr := lookup slice(sli:unit body, unit) dissolve sprite(spr, dissolve:vapourise, speed) end script, trigger unit special attack, unit, begin # Returns true if the special attack actually happened if(get attack started(unit)) then( exit returning(false) ) variable(cb, result) cb := get attack start callback(unit) if(cb) then( result := run script by id(cb, unit) if(result) then( set attack started(unit, true) preview unit(unit) ) ) exit returning(result) end script, trigger unit charm attack, unit, begin # Returns true if the special attack actually happened if(get attack started(unit)) then( exit returning(false) ) variable(cb, result) cb := get attack start callback(unit) if(cb && cb == @start succubus attack) then( result := run script by id(cb, unit) if(result) then( set attack started(unit, true) preview unit(unit) ) ) exit returning(result) end script, update special attack, unit, begin # Returns true if the animation is still in progress, or false if it is finished if(not(unit)) then( exit returning(false) ) if(get attack complete(unit)) then( exit returning(false) ) variable(cb, result) cb := get attack update callback(unit) if(cb) then( result := run script by id(cb, unit) if(not(result)) then( set attack complete(unit, true) clear unit preview exit returning(false) ) ) exit returning(true) end script, get paladin, begin variable(tile, unit) tile := first child(game board) while(tile) do( unit := get tile unit(tile) if(unit) then( if(unit is paladin(unit)) then(exit returning(unit)) ) tile := next sibling(tile) ) exit returning(0) end script, get adjacent paladin, unit, begin variable(i, tile, tx, ty, px, py, pt, pu) tile := get unit tile(unit) tx := get tile x(tile) ty := get tile y(tile) for(i, 0, 3) do( px := tx + compass x(i) py := ty + compass y(i) pt := tile at pos(px, py) pu := get tile unit(pt) if(unit is paladin(pu)) then( exit returning(pu) ) ) exit returning(0) end script, get octo adjacent paladin, unit, begin variable(i, tile, tx, ty, px, py, pt, pu) tile := get unit tile(unit) tx := get tile x(tile) ty := get tile y(tile) for(i, 0, 7) do( px := tx + octo compass x(i) py := ty + octo compass y(i) pt := tile at pos(px, py) pu := get tile unit(pt) if(unit is paladin(pu)) then( exit returning(pu) ) ) exit returning(0) end script, get linear knifeable paladin, unit, begin # Can knife any paladin in a straight line more than 1 tile away. variable(tile, tx, ty, px, py, pt, pu, diff, axis) tile := get unit tile(unit) tx := get tile x(tile) ty := get tile y(tile) # Horizontal py := ty for(px, 0, lastrow) do( pt := tile at pos(px, py) pu := get tile unit(pt) if(pu) then( if(unit is paladin(pu)) then( diff := px -- tx if(abs(diff) > 1) then( exit returning(pu) ) ) ) ) # Vertical px := tx for(py, 0, lastrow) do( pt := tile at pos(px, py) pu := get tile unit(pt) if(pu) then( if(unit is paladin(pu)) then( diff := py -- ty if(abs(diff) > 1) then( exit returning(pu) ) ) ) ) exit returning(0) end script, get diagonal knifeable paladin, unit, begin # Can knife any paladin in a diagonal line more than 1 tile away. variable(tile, tx, ty, i, j, px, py, pt, pu) tile := get unit tile(unit) tx := get tile x(tile) ty := get tile y(tile) for(i, 0, 3) do( for(j, 2, lastrow) do( px := tx + j * diag compass x(i) py := ty + j * diag compass y(i) if(px >= 0 && px <= lastrow && py >= 0 && py <= lastrow) then( pt := tile at pos(px, py) pu := get tile unit(pt) if(pu) then( if(unit is paladin(pu)) then( exit returning(pu) ) ) ) ) ) exit returning(0) end script, get chain to paladin, unit, begin clear visited variable(paladin, start tile, end tile) paladin := get paladin start tile := get unit tile(unit) end tile := get unit tile(paladin) variable(c) c := get unit color(unit) exit returning(find color chain(0, start tile, end tile, c)) end script, clear visited, begin for each tile(@clear tile visited) end script, clear tile visited, tile, begin variable(unit) unit := get tile unit(tile) if(unit) then( set visited(unit, false) ) end script, find color chain, up chain, start tile, end tile, find color, begin variable(result chain, branch chain, node, node2, choices, found, i, tx, ty, fx, fy, ft, cur unit, cur col) cur unit := get tile unit(start tile) if(not(cur unit)) then(exit returning(0)) if(get visited(cur unit)) then(exit returning(0)) #string sprintf(0, $1="%d%c", get visited(cur unit), 65 + (ticks ,mod, 26)) #tile debug(start tile, 0) #wait(1) #ticks += 1 if(not(unit is paladin(cur unit))) then( cur col := get unit color(cur unit) if(cur col <> find color) then( set visited(cur unit, true) exit returning(0) ) ) if(up chain) then( node := first child(up chain) while(node) do( if(cur unit == get slice extra(node, 0)) then( # Already saw this unit in the up chain exit returning(0) ) node := next sibling(node) ) ) result chain := create container(0, 0) set slice visible(result chain, false) set slice lookup(result chain, sli:chain array) node := create container(0, 0) set slice lookup(node, sli:chain node) set slice extra(node, 0, cur unit) set parent(node, result chain) if(start tile == end tile) then( exit returning(result chain) # Found the target, yay! ) branch chain := create container(0, 0) set slice visible(branch chain, false) set slice lookup(branch chain, sli:branch chain) if(up chain) then( merge chains(branch chain, up chain) ) node := create container(0, 0) set slice lookup(node, sli:chain node) set slice extra(node, 0, cur unit) set parent(node, branch chain) choices := create container(0, 0) tx := get tile x(start tile) ty := get tile y(start tile) for(i, 0, 7) do( fx := tx + octo compass x(i) fy := ty + octo compass y(i) ft := tile at pos(fx, fy) if(ft) then( found := find color chain(branch chain, ft, end tile, find color) if(found) then( set parent(found, choices) ) ) ) variable(shortest) shortest := -1 for(i, 0, child count(choices) -- 1) do( found := slice child(choices, i) if(shortest == -1 || child count(found) < shortest) then( shortest := i ) ) if(shortest == -1) then( # no options found. set visited(cur unit, true) free slice(result chain) result chain := 0 )else( found := slice child(choices, shortest) merge chains(result chain, found) ) free slice(choices) free slice(branch chain) exit returning(result chain) end script, merge chains, chain, chain2, begin variable(node, new node) node := first child(chain2) while(node) do( new node := create container(0, 0) set slice lookup(new node, sli:chain node) set slice extra(new node, 0, get slice extra(node, 0)) set parent(new node, chain) node := next sibling(node) ) end script, cardinal from to, u1, u2, begin # Ties favor the x axis variable(x1, y1, x2, y2, dx, dy) x1 := slice screen x(u1) y1 := slice screen y(u1) x2 := slice screen x(u2) y2 := slice screen y(u2) dx := x2 -- x1 dy := y2 -- y1 if(abs(dy) > abs(dx)) then( if(dy <= 0) then( exit returning(north) )else( exit returning(south) ) )else( if(dx > 0) then( exit returning(east) )else( exit returning(west) ) ) end script, diag cardinal from to, u1, u2, begin variable(x1, y1, x2, y2, dx, dy) x1 := slice screen x(u1) y1 := slice screen y(u1) x2 := slice screen x(u2) y2 := slice screen y(u2) if(x2 <= x1) then( if(y2 <= y1) then( exit returning(0) )else( exit returning(3) ) )else( if(y2 <= y1) then( exit returning(1) )else( exit returning(2) ) ) end script, unit taxicab distance, u1, u2, begin variable(dx, dy) dx := abs(slice screen x(u2) -- slice screen x(u1)) dy := abs(slice screen y(u2) -- slice screen y(u1)) exit returning(dx + dy) end script, get unit pair direction, from unit, to unit, begin exit returning(get tile pair direction(get unit tile(from unit), get unit tile(to unit))) end #----------------------------------------------------------------------- # UNITS (SPECIFIC) script, create paladin, begin variable(sl) sl := create unit(5, -1) set unit is paladin(sl, true) set alt color(sl, -1) exit returning(sl) end script, create warrior, c, begin variable(sl) sl := create unit(1, c) set attack start callback(sl, @start warrior attack) set attack update callback(sl, @update warrior attack) exit returning(sl) end script, create assassin, c, begin variable(sl) sl := create unit(2, c) set attack start callback(sl, @start assassin attack) set attack update callback(sl, @update assassin attack) exit returning(sl) end script, create succubus, c, begin variable(sl) sl := create unit(3, c) set attack start callback(sl, @start succubus attack) set attack update callback(sl, @update succubus attack) exit returning(sl) end script, create mage, c, begin variable(sl) sl := create unit(4, c) set attack start callback(sl, @start mage attack) set attack update callback(sl, @update mage attack) exit returning(sl) end script, get unit name, unit, str id, begin variable(spr, pic id) spr := lookup slice(sli:unit body, unit) pic id := get sprite set number(spr) switch(pic id) do( case(0) do($str id="Paladin") case(1) do($str id="Warrior") case(2) do($str id="Assassin") case(3) do($str id="Succubus") case(4) do($str id="Mage") ) exit returning(str id) end #----------------------------------------------------------------------- # UNIT SPECIAL ATTACKS script, start warrior attack, unit, begin variable(p, a) p := get adjacent paladin(unit) if(p) then( a := create warrior slash(p) set age(unit, 0) variable(d) d := get unit pair direction(unit, p) move slice to(unit, tilesize / 4 * compass x(d), tilesize / 4 * compass y(d), second / 4) play sound(sfx:nom) exit returning(true) ) end script, update warrior attack, unit, begin if(get age(unit) < second / 2) then( if(not(slice is moving(unit))) then( move slice to(unit, 0, 0, second / 4) ) exit returning(true) ) deal damage(3) exit returning(false) end script, start assassin attack, unit, begin variable(p, a) p := get linear knifeable paladin(unit) if(p) then( a := create assassin knife(unit, p) set age(unit, 0) play sound(sfx:squinch02) exit returning(true) ) p := get diagonal knifeable paladin(unit) if(p) then( a := create diagonal assassin knife(unit, p) set age(unit, 0) play sound(sfx:squinch02) exit returning(true) ) end script, update assassin attack, unit, begin if(any effects are moving) then( exit returning(true) ) deal damage(1) play sound(sfx:plod01) exit returning(false) end script, start mage attack, unit, begin variable(adj, chain, a) adj := get adjacent paladin(unit) if(adj) then( # Can't attack directly exit returning(false) ) chain := get chain to paladin(unit) if(chain) then( a := create mage chain lightning(chain) free slice(chain) set age(unit, 0) play sound(sfx:blast03) exit returning(true) ) end script, update mage attack, unit, begin if(get age(unit) < second / 2) then( exit returning(true) ) deal damage(1) exit returning(false) end script, start succubus attack, unit, begin variable(p, a) p := get octo adjacent paladin(unit) if(p) then( a := create succubus heart(p, get unit color(unit)) set age(unit, 0) play sound(sfx:kiss02) exit returning(true) ) end script, update succubus attack, unit, begin if(get age(unit) < second / 2) then( exit returning(true) ) hits dealt += 1 total hits += 1 update score display exit returning(false) end #----------------------------------------------------------------------- # UNIT PREVIEW script, clear unit preview, begin variable(win) win := lookup slice(sli:score window) if(not(win)) then(exit script) variable(preview sl) preview sl := lookup slice(sli:unit preview, win) set slice visible(preview sl, false) variable(txt) $0="" txt := lookup slice(sli:unit name txt, win) set slice text(txt, 0) end script, preview unit, unit, detail=false, begin if(not(unit)) then( string sprintf(0, $1="preview unit: null unit") script error(0) ) variable(win) win := lookup slice(sli:score window) if(not(win)) then(exit script) variable(preview sl) preview sl := lookup slice(sli:unit preview, win) set slice visible(preview sl, true) variable(c, pal) c := get unit color(unit) pal := palette for color(c) set sprite palette(preview sl, pal) variable(spr, body) spr := lookup slice(sli:unit body, unit) body := lookup slice(sli:unit preview body, preview sl) replace hero sprite(body, get sprite set number(spr)) set sprite palette(body, pal) # Update text fields variable(txt) get unit name(unit, 0) if(not(detail)) then($0="") txt := lookup slice(sli:unit name txt, win) set slice text(txt, 0) end script, show unit detail, begin variable(win) win := lookup slice(sli:score window) if(not(win)) then(exit script) variable(preview sl) preview sl := lookup slice(sli:unit preview, win) if(not(get slice visible(preview sl))) then( exit script ) play sound(sfx:wibble01) variable(body) body := lookup slice(sli:unit preview body, preview sl) variable(id, pal) id := get sprite set number(body) pal := get sprite palette(body) variable(fuzz) fuzz := create fuzzy layer variable(col) col := load slice collection(slicol:detail) variable(sel, cur) sel := lookup slice(sli:detail select, col) set select slice index(sel, id) cur := slice child(sel, id) variable(spr) spr := lookup slice(sli:unit preview, cur) set sprite palette(spr, pal) spr := lookup slice(sli:unit preview body, cur) set sprite palette(spr, pal) # Threat preview sprites spr := lookup slice(sli:preview threat tile, cur) while(spr) do( set sprite set number(spr, first base color sprite + c for pal(pal) + 1) set sprite palette(spr, pal) set slice lookup(spr, none) spr := lookup slice(sli:preview threat tile, cur) ) spr := lookup slice(sli:preview threat body, cur) while(spr) do( set sprite palette(spr, pal) set slice lookup(spr, none) spr := lookup slice(sli:preview threat body, cur) ) variable(outer) outer := lookup slice(sli:detail outer box, col) set slice width(outer, 0) set slice height(outer, 0) variable(t, sec) sec := second / 3 while(true) do( if(t < sec) then( adjust detail box(outer, fuzz, 320 * t / sec, 200 * t / sec, 100 * t / sec) )else( adjust detail box(outer, fuzz, 320, 200, 100) if(mouse click(left button)) then( play sound(sfx:chuff01) break ) ) wait(1) t += 1 ) for(t, sec, 0, -1) do( adjust detail box(outer, fuzz, 320 * t / sec, 200 * t / sec, 100 * t / sec) wait(1) ) free slice(col) free slice(fuzz) end script, adjust detail box, outer, fuzz, size x, size y, f, begin set slice width(outer, size x) set slice height(outer, size y) adjust fuzz(fuzz, f) end #----------------------------------------------------------------------- # FUZZY LAYER script, create fuzzy layer, targ=50, begin variable(sl) sl := create rect(0, 0) set slice lookup(sl, sli:fuzz rect) fill parent(sl, true) set rect border(sl, border:none) set rect fuzziness(sl, targ) set slice extra(sl, 0, targ) exit returning(sl) end script, get fuzzy layer, parent, targ=50, begin variable(sl) sl := lookup slice(sli:fuzz rect) set rect fuzziness(sl, targ) set slice extra(sl, 0, targ) exit returning(sl) end script, adjust fuzz, sl, percent of targ, begin variable(n, targ) targ := get slice extra(sl, 0) n := targ * percent of targ / 100 if(percent of targ == 100) then(n := targ) set rect fuzziness(sl, bounds(n, 0, 100)) end script, fuzz in, fuzz, begin variable(i) for(i, 0, second / 2) do( adjust fuzz(fuzz, 100 * i / (second / 2)) wait(1) ) end script, fuzz out, fuzz, begin variable(i) for(i, second / 2, 0, -1) do( adjust fuzz(fuzz, 100 * i / (second / 2)) wait(1) ) end #----------------------------------------------------------------------- # VISUAL EFFECTS script, update effects layer, begin variable(e, next e) e := first child(effect layer) while(e) do( next e := next sibling(e) update effect(e) if(get remove me(e)) then( free slice(e) ) e := next e ) end script, clear effects layer, begin if(effect layer) then( free slice children(effect layer) ) end script, create effect, pic num, at unit, begin variable(sl, tile) tile := get unit tile(at unit) sl := load walkabout sprite(pic num) set parent(sl, effect layer) add metadata(sl) set horiz anchor(sl, edge:center) set vert anchor(sl, edge:center) set slice x(sl, slice edge x(tile, edge:center)) set slice y(sl, slice edge y(tile, edge:center)) exit returning(sl) end script, update effect, sl, begin variable(cb) cb := get attack update callback(sl) if(cb) then( run script by id(cb, sl) ) end script, create warrior slash, at unit, begin variable(sl) sl := create effect(2, at unit) set attack update callback(sl, @update warrior slash) exit returning(sl) end script, update warrior slash, sl, begin if(frame to last(sl, 0, 7, 4)) then( set remove me(sl, true) ) end script, create assassin knife, at unit, targ unit, begin variable(sl) sl := create effect(3, at unit) set attack update callback(sl, @update assassin knife) set target unit(sl, targ unit) set direction(sl, cardinal from to(at unit, targ unit)) variable(mx, my, dist, over) mx := slice edge x(get unit tile(targ unit), edge:center) my := slice edge y(get unit tile(targ unit), edge:center) dist := unit taxicab distance(at unit, targ unit) over := large(dist / tilesize * second / 8, 1) move slice to(sl, mx, my, over) exit returning(sl) end script, update assassin knife, sl, begin set sprite frame(sl, get direction(sl)) if(not(slice is moving(sl))) then( set attack update callback(sl, @update assassin knife hit) ) end script, update assassin knife hit, sl, begin if(frame to last(sl, 4, 7, 4)) then( set remove me(sl, true) ) end script, create diagonal assassin knife, at unit, targ unit, begin variable(sl) sl := create effect(6, at unit) set attack update callback(sl, @update assassin knife) set target unit(sl, targ unit) set direction(sl, diag cardinal from to(at unit, targ unit)) variable(mx, my, dist, over) mx := slice edge x(get unit tile(targ unit), edge:center) my := slice edge y(get unit tile(targ unit), edge:center) dist := unit taxicab distance(at unit, targ unit) over := large(dist / tilesize * second / 8, 1) move slice to(sl, mx, my, over) exit returning(sl) end script, create mage chain lightning, chain, begin variable(node, unit) node := first child(chain) while(node) do( unit := get slice extra(node, 0) create chain lightning segment(unit) node := next sibling(node) ) end script, create chain lightning segment, at unit, begin variable(sl) sl := create effect(4, at unit) set attack update callback(sl, @update chain lightning segment) set age(sl, 0) exit returning(sl) end script, update chain lightning segment, sl, begin set sprite frame(sl, random(0, 7)) if(get age(sl) > second / 4) then( set remove me(sl, true) ) end script, create succubus heart, at unit, color, begin variable(sl) sl := create effect(5, at unit) set attack update callback(sl, @update succubus heart) set alt color(at unit, color) set charmed(at unit, true) exit returning(sl) end script, update succubus heart, sl, begin if(frame to last(sl, 0, 7, 4)) then( set remove me(sl, true) ) end script, create damage effect, at unit, dmg, begin variable(sl, tile) tile := get unit tile(at unit) sl := create container(0, 8) set parent(sl, effect layer) add metadata(sl) set horiz anchor(sl, edge:center) set vert anchor(sl, edge:center) set slice x(sl, slice edge x(tile, edge:center)) set slice y(sl, slice edge y(tile, edge:center) + tilesize / 4) while(dmg) do( add tiny digit(sl, (dmg ,mod, 10)) dmg := dmg / 10 ) add tiny digit(sl, 10) set attack update callback(sl, @update damage effect) move slice by(sl, 0, tilesize * 2 / 3 * -1, second / 2) exit returning(sl) end script, update damage effect, sl, begin if(not(slice is moving(sl))) then( set remove me(sl, true) ) end script, add tiny digit, cont, fr, begin variable(digit) digit := load border sprite(1) set parent(digit, cont) set sprite frame(digit, fr) realign slice(digit, edge:right, edge:center, edge:right, edge:center) set slice x(digit, slice width(cont) * -1 + (16 -- 6)) set slice width(cont, slice width(cont) + 6) end script, any effects are moving, begin # Return true if any effects are moving their x,y positions. # Does not care about effects that are only moving by animating their frames variable(e) e := first child(effect layer) while(e) do( if(slice is moving(e)) then(exit returning(e)) e := next sibling(e) ) exit returning(false) end script, create blood splash, at unit, begin variable(i) for(i, 0, 19) do( create blood droplet(at unit) ) end script, create blood droplet, at unit, begin variable(sl, tile) tile := get unit tile(at unit) sl := create container(0, 0) set parent(sl, effect layer) add metadata(sl) set horiz anchor(sl, edge:center) set vert anchor(sl, edge:center) set slice x(sl, slice edge x(tile, edge:center)) set slice y(sl, slice edge y(tile, edge:center)) variable(pic) pic := load border sprite(2) set slice lookup(pic, sli:blood droplet pic) set parent(pic, sl) center slice(pic) set attack update callback(sl, @blood droplet update) variable(t) t := random(second / 2, second) set slice extra(sl, 0, t) move slice to random in radius(sl, tilesize * 2, t) set slice extra(pic, 0, random(3, 6)) set sprite frame(pic, random(0, 7)) horiz flip sprite(pic, random(0, 1)) exit returning(sl) end script, move slice to random in radius, sl, radius, t, begin variable(x, y, i) for(i, 0, 9) do( # Only actually try to keep inside the radius 10 times. If we fail that much who cares. x := random(radius * -1, radius) y := random(radius * -1, radius) if(x ^ 2 + y ^ 2 <= radius ^ 2) then( # Inside radius break ) ) move slice to(sl, slice x(sl) + x, slice y(sl) + y, t) end script, blood droplet update, sl, begin variable(pic, f) pic := lookup slice(sli:blood droplet pic, sl) f := get slice extra(pic, 0) set slice y(pic, slice y(pic) -- f) if(f > -10) then(f -= 1) set slice extra(pic, 0, f) if(slice y(pic) > 0) then( set slice y(pic, 0) set attack update callback(sl, @blood droplet pool update) stop slice(sl) ) end script, blood droplet pool update, sl, begin variable(pic) pic := lookup slice(sli:blood droplet pic, sl) if(frame to last(pic, 8, 15)) then( set remove me(sl, true) ) end #----------------------------------------------------------------------- # BATTLE SCORE script, init score, begin battle number := 1 paladin max hp := paladin hp for battle(battle number) reset battle end script, reset battle, begin round number := 1 damage bonus := 100 reset round last matched := 0 last hits := 0 total matches := 0 total hits := 0 damage dealt := 0 paladin hp := paladin max hp update score display clear effects layer clear unit preview play song(((battle number -- 1) ,mod, 10)) end script, reset round, begin last matched := matched tiles last hits := hits dealt matched tiles := 0 hits dealt := 0 end script, next round, begin if(paladin hp <= 0) then( play sound(sfx:long01) scores done already := false next battle )else( round number += 1 if(hits dealt == 0) then( # Damage bonus halves when no hits are made if(damage bonus > 100) then( play sound(sfx:laugh02) ) damage bonus := large(damage bonus / 2, 100) )else( damage bonus += 100 * (matched tiles -- 3) / 3 ) reset round update score display ) end script, next battle, begin mid victory save := true play song(19) save game victory screen # screen is faded out here battle number += 1 if(battle number > last battle) then( credits screen ) cumulative damage += damage dealt cumulative rounds += round number paladin max hp := paladin hp for battle(battle number) regenerate board wait(1) fade screen in mid victory save := false scores done already := false save game end script, paladin hp for battle, bnum, begin exit returning(50 * 2 ^ (bnum -- 1)) end script, update score display, begin variable(win) win := lookup slice(sli:score window) if(not(win)) then( # This might be called before the slice collection has been loaded exit script ) variable(txt, meter) # Battle and round txt := lookup slice(sli:battle txt, win) string sprintf(0, $1="Battle: %d/%d", battle number, last battle) set slice text(txt, 0) txt := lookup slice(sli:rounds txt, win) string sprintf(0, $1="Round: %d", round number) set slice text(txt, 0) # Paladin HP txt := lookup slice(sli:paladin hp txt, win) string sprintf(0, $1="%d/%d", paladin hp, paladin max hp) set slice text(txt, 0) meter := lookup slice(sli:paladin hp meter, win) update meter(meter, paladin hp, paladin max hp) # Damage per round variable(dpr) dpr := calc damage rate txt := lookup slice(sli:damage rate txt, win) string sprintf(0, $1="%cRate: %d.%d", 136, dpr / 100, (dpr ,mod, 100)) set slice text(txt, 0) # Bonus damage txt := lookup slice(sli:damage bonus txt, win) string sprintf(0, $1="%d.%d", damage bonus / 100, (damage bonus ,mod, 100)) set slice text(txt, 0) # Last round stats variable(n) if(play mode == mode:player) then( n := last matched )else( n := matched tiles ) txt := lookup slice(sli:last matched txt, win) string sprintf(0, $1="Matches: %d", n / 3) switch(n ,mod, 3) do( case(1) do(append ascii(0, 127)) case(2) do(append ascii(0, 128)) ) set slice text(txt, 0) if(play mode == mode:player) then( n := last hits )else( n := hits dealt ) txt := lookup slice(sli:last hits txt, win) string sprintf(0, $1="Hits dealt: %d", n) set slice text(txt, 0) end script, deal damage, base dmg, begin variable(dmg) dmg := base dmg * damage bonus / 100 paladin hp := large(paladin hp -- dmg, 0) variable(p) p := get paladin create damage effect(p, dmg) hits dealt += 1 total hits += 1 damage dealt += dmg update score display if(paladin hp <= 0) then( create blood splash(p) ) end script, calc damage rate, begin exit returning(damage dealt * 100 / round number) end #----------------------------------------------------------------------- # VICTORY SCREEN script, victory screen, begin variable(col, i, mode, fuzz, p, vp) col := load slice collection(slicol:victory) fuzz := get fuzzy layer(col) p := get paladin dissolve unit(get paladin, second * 2) vp := lookup slice(sli:victory paladin, col) vp := lookup slice(sli:unit body, vp) dissolve sprite(vp, dissolve:vapourise, second * 2) victory animate radius := 0 fuzz in(fuzz) while(mode >= 0) do( # set mode to -1 to break the loop if(mouse click(left button)) then( mode := advance victory mode(col, mode) ) if(keyval(key:Ctrl) > 0) then( if(keyval(key:X) > 1) then(delete save(1), reset game) ) p := get paladin if(p) then( if(not(unit is dissolving(p))) then( set remove me(p, true) set charmed(p, false) ) ) vp := lookup slice(sli:victory paladin, col) vp := lookup slice(sli:unit body, vp) if(vp) then( if(not(sprite is dissolving(vp))) then(free slice(vp)) ) if(mode == 1) then( victory screen game board animate ) update removals wait(1) ) fade screen out wait(1) free slice(col) end script, advance victory mode, col, mode, begin variable(txt) txt := lookup slice(sli:victory txt, col) switch(mode) do( case(0) do( if(not(scores done already)) then( show high score table ) $0="Remain vigilant! A stronger Paladin is now invading." if(battle number == last battle) then( $0="No more Paladins dare to invade." ) set slice text(txt, 0) exit returning(1) )else( # All done! exit returning(-1) ) ) end script, victory screen game board animate, begin if(victory animate radius > 320) then(exit script) victory animate radius += 3 for each tile(@victory screen tile update) end script, victory screen tile update, tile, begin variable(unit, p, pic, x, y, px, py) p := get paladin unit := get tile unit(tile) if(unit && unit <> p) then( pic := lookup slice(sli:unit body, unit) if(pic) then( if(not(slice is moving(pic)) && slice y(pic) < 40) then( x := slice screen x(unit) y := slice screen y(unit) px := slice screen x(game board) py := slice screen y(game board) if((x -- px)^2 + (y -- py)^2 < victory animate radius^2) then( move slice to(pic, 0, 40, second) ) ) ) ) end #----------------------------------------------------------------------- # HISCORES script, show high score table, begin show high score table for battle(battle number, true) end script, show high score table for battle, battle, update=true, begin variable(col, holder, fuzz) variable(plank, my plank) fuzz := create fuzzy layer(42) adjust fuzz(fuzz, 0) col := load slice collection(slicol:hiscore screen) holder := lookup slice(sli:hiscore holder, col) if(update) then( if(string length(str:player name) == 0) then( name entry prompt ) my plank := create hiscore plank(-1, str:player name, calc damage rate, round number, total matches, total hits, damage dealt) set parent(my plank, holder) set slice extra(my plank, 1, true) ) variable(i, rate, rounds, matches, hits, damage) for(i, 0, hiscore slots per battle -- 1) do( if(hiscore slot is used(i, battle)) then( read hiscore name(str:tmp name, i, battle) rate := read hiscore rate(i, battle) rounds := read hiscore rounds(i, battle) matches := read hiscore matches(i, battle) hits := read hiscore hits(i, battle) damage := read hiscore damage(i, battle) plank := create hiscore plank(i, str:tmp name, rate, rounds, matches, hits, damage) set parent(plank, holder) ) ) if(my plank) then( slice to front(my plank) ) fuzz in(fuzz) sort hiscore planks(holder) if(update) then( write hiscore planks(holder, battle) scores done already := true export globals(1, @scores done already, @scores done already) ) if(child count(holder) > hiscore slots per battle) then( plank := last child(holder) if(not(get slice extra(plank, 1))) then( # The last score is not from your current play move slice to(plank, 0, 201, second / 8) ) ) if(my plank) then( slice to front(my plank) ) while(true) do( if(mouse click(left button)) then(break) animate hiscore planks(holder) wait(1) ticks += 1 ) fuzz out(fuzz) free slice(holder) free slice(fuzz) end script, write hiscore planks, holder, battle, begin # Assumes that all the hiscore planks for the current battle are loaded, and correctly sorted variable(plank, i, slot, rate, rounds, matches, hits, damage) plank := first child(holder) while(plank) do( rate := get slice extra(lookup slice(sli:hiscore rate, plank), 0) rounds := get slice extra(lookup slice(sli:hiscore rounds, plank), 0) matches := get slice extra(lookup slice(sli:hiscore matches, plank), 0) hits := get slice extra(lookup slice(sli:hiscore hits, plank), 0) damage := get slice extra(lookup slice(sli:hiscore damage, plank), 0) get slice text(str:tmp name, lookup slice(sli:hiscore name, plank)) write hiscore(slot, battle, str:tmp name, rate, rounds, matches, hits, damage) slot += 1 if(slot >= hiscore slots per battle) then( break ) plank := next sibling(plank) ) for(i, slot, hiscore slots per battle -- 1) do( erase hiscore(i, battle) ) end script, sort hiscore planks, holder, begin variable(plank, slot, moved, p2) while(true) do( moved := false plank := first child(holder) while(plank) do( p2 := first child(holder) while(p2) do( if(plank <> p2) then( if(slice edge y(p2, edge:bottom) < 200 && slice collide(plank, p2))then( if(compare hiscore planks(plank, p2) > 0) then( set slice y(p2, slice y(p2) + 4) moved := true ) ) ) p2 := next sibling(p2) ) plank := next sibling(plank) ) animate hiscore planks(holder) wait(1) ticks += 1 if(not(moved)) then(break) ) y sort children(holder) end script, animate hiscore planks, holder, begin variable(plank, main, rect, fuzz, c, p) plank := first child(holder) while(plank) do( main := get slice extra(plank, 1) rect := lookup slice(sli:hiscore rect, plank) c := 249 if(main && ticks ,mod, (second / 2) < second / 4) then(c := 253) set rect fgcol(rect, c) fuzz := lookup slice(sli:hiscore fuzz, plank) p := 100 -- 100 * slice edge y(plank, edge:center) / 200 if(main) then (p := 100) set rect fuzziness(fuzz, bounds(p, 0, 100)) plank := next sibling(plank) ) end script, compare hiscore planks, p1, p2, begin # Return 1 if p1 is better, -1 if p2 is better, and 0 if they are tied variable(ra1, ra2, ro1, ro2, m1, m2, h1, h2, d1, d2) ra1 := get slice extra(lookup slice(sli:hiscore rate, p1), 0) ra2 := get slice extra(lookup slice(sli:hiscore rate, p2), 0) if(ra1 <> ra2) then(exit returning(sign(ra1 -- ra2))) ro1 := get slice extra(lookup slice(sli:hiscore rounds, p1), 0) ro2 := get slice extra(lookup slice(sli:hiscore rounds, p2), 0) if(ro1 <> ro2) then(exit returning(sign(ro2 -- ro1))) # Lower rounds is better m1 := get slice extra(lookup slice(sli:hiscore matches, p1), 0) m2 := get slice extra(lookup slice(sli:hiscore matches, p2), 0) if(m1 <> m2) then(exit returning(sign(m1 -- m2))) h1 := get slice extra(lookup slice(sli:hiscore hits, p1), 0) h2 := get slice extra(lookup slice(sli:hiscore hits, p2), 0) if(h1 <> h2) then(exit returning(sign(h1 -- h2))) d1 := get slice extra(lookup slice(sli:hiscore damage, p1), 0) d2 := get slice extra(lookup slice(sli:hiscore damage, p2), 0) if(d1 <> d2) then(exit returning(sign(d1 -- d2))) exit returning(0) end script, create hiscore plank, slot, name str, rate, rounds, matches, hits, damage, begin variable(col, plank) col := load slice collection(slicol:hiscore plank) plank := lookup slice(sli:plank, col) set parent(plank, sprite layer) free slice(col) set slice extra(plank, 0, slot) string sprintf(0, $1="%d.%d", rate / 100, (rate ,mod, 100)) set plank string(plank, sli:hiscore rate, 0, rate, 8) string sprintf(0, $1="%d", rounds) set plank string(plank, sli:hiscore rounds, 0, rounds, 6) string sprintf(0, $1="%d", matches / 3) switch(matches ,mod, 3) do( case(1) do(append ascii(0, 127)) case(2) do(append ascii(0, 128)) ) set plank string(plank, sli:hiscore matches, 0, matches, 6) string sprintf(0, $1="%d", hits) set plank string(plank, sli:hiscore hits, 0, hits, 5) string sprintf(0, $1="%d", damage) set plank string(plank, sli:hiscore damage, 0, damage, 6) variable(txt) txt := lookup slice(sli:hiscore name, plank) set slice text(txt, name str) exit returning(plank) end script, set plank string, plank, code, str id, value, pad, begin variable(txt) txt := lookup slice(code, plank) while(string length(str id) < pad) do( $str id+" " ) set slice text(txt, str id) set slice extra(txt, 0, value) end script, name entry prompt, begin variable(fuzz, col) fuzz := create fuzzy layer col := load slice collection(slicol:name entry prompt) variable(txt) txt := lookup slice(sli:name entry battle txt, col) get slice text(1, txt) string sprintf(0, 1, battle number, last battle) set slice text(txt, 0) fuzz in(fuzz) while(true) do( if(mouse click(left button)) then( break ) wait(1) ) while(mouse button(left button)) do(wait(1)) $str:player name="" input string with mouse keyboard(str:player name) free slice(col) free slice(fuzz) end script, calc hiscore slot start, slot, battle, begin variable(start) start := @hiscore table + battle * (globals per battle * hiscore slots per battle) + slot * globals per battle exit returning(start) end script, write hiscore, slot, battle, name str, rate, rounds, matches, hits, damage, begin variable(start) start := calc hiscore slot start(slot, battle) write global(start + 0, true) write global(start + 1, rate) write global(start + 2, rounds) write global(start + 3, matches) write global(start + 4, hits) write global(start + 5, damage) string to globals(name str, start + 6, 40) export globals(31, start, start + globals per battle -- 1) end script, erase all hiscores, begin variable(battle, slot) for(battle, 0, last battle) do( for(slot, 0, hiscore slots per battle -- 1) do( erase hiscore(slot, battle) ) ) end script, erase hiscore, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) write global(start + 0, false) write global(start + 1, 0) write global(start + 2, 0) write global(start + 3, 0) write global(start + 4, 0) write global(start + 5, 0) $0="" string to globals(0, start + 6, 40) export globals(31, start, start + globals per battle -- 1) end script, hiscore slot is used, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) exit returning(import globals(31, start + 0)) end script, read hiscore rate, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) exit returning(import globals(31, start + 1)) end script, read hiscore rounds, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) exit returning(import globals(31, start + 2)) end script, read hiscore matches, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) exit returning(import globals(31, start + 3)) end script, read hiscore hits, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) exit returning(import globals(31, start + 4)) end script, read hiscore damage, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) exit returning(import globals(31, start + 5)) end script, read hiscore name, str id, slot, battle, begin variable(start) start := calc hiscore slot start(slot, battle) import globals(31, start + 6, start + 6 + 39) globals to string(str id, start + 6, 40) exit returning(str id) end #----------------------------------------------------------------------- # CREDITS SCREEN script, show hiscore index, begin variable(col, grid, fuzz, i, plank, bnum, empty) fuzz := create fuzzy layer col := load slice collection(slicol:hiscore index) grid := lookup slice(sli:hiscore index grid) set slice edge y(grid, edge:top, 100) move slice to(grid, 0, 0, second / 2) for(i, 1, last battle) do( create hiscore index plank(i, grid) ) fuzz in(fuzz) while(true) do( if(click button(sli:hiscore index back button, col)) then( break ) plank := first child(grid) while(plank) do( #show high score table for battle if(click button handle(plank)) then( empty := get slice extra(plank, 1) if(not(empty)) then( bnum := get slice extra(plank, 0) show high score table for battle(bnum, false) ) ) plank := next sibling(plank) ) wait(1) ) move slice to(grid, 0, 300, second / 2) fuzz out(fuzz) free slice(col) free slice(fuzz) end script, create hiscore index plank, bnum, grid, begin variable(plank) plank := load slice collection(slicol:hiscore index plank) set parent(plank, grid) set slice extra(plank, 0, bnum) variable(txt) txt := lookup slice(sli:hiscore index battle txt, plank) get slice text(1, txt) string sprintf(0, 1, bnum) set slice text(txt, 0) variable(rate) txt := lookup slice(sli:hiscore index best txt, plank) if(hiscore slot is used(0, bnum)) then( rate := read hiscore rate(0, bnum) get slice text(1, txt) string sprintf(0, 1, rate / 100, (rate ,mod, 100)) )else( $0="Unplayed" set slice extra(plank, 1, true) ) set slice text(txt, 0) exit returning(plank) end #----------------------------------------------------------------------- # CREDITS SCREEN script, credits screen, begin play song(20) variable(col, holder) col := load slice collection(slicol:credits) holder := lookup slice(sli:credits holder, col) set slice y(holder, 0) move slice to(holder, 0, -1 * (slice height(holder) -- slice height(sprite layer)), second * 40) variable(txt) txt := lookup slice(sli:credits for all battles txt, col) get slice text(1, txt) string sprintf(0, 1, last battle, last battle) set slice text(txt, 0) variable(cumulative rate) cumulative rate := cumulative damage * 100 / cumulative rounds txt := lookup slice(sli:credits total damage rate txt, col) get slice text(1, txt) string sprintf(0, 1, cumulative rate / 100, (cumulative rate ,mod, 100)) set slice text(txt, 0) txt := lookup slice(sli:credits total play time txt, col) $0="" if(days of play > 0) then( append number(0, days of play) $0+" days " ) append number(0, hours of play) $0+" hours " append number(0, minutes of play) $0+" minutes" set slice text(txt, 0) variable(heart) heart := lookup slice(sli:credits heart, col) animate credits background(col) wait(1) fade screen in wait for mouse release(left button) while(true) do( if(mouse click(left button)) then( if(confirm action($0="Play the game again from the start.")) then( break ) ) loop frame(heart, 0, 7) animate credits background(col) wait(1) ) free slice(col) delete save(1) reset game end script, animate credits background, col, begin variable(holder, rect, targ, f) holder := lookup slice(sli:credits background, col) rect := first child(holder) while(rect) do( targ := get slice extra(rect, 0) f := bounds(random(targ -- 10, targ + 10), 0, 100) set rect fuzziness(rect, f) rect := next sibling(rect) ) variable(flame layer, fl, spr) flame layer := lookup slice(sli:credits flame layer, col) if(child count(flame layer) == 0) then( # No flames yet, create the starting ones fl := create flame plank(flame layer) set slice y(fl, -80) fl := create flame plank(flame layer) set slice y(fl, 0) fl := create flame plank(flame layer) set slice y(fl, 80) fl := create flame plank(flame layer) set slice y(fl, 160) )else( variable(next fl, new fl) fl := first child(flame layer) while(fl) do( next fl := next sibling(fl) if(fl) then( if(slice y(fl) >= 200) then( new fl := create flame plank(flame layer) set slice y(new fl, slice y(fl) -- 320) free slice(fl) ) ) fl := next fl ) ) end script, create flame plank, parent, begin variable(col, fl) col := load slice collection(slicol:flame plank) fl := lookup slice(sli:flame plank, col) set parent(fl, parent) set slice velocity y(fl, 1) variable(spr) spr := lookup slice(sli:flame left, fl) set sprite set number(spr, random(1, 6)) spr := lookup slice(sli:flame right, fl) set sprite set number(spr, random(1, 6)) free slice(col) exit returning(fl) end #----------------------------------------------------------------------- # METERS script, update meter, sl, cur, max, begin variable(bar) bar := lookup slice(sli:meter bar, sl) variable(w) w := slice width(sl) * cur / max set slice width(bar, w) end #----------------------------------------------------------------------- # TITLE SCREEN script, title screen, begin play song(19) variable(col, rect, i) col := load slice collection(slicol:title) while(true) do( if(click button(sli:title start button, col)) then( break ) if(click button(sli:title hiscore button, col)) then( show hiscore index ) wait(1) ) free slice(col) play song(((battle number -- 1) ,mod, 10)) end #----------------------------------------------------------------------- # PAUSE MENU script, show pause menu, begin variable(col, rect, fuzz, i, quitbutton) fuzz := create fuzzy layer(100) col := load slice collection(slicol:menu) rect := lookup slice(sli:menu rect, col) set slice edge x(rect, edge:right, -160) set slice edge y(rect, edge:bottom, -100) move slice to(rect, 0, 0, second / 2) quitbutton := lookup slice(sli:save and quit button, col) set slice edge x(quitbutton, edge:left, 0) set slice edge y(quitbutton, edge:bottom, 0) move slice to(quitbutton, -3, 3, second / 2) play sound(sfx:wibble01) fuzz in(fuzz) while(true) do( if(click button(sli:save and quit button, col) || keyval(key:ESC) > 1) then( # Does not actually need to do any saving because of auto-save game over ) if(click button(sli:keep playing button, col)) then( break ) if(click button(sli:change name button, col)) then( input string with mouse keyboard(str:player name) wait for mouse release(left button) ) if(click button(sli:restart game button, col)) then( if(confirm action($0="Really discard your progress and restart the game?")) then( delete save(1) reset game ) ) if(click button(sli:erase high scores button, col)) then( if(confirm action($0="Are you sure you want to erase high scores? This cannot be undone.")) then( erase all hiscores ) ) wait(1) ) move slice to(rect, -320, -200, second / 2) move slice to(quitbutton, 160, -50, second / 2) play sound(sfx:chuff01) fuzz out(fuzz) free slice(col) free slice(fuzz) end script, confirm action, str id, begin variable(result, col, rect, fuzz, i) fuzz := create fuzzy layer(55) set rect bgcol(fuzz, 4) col := load slice collection(slicol:confirm) rect := lookup slice(sli:confirm rect, col) set slice edge x(rect, edge:left, slice width(rect)) move slice to(rect, 0, 0, second / 2) variable(txt) txt := lookup slice(sli:confirm txt, col) set slice text(txt, str id) play sound(sfx:wibble01) fuzz in(fuzz) while(true) do( if(click button(sli:confirm button, col)) then( result := true break )else( if(mouse click(left button)) then( result := false break ) ) wait(1) ) move slice to(rect, slice width(rect), 0, second / 2) play sound(sfx:chuff01) fuzz out(fuzz) free slice(col) free slice(fuzz) exit returning(result) end #----------------------------------------------------------------------- # MOUSE CURSOR script, create mouse cursor, begin mouse cursor := create container(0, 0) variable(ring) ring := load attack sprite(1) set slice lookup(ring, sli:mouse ring) set parent(ring, mouse cursor) center slice(ring) end script, wait for mouse release, button, begin while(mouse button(button)) do(wait(1)) end #----------------------------------------------------------------------- # ANIMATION UTILITY script, loop frame, sl, first, last, tickmod=1, begin if(tickmod > 0 && ticks ,mod, tickmod <> 0) then(exit script) variable(fr) fr := get sprite frame(sl) fr += 1 if(fr < first) then(fr := first) if(fr > last) then(fr := first) set sprite frame(sl, fr) end script, frame to last, sl, first, last, tickmod=1, begin # Returns true if the frame has reached the last if(tickmod > 0 && ticks ,mod, tickmod <> 0) then(exit script) variable(fr) fr := get sprite frame(sl) fr += 1 if(fr < first) then(fr := first) if(fr > last) then(fr := last) set sprite frame(sl, fr) exit returning(fr == last) end script, loop frame set, pic, first, last, tickmod=1, begin if(tickmod > 0 && ticks ,mod, tickmod <> 0) then(exit script) variable(curset, fr) curset := get sprite set number(pic) fr := curset + 1 if(fr < first) then(fr := first) if(fr > last) then(fr := first) set sprite set number(pic, fr) end script, frame set to last, pic, first, last, tickmod=1, begin # Returns true when the frame has reached the last if(tickmod > 0 && ticks ,mod, tickmod <> 0) then(exit script) variable(curset, fr) curset := get sprite set number(pic) fr := curset if(fr == last) then(exit script) fr += 1 if(fr < first) then(fr := first) if(fr > last) then(fr := last) set sprite set number(pic, fr) exit returning(fr == last) end #----------------------------------------------------------------------- # SLICE METADATA # extra 0 = bitsets # 0 = not used # 1 = remove me # 2 = is paladin # 3 = attack started # 4 = attack complete # 5 = visited # 6 = charmed # extra 1 = color # extra 2 = attack start callback # x = attack update callback # y = age # width = target unit # height = direction # pad top = alt color script, add metadata, sl, begin variable(meta) meta := lookup slice(sli:metadata, sl) if(not(meta)) then( meta := create container(0,0) set slice lookup(meta, sli:metadata) set parent(meta, sl) set slice visible(meta, false) ) end script, get meta, sl, begin variable(meta) meta := lookup slice(sli:metadata, sl) if(not(meta)) then( string sprintf(0, $1="Failed to get meta data for slice %s", sl) script error(0) ) exit returning(meta) end script, get unit color, sl, begin exit returning(get slice extra(get meta(sl), 1)) end script, set unit color, sl, v, begin set slice extra(get meta(sl), 1, v) apply unit color(sl, v) end script, get attack start callback, sl, begin exit returning(get slice extra(get meta(sl), 2)) end script, set attack start callback, sl, v, begin set slice extra(get meta(sl), 2, v) end script, get attack update callback, sl, begin exit returning(slice x(get meta(sl))) end script, set attack update callback, sl, v, begin set slice x(get meta(sl), v) end script, get age, sl, begin exit returning(ticks -- slice y(get meta(sl))) end script, set age, sl, v, begin set slice y(get meta(sl), ticks + v) end script, get target unit, sl, begin exit returning(slice width(get meta(sl))) end script, set target unit, sl, v, begin set slice width(get meta(sl), v) end script, get direction, sl, begin exit returning(slice height(get meta(sl))) end script, set direction, sl, v, begin set slice height(get meta(sl), v) end script, get alt color, sl, begin exit returning(get top padding(get meta(sl))) end script, set alt color, sl, v, begin set top padding(get meta(sl), v) end #----------------------------------------------------------------------- # SLICE METADATA BITS script, get exbit, sl, bit, begin variable(meta, n) meta := get meta(sl) n := get slice extra(meta, 0) if(n,and,2^bit) then(exit returning(true)) exit returning(false) end script, set exbit, sl, bit, value=1, begin variable(meta, n) meta := get meta(sl) n := get slice extra(meta, 0) if(value) then(n := n, or, 2^bit) else(n := n, and, (-1, xor, 2^bit)) set slice extra(meta, 0, n) end script, get remove me, sl ( exit returning(get exbit(sl, 1)) ) script, set remove me, sl, value ( set exbit(sl, 1, value) ) script, unit is paladin, sl ( exit returning(get exbit(sl, 2)) ) script, set unit is paladin, sl, value ( set exbit(sl, 2, value) ) script, get attack started, sl ( exit returning(get exbit(sl, 3)) ) script, set attack started, sl, value ( set exbit(sl, 3, value) ) script, get attack complete, sl ( exit returning(get exbit(sl, 4)) ) script, set attack complete, sl, value ( set exbit(sl, 4, value) ) script, get visited, sl ( exit returning(get exbit(sl, 5)) ) script, set visited, sl, value ( set exbit(sl, 5, value) ) script, get charmed, sl ( exit returning(get exbit(sl, 6)) ) script, set charmed, sl, value ( set exbit(sl, 6, value) ) #----------------------------------------------------------------------- # UTILITY script, small, v1, v2, begin if(v1 >> v2) then(exit returning(v2)) exit returning(v1) end script, large, v1, v2, begin if(v1 << v2) then(exit returning(v2)) exit returning(v1) end script, bounds, value, min, max, begin if(value << min) then(exit returning(min)) if(value >> max) then(exit returning(max)) exit returning(value) end script, set parent preserve pos, sl, new parent, begin variable(x, y) x := slice screen x(sl) y := slice screen y(sl) set parent(sl, new parent) put slice screen(sl, x, y) end script, compass x, d, begin switch(d) do( case(north) do (exit returning(0)) case(east) do (exit returning(1)) case(south) do (exit returning(0)) case(west) do (exit returning(-1)) ) end script, compass y, d, begin switch(d) do( case(north) do (exit returning(-1)) case(east) do (exit returning(0)) case(south) do (exit returning(1)) case(west) do (exit returning(0)) ) end script, diag compass x, d, begin switch(d) do( case(0) do (exit returning(-1)) case(1) do (exit returning(1)) case(2) do (exit returning(1)) case(3) do (exit returning(-1)) ) end script, diag compass y, d, begin switch(d) do( case(0) do (exit returning(-1)) case(1) do (exit returning(-1)) case(2) do (exit returning(1)) case(3) do (exit returning(1)) ) end script, octo compass x, i, begin switch(i) do( case(0) do (exit returning(-1)) case(1) do (exit returning(1)) case(2) do (exit returning(1)) case(3) do (exit returning(-1)) case(4) do (exit returning(0)) case(5) do (exit returning(1)) case(6) do (exit returning(0)) case(7) do (exit returning(-1)) ) end script, octo compass y, i, begin switch(i) do( case(0) do (exit returning(-1)) case(1) do (exit returning(-1)) case(2) do (exit returning(1)) case(3) do (exit returning(1)) case(4) do (exit returning(-1)) case(5) do (exit returning(0)) case(6) do (exit returning(1)) case(7) do (exit returning(0)) ) end script, axis val, x, y, axis, begin if(axis == 0) then(exit returning(x)) if(axis == 1) then(exit returning(y)) string sprintf(0, $1="axis val: invalid axis %d", axis) script error(0) end script, other axis, axis, begin if(axis == 0) then(exit returning(1)) if(axis == 1) then(exit returning(0)) string sprintf(0, $1="other axis: invalid axis %d", axis) script error(0) end