# (C) 2009-2013 James Paige # Don't Eat Soap! - An Educational Game Staring Bob the Hamster #----------------------------------------------------------------------- include, plotscr.hsd include, scancode.hsi include, eatsoap.hsi #----------------------------------------------------------------------- define constant(8, gravity) define constant(55, jump force) define constant(6, fall speed) define constant(6, default move speed) define constant(4, player walk speed) define constant(10, bubble shot speed) define constant(50, default shot force) define constant(8, default shot delay) define constant(2, bubble push speed) define constant(9, player pop bubble distance) define constant(17, bubble pop bubble distance) define constant(19, player push bubble distance) define constant(12, bubble push bubble distance) define constant(8, monster catch distance) define constant(18, bubble jump distance) define constant(100, fly away force) define constant(12, fly away time) define constant(20, reward pull distance) define constant(10, reward pickup distance) define constant(12, reward push reward distance) define constant(9, pull speed) define constant(2, score floater rise force) define constant(10, score floater ticks) define constant(14, powerup npc pic) define constant(15, first powerup) define constant(5, powerup count) define constant(700, far toggle speed) define constant(8, powerup appear delay) define constant(16, powerup flicker delay) define constant(18, powerup remove delay) define constant(7, bubble generator time) define constant(10, player death distance) define constant(1, weak wind) define constant(2, strong wind) define constant(0, grav:falling) define constant(1, grav:standing) define constant(2, grav:floating) define constant(3, grav:jumping) define constant(9, grav:jumping max) define constant(0, wep:bubble) define constant(1, wep:maturing bubble) define constant(2, wep:bubble shot) define constant(3, wep:bubble pop) define constant(4, wep:compressed bubble) define constant(5, wep:first reward) define constant(8, reward count) define constant(40, lastlev) define constant(0, bit:remove) define constant(1, bit:dying) define constant(2, bit:nowalls) define constant(3, bit:nograv) define constant(4, bit:hero) define constant(5, bit:angry) define constant(6, bit:immortal) define constant(7, bit:respawn) define constant(8, bit:vdir) define constant(9, bit:noanim) define constant(10, bit:noescape) define constant(11, bit:nopopkill) define constant(12, bit:nokillplayer) define constant(13, bit:vanishwrap) define constant(14, bit:multireward) define constant(15, bit:bubblestopper) define constant(1, tiles:blank) define constant(2, tiles:arrows) define constant(1, tmpstr) define constant(2, buildstr) define constant(3, linestr) define constant(4, padstr) define constant(5, curstr) define constant(6, lastname) define constant(7, lastname2) define constant(8, compstr) define constant(9, passstr) define constant(10, debugstr) define constant(1, phase timer) define constant(0, play phase) define constant(1, reward phase) define constant(2, advance phase) define constant(3, enter phase) define constant(18, seconds) define constant(5, reward phase length) define constant(2, death length) define constant(3, respawn length) define constant(14, angry palette) define constant(18, respawn palette) define constant(18, time till anger) define constant(23, time till escape) define constant(10, time till calm) define constant(8, time till reward flicker) define constant(12, time till reward vanish) define constant(3, tri:normal) define constant(15, tri:spin) define constant(18, tri:boss) define constant(11, turt:normal) define constant(12, turt:shell) define constant(13, turt:naked) define constant(17, litbolt pic) define constant(24, spikeball pic) define constant(25, chainlink pic) define constant(27, bunspell pic) #----------------------------------------------------------------------- global variable(0, pl1) global variable(1, pl2) global variable(2, map layer) global variable(3, score1) global variable(4, score1 sl) global variable(5, score2) global variable(6, score2 sl) global variable(7, pop groups) global variable(8, phase) global variable(9, slow tickstamp) global variable(10, share tog) global variable(11, blessing) global variable(12, lives1) global variable(13, lives1 sl) global variable(14, lives2) global variable(15, lives2 sl) global variable(16, ticks) global variable(17, continue prompt) global variable(18, boss meter box) global variable(19, boss meter) global variable(20, continue prompt pass) global variable(21, ui border sl) # globals >= 100 are saved permanently global variable(500, tv safe zone) #----------------------------------------------------------------------- plotscript, load high scores and init game, begin init high scores first time init init game end plotscript, init game, begin set tag(2, running on desktop) #tag 2 used to hide/show the instructions in the menu set tag(3, running on console) #tag 3 used to hide/show the toggle tv safe zone menu option tweak palette(-63, -63, -63) update palette teleport to map(0, 0, 0) reset palette update palette suspend player flush globals create map layer create groups create score create player(0, 5) set phase(play phase) init current map create continue prompt introduction main game loop end script, first time init, begin if(running on console) then( tv safe zone := true export globals(1, @tv safe zone, @tv safe zone) ) end script, flush globals, begin # the high score system might have saved some globals that should not have been saved variable(i) for(i, 0, 99) do( write global(i, 0) ) end #----------------------------------------------------------------------- script, introduction, begin variable(tmp) variable(time) variable(save song) save song := current song play song(3) # make background variable(bg) bg := create rect(320, 200, -1) set rect bg col(bg, 7) # make logo variable(logo) logo := load large enemy sprite(0) set horiz anchor(logo, edge:right) tmp := load large enemy sprite(1) set horiz align(tmp, edge:right) set parent(tmp, logo) set parent(logo, bg) set slice x(logo, 160) set slice y(logo, 50) # make intro text variable(tx) tx := create text set parent(tx, logo) set slice x(tx, 16) set slice y(tx, 80) set horiz anchor(tx, edge:center) set vert align(tx, edge:bottom) set horiz align(tx, edge:right) set wrap(tx, true) set slice width(tx, 312) clear string(buildstr) fill text from boxes(tx, 3, 5) variable(prompt) prompt := create text $tmpstr = "press a key" set slice text(prompt, tmpstr) set parent(prompt, logo) set horiz anchor(prompt, edge:center) set slice x(prompt, 80) set slice y(prompt, 100) # show title logo while(true) do( if(any player menu key) then(trigger menu(1)) if(almost any dang key) then(break) set slice visible(prompt, (abs(milliseconds, mod, 800) >> 100)) wait(1) ) free slice(prompt) wait(1) # scroll up instructions variable(skipwait) skipwait := false while(true) do( if(any player menu key) then(trigger menu(1)) if(almost any dang key) then( skipwait := true ) set slice y(logo, slice y(logo) -- 1) if(skipwait == false) then( wait(1) ) if(slice screen y(tx) << 20) then(break) ) play sound(sfx:menu use) wait(2) prompt := create text $tmpstr = "press a key" set slice text(prompt, tmpstr) set parent(prompt, bg) realign slice(prompt, edge:center, edge:bottom, edge:center, edge:top) set slice y(prompt, -20) set text color(prompt, 10) while(true) do( if(keyval(any player menu key) >> 1) then(trigger menu(1)) if(almost any dang key) then(break) set slice visible(prompt, (abs(milliseconds, mod, 800) >> 100)) wait(1) ) play sound(sfx:menu use) free slice(prompt) free slice(logo) wait(2) dont eat soap minigame(bg) hide wind arrows free slice(bg) if(running on desktop) then( # show keyboard controls show text box(1) wait for text box ) play song(save song) end script, dont eat soap minigame, bg, allow quit=true, begin variable(save song) save song := current song play song(3) variable(bob, soap, caption, praise) soap := load medium enemy sprite(0) set parent(soap, bg) set horiz anchor(soap, edge:center) set vert anchor(soap, edge:center) set slice x(soap, slice width(bg) -- 30) set slice y(soap, 110) bob := load attack sprite(0) set parent(bob, bg) set horiz anchor(bob, edge:center) set vert anchor(bob, edge:center) set slice x(bob, 30) set slice y(bob, 100) caption := create text set parent(caption, bg) set horiz align(caption, edge:center) set horiz anchor(caption, edge:center) set slice y (caption, 30) $tmpstr = "PRESS ANY KEY TO NOT EAT SOAP!" set slice text(caption, tmpstr) praise := create text set parent(praise, bg) set horiz align(praise, edge:center) set vert align(praise, edge:bottom) set horiz anchor(praise, edge:center) set vert anchor(praise, edge:bottom) set slice y(praise, -30) variable(diff, praise line, time, speed, noise) speed := 1 while(true) do( if(keyval(key:left) >> 0 || keyval(key:A) >> 0) then( set slice x(soap, slice x(soap) -- 8) )else( if(almost any dang key || keyval(key:ESC) >> 1) then( set slice x(soap, slice width(bg) -- 30) string from text box(tmpstr, 6, praise line) set slice text(praise, tmpstr) set text color(praise, random(9, 14)) time := milliseconds praise line := (praise line + 1), mod, 8 if(percent chance(20)) then(speed += 1) play sound(sfx:yoop) ) ) if(time <> 0 && milliseconds -- time >> 5000) then( clear string(tmpstr) set slice text(praise, tmpstr) time := 0 ) set slice visible(caption, (abs(milliseconds, mod, 800) >> 100)) set slice x(soap, slice x(soap) -- speed) if(noise == 0) then(play sound(sfx:squeep)) if(speed >= 20) then( noise := 0 )else( noise := (noise + 1), mod, (20 -- speed) ) if(noise << 0) then(noise := 0) wait(1) diff := slice x(soap) -- slice x(bob) set sprite frame(bob, 0) if(diff << 10) then( set sprite frame(bob, 2) free sprite(soap) break ) if(diff << 40) then( set sprite frame(bob, 1) continue ) if(diff << 100) then( set slice x(bob, slice x(bob), xor, 1) continue ) ) play sound(sfx:failure) $tmpstr = "OH NOES! YOU ATE THE SOAP!" set slice text(caption, tmpstr) set text color(caption, 12) set outline(caption, true) $tmpstr = "press a key - tragic consequences!" set slice text(praise, tmpstr) set text color(praise, 15) wait(4) while(true) do( if(any player menu key) then(break) if(almost any dang key) then(break) set slice visible(praise, (abs(milliseconds, mod, 800) >> 100)) wait(1) ) play sound(sfx:menu use) set rect bg col(bg, 1) $tmpstr = "The most important thing now..." set slice text(caption, tmpstr) set text color(caption, 15) set outline(caption, false) set slice visible(caption, true) $tmpstr = "is to get the soap out of your mouth!" set slice text(praise, tmpstr) set text color(praise, 15) set slice visible(praise, true) wait(2) time := milliseconds while(milliseconds -- time << 4000) do( if(almost any dang key) then(break) wait(1) ) wait(2) play song(savesong) end plotscript, minigame, begin variable(bg) bg := create rect(320, 200, -1) set rect bg col(bg, 7) dont eat soap minigame(bg, false) free slice(bg) end script, almost any dang key, begin variable(i) for(i, 2, 93) do( if(keyval(i) >> 1) then(exit returning(true)) ) exit returning(false) end script, any player menu key, begin exit returning(keyval(key:esc) >> 1 || keyval(key:tilde) >> 1) end script, fill text from boxes, sl, first box, last box, skip=0, center=false, begin variable(box, line, blank, first) for(box, first box, last box) do( if(box <> first box) then( add newlines(buildstr, skip) ) for(line, 0, 7) do( string from textbox(linestr, box, line) if(string length(linestr) == 0) then(blank += 1) else(blank := 0) if(blank <= 1) then( if(center) then(pad center string(linestr, 40)) append ascii(linestr, 10) buildstr $+ linestr ) ) ) set slice text(sl, buildstr) end script, pad center string, str, width, begin variable(len, pre, post, i) len := string length(str) pre := (width -- len) / 2 post := width -- len -- pre $padstr="" for(i, 1, pre) do( $padstr+" " ) tmpstr $= str str $= padstr str $+ tmpstr end script, add newlines, str, count, begin variable(i) for(i, 1, count) do( append ascii(str, 10) ) end script, add newlines to slice, sl, count, begin add newlines(buildstr, count) set slice text(sl, buildstr) end script, show credits, begin variable(old song) old song := current song play song(4) # make background variable(bg) bg := create rect(320, 200, -1) set rect bg col(bg, 0) clear string(buildstr) variable(tx) tx := create text set parent(tx, bg) set wrap(tx, true) set slice width(tx, 320) set slice y(tx, 200) fill text from boxes(tx, 7, 7, 2, true) variable(heart, bob1, misa1) heart := load weapon sprite(28) set parent(heart, tx) set horiz align(heart, edge:center) set horiz anchor(heart, edge:center) set slice y(heart, slice height(tx)) bob1 := load walkabout sprite(1) set parent(bob1, heart) realign slice(bob1, edge:left, edge:bottom, edge:right, edge:top) set sprite frame(bob1, 3) misa1 := load walkabout sprite(5) set parent(misa1, heart) realign slice(misa1, edge:right, edge:bottom, edge:left, edge:top) set sprite frame(misa1, 3) horiz flip sprite(misa1, true) add newlines to slice(tx, 6) fill text from boxes(tx, 8, 9, 2, true) variable(cat, tubax) cat := load large enemy sprite(2) set parent(cat, tx) set horiz align(cat, edge:center) set slice y(cat, slice height(tx) -- 35) tubax := load large enemy sprite(3) set parent(tubax, cat) set slice x(tubax, -25) set slice y(tubax, 30) add newlines to slice(tx, 10) fill text from boxes(tx, 10, 10, 5, true) add newlines to slice(tx, 2) add box and walkabout(tx, 11, 1) add box and walkabout(tx, 12, 5) add box and walkabout(tx, 13, 3) add box and walkabout(tx, 14, 7) add box and walkabout(tx, 15, 6) add newlines to slice(tx, 3) fill text from boxes(tx, 16, 16, 5, true) wait(1 * seconds) variable(cycle, y, key) while(true) do( cycle := (cycle + 1), mod, 3 key := false if(almost any dang key) then(key := true) y := slice y(tx) if(cycle >> 0) then( if(slice screen y(tx) + slice height(tx) >> 100) then( y -= 1 + key*4 )else( if(key) then(break) ) ) set slice y(tx, y) wait(1) ) free slice(bg) play song(old song) end script, add box and walkabout, tx, box, pic id, begin variable(spr) fill text from boxes(tx, box, box, 5, true) spr := load walkabout sprite(pic id) set parent(spr, tx) set horiz anchor(spr, edge:center) set horiz anchor(spr, edge:bottom) set horiz align(spr, edge:center) set slice y(spr, slice height(tx) -- 18) horiz flip sprite(spr, random(0,1)) set sprite frame(spr, 2) add newlines to slice(tx, 3) end #----------------------------------------------------------------------- script, create player, n, lives, begin variable(pl) pl := load walkabout sprite(player sprite(n)) set slice x(pl, map width * 20 / 2) set slice y(pl, 20) create game object(pl) set exbit(pl, bit:hero) set handler(pl, @player handler) set collision handler(pl, @check player collisions) set player(n, pl) init player(pl) set lives for player(pl, lives) end script, init player, pl, begin set shot force(pl, default shot force) set shot delay(pl, default shot delay) end script, create groups, begin pop groups := create container(0,0) set slice visible(pop groups, false) end script, create map layer, begin map layer := lookup slice(sl:map layer 1) end script, load next map, begin fade screen out variable(old map) old map := current map teleport to map(current map + 1, 0, 0) init current map set phase(enter phase) wait(1) if(old map == current map) then( reset palette update palette show credits on both players(@check for high score) reset game ) fade screen in end script, init current map, begin clear all objects convert npcs into slices hide wind arrows reset level specials end script, reset level specials, begin slow tickstamp := 0 blessing := none set slice visible(boss meter box, false) end script, main game loop, begin while(true) do( ticks += 1 share tog := share tog, xor, 1 handle keys update camera update sprites wait(1) ) end script, handle keys, begin if(any player menu key || keyval(key:Enter) >> 1) then(pause menu) handle player 1 keys(pl1) handle player 2 keys(pl2) if(keyval(key:ctrl) >> 0) then( if(keyval(key:B) >> 1) then(toggle wind arrows) if(keyval(key:P) >> 1) then(create random powerup(random(0, slice width(map layer)), random(0, slice height(map layer)))) if(keyval(key:T) >> 1) then(teleport cheat) if(keyval(key:F) >> 1) then(spit monster bubble(pl1, 2)) if(keyval(key:Y) >> 1) then(show credits) ) end script, handle player 1 keys, sl, begin if(sl == 0 && (keyval(key:right shift) >> 1 || keyval(key:right ctrl) >> 1)) then( player joins(0) exit script ) if(sl == 0) then(exit script) if(phase == advance phase || phase == enter phase) then(exit script) if(get exbit(sl, bit:dying)) then(exit script) variable(i) # check keys for left and right if(keyval(key:left) >> 0) then( set force x(sl, player walk speed, -1) horiz flip sprite(sl, true) ) if(keyval(key:right) >> 0) then( set force x(sl, player walk speed, 1) horiz flip sprite(sl, false) ) if(keyval(key:right ctrl) >> 1) then(jump(sl)) if(keyval(key:space) >> 1) then(do attack(sl)) if(keyval(key:right shift) >> 1) then(do attack(sl)) if(running on desktop) then( if(keyval(key:up) >> 1) then(jump(sl)) if(keyval(key:down) >> 1) then(do attack(sl)) ) end script, handle player 2 keys, sl, begin if(sl == 0 && (keyval(key:left shift) >> 1 || keyval(key:left ctrl) >> 1)) then( player joins(1) exit script ) if(sl == 0) then(exit script) if(phase == advance phase || phase == enter phase) then(exit script) if(get exbit(sl, bit:dying)) then(exit script) variable(i) # check keys for left and right # check keys for left and right if(keyval(key:A) >> 0) then( set force x(sl, player walk speed, -1) horiz flip sprite(sl, true) ) if(keyval(key:D) >> 0) then( set force x(sl, player walk speed, 1) horiz flip sprite(sl, false) ) if(keyval(key:left ctrl) >> 1) then(jump(sl)) if(keyval(key:tab) >> 1) then(do attack(sl)) if(keyval(key:left shift) >> 1) then(do attack(sl)) if(running on desktop) then( if(keyval(key:W) >> 1) then(jump(sl)) if(keyval(key:S) >> 1) then(do attack(sl)) ) end script, do attack, sl, begin if(get attack delay(sl) <= 0) then( set attack delay(sl, get shot delay(sl)) create bubble shot(sl) ) end script, jump, sl, begin variable(state) state := get gravstate(sl) if(state == grav:standing) then( set gravstate(sl, grav:jumping) if(is player(sl)) then( play sound(sfx:jump) ) ) end script, update camera, begin if(pl1 == 0 && pl2 == 0) then(exit script) variable(x, y) if(pl1 == 0) then( x := slice edge x(pl2, edge:center) y := slice edge y(pl2, edge:center) )else( if(pl2 == 0) then( x := slice edge x(pl1, edge:center) y := slice edge y(pl1, edge:center) )else( variable(x1, y1, x2, y2) x1 := slice edge x(pl1, edge:center) y1 := slice edge y(pl1, edge:center) x2 := slice edge x(pl2, edge:center) y2 := slice edge y(pl2, edge:center) x := (x1 + x2) / 2 y := (y1 + y2) / 2 ) ) put camera(x -- 160, y -- 100) end script, update sprites, begin if(phase == advance phase || phase == enter phase) then( on both players(@update sprite) exit script ) variable(sl, delete) sl := first child(map layer) while(sl) do( delete := false update sprite(sl) if(get exbit(sl, bit:remove)) then(delete := sl) sl := next sibling(sl) if(delete) then(free slice(delete)) ) end script, update sprite, sl, begin if(sl == 0) then(exit script) if(slowness(sl)) then(exit script) reduce attack delay(sl) sprite gravity(sl) # deal with walls and floors default state is falling(sl) if(get exbit(sl, bit:nowalls) == false) then( variable(i) for(i, 0, 3) do( if(care about corner(sl, i)) then( check corner(sl, i) ) ) ) # animate and move sprite animation(sl) move sprite(sl) wrap edges(sl) # run handlers variable(old parent) old parent := parent slice(sl) variable(fn) fn := get collision handler(sl) if(fn) then( run script by id(fn, sl) ) if(old parent <> parent slice(sl)) then( # parent has changed, that means we are in a bubble, and should not run ai )else( fn := get handler(sl) if(fn) then( run script by id(fn, sl) ) ) end script, slowness, sl, begin if(slow tickstamp == 0) then(exit returning(false)) if(sl == pl1 || sl == pl2) then(exit returning(false)) if(slow tickstamp << ticks) then( slow tickstamp := 0 exit returning(false) )else( exit returning(share tog) ) end script, wrap edges, sl, begin variable(wrapped) wrapped := false if(slice edge x(sl, edge:right) <= 0) then( set slice x(sl, slice width(map layer) -- 1) wrapped := true ) if(slice edge x(sl, edge:left) >= slice width(map layer)) then( set slice x(sl, 1 -- slice width(sl)) wrapped := true ) if(slice edge y(sl, edge:bottom) <= 0) then( set slice y(sl, slice height(map layer) -- 1) wrapped := true ) if(slice edge y(sl, edge:top) >= slice height(map layer)) then( if(is player(sl) && phase == advance phase) then( load next map on both players(@set slice to top) ) set slice to top(sl) wrapped := true ) if(wrapped) then( if(get exbit(sl, bit:vanishwrap)) then( set exbit(sl, bit:remove) ) ) end script, set slice to top, sl, begin if(sl == 0) then(exit script) set slice y(sl, 1 -- slice height(sl)) end script, player handler, sl, begin if(get exbit(sl, bit:respawn)) then( variable(pal) pal := get sprite palette(sl) if(pal == -1) then(pal := respawn palette) else(pal := -1) set sprite palette(sl, pal) if(get ticks elapsed(sl) >> seconds * respawn length) then( player finish respawn(sl) ) ) if(phase == advance phase || phase == enter phase) then( float down to next level(sl) ) if(get exbit(sl, bit:dying)) then( horiz flip sprite(sl, abs(milliseconds, mod, 200), and, 1) vert flip sprite(sl, abs(milliseconds, mod, 80), and, 1) if(get ticks elapsed(sl) >> seconds * death length) then( death wobble complete(sl) ) ) end script, death wobble complete, sl, begin variable(lives) lives := get lives for player(sl) lives -= 1 set lives for player(sl, lives) if(lives <= 0) then( player fully dies(sl) )else( respawn player(sl) ) end script, player fully dies, sl, begin check for high score(sl) reset score(sl) set exbit(sl, bit:remove) clear player(sl) update continue prompt end script, reset score, sl, begin if(sl) then( set score for player(sl, 0) add score(sl, 0) ) end script, create continue prompt, begin variable(sl) sl := create rect(310, 55) set rect style(sl, 2) set rect trans(sl, true) center slice(sl) variable(tx) tx := create text set outline(tx, true) #set wrap(tx, true) $tmpstr=" GAME OVER. CONTINUE?" append ascii(tmpstr, 10) append ascii(tmpstr, 10) if(running on desktop) then( $tmpstr+"LSHIFT=Misa RSHIFT=Bob" ) set parent(tx, sl) center slice(tx) set slice text(tx, tmpstr) variable(bob, misa) bob := load walkabout sprite(1) horiz flip sprite(bob) set parent(bob, tx) realign slice(bob, edge:right, edge:bottom, edge:left, edge:bottom) misa := load walkabout sprite(5) set parent(misa, tx) realign slice(misa, edge:left, edge:bottom, edge:right, edge:bottom) set slice visible(sl, false) continue prompt pass := create text set parent(continue prompt pass, sl) realign slice(continue prompt pass, edge:center, edge:bottom, edge:center, edge:bottom) set slice y(continue prompt pass, -4) continue prompt := sl end script, update continue prompt, begin get code for level(current map, passstr) if(string length(passstr)) then( $tmpstr="Your password: " concatenate strings(tmpstr, passstr) )else( $tmpstr="" ) set slice text(continue prompt pass, tmpstr) set outline(continue prompt pass, true) set slice visible(continue prompt, pl1 == 0 && pl2 == 0) end script, respawn player, sl, begin set slice x(sl, player start x(sl)) set slice y(sl, player start y(sl)) init player(sl) set exbit(sl, bit:nograv, false) set exbit(sl, bit:dying, false) horiz flip sprite(sl, false) vert flip sprite(sl, false) set exbit(sl, bit:respawn) set tickstamp(sl) update continue prompt if(phase == advance phase) then( enbubble player(sl) ) end script, player finish respawn, sl, begin set sprite palette(sl, -1) set exbit(sl, bit:respawn, false) end script, generator handler, sl, begin variable(bub, ob) if(get attack delay(sl) == 0) then( bub := create bubble shot(sl) set force x(bub, 0) set force y(bub, 0) set attack delay(sl, seconds * bubble generator time) ob := copy of monster(sl) catch monster(ob, bub) set exbit(ob, bit:noescape, true) set exbit(ob, bit:nopopkill, true) ) end script, copy of monster, sl, begin variable(pic id, copy) pic id := get sprite set number(sl) copy := create monster(pic id, slice x(sl), slice y(sl), sprite is horiz flipped(sl)) exit returning(copy) end script, monster handler, sl, begin variable(ai) if(get exbit(sl, bit:dying)) then( update dying monster(sl) )else( ai := get ai(sl) if(ai) then(run script by id(ai, sl)) ) if(get exbit(sl, bit:angry)) then( if(get ticks elapsed(sl) >> seconds * time till calm) then( cancel anger(sl) )else( flash angry(sl) ) ) end script, bubble handler, sl, begin variable(id) id := get sprite set number(sl) switch(id) do( case(wep:bubble shot) do(update bubble shot(sl)) case(wep:maturing bubble) do(mature bubble(sl)) case(wep:bubble pop) do(bubble pop decay(sl)) case(wep:compressed bubble) do(bubble wobble decay(sl)) ) if(wind can blow(id)) then( apply wind force(sl) ) variable(mon) mon := get monster inside(sl) if(mon) then( variable(time) if(get exbit(mon, bit:noescape) == false) then( time := get ticks elapsed(sl) if(time >> seconds * time till anger) then( make trapped monster angry(sl) ) if(time >> seconds * time till escape) then( free trapped monster(sl) ) ) ) end script, free trapped monster, bub, begin variable(sl) sl := get monster inside(bub) if(sl) then( remove from bubble(bub) vert flip sprite(sl, false) set sprite frame(sl, 0) set tickstamp(sl) ) set exbit(bub, bit:remove) end script, make trapped monster angry, bub, begin variable(sl) sl := get monster inside(bub) if(sl) then( horiz flip sprite(sl, random(0,1)) vert flip sprite(sl, random(0,1)) start anger(sl) flash angry(sl) ) end script, start anger, sl, begin set exbit(sl, bit:angry, true) special monster settings(sl) variable(speed) speed := get move speed(sl) set move speed(sl, speed + (speed * 3 / 4)) end script, cancel anger, sl, begin set sprite palette(sl, -1) set exbit(sl, bit:angry, false) special monster settings(sl) end script, flash angry, sl, begin variable(pal) pal := get sprite palette(sl) if(pal == -1) then( pal := angry palette )else( pal := -1 ) set sprite palette(sl, pal) end script, reward handler, sl, begin reward motion(sl) variable(time) time := get ticks elapsed(sl) if(time >> seconds * time till reward flicker) then( set slice visible(sl, not(get slice visible(sl))) ) if(time >> seconds * time till reward vanish) then( set exbit(sl, bit:remove) ) end script, update dying monster, sl, begin vflip monster(sl) if(get attack delay(sl) <= 0) then( if(get exbit(sl, bit:nograv)) then( # first stage of death has ended set exbit(sl, bit:nograv, false) set force y(sl, 0) set attack delay(sl, fly away time / 2) )else( # second stage has ended set exbit(sl, bit:nowalls, false) transform into reward(sl) ) ) end script, transform into reward, sl, begin # transform the given monster into a reward cancel anger(sl) set sprite frame(sl, 0) variable(pic) pic := get bonus pic(sl) replace weapon sprite(sl, pic) init reward(sl) set exbit(sl, bit:nograv, false) end script, create reward, pic, x, y, points, begin variable(sl) sl := load weapon sprite(pic) create game object(sl) set slice x(sl, x) set slice y(sl, y) init reward(sl, points) end script, init reward, sl, points=-1, begin if(points >> -1) then( set points(sl, points) ) vert flip sprite(sl, false) horiz flip sprite(sl, false) set handler(sl, @reward handler) set collision handler(sl, @check reward to reward collisions) set collision with player handler(sl, @player reward collision) set tickstamp(sl) end script, wind can blow, pic id, begin exit returning(pic id == wep:bubble || pic id == wep:compressed bubble || pic id == wep:bubble pop) end script, default state is falling, sl, begin variable(state) state := get gravstate(sl) if(state == grav:standing) then(set gravstate(sl, grav:falling)) end script, move sprite, sl, begin variable(axis, n, go, movement) for(axis, x axis, y axis) do( n := slice coord by axis(sl, axis) go := get force(sl, axis) movement := cap movement by axis(sl, go, axis) set slice coord by axis(sl, axis, n + movement) set force(sl, axis, go -- movement) ) end script, cap movement by axis, sl, go, axis, begin switch(axis) do( case(x axis) do(exit returning(cap movement(sl, go))) case(y axis) do(exit returning(cap falling(sl, go))) ) end script, cap movement, sl, go, begin variable(s, a, speed) s := sign(go) a := abs(go) speed := get move speed(sl) if(a >> speed) then(a := speed) exit returning(a * s) end script, cap falling, sl, go, begin variable(s, a, speed) s := sign(go) a := abs(go) if(get exbit(sl, bit:nograv)) then( speed := get move speed(sl) )else( speed := fall speed ) if(a >> speed) then(a := speed) exit returning(a * s) end script, sprite gravity, sl, begin if(get exbit(sl, bit:nograv)) then(exit script) variable(state) state := get gravstate(sl) if(state == grav:falling || state == grav:standing) then(set force y(sl, gravity)) if(state == grav:jumping) then(set force y(sl, jump force * -1)) if(state == grav:jumping max) then(set gravstate(sl, grav:falling)) if(state >= grav:jumping && state << grav:jumping max) then( set gravstate(sl, state+1) ) end script, clear all objects, begin variable(sl, delete) sl := first child(map layer) while(sl) do( delete := false if(is bubble(sl)) then(delete := sl) if(is monster(sl)) then(delete := sl) if(is reward(sl)) then(delete := sl) if(is powerup(sl)) then(delete := sl) if(slice is text(sl)) then(delete := sl) sl := next sibling(sl) if(delete) then(free slice(delete)) ) end #----------------------------------------------------------------------- script, reward motion, sl, begin if(get gravstate(sl) == grav:standing) then(set force x(sl, 0)) if(slice edge x(sl, edge:center) <= 27) then(set force x(sl, get move speed(sl))) if(slice edge x(sl, edge:center) >= slice width(map layer) -- 27) then(set force x(sl, get move speed(sl) * -1)) end script, powerup handler, sl, begin reward motion(sl) variable(time) time := get ticks elapsed(sl) if(time >> powerup remove delay * seconds) then( set exbit(sl, bit:remove) )else( if(time >> powerup flicker delay * seconds) then( set slice visible(sl, share tog) )else( if(time >> powerup appear delay * seconds) then( set slice visible(sl, true) ) ) ) end script, player powerup collision, who, ob, begin variable(c sq) c sq := get c squared(who, ob) if(c sq << reward pickup distance^2) then(pickup powerup(who, ob)) end script, pickup powerup, who, sl, begin if(get slice visible(sl) == false) then(exit script) variable(type) type := get sprite set number(sl) -- first powerup switch(type) do( case(0) do(powerup extend range(who, sl)) case(1) do(powerup fast shot(who, sl)) case(2) do(powerup slow time(who, sl)) case(3) do(powerup coin(who, sl)) case(4) do(powerup money bag(who, sl)) ) set exbit(sl, bit:remove) play sound(sfx:reward pickup) end script, powerup extend range, who, pow, begin set shot force(who, get shot force(who) + 40) $tmpstr="range up!" create powerup floater(pow, tmpstr) end script, powerup fast shot, who, pow, begin set shot delay(who, get shot delay(who) / 2) $tmpstr="fast shot!" create powerup floater(pow, tmpstr) end script, powerup slow time, who, pow, begin slow tickstamp := ticks + 10 * seconds $tmpstr="slow time" create powerup floater(pow, tmpstr) end script, powerup coin, who, pow, begin add score floater(who, pow, 100) end script, powerup money bag, who, pow, begin blessing := 18 $tmpstr="coin blessing" create powerup floater(pow, tmpstr) end #----------------------------------------------------------------------- plotscript, trigger close menu from menu, begin wait(1) trigger menu(1) end script, trigger menu, menu id, begin play sound(sfx:menu use) variable(mh, mi, close delay) close delay := 5 mh := open menu(menu id) while(menu is open(mh)) do( if(close delay >> 0) then( close delay -= 1 )else( if(any player menu key || keyval(key:left shift) >> 1 || keyval(key:right shift) >> 1) then(break) ) if(keyval(key:left ctrl) >> 1 || keyval(key:right ctrl) >> 1 || keyval(key:enter) >> 1 || keyval(key:space) >> 1) then( use menu item(selected menu item(mh)) ) if(keyval(key:up) >> 1 || keyval(key:w) >> 1) then( mi := previous menu item(selected menu item(mh)) if(mi) then( play sound(sfx:menu move) select menu item(mi) ) ) if(keyval(key:down) >> 1 || keyval(key:s) >> 1) then( mi := next menu item(selected menu item(mh)) if(mi) then( play sound(sfx:menu move) select menu item(mi) ) ) wait(1) ) close menu(mh) end script, pause menu, begin variable(menu) menu := trigger menu(0) wait for text box end plotscript, exit from menu, begin on both players(@check for high score) play sound(sfx:goodbye) wait(2) game over end #----------------------------------------------------------------------- script, set phase, ph, begin phase := ph switch(phase) do( case(play phase) do( on both players(@disbubble player) ) case(reward phase) do( pop all bubbles variable(time) time := reward phase length + count possible rewards if(blessing >> 0) then(time += 2) set timer(phase timer, time -- 1, seconds, @end reward phase) reset level specials ) ) end script, end reward phase, begin set phase(advance phase) on both players(@enbubble player) end script, enbubble player, sl, begin if(sl == 0) then(exit script) set sprite frame(sl, 4) set exbit(sl, bit:nograv) set exbit(sl, bit:nowalls) variable(bub) bub := load weapon sprite(wep:bubble) set parent(bub, sl) center slice(bub) end script, disbubble player, sl, begin if(sl == 0) then(exit script) variable(ob, delete) ob := first child(sl) while(ob) do( delete := false if(is bubble(ob)) then(delete := ob) ob := next sibling(ob) if(delete) then(free slice(delete)) ) set sprite frame(sl, 0) set exbit(sl, bit:nograv, false) set exbit(sl, bit:nowalls, false) end script, count monsters, begin variable(sl, n, inside) n := 0 sl := first child(map layer) while(sl) do( if(slice is sprite(sl)) then( switch(get sprite type(sl)) do( case(spritetype:walkabout) do( if(get exbit(sl, bit:hero) == false) then( if(get exbit(sl, bit:dying) == false) then( if(get exbit(sl, bit:immortal) == false) then( if(get exbit(sl, bit:nokillplayer) == false) then( n += 1 ) ) ) ) ) case(spritetype:weapon) do( if(is bubble(sl)) then( inside := get monster inside(sl) if(inside) then( if(get exbit(inside, bit:immortal) == false) then( if(get exbit(inside, bit:nokillplayer) == false) then( n += 1 ) ) ) ) ) ) ) sl := next sibling(sl) ) exit returning(n) end script, count possible rewards, begin variable(sl, n) n := 0 sl := first child(map layer) while(sl) do( if(slice is sprite(sl)) then( switch(get sprite type(sl)) do( case(spritetype:walkabout) do( if(get exbit(sl, bit:hero) == false) then( if(get exbit(sl, bit:dying) == true) then( n += 1 ) ) ) case(spritetype:weapon) do( if(is reward(sl)) then( n += 1 ) ) ) ) sl := next sibling(sl) ) exit returning(n) end script, float down to next level, sl, begin variable(force) force := get move speed(sl) / 2 if((milliseconds / 1400), and, 1) then(force := force * -1) set force x(sl, force) set force y(sl, 3) if(phase == enter phase && slice y(sl) >> slice height(map layer) / 2) then( variable(xdiff, ydiff, xforce, yforce) xdiff := player start x(sl) -- slice x(sl) ydiff := player start y(sl) -- slice y(sl) xforce := get move speed(sl) yforce := get move speed(sl) if(xforce >> abs(xdiff)) then(xforce := abs(xdiff) + 1) if(yforce >> abs(ydiff)) then(yforce := abs(ydiff) + 1) set force x(sl, xforce * sign(xdiff)) set force y(sl, yforce * sign(ydiff)) if(abs(xdiff)^2 + abs(ydiff)^2 << (get move speed(sl))^2) then( set phase(play phase) ) ) ) #----------------------------------------------------------------------- script, check player collisions, sl, begin if(phase == enter phase) then(exit script) variable(ob, fn) ob := first child(map layer) while(ob) do( fn := get collision with player handler(ob) if(fn) then( if(slice collide(sl, ob)) then( run script by id(fn, sl, ob) ) ) ob := next sibling(ob) ) end script, get c squared, sl1, sl2, begin variable(a, b) a := slice edge x(sl1, edge:center) -- slice edge x(sl2, edge:center) b := slice edge y(sl1, edge:center) -- slice edge y(sl2, edge:center) exit returning(abs(a)^2 + abs(b)^2) end script, within distance, sl1, sl2, dist, begin variable(a, b, c sq) a := slice edge x(sl1, edge:center) -- slice edge x(sl2, edge:center) b := slice edge y(sl1, edge:center) -- slice edge y(sl2, edge:center) c sq := abs(a)^2 + abs(b)^2 exit returning(c sq << dist^2) end script, within xdist, sl1, sl2, dist, begin variable(diff) diff := slice edge x(sl2, edge:center) -- slice edge x(sl1, edge:center) exit returning(abs(diff) <= dist) end script, within ydist, sl1, sl2, dist, begin variable(diff) diff := slice edge y(sl2, edge:center) -- slice edge y(sl1, edge:center) exit returning(abs(diff) <= dist) end script, is facing, sl, sl2, begin if(slice x(sl) >> slice x(sl2)) then( exit returning(sprite is horiz flipped(sl)) )else if(slice x(sl) << slice x(sl2)) then( exit returning(not(sprite is horiz flipped(sl))) ) exit returning(false) end script, is above, sl, sl2, begin exit returning(slice y(sl) << slice y(sl2)) end script, player monster collision, who, mon, begin if(get exbit(who, bit:dying) || get exbit(who, bit:respawn)) then(exit script) if(within distance(who, mon, player death distance)) then( if(get exbit(mon, bit:dying) == false) then( if(get exbit(mon, bit:nokillplayer) == false) then( player dies(who) ) ) ) end script, player dies, sl, begin set exbit(sl, bit:dying) set exbit(sl, bit:nograv) set tickstamp(sl) play sound(sfx:deathwail) end script, player bubble collision, who, bub, begin variable(c sq) c sq := get c squared(who, bub) if(get force y(who) >= 0 && c sq << bubble jump distance^2) then( if(jump key for player(who)) then( wobble bubble(bub) set gravstate(who, grav:standing) set force y(who, 0) jump(who) exit script ) ) if(c sq << player pop bubble distance^2) then( create pop group(who, bub) pop bubble(bub) ) if(c sq << player push bubble distance^2) then(push bubble away(who, bub)) end script, player reward collision, who, rew, begin variable(c sq) c sq := get c squared(who, rew) if(c sq << reward pickup distance^2) then(pickup reward(who, rew)) if(c sq << reward pull distance^2) then(pull towards(who, rew, pull speed)) end script, wobble bubble, bub, begin replace weapon sprite(bub, wep:compressed bubble) set sprite frame(bub, 1) set attack delay(bub, 3) end script, check monster collisions, sl, begin variable(ob, next, type, id, fn, collide, bubblestop, immortal) bubblestop := get exbit(sl, bit:bubblestopper) immortal := get exbit(sl, bit:immortal) fn := get monster collision handler(sl) ob := first child(map layer) while(ob) do( next := next sibling(ob) # pre-cache next sibling because ob might get reparented. if(is a catching bubble(ob)) then( collide := slice collide(sl, ob) if(bubblestop) then( if(collide) then( mature bubble(ob) play sound(sfx:bubbleblock) ) )else if(not(immortal)) then( if(slice collide(sl, ob)) then( monster bubble catch attempt(sl, ob) ) ) ) if(fn) then(run script by id(fn, sl, ob)) ob := next ) end script, is a catching bubble, bub, begin variable(type, id) if(slice is sprite(bub)) then( type := get sprite type(bub) id := get sprite set number(bub) if(type == spritetype:weapon) then( if(id == wep:bubble shot || id == wep:maturing bubble) then(exit returning(true)) ) ) exit returning(false) end script, monster bubble catch attempt, who, bub, begin if(within distance(who, bub, monster catch distance)) then( catch monster(who, bub) ) end script, catch monster, who, bub, begin play sound(sfx:bubblecatch) mature bubble(bub) cancel anger(who) put inside bubble(who, bub) set tickstamp(bub) end script, put inside bubble, who, bub, begin capture handler(who, bub) set parent(who, bub) center slice(who) set slice x(who, 0) set slice y(who, 0) set sprite frame(who, 4) end script, push bubble away, who, bub, begin variable(xdiff, ydiff) xdiff := slice edge x(bub, edge:center) -- slice edge x(who, edge:center) ydiff := slice edge y(bub, edge:center) -- slice edge y(who, edge:center) set force x(bub, get force x(bub) + bubble push speed * sign(xdiff)) set force y(bub, get force y(bub) + bubble push speed * sign(ydiff)) end script, pop bubble, bub, begin replace weapon sprite(bub, wep:bubble pop) set collision with player handler(bub, none) kill trapped monster(bub) set attack delay(bub, 3) play sound(sfx:little pop) variable(popper) popper := get bubble popper(bub) if(popper) then( add score(popper, 1) ) end script, pop all bubbles, begin variable(sl) sl := first child(map layer) while(sl) do( if(is bubble(sl)) then( create blessing(sl) pop bubble(sl) ) sl := next sibling(sl) ) end script, create blessing, sl, begin if(blessing == 0) then(exit script) create reward(blessing, slice x(sl), slice y(sl), 100) end script, bubble pop decay, bub, begin if(get attack delay(bub) == 0) then( set exbit(bub, bit:remove, true) remove from pop group(bub) ) end script, bubble wobble decay, bub, begin if(get attack delay(bub) == 0) then(mature bubble(bub)) end script, check bubble to bubble collisions, sl, begin variable(ob) ob := first child(map layer) while(ob) do( if(is bubble colideable bubble(ob)) then( bubble bubble collision(sl, ob) ) ob := next sibling(ob) ) end script, is bubble, sl, begin variable(id) if(slice is sprite(sl)) then( if(get sprite type(sl) == spritetype:weapon) then( id := get sprite set number(sl) exit returning(id << wep:first reward) ) ) exit returning(false) end script, is bubble colideable bubble, sl, begin variable(id) if(slice is sprite(sl)) then( if(get sprite type(sl) == spritetype:weapon) then( id := get sprite set number(sl) exit returning(id == wep:bubble || id == wep:compressed bubble || id == wep:bubble pop) ) ) exit returning(false) end script, bubble bubble collision, who, bub, begin variable(c sq) c sq := get c squared(who, bub) if(c sq << bubble pop bubble distance^2) then( if(get sprite set number(who) == wep:bubble pop) then( # a popping bubble can pop others if(get sprite set number(bub) <> wep:bubble pop) then( # but obviously only when the bubble is not already popping add to pop group(who, bub) pop bubble(bub) exit script ) ) ) if(c sq << bubble push bubble distance^2) then( push bubble away(who, bub) ) end script, get monster inside, bub, begin exit returning(next sibling(first child(bub))) end script, kill trapped monster, bub, begin variable(sl, gr, popper) sl := get monster inside(bub) if(sl) then( gr := get pop group(bub) if(gr) then( popper := get slice extra(gr, extra 2) ) if(get exbit(sl, bit:nopopkill)) then( free trapped monster(bub) variable(flip) if(popper) then( flip := not(sprite is horiz flipped(popper)) )else( flip := random(0,1) ) horiz flip sprite(sl, flip) exit script ) if(is player(popper) == false) then( free trapped monster(bub) exit script ) remove from bubble(bub) variable(bonus lev, bonus pic) bonus lev := increment pop group bonus(bub) bonus pic := wep:first reward + bonus lev if(bonus lev >= reward count) then(bonus pic := wep:first reward + reward count -- 1) kill monster(sl, bonus pic, (bonus lev + 1) * 1000) variable(giant) giant := get giant(sl) if(giant) then( free slice(giant) # special handling for killing the boss replace walkabout sprite(sl, tri:normal) ) if(get exbit(sl, bit:multireward)) then( variable(i, dup) for(i, 0, 8) do( dup := copy of monster(sl) bonus lev := increment pop group bonus(bub) bonus pic := wep:first reward + bonus lev if(bonus lev >= reward count) then(bonus pic := wep:first reward + reward count -- 1) kill monster(dup, bonus pic, (bonus lev + 1) * 1000) ) ) ) end script, kill monster, sl, bonus pic, bonus value, begin set move speed(sl, randomize(default move speed, 3)) variable(force) force := fly away force * 2 if(percent chance(50)) then(force := force * -1) set force x(sl, force) set force y(sl, fly away force * -1 + random(-2,0)) set exbit(sl, bit:dying, true) set exbit(sl, bit:nowalls, true) set exbit(sl, bit:nograv, true) set bonus pic(sl, bonus pic) set points(sl, bonus value) set attack delay(sl, fly away time + random(0, 9)) play sound(sfx:monster pop) if(count monsters == 0) then(set phase(reward phase)) end script, remove from bubble, bub, begin variable(sl) sl := get monster inside(bub) if(sl) then( set parent(sl, map layer) realign slice(sl, edge:left, edge:top, edge:left, edge:top) set slice x(sl, slice x(bub)) set slice y(sl, slice y(bub)) ) end script, pickup reward, who, sl, begin add score floater(who, sl, get points(sl)) set exbit(sl, bit:remove) play sound(sfx:reward pickup) end script, check reward to reward collisions, sl, begin variable(ob) ob := first child(map layer) while(ob) do( if(is reward(ob) || is powerup(ob)) then( if(sl <> ob) then( reward reward collision(sl, ob) ) ) ob := next sibling(ob) ) end script, is reward, sl, begin variable(type) if(slice is sprite(sl)) then( type := get sprite type(sl) if(type == spritetype:weapon) then( if(is bubble(sl)) then(exit returning(false)) if(is powerup(sl)) then(exit returning(false)) exit returning(true) ) ) exit returning(false) end script, reward reward collision, who, rew, begin if(within distance(who, rew, reward push reward distance)) then( push away(who, rew, pull speed) ) end script, pull towards, who, ob, amount, begin variable(xdiff, ydiff) xdiff := slice edge x(who, edge:center) -- slice edge x(ob, edge:center) ydiff := slice edge y(who, edge:center) -- slice edge y(ob, edge:center) set force x(ob, get force x(ob) + amount * sign(xdiff)) set force y(ob, get force y(ob) + amount * sign(ydiff)) end script, push away, who, ob, amount, begin variable(xdiff, ydiff) xdiff := slice edge x(ob, edge:center) -- slice edge x(who, edge:center) ydiff := slice edge y(ob, edge:center) -- slice edge y(who, edge:center) set force x(ob, get force x(ob) + amount * sign(xdiff)) set force y(ob, get force y(ob) + amount * sign(ydiff)) end script, is player, sl, begin exit returning(sl <> 0 && (sl == pl1 || sl == pl2)) end script, is powerup, sl, begin variable(type, id) if(slice is sprite(sl)) then( type := get sprite type(sl) id := get sprite set number(sl) if(type == spritetype:weapon) then( if(id >= first powerup && id << first powerup + powerup count) then( exit returning(true) ) ) ) exit returning(false) end script, is monster, sl, begin if(sl == 0) then(exit returning(false)) if(is player(sl)) then(exit returning(false)) variable(type, id) if(slice is sprite(sl)) then( type := get sprite type(sl) id := get sprite set number(sl) if(type == spritetype:walkabout) then( exit returning(true) ) ) exit returning(false) end #----------------------------------------------------------------------- script, create pop group, popper, first pop, begin variable(gr) gr := create container(0,0) set parent (gr, pop groups) set pop group(first pop, gr) set slice extra(gr, extra 0, 1) set slice extra(gr, extra 2, popper) end script, add to pop group, old pop, new pop, begin variable(gr) gr := get pop group(old pop) set pop group(new pop, gr) set slice extra(gr, extra 0, get slice extra(gr, extra 0) + 1) end script, remove from pop group, bub, begin variable(gr) gr := get pop group(bub) if(gr) then( set slice extra(gr, extra 0, get slice extra(gr, extra 0) -- 1) if(get slice extra(gr, extra 0) <= 0) then(free slice(gr)) ) end script, increment pop group bonus, bub, begin variable(gr) gr := get pop group(bub) if(gr) then( variable(bonus) bonus := get slice extra(gr, extra 1) set slice extra(gr, extra 1, bonus + 1) exit returning(bonus) ) exit returning(0) end script, get bubble popper, bub, begin variable(gr) gr := get pop group(bub) if(gr) then( exit returning(get slice extra(gr, extra 2)) ) end #----------------------------------------------------------------------- script, flip monster, sl, begin variable(flip) flip := sprite is horiz flipped(sl) flip := not(flip) horiz flip sprite(sl, flip) end script, vflip monster, sl, begin variable(flip) flip := sprite is vert flipped(sl) flip := not(flip) vert flip sprite(sl, flip) end script, vdir flip monster, sl, begin set exbit(sl, bit:vdir, not(get exbit(sl, bit:vdir))) end script, walk monster forward, sl, begin variable(flip, force) flip := sprite is horiz flipped(sl) force := get move speed(sl) + 1 if(flip) then(force := force * -1) set force x(sl, force) end script, hover monster forward, sl, begin variable(vdir, force) vdir := get exbit(sl, bit:vdir) force := get move speed(sl) + 1 if(vdir == 0) then(force := force * -1) set force y(sl, force) end script, monster is under player, sl, begin variable(y) y := slice edge y(sl, edge:top) exit returning((pl1 <> 0 && y >> slice edge y(pl1, edge:bottom)) || (pl2 <> 0 && y >> slice edge y(pl2, edge:bottom))) end script, face other, sl, sl2, begin horiz flip sprite(sl, slice edge x(sl2, edge:center) << slice edge x(sl, edge:center)) end script, face player, sl, begin if(pl1 == 0 && pl2 == 0) then(exit script) if(pl1 == 0) then(horiz flip sprite(sl, slice x(pl2) << slice x(sl)), exit script) if(pl2 == 0) then(horiz flip sprite(sl, slice x(pl1) << slice x(sl)), exit script) variable(diff1, diff2) diff1 := slice x(pl1) -- slice x(sl) diff2 := slice x(pl2) -- slice x(sl) if(sign(diff1) == sign(diff2)) then( horiz flip sprite(sl, diff1 << 0) )else( if(abs(diff1) << abs(diff2)) then( horiz flip sprite(sl, diff1 << 0) )else( horiz flip sprite(sl, diff2 << 0) ) ) end script, floor ahead, sl, xdist=20, begin variable(x, y) x := slice edge x(sl, edge:center) if(sprite is horiz flipped(sl)) then(x -= xdist) else(x += xdist) y := slice edge y(sl, edge:center) + 20 variable(tile) tile := wrap read pass block(x / 20, y / 20) exit returning((tile, and, north wall) >> 0) end script, jump or flip at edge, sl, chance, begin if(floor ahead(sl, 10) == false) then( if(percent chance(chance)) then(jump(sl)) else(flip monster(sl)) ) end script, maybe jump at edge, sl, chance, begin if(floor ahead(sl, 10) == false) then( if(percent chance(chance)) then(jump(sl)) ) end script, four frame cycle, sl, begin set sprite frame(sl, (get sprite frame(sl)+1),mod,4) end script, two frame cycle, sl, begin # This is only for normal walking when bit:noanim is on set sprite frame(sl, (get sprite frame(sl)+1),mod,2) end script, transform monster, sl, pic id, begin replace walkabout sprite(sl, pic id) special monster settings(sl) end script, create shot, sl, pic id, begin variable(shot) shot := create monster(pic id, slice x(sl), slice y(sl), sprite is horiz flipped(sl)) set exbit(shot, bit:nowalls) set exbit(shot, bit:nograv) set exbit(shot, bit:immortal) set tickstamp(shot) exit returning(shot) end script, spit monster bubble, who, monster pic, begin variable(bub, mon, x) if(get attack delay(who) <= 0) then( set attack delay(who, get shot delay(who)) bub := create bubble shot(who) x := slice x(bub) if(sprite is horiz flipped(who)) then(x -= 10) else(x += 10) set slice x(bub, x) mon := create monster(monster pic, 0, 0) catch monster(mon, bub) ) end script, erase all A tiles, begin variable(x, y, tile) for(y, 0, map height -- 1) do( for(x, 0, map width -- 1) do( tile := read pass block(x, y) if((tile,and,vehicle A) >> 0) then( write pass block(x, y, 0) write map block(x, y, 0, 0) write map block(x, y, 0, 1) ) ) ) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, plip ai, sl, begin if(get attack delay(sl) >> 1) then( exit script ) if(get attack delay(sl) == 1) then( jump(sl) exit script ) if(monster is under player(sl) && percent chance(5)) then( set attack delay(sl, 6) ) if(get gravstate(sl) == grav:standing) then( if(get force x(sl) == 0) then(flip monster(sl)) walk monster forward(sl) ) end script, mr triangle ai, sl, begin variable(go) go := get force x(sl) if(go == 0) then(flip monster(sl)) if(monster is under player(sl) && percent chance(5)) then( jump(sl) ) if(percent chance(2)) then( transform monster(sl, tri:spin) set attack delay(sl, 10) play sound(sfx:spinphase) ) walk monster forward(sl) end script, mr triangle spinning ai, sl, begin if(get attack delay(sl) == 0) then(transform monster(sl, tri:normal)) walk monster forward(sl) four frame cycle(sl) end script, kitten ai, sl, begin if(percent chance(3)) then( set attack delay(sl, 18) ) variable(delay) delay := get attack delay(sl) if(delay >> 0) then( face player(sl) if(delay == 1) then( set move speed(sl, 100 + get exbit(sl, bit:angry) * 50) walk monster forward(sl) set move speed(sl, 10 + get exbit(sl, bit:angry) * 5) jump(sl) play sound(sfx:catyowl) exit script ) exit script ) if(get gravstate(sl) == grav:standing) then( set move speed(sl, 2) if(get force x(sl) == 0) then(flip monster(sl)) walk monster forward(sl) ) end script, tim ai, sl, begin if(get gravstate(sl) == grav:standing) then( jump(sl) play sound(sfx:timjump) ) if(get force x(sl) == 0) then(flip monster(sl)) walk monster forward(sl) end script, steve ai, sl, begin variable(delay) delay := get attack delay(sl) if(delay >> 0) then( if(delay == 1) then( create shot(sl, 8) play sound(sfx:quickfire) walk monster forward(sl) ) exit script ) variable(go) go := get force x(sl) if(get gravstate(sl) == grav:standing && delay == 0) then( if(get force x(sl) == 0) then(flip monster(sl)) if(floor ahead(sl, 10) == false) then(flip monster(sl)) walk monster forward(sl) ) if(percent chance(3 + get exbit(sl, bit:angry)*3)) then( set attack delay(sl, 5) ) end script, firebolt ai, sl, begin walk monster forward(sl) if(get ticks elapsed(sl) >> 33) then(set exbit(sl, bit:remove)) end script, sloth ai, sl, begin variable(state, delay) state := get gravstate(sl) delay := get attack delay(sl) if(delay == 0) then(set move speed(sl, 2)) else(set move speed(sl, 4)) if(state <> grav:standing && delay == 0) then( exit script ) if(state == grav:standing) then( if(percent chance(2)) then( set attack delay(sl, 10 + get exbit(sl, bit:angry)*4) ) if(percent chance(1)) then( jump(sl) exit script ) if(get force x(sl) == 0) then(flip monster(sl)) if(delay == 0 && floor ahead(sl, 10) == false) then(flip monster(sl)) ) walk monster forward(sl) end script, hoverbeaver ai, sl, begin variable(go x, go y) go x := get force x(sl) go y := get force y(sl) if(go x == 0) then(flip monster(sl)) walk monster forward(sl) if(go y == 0) then(vdir flip monster(sl)) hover monster forward(sl) four frame cycle(sl) end script, jellypus ai, sl, begin variable(delay) delay := get attack delay(sl) # Jellypus uses this to change directions # wander aimlessly set move speed(sl, 2) if(delay == 0) then( # change directions if(random(0,2) == 0) then(flip monster(sl)) if(random(0,2) == 0) then(vdir flip monster(sl)) set attack delay(sl, 15) ) walk monster forward(sl) hover monster forward(sl) two frame cycle(sl) if(jellypus wants to plummet(sl)) then( set ai(sl, @jellypus plummet) play sound(sfx:squidcry) set attack delay(sl, 30) ) if(jellypus wants to flee(sl)) then( set ai(sl, @jellypus flee) set attack delay(sl, 10) set exbit(sl, bit:vdir, false) if(random(0,3) == 0) then( #flee down instead of up 1/4 of the time set exbit(sl, bit:vdir, true) ) ) end script, jellypus plummet, sl, begin # Plummet at a player set move speed(sl, 6) if(get force y(sl) == 0) then( set ai(sl, @jellypus ai) set attack delay(sl, 30) ) set exbit(sl, bit:vdir, true) hover monster forward(sl) set sprite frame(sl, 3) if(get attack delay(sl) <= 0) then( set ai(sl, @jellypus ai) ) end script, jellypus flee, sl, begin # fleeing a player set move speed(sl, 5) variable(p) p := nearest player(sl) if(p) then( face other(sl, p) flip monster(sl) walk monster forward(sl) hover monster forward(sl) set sprite frame(sl, 2) ) if(get attack delay(sl) <= 0) then( set ai(sl, @jellypus ai) ) end script, jellypus wants to plummet, sl, begin if(random(0,2) == 0) then(exit returning(false)) if(get attack delay(sl) >> 15) then(exit returning(false)) variable(p) p := nearest player(sl) if(p) then( if(is above(sl, p)) then( if(within xdist(sl, p, 20)) then( exit returning(true) ) ) ) exit returning(false) end script, jellypus wants to flee, sl, begin if(random(0,2) == 0) then(exit returning(false)) variable(p) p := nearest player(sl) if(p) then( if(within xdist(sl, p, 100) && within ydist(sl, p, 20)) then( exit returning(true) ) ) exit returning(false) end script, turtle ai, sl, begin variable(delay) variable(state) state := get gravstate(sl) delay := get attack delay(sl) if(delay >> 0) then( if(delay == 1) then( transform monster(sl, turt:naked) set attack delay(sl, 6) variable(shot) shot := create monster(turt:shell, slice x(sl), slice y(sl), sprite is horiz flipped(sl)) walk monster forward(shot) exit script ) ) if(delay == 0 && state == grav:standing) then( if(percent chance 00 (175)) then( set attack delay(sl, 10) ) if(get force x(sl) == 0) then(flip monster(sl)) jump or flip at edge(sl, 50) if(percent chance 00(60)) then(jump(sl)) ) if(delay == 0) then(walk monster forward(sl)) end script, turtle capture, sl, bub, begin transform monster(sl, turt:shell) create monster(turt:naked, slice x(sl), slice y(sl), sprite is horiz flipped(sl)) end script, turtle shell ai, sl, begin if(get force x(sl) == 0) then(flip monster(sl)) walk monster forward(sl) four frame cycle(sl) end script, naked turtle ai, sl, begin variable(delay) variable(state) delay := get attack delay(sl) state := get gravstate(sl) if(delay == 0 && state == grav:standing) then( if(get force x(sl) == 0) then(flip monster(sl)) maybe jump at edge(sl, 20) if(percent chance 00(150)) then(jump(sl)) ) if(delay == 0) then(walk monster forward(sl)) end script, turtle shell collision, shell, mon, begin if(is monster(mon)) then( if(get sprite type(mon) == spritetype:walkabout) then( if(get sprite set number(mon) == turt:naked) then( if(get attack delay(mon) == 0) then( if(within distance(shell, mon, 17)) then( set exbit(shell, bit:remove) transform monster(mon, turt:normal) ) ) ) ) ) end script, needler ai, sl, begin variable(time) time := get tickstamp(sl) if(time + seconds * 2 << ticks) then( if(percent chance(50)) then(face player(sl)) else(horiz flip sprite(sl, random(0,1))) set tickstamp(sl) ) end script, needler collision, sl, ob, begin variable(xdiff, ydiff) variable(delay) if(is bubble(ob)) then( if(within distance(sl, ob, 12)) then( if(get attack delay(sl) >> 0 || get force y(sl) << 0) then( variable(pic) pic := get sprite set number(ob) if(pic <> wep:bubble pop) then( if(get monster inside(ob)) then( free trapped monster(ob) ) create pop group(sl, ob) pop bubble(ob) exit script ) ) ) xdiff := slice x(ob) -- slice x(sl) ydiff := slice y(ob) -- slice y(sl) if(abs(xdiff) << 40 && ydiff << 10 && ydiff >> -70) then( if(get attack delay(sl) == 0) then( if(ydiff << -10) then(jump(sl)) ) if(sprite is horiz flipped(sl) == (xdiff << 0)) then( walk monster forward(sl) set attack delay(sl, 7) ) ) ) end script, goldlord ai, sl, begin variable(go, state) go := get force x(sl) if(go == 0) then(flip monster(sl)) state := get gravstate(sl) if(state == grav:standing) then( if(monster is under player(sl) && percent chance(5)) then( jump(sl) )else( if(percent chance(40)) then( jump or flip at edge(sl, 60) ) ) ) variable(p) p := nearest player(sl) if(p) then( if(is facing(sl, p) && within xdist(sl, p, 100) && within ydist(sl, p, 20)) then( do goldlord attack(sl) exit script ) ) walk monster forward(sl) end script, do goldlord attack, sl, begin variable(ch) ch := get chain child(sl) if(slice is valid(ch)) then(exit script) set ai(sl, @goldlord attack ai) set attack delay(sl, 10) variable(shot) shot := create shot(sl, spikeball pic) connect chain(sl, shot) end script, goldlord attack ai, sl, begin if(get attack delay(sl) <= 0) then( set ai(sl, @goldlord ai) flip monster(sl) ) end script, goldlord capture, sl, bub, begin drop chain child(sl) end script, spikeball ai, sl, begin variable(retract) retract := 6 # shot delay holds attachment reference if(tug chain(sl)) then( set exbit(sl, bit:remove) exit script ) variable(age, link, gp) age := get ticks elapsed(sl) if(age << retract) then( walk monster forward(sl) # Insert a link into the chain link := create shot(sl, chainlink pic) insert chain parent(sl, link) exit script ) if(age == retract) then( gp := chain grandparent(sl) set gravity on child chain(gp) exit script ) if(age >> retract) then( gp := chain grandparent(sl) if(gp) then( chain absorb child(gp) ) ) end script, chainlink ai, sl, begin if(tug chain(sl)) then( set exbit(sl, bit:remove) exit script ) variable(ch) ch := get chain child(sl) if(not(slice is valid(ch))) then( set exbit(sl, bit:remove) exit script ) end script, litbolt ai, sl, begin walk monster forward(sl) end script, litbolt collision, sl, ob, begin if(sl == ob) then(exit script) if(is monster(ob)) then( if(within distance(sl, ob, 18)) then( if(get exbit(ob, bit:dying) == false) then( if(get exbit(ob, bit:immortal) == false) then( kill monster(ob, 30, 4100) ) ) ) ) end script, spikefall ai, sl, begin end script, laser bolt ai, sl, begin walk monster forward(sl) variable(points) points := get points(sl) if(points) then( if((ticks, mod, points) == 0) then(hover monster forward(sl)) ) end script, bunmaster ai, sl, begin variable(go, state) go := get force x(sl) if(go == 0) then(flip monster(sl)) state := get gravstate(sl) if(state == grav:standing) then( if(percent chance(4)) then( jump(sl) )else if(percent chance(25)) then( jump or flip at edge(sl, 75) )else( if(get ticks elapsed(sl) >> 50) then( bunmaster start casting(sl) exit script ) ) ) walk monster forward(sl) end script, bunmaster start casting, sl, begin play sound(sfx:bunspellcast) set ai(sl, @bunmaster spellcast ai) variable(sp) sp := create shot(sl, bunspell pic) set chain child(sl, sp) set attack delay(sp, 17) set attack delay(sl, 17) walk monster forward(sp) if(percent chance(50)) then( set tickstamp(sl, ticks + random(0,10)) ) end script, bunmaster spellcast ai, sl, begin if(get attack delay(sl) <= 0) then( set ai(sl, @bunmaster ai) flip monster(sl) ) end script, bunspell ai, sl, begin # use shot force for x-step # use shot delay for y-step two frame cycle(sl) if(get attack delay(sl) <= 0) then( variable(p) p := nearest player(sl) if(p) then( variable(xdiff, ydiff) xdiff := slice x(p) -- slice x(sl) ydiff := slice y(p) -- slice y(sl) set shot force(sl, xdiff / 28) set shot delay(sl, ydiff / 28) set ai(sl, @bunspell move ai) set attack delay(sl, 28) )else( # no player target, fizzle out set exbit(sl, bit:remove) ) ) end script, bunspell move ai, sl, begin # use shot force for x-step # use shot delay for y-step set force x(sl, get shot force(sl)) set force y(sl, get shot delay(sl)) variable(delay) delay := get attack delay(sl) set sprite frame(sl, (28--delay) / 8 * 2 + (delay ,and, 1)) if(delay <= 0) then( play sound(sfx:bunspellexplode) set ai(sl, @bunspell explode ai) set attack delay(sl, 3) ) end script, bunspell explode ai, sl, begin variable(delay, big) delay := get attack delay(sl) if(delay == 2) then( big := load attack sprite(1) set parent(big, sl) center slice(big) set chain child(sl, big) set sprite frame(big, 0) )else if(delay == 1) then( big := get chain child(sl) if(big) then( set sprite frame(big, 1) ) )else if(delay <= 0) then( big := get chain child(sl) if(big) then( set sprite frame(big, 2) ) set exbit(sl, bit:remove) ) bunspell kill zone(sl) end script, bunspell kill zone, sl, begin variable(ob) ob := first child(map layer) while(ob) do( if(slice is sprite(ob)) then( if(slice collide(sl, ob)) then( if(within distance(sl, ob, 36)) then( if(get exbit(ob, bit:hero) && get exbit(sl, bit:dying) == false) then( player dies(ob) ) ) if(within distance(sl, ob, 40)) then( push away(sl, ob, 10) ) ) ) ob := next sibling(ob) ) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, boss potion collision, sl, mon, begin if(get sprite type(mon) == spritetype:walkabout) then( variable(pic id) pic id := get sprite set number(mon) if(pic id == tri:normal || pic id == tri:spin) then( if(within distance(sl, mon, 17)) then( set exbit(sl, bit:remove) transform monster(mon, tri:boss) erase all A tiles set slice visible(boss meter box, true) play sound(sfx:warning) set attack delay(mon, 20) ) ) ) end script, mr triangle boss ai, sl, begin variable(go) go := get force x(sl) if(go == 0) then(flip monster(sl)) if((monster is under player(sl) && percent chance(6)) || percent chance 00(075)) then( jump(sl) ) if(percent chance 00(050)) then( set ai(sl, @mr triangle boss spin) set tickstamp(sl, ticks + random(0, seconds * 3)) set exbit(sl, bit:nograv) set move speed(sl, 5) ) if(percent chance 00(095)) then( set ai(sl, @mr triangle boss laser) set tickstamp(sl) ) if(get attack delay(sl) == 0) then( walk monster forward(sl) ) mr triangle boss animation(sl) end script, mr triangle boss spin, sl, begin variable(go x, go y) go x := get force x(sl) go y := get force y(sl) if(go x == 0) then(flip monster(sl)) walk monster forward(sl) if(go y == 0) then(vdir flip monster(sl)) hover monster forward(sl) mr triangle boss spin animation(sl) variable(time) time := get ticks elapsed(sl) if(time >> seconds * 4) then( set ai(sl, @mr triangle boss ai) set exbit(sl, bit:nograv, false) set move speed(sl, 3) ) if((time, mod, 8) == 1) then( play sound(sfx:spinphase) ) if((time, mod, 11) == 0) then( variable(shot) shot := create monster(20, slice x(sl), slice y(sl)) play sound(sfx:drop) ) end script, mr triangle boss laser, sl, begin set attack delay(sl, 2) variable(time) time := get ticks elapsed(sl) if(time == seconds) then( variable(i, shot) for(i, 0, 2) do( shot := create monster(21, slice x(sl), slice y(sl), sprite is horiz flipped(sl)) set points(shot, i * 2) ) play sound(sfx:laser) ) if(time >> seconds * 2) then( set ai(sl, @mr triangle boss ai) ) mr triangle boss animation(sl) end script, mr triangle boss animation, sl, begin variable(giant) giant := get giant(sl) horiz flip sprite(giant, sprite is horiz flipped(sl)) variable(frame) frame := get sprite frame(sl) if(frame <= 3) then( replace medium enemy sprite(giant, frame + 1) ) end script, mr triangle boss spin animation, sl, begin variable(giant) giant := get giant(sl) horiz flip sprite(giant, sprite is horiz flipped(sl)) variable(frame) frame := ticks, mod, 3 replace medium enemy sprite(giant, 6 + frame) end script, get giant, sl, begin variable(meta) meta := first child(sl) exit returning(next sibling(meta)) end script, mr triangle boss collision, sl, ob, begin if(sl == ob) then(exit script) variable(xdiff, ydiff) variable(check) if(is bubble(ob)) then( variable(pic) pic := get sprite set number(ob) if(pic == wep:bubble pop) then(exit script) check := true ) if(is player(ob)) then( check := true ) if(check) then( variable(giant) giant := get giant(sl) if(giant == 0) then(exit script) if(slice collide(giant, ob)) then( xdiff := slice edge x(ob, edge:center) -- slice edge x(sl, edge:center) ydiff := slice edge y(ob, edge:bottom) -- slice edge y(sl, edge:bottom) if(abs(xdiff) + abs(ydiff) << 40) then( # hit if(is bubble(ob)) then( if(get exbit(sl, bit:nograv)) then( # spin mode pops all bubbles create pop group(sl, ob) pop bubble(ob) ) if(is a catching bubble(ob)) then( # damage damage boss(sl, ob) ) ) if(is player(ob)) then( if(get exbit(ob, bit:dying) || get exbit(ob, bit:respawn)) then(exit script) if(get exbit(sl, bit:dying) == false) then( player dies(ob) ) ) ) ) ) end script, damage boss, sl, bub, amount=1, begin variable(points) points := get points(sl) points += amount set points(sl, points) set slice width(boss meter, 180 -- points * 2) if(points >= 90) then( boss dies(sl, bub) )else( create pop group(sl, bub) pop bubble(bub) ) end script, boss dies, sl, bub, begin set points(sl, 0) set force x(bub, 0) set force y(bub, 0) catch monster(sl, bub) set exbit(sl, bit:noescape) set exbit(sl, bit:multireward) variable(giant) giant := get giant(sl) replace medium enemy sprite(giant, 5) variable(big bub) big bub := load medium enemy sprite(9) set parent(big bub, giant) center slice(big bub) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, drop chain child, sl, begin set gravity on child chain(sl) variable(ch) ch := get chain child(sl) if(slice is valid(ch)) then( set chain parent(ch, 0) ) set chain child(sl, 0) end script, set gravity on child chain, sl, begin variable(ch, next) ch := get chain child(sl) while(slice is valid(ch)) do( set exbit(sl, bit:nograv, false) ch := get chain child(ch) ) end script, chain absorb child, sl, begin variable(ch, gch) ch := get chain child(sl) if(slice is valid(ch)) then( gch := get chain child(ch) set chain child(sl, gch) if(slice is valid(gch)) then( set chain parent(gch, sl) ) set chain parent(ch, 0) set chain child(ch, 0) set exbit(ch, bit:remove) ) end script, chain grandparent, sl, begin variable(gp) while(true) do( sl := get chain parent(sl) if(slice is valid(sl)) then( gp := sl )else( exit returning(gp) ) ) end script, insert chain parent, sl, link, begin variable(par) par := get chain parent(sl) set chain parent(link, par) set chain parent(sl, link) set chain child(link, sl) if(par) then( set chain child(par, link) ) end script, connect chain, par, ch, begin set chain parent(ch, par) set chain child(par, ch) end script, tug chain, sl, begin # Enforce max distance from chained slice. # Returns true if the chain has been broken # Also applies 1 pixel of chain retraction force variable(chain) chain := get chain parent(sl) if(not(slice is valid(chain))) then( set chain parent(sl, 0) exit returning(true) ) variable(xdiff, ydiff) while(not(within distance(sl, chain, 14))) do( xdiff := slice x(sl) -- slice x(chain) set slice x(sl, slice x(sl) -- sign(xdiff)) ydiff := slice y(sl) -- slice y(chain) set slice y(sl, slice y(sl) -- sign(ydiff)) ) pull towards(chain, sl, 1) exit returning(false) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, convert npcs into slices, begin variable(ref, id, pic id, x, y) for(ref, -300, -1) do( id := get npc id(ref) if(id >= 0) then( pic id := read npc(id, NPCstat:picture) x := npc x(ref) * 20 y := npc y(ref) * 20 switch(pic id) do( case(powerup npc pic) do(create random powerup(x, y)) case(litbolt pic) do(create generator(litbolt pic, x, y)) else( create monster(pic id, x, y, npc direction(ref) == west) ) ) destroy npc(ref) ) ) end script, create random powerup, x, y, begin variable(pic) while(true) do( pic := random(first powerup, first powerup + powerup count -- 1) if(pic == 18) then(continue) # no random coins break ) create powerup(pic, x, y) end script, create powerup, pic, x, y, begin variable(sl) sl := load weapon sprite(pic) create game object(sl) set slice x(sl, x) set slice y(sl, y) set handler(sl, @powerup handler) set collision handler(sl, @check reward to reward collisions) set collision with player handler(sl, @player powerup collision) set exbit(sl, bit:nograv) set tickstamp(sl) set slice visible(sl, false) end script, create generator, pic id, x, y, begin variable(sl) sl := load walkabout sprite(pic id) create game object(sl) set slice visible(sl, false) set slice x(sl, x) set slice y(sl, y) set exbit(sl, bit:immortal, true) set handler(sl, @generator handler) set collision handler(sl, none) set collision with player handler(sl, none) set attack delay(sl, seconds * bubble generator time) exit returning(sl) end script, create monster, pic id, x, y, flip=false, begin variable(sl) sl := load walkabout sprite(pic id) create game object(sl) set slice x(sl, x) set slice y(sl, y) horiz flip sprite(sl, flip) set handler(sl, @monster handler) set collision handler(sl, @check monster collisions) set collision with player handler(sl, @player monster collision) special monster settings(sl) exit returning(sl) end script, special monster settings, sl, begin variable(pic id) pic id := get sprite set number(sl) switch(pic id) do( case(2) do(special plip settings(sl)) case(3) do(special mr triangle settings(sl)) case(4) do(special kitten settings(sl)) case(6) do(special tim settings(sl)) case(7) do(special steve settings(sl)) case(8) do(special firebolt settings(sl)) case(9) do(special sloth settings(sl)) case(10) do(special hoverbeaver settings(sl)) case(11) do(special turtle settings(sl)) case(12) do(special turtle shell settings(sl)) case(13) do(special naked turtle settings(sl)) case(15) do(special mr triangle spinning settings(sl)) case(16) do(special needler settings(sl)) case(17) do(special litbolt settings(sl)) case(18) do(special mr triangle boss settings(sl)) case(19) do(special boss potion settings(sl)) case(20) do(special spikefall settings(sl)) case(21) do(special laser bolt settings(sl)) case(22) do(special jellypus settings(sl)) case(23) do(special goldlord settings(sl)) case(24) do(special spikeball settings(sl)) case(25) do(special chainlink settings(sl)) case(26) do(special bunmaster settings(sl)) case(27) do(special bunspell settings(sl)) ) end script, special plip settings, sl, begin set move speed(sl, 2) set ai(sl, @plip ai) end script, special mr triangle settings, sl, begin set move speed(sl, 3) set ai(sl, @mr triangle ai) set exbit(sl, bit:nograv, false) set exbit(sl, bit:noanim, false) end script, special mr triangle spinning settings, sl, begin set move speed(sl, 5) set ai(sl, @mr triangle spinning ai) set exbit(sl, bit:nograv, true) set exbit(sl, bit:noanim, true) end script, special kitten settings, sl, begin set move speed(sl, 2) set ai(sl, @kitten ai) end script, special tim settings, sl, begin set move speed(sl, 3) set ai(sl, @tim ai) end script, special steve settings, sl, begin set move speed(sl, 2) set ai(sl, @steve ai) end script, special firebolt settings, sl, begin set move speed(sl, 6) set ai(sl, @firebolt ai) end script, special sloth settings, sl, begin set move speed(sl, 2) set ai(sl, @sloth ai) end script, special hoverbeaver settings, sl, begin set move speed(sl, 1) set ai(sl, @hoverbeaver ai) set exbit(sl, bit:nograv) set exbit(sl, bit:noanim) end script, special turtle settings, sl, begin set move speed(sl, 1) set ai(sl, @turtle ai) set exbit(sl, bit:noanim, false) set capture handler(sl, @turtle capture) set monster collision handler(sl, none) end script, special turtle shell settings, sl, begin set move speed(sl, 5) set ai(sl, @turtle shell ai) set exbit(sl, bit:noanim) set capture handler(sl, none) set monster collision handler(sl, @turtle shell collision) end script, special naked turtle settings, sl, begin set move speed(sl, 3) set ai(sl, @naked turtle ai) set exbit(sl, bit:noanim, false) set capture handler(sl, none) set monster collision handler(sl, none) end script, special needler settings, sl, begin set move speed(sl, 3) set ai(sl, @needler ai) set monster collision handler(sl, @needler collision) end script, special litbolt settings, sl, begin set move speed(sl, 8) set ai(sl, @litbolt ai) set monster collision handler(sl, @litbolt collision) set exbit(sl, bit:nograv) set exbit(sl, bit:nowalls) set exbit(sl, bit:nokillplayer) set exbit(sl, bit:immortal) set exbit(sl, bit:vanishwrap) end script, special boss potion settings, sl, begin set exbit(sl, bit:noanim) set monster collision handler(sl, @boss potion collision) set exbit(sl, bit:nokillplayer) set exbit(sl, bit:immortal) end script, special mr triangle boss settings, sl, begin set move speed(sl, 3) set ai(sl, @mr triangle boss ai) set sprite frame(sl, 1) set exbit(sl, bit:immortal) set exbit(sl, bit:noanim, false) set exbit(sl, bit:nograv, false) set monster collision handler(sl, @mr triangle boss collision) variable(giant) giant := get giant(sl) if(giant == 0) then( giant := load medium enemy sprite(1) set parent(giant, sl) realign slice(giant, edge:center, edge:bottom, edge:center, edge:bottom) ) variable(big bub) big bub := first child(giant) if(big bub <> 0) then(free slice(big bub)) end script, special spikefall settings, sl, begin set move speed(sl, 8) set ai(sl, @spikefall ai) set exbit(sl, bit:nowalls) set exbit(sl, bit:immortal) set exbit(sl, bit:vanishwrap) end script, special laser bolt settings, sl, begin set move speed(sl, 8) set ai(sl, @laser bolt ai) set exbit(sl, bit:nograv) set exbit(sl, bit:nowalls) set exbit(sl, bit:immortal) set exbit(sl, bit:vanishwrap) end script, special jellypus settings, sl, begin set move speed(sl, 2) set ai(sl, @jellypus ai) set exbit(sl, bit:nograv) set exbit(sl, bit:noanim) end script, special goldlord settings, sl, begin set move speed(sl, 3) set ai(sl, @goldlord ai) set capture handler(sl, @goldlord capture) end script, special spikeball settings, sl, begin set move speed(sl, 10) set ai(sl, @spikeball ai) set exbit(sl, bit:bubblestopper) end script, special chainlink settings, sl, begin set move speed(sl, 5) set ai(sl, @chainlink ai) set exbit(sl, bit:nokillplayer) end script, special bunmaster settings, sl, begin set move speed(sl, 4) set ai(sl, @bunmaster ai) set tickstamp(sl, random(40, 50)) end script, special bunspell settings, sl, begin set move speed(sl, 8) set ai(sl, @bunspell ai) set exbit(sl, bit:noanim) set exbit(sl, bit:nograv) set exbit(sl, bit:nowalls) set exbit(sl, bit:nokillplayer) end #----------------------------------------------------------------------- script, create game object, sl, begin set parent(sl, map layer) create metadata(sl) set move speed(sl, default move speed) end #----------------------------------------------------------------------- script, create bubble shot, shooter, begin variable(bub, force) bub := load weapon sprite(wep:bubble shot) create game object(bub) set handler(bub, @bubble handler) set collision handler(bub, @check bubble to bubble collisions) set slice x(bub, slice x(shooter) -- 2) set slice y(bub, slice y(shooter) -- 2) force := get shot force(shooter) if(sprite is horiz flipped(shooter)) then(force := force * -1) set force x(bub, force) set gravstate(bub, grav:floating) set move speed(bub, bubble shot speed) if(shooter == pl1) then(play sound(sfx:bubble shot)) if(shooter == pl2) then(play sound(sfx:bubble shot high)) exit returning(bub) end script, update bubble shot, sl, begin if(get force x(sl) == 0) then( start maturing bubble(sl) ) end script, start maturing bubble, bub, begin replace weapon sprite(bub, wep:maturing bubble) end script, mature bubble, bub, begin replace weapon sprite(bub, wep:bubble) set collision with player handler(bub, @player bubble collision) end #----------------------------------------------------------------------- script, sprite animation, sl, begin variable(type) if(slice is sprite(sl)) then( type := get sprite type(sl) switch(type) do( case(spritetype:walkabout) do(animate walkabout(sl)) case(spritetype:weapon) do(animate weapon(sl)) ) ) end script, animate walkabout, sl, begin if(get exbit(sl, bit:noanim)) then(exit script) variable(frame) frame := get sprite frame(sl) if(frame == 4) then(exit script) if(frame == 1) then( frame := 0 )else( frame := 1 ) variable(state) state := get gravstate(sl) if(state >= grav:jumping) then( frame := 3 ) if(get attack delay(sl) >> 0) then( frame := 2 ) set sprite frame(sl, frame) end script, animate weapon, sl, begin variable(frame) frame := get sprite frame(sl) frame := frame , xor, 1 set sprite frame(sl, frame) end #----------------------------------------------------------------------- script, jump key for player, sl, begin if(sl == 0) then(exit returning(false)) if(sl == pl1) then( if(keyval(key:right ctrl) >> 0) then(exit returning(true)) if(running on desktop) then( if(keyval(key:up) >> 0) then(exit returning(true)) ) ) if(sl == pl2) then( if(keyval(key:left ctrl) >> 0) then(exit returning(true)) if(running on desktop) then( if(keyval(key:W) >> 0) then(exit returning(true)) ) ) exit returning(false) end script, update border padding, begin if(tv safe zone) then( set left padding(ui border sl, 16) set right padding(ui border sl, 16) set top padding(ui border sl, 12) set bottom padding(ui border sl, 10) )else( set left padding(ui border sl, 0) set right padding(ui border sl, 0) set top padding(ui border sl, 0) set bottom padding(ui border sl, 0) ) end plotscript, toggle tv safe zone, begin tv safe zone := not(tv safe zone) update border padding # Force immediate save of this setting export globals(1, @tv safe zone, @tv safe zone) end script, create score, begin # Make ui border container ui border sl := create container(0,0) fill parent(ui border sl, true) update border padding # Make score slices score1 sl := create text set parent(score1 sl, ui border sl) set outline(score1 sl, true) put slice(score1 sl, 8, 0) score2 sl := create text set parent(score2 sl, ui border sl) set outline(score2 sl, true) set horiz anchor(score2 sl, edge:right) set horiz align(score2 sl, edge:right) put slice(score2 sl, -8, 0) # make lives slices lives1 sl := create text set parent(lives1 sl, ui border sl) set outline(lives1 sl, true) set vert anchor(lives1 sl, edge:bottom) set vert align(lives1 sl, edge:bottom) put slice(lives1 sl, 8, 0) lives2 sl := create text set parent(lives2 sl, ui border sl) set outline(lives2 sl, true) set vert anchor(lives2 sl, edge:bottom) set vert align(lives2 sl, edge:bottom) set horiz anchor(lives2 sl, edge:right) set horiz align(lives2 sl, edge:right) put slice(lives2 sl, -8, 0) # make boss meter boss meter box := create rect(182, 6, -1) set parent(boss meter box, ui border sl) set rect fg col(boss meter box, 4) set slice visible(boss meter box, false) realign slice(boss meter box, edge:center, edge:bottom, edge:center, edge:bottom) put slice(boss meter box, 0, -3) boss meter := create rect(180, 4, -1) set rect fg col(boss meter, 12) set rect bg col(boss meter, 12) set parent(boss meter, boss meter box) set slice x(boss meter, 1) set slice y(boss meter, 1) end script, lives sl for player, sl, begin if(sl == pl1) then(exit returning(lives1 sl)) else(exit returning(lives2 sl)) end script, set lives for player, sl, n, begin if(sl == pl1) then(lives1 := n) else(lives2 := n) update lives display(sl) end script, get lives for player, sl, begin if(sl == pl1) then(exit returning(lives1)) else(exit returning(lives2)) end script, update lives display, sl, begin if(sl == 0) then(exit script) if(sl == pl1) then($tmpstr="Bob:") else($tmpstr="Misa:") variable(tx) tx := lives sl for player(sl) append number(tmpstr, get lives for player(sl)) set slice text(tx, tmpstr) end script, score sl for player, sl, begin if(sl == pl1) then(exit returning(score1 sl)) if(sl == pl2) then(exit returning(score2 sl)) end script, set score for player, sl, n, begin if(sl == pl1) then(score1 := n, exit script) if(sl == pl2) then(score2 := n, exit script) if(n >> 1) then( $tmpstr="Unowned score " append number(tmpstr, n) trace(tmpstr) ) end script, get score for player, sl, begin if(sl == pl1) then(exit returning(score1)) if(sl == pl2) then(exit returning(score2)) end script, add score, who, points, begin set score for player(who, get score for player(who) + points) $tmpstr="" append number(tmpstr, get score for player(who)) variable(sl) sl := score sl for player(who) if(sl) then( set slice text(sl, tmpstr) ) end script, add score floater, who, sl, points, begin add score(who, points) variable(text) text := create text create game object(text) set handler(text, @score floater handler) set horiz anchor(text, edge:center) set vert anchor(text, edge: center) set slice x(text, slice edge x(sl, edge:center)) set slice y(text, slice edge y(sl, edge:center)) set exbit(text, bit:nograv) set exbit(text, bit:nowalls) set attack delay(text, score floater ticks) clear string(tmpstr) append number(tmpstr, points) set slice text(text, tmpstr) end script, score floater handler, sl, begin if(get attack delay(sl) == 0) then( set exbit(sl, bit:remove) ) set force y(sl, score floater rise force * -1) end script, create powerup floater, sl, str, begin variable(text) text := create text create game object(text) set handler(text, @score floater handler) set horiz anchor(text, edge:center) set vert anchor(text, edge: center) set slice x(text, slice edge x(sl, edge:center)) set slice y(text, slice edge y(sl, edge:center)) set exbit(text, bit:nograv) set exbit(text, bit:nowalls) set attack delay(text, score floater ticks) set slice text(text, str) end #----------------------------------------------------------------------- script, check for high score, sl, begin variable(score) score := get score for player(sl) variable(slot) slot := find high score slot(score) if(slot >= 0) then( set saved high score(slot, score) prompt for name(sl, slot, score) show high scores(0,0,0, slot) ) end script, prompt for name, sl, slot, score, begin variable(style, pnum) if(sl == pl1) then(pnum := 0, style := 0) else(pnum := 1, style := 2) variable(bg) bg := create rect(260, 120, style) center slice(bg) variable(tx) tx := create text if(sl == pl1) then($tmpstr="Bob the Hamster") else($tmpstr="Misa DuHamstre") set slice text(tx, tmpstr) set parent(tx, bg) realign slice(tx, edge:center, edge:top, edge:center, edge:top) set slice y(tx, 10) set outline(tx, true) variable(spr) spr := load walkabout sprite(get sprite set number(sl)) set parent(spr, bg) set slice x(spr, 10) set slice y(spr, 10) tx := create text $tmpstr="You got a high score!" set slice text(tx, tmpstr) set parent(tx, bg) realign slice(tx, edge:center, edge:top, edge:center, edge:top) set slice y(tx, 25) set outline(tx, true) tx := create text $tmpstr="" append number(tmpstr, score) $tmpstr+" points" set slice text(tx, tmpstr) set parent(tx, bg) realign slice(tx, edge:center, edge:top, edge:center, edge:top) set slice y(tx, 45) set outline(tx, true) set text color(tx, 11) tx := create text $tmpstr="type your name" set slice text(tx, tmpstr) set parent(tx, bg) realign slice(tx, edge:center, edge:bottom, edge:center, edge:bottom) set slice y(tx, -20) set outline(tx, true) wait(1) copy string(tmpstr, lastname+pnum) while(true) do( play sound(sfx:squeep) if(not(running on desktop)) then( input string with virtual keyboard(tmpstr, 16, pnum) )else( input string(tmpstr, 16, true) ) if(string length(tmpstr) >> 0) then(break) ) copy string(lastname+pnum, tmpstr) set hero name(tmpstr, slot) hide string(tmpstr) free slice(bg) end plotscript, show high scores, ex0=0, ex1=0, ex2=0, flash=-1, begin variable(bg) bg := create rect(280, 180, 0) center slice(bg) variable(flash sl) variable(tx) tx := create text $tmpstr="**HIGH SCORES**" set slice text(tx, tmpstr) set parent(tx, bg) realign slice(tx, edge:center, edge:top, edge:center, edge:top) set slice y(tx, 10) variable(i) for(i, 0, 9) do( tx := create text $buildstr="#" append number(buildstr, i + 1) $buildstr+" " get hero name(tmpstr, i) buildstr $+ tmpstr $buildstr+" " $tmpstr="" append number(tmpstr, get saved high score(i)) while(string length(buildstr) + string length(tmpstr) << 30) do( $buildstr+"." ) $buildstr+" " append number(buildstr, get saved high score(i)) set slice text(tx, buildstr) set parent(tx, bg) realign slice(tx, edge:center, edge:top, edge:center, edge:top) set slice y(tx, 30 + i * 15) set text color(tx, 15 -- i) if(i == flash) then(flash sl := tx) else(set outline(tx, true)) ) wait(9) variable(tog) while(true) do( tog := (tog + 1), mod, 4 if(any player menu key) then(break) if(almost any dang key) then(break) if(flash sl) then( set text bg(flash sl, 2 * (tog<=1)) ) wait(1) ) wait(4) free slice(bg) save in slot(1) end script, find high score slot, score, begin variable(i) for(i, 0, 9) do( if(score >> get saved high score(i)) then( move high scores down(i) exit returning(i) ) ) exit returning(-1) end script, move high scores down, slot, begin variable(i) for(i, 9, slot + 1, -1) do( set saved high score(i, get saved high score(i -- 1)) get hero name(tmpstr, i -- 1) set hero name(tmpstr, i) ) set saved high score(slot, 0) clear string(tmpstr) set hero name(tmpstr, slot) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get saved high score, slot, begin exit returning(total experience(slot)) end script, set saved high score, slot, n, begin set experience(slot, n) end script, init high scores, begin tweak palette(-63, -63, -63) update palette load from slot(1) reset palette update palette # this script only continues if no previous saved high scores exist variable(i) for(i, 0, 8) do( add hero(0) ) $tmpstr="Genny" set hero name(tmpstr, 0) set saved high score(0, 100000) $tmpstr="James" set hero name(tmpstr, 1) set saved high score(1, 80000) $tmpstr="Sloth" append ascii(tmpstr, 133) $tmpstr+"Chunk" set hero name(tmpstr, 2) set saved high score(2, 60000) $tmpstr="Sir Elton John" set hero name(tmpstr, 3) set saved high score(3, 50000) $tmpstr="Meat Loaf" set hero name(tmpstr, 4) set saved high score(4, 40000) $tmpstr="Janet Weiss" set hero name(tmpstr, 5) set saved high score(5, 30000) $tmpstr="Brad Majors" set hero name(tmpstr, 6) set saved high score(6, 20000) $tmpstr="Buffy Wilson" set hero name(tmpstr, 7) set saved high score(7, 10000) $tmpstr="Scott Howard" set hero name(tmpstr, 8) set saved high score(8, 5000) $tmpstr="Emmet Brown" set hero name(tmpstr, 9) set saved high score(9, 1000) save in slot(1) end #----------------------------------------------------------------------- plotscript, level skip password, begin variable(pnum) if (keyval(key:left ctrl) >> 1) then( pnum := 1 ) variable(box) box := create rect(200, 100, 4) center slice(box) set padding(box, 10) variable(txt) txt := create text set parent(txt, box) $tmpstr="INPUT PASSWORD" set slice text(txt, tmpstr) realign slice(txt, 1, 0, 1, 0) set text color(txt, 15) variable(smbox) smbox := create rect(50, 16, 7) set parent(smbox, box) center slice(smbox) set slice y(smbox, 16) wait(1) $passstr="" if(not(running on desktop)) then( input string with virtual keyboard(passstr, 5, pnum) )else( input string(passstr, 5) ) free slice(box) variable(match) variable(i) for(i, 1, lastlev) do( get code for level(i, compstr) if(string length(compstr) >> 0 && string compare(passstr, compstr)) then( match := i break ) ) if(match >> 0) then( # Good password, teleport to level! teleport to level(match) )else( # no match play sound(sfx:failure) ) end script, get code for level, lev, strid, begin # Fill string strid with a code that corresponds with a level number. # If the level number is not valid, the string will be blank $strid="" switch(lev) do( #case(0) do($strid="OSAKA") case(1) do($strid="MATSU") case(2) do($strid="COPER") case(3) do($strid="LOCAL") case(4) do($strid="SPREE") case(5) do($strid="MANIA") case(6) do($strid="QUINT") case(7) do($strid="KYLIE") case(8) do($strid="NECHO") case(9) do($strid="BUTEO") case(10) do($strid="COOLS") case(11) do($strid="EASER") case(12) do($strid="JEMMY") case(13) do($strid="KAFIR") case(14) do($strid="ONCER") case(15) do($strid="FLOIS") case(16) do($strid="TILAK") case(17) do($strid="FOYER") case(18) do($strid="ETHAL") case(19) do($strid="STERN") case(20) do($strid="LOTTO") case(21) do($strid="RADIO") case(22) do($strid="COLLA") case(23) do($strid="CROSS") case(24) do($strid="HEDGE") case(25) do($strid="AUDIT") case(26) do($strid="GOOEY") case(27) do($strid="POORT") case(28) do($strid="ORDER") case(29) do($strid="TENON") case(30) do($strid="LYCON") case(31) do($strid="ETWEE") case(32) do($strid="NORMA") case(33) do($strid="RASPY") case(34) do($strid="SMOTE") case(35) do($strid="HALER") case(36) do($strid="IDLED") case(37) do($strid="RATAL") case(38) do($strid="PERIL") case(39) do($strid="LITAS") # case(40) do($strid="KNOCK") # case() do($strid="PLANE") # case() do($strid="BATED") # case() do($strid="LEVIT") # case() do($strid="MARIA") # case() do($strid="CREAM") # case() do($strid="WILDA") # case() do($strid="FOCAL") # case() do($strid="ENROL") ) end script, teleport cheat, begin variable(caption) $tmpstr="Teleport Cheat - Type Level #" caption := create text center slice(caption) set slice y(caption, -20) set slice text(caption, tmpstr) variable(map num) input string(tmpstr, 3) hide string(tmpstr) map num := number from string(tmpstr, -1) if(map num >= 0) then( teleport to level(map num) ) free slice(caption) end script, teleport to level, map num, begin set phase(advance phase) if(pl1==0 && pl2==0) then( player joins(0) ) on both players(@enbubble player) on both players(@reset score) teleport to map(map num, 0, 0) init current map set phase(enter phase) wait(1) end #----------------------------------------------------------------------- script, hide wind arrows, begin change tileset(tiles:blank, 2) end script, show wind arrows, begin change tileset(tiles:arrows, 2) end script, toggle wind arrows, begin switch(layer tileset(2)) do( case(tiles:blank) do(show wind arrows) case(tiles:arrows) do(hide wind arrows) ) end script, apply wind force, sl, begin variable(x, y, tile, d, force, axis, mode) x := slice edge x(sl, edge:center) y := slice edge y(sl, edge:center) tile := read map block(x / 20, y / 20, 2) force := 0 mode := 0 if(tile >= 1 && tile <= 4) then( # slow wind d := tile -- 1 force := weak wind ) if(tile >= 5 && tile <= 8) then( # strong wind d := tile -- 5 force := strong wind ) if(tile >= 9 && tile <= 12) then( force := weak wind d := tile -- 9 mode := 1 ) if(tile >= 13 && tile <= 16) then( force := strong wind d := tile -- 13 mode := 1 ) if(tile == 17) then( force := weak wind d := random(0,3) mode := random(0,1) ) if(tile == 18) then( force := strong wind d := random(0,3) mode := random(0,1) ) if(tile == 19) then( force := weak wind d := (ticks / seconds), mod, 4 ) if(tile == 20) then( force := strong wind d := (ticks / seconds), mod, 4 ) switch(mode) do( case(0) do( axis := compass axis(d) set force(sl, axis, get force(sl, axis) + force * compass sign(d)) ) case(1) do( axis := compass axis(d) set force(sl, axis, get force(sl, axis) + force * compass sign(d)) axis := compass axis(d -- 1) set force(sl, axis, get force(sl, axis) + force * compass sign(d -- 1)) ) ) end #----------------------------------------------------------------------- script, care about corner, sl, corner, begin variable(xgo, ygo) xgo := get force x(sl) ygo := get force y(sl) switch(corner) do( case(0) do(exit returning(xgo << 0 || ygo << 0)) case(1) do(exit returning(xgo >> 0 || ygo << 0)) case(2) do(exit returning(xgo >> 0 || ygo >> 0)) case(3) do(exit returning(xgo << 0 || ygo >> 0)) ) end script, care about direction, sl, dir, begin variable(xgo, ygo) xgo := get force x(sl) ygo := get force y(sl) switch(dir) do( case(up) do(exit returning(ygo << 0)) case(right) do(exit returning(xgo >> 0)) case(down) do(exit returning(ygo >> 0)) case(left) do(exit returning(xgo << 0)) ) end script, check corner, sl, corner, begin variable(i, axis, n, go, start, stop, step) if(get force x(sl) >> 0) then( # When moving right, check corners counterclockwise start := 3 stop := 0 step := -1 )else( # When moving left, check corners clockwise start := 0 stop := 3 step := 1 ) for(i, start, stop, step) do( if(care about direction(sl, i)) then( axis := compass axis(i) n := slice corner by axis(sl, corner, axis) go := cap movement by axis(sl, get force(sl, axis), axis) if (n/20 <> (n+go)/20) then( # movement crosses a tile border at this corner if(check for wall(sl, corner, i)) then( # obstructed! align force with barrier(sl, axis) if(i == down && corner >= 2) then( # hit the ground set gravstate(sl, grav:standing) ) ) ) ) ) end script, check for wall, sl, corner, dir, begin variable(tile, x, y) x := slice corner x(sl, corner) + cap movement(sl, get force x(sl)) y := slice corner y(sl, corner) + cap falling(sl, get force y(sl)) tile := wrap read pass block(x / 20, y / 20) exit returning(tile, and, compass wall(dir)) end script, slice coord by axis, sl, axis, begin switch(axis) do( case(x axis) do(exit returning(slice x(sl))) case(y axis) do(exit returning(slice y(sl))) ) end script, set slice coord by axis, sl, axis, coord, begin switch(axis) do( case(x axis) do(set slice x(sl, coord)) case(y axis) do(set slice y(sl, coord)) ) end script, slice corner by axis, sl, corner, axis, begin switch(axis) do( case(x axis) do(exit returning(slice corner x(sl, corner))) case(y axis) do(exit returning(slice corner y(sl, corner))) ) end script, slice corner x, sl, corner, begin switch(corner) do( case(0) do(exit returning(slice x(sl))) case(1) do(exit returning(slice x(sl) + slice width(sl) -- 1)) case(2) do(exit returning(slice x(sl) + slice width(sl) -- 1)) case(3) do(exit returning(slice x(sl))) ) end script, slice corner y, sl, corner, begin switch(corner) do( case(0) do(exit returning(slice y(sl))) case(1) do(exit returning(slice y(sl))) case(2) do(exit returning(slice y(sl) + slice height(sl) -- 1)) case(3) do(exit returning(slice y(sl) + slice height(sl) -- 1)) ) end #----------------------------------------------------------------------- script, create metadata, sl, begin variable(meta, meta2) meta := create container(0,0) set slice visible(meta, false) set parent(meta, sl) meta2 := create container(0,0) set parent(meta2, meta) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, align force with barrier, sl, axis, begin variable(n, go) n := slice coord by axis(sl, axis) go := get force(sl, axis) while(go <> 0) do( go := go -- sign(go) if((n+go), mod, 20 == 0) then(break) ) set force (sl, axis, go) end script, get force x, sl, begin exit returning(get force(sl, x axis)) end script, get force y, sl, begin exit returning(get force(sl, y axis)) end script, set force x, sl, n, fsign=1, begin set force(sl, x axis, n, fsign) end script, set force y, sl, n, fsign=1, begin set force(sl, y axis, n, fsign) end script, set force, sl, axis, value, fsign=1, begin set slice extra(sl, get force extra slot(axis), value * fsign) end script, get force, sl, axis, begin exit returning(get slice extra(sl, get force extra slot(axis))) end script, get force extra slot, axis, begin switch(axis) do( case(x axis) do(exit returning(extra 0)) case(y axis) do(exit returning(extra 1)) ) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get gravstate, sl, begin exit returning(get slice extra(sl, extra 2)) end script, set gravstate, sl, n, begin set slice extra(sl, extra 2, n) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get attack delay, sl, begin variable(meta) meta := first child(sl) exit returning(get slice extra(meta, extra 0)) end script, set attack delay, sl, n, begin variable(meta) meta := first child(sl) set slice extra(meta, extra 0, n) end script, reduce attack delay, sl, begin variable(meta, n) meta := first child(sl) n := get slice extra(meta, extra 0) if(n >> 0) then( n -= 1 set slice extra(meta, extra 0, n) ) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get move speed, sl, begin variable(meta) meta := first child(sl) exit returning(get slice extra(meta, extra 1)) end script, set move speed, sl, n, begin variable(meta) meta := first child(sl) set slice extra(meta, extra 1, n) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get exbit, sl, bit, begin variable(meta, n) meta := first child(sl) n := get slice extra(meta, extra 2) 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 := first child(sl) n := get slice extra(meta, extra 2) if(value) then(n := n, or, 2^bit) else(n := n, and, (-1, xor, 2^bit)) set slice extra(meta, extra 2, n) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get handler, sl, begin variable(meta) meta := first child(sl) exit returning(slice x(meta)) end script, set handler, sl, n, begin variable(meta) meta := first child(sl) set slice x(meta, n) end script, get collision handler, sl, begin variable(meta) meta := first child(sl) exit returning(slice y(meta)) end script, set collision handler, sl, n, begin variable(meta) meta := first child(sl) set slice y(meta, n) end script, get collision with player handler, sl, begin variable(meta) meta := first child(sl) exit returning(slice width(meta)) end script, set collision with player handler, sl, n, begin variable(meta) meta := first child(sl) set slice width(meta, n) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get pop group, sl, begin variable(meta) meta := first child(sl) exit returning(get top padding(meta)) end script, set pop group, sl, n, begin variable(meta) meta := first child(sl) set top padding(meta, n) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get bonus pic, sl, begin variable(meta) meta := first child(sl) exit returning(get right padding(meta)) end script, set bonus pic, sl, n, begin variable(meta) meta := first child(sl) set right padding(meta, n) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get tickstamp, sl, begin variable(meta) meta := first child(sl) exit returning(get bottom padding(meta)) end script, set tickstamp, sl, n=0, begin variable(meta) meta := first child(sl) if(n == 0) then(n := ticks) set bottom padding(meta, n) end script, get ticks elapsed, sl, begin exit returning(ticks -- get tickstamp(sl)) end #. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . script, get ai, sl, begin variable(meta) meta := first child(sl) exit returning(get left padding(meta)) end script, set ai, sl, n, begin variable(meta) meta := first child(sl) set left padding(meta, n) end script, get capture handler, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(get slice extra(meta2, extra 0)) end script, set capture handler, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice extra(meta2, extra 0, n) end script, capture handler, sl, bub, begin variable(fn) fn := get capture handler(sl) if(fn) then( run script by id(fn, sl, bub) ) end script, get monster collision handler, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(get slice extra(meta2, extra 1)) end script, set monster collision handler, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice extra(meta2, extra 1, n) end script, get shot force, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(get slice extra(meta2, extra 2)) end script, set shot force, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice extra(meta2, extra 2, n) end script, get shot delay, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(slice x(meta2)) end script, set shot delay, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice x(meta2, n) end script, get points, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(slice y(meta2)) end script, set points, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice y(meta2, n) end script, get chain parent, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(slice width(meta2)) end script, set chain parent, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice width(meta2, n) end script, get chain child, sl, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) exit returning(slice height(meta2)) end script, set chain child, sl, n, begin variable(meta, meta2) meta := first child(sl) meta2 := first child(meta) set slice height(meta2, n) end #----------------------------------------------------------------------- script, get player, n, begin if(n == 0) then(exit returning(pl1)) else(exit returning(pl2)) end script, set player, n, handle, begin if(n == 0) then(pl1 := handle) else(pl2 := handle) end script, player sprite, n, begin if(n == 0) then(exit returning(1)) else(exit returning(5)) end script, on both players, fn, begin run script by id(fn, pl1) run script by id(fn, pl2) end script, player start x, sl, begin if(sl == pl1) then(exit returning(50)) if(sl == pl2) then(exit returning(slice width(map layer) -- 70)) end script, player start y, sl, begin exit returning(slice height(map layer) -- 50) end script, player joins, n, begin variable(need restart) if(pl1 == 0 && pl2 == 0) then(need restart := true) create player(n, 5) variable(sl) sl := get player(n) respawn player(sl) if(need restart) then( teleport to level(current map) ) end script, clear player, sl, begin if(sl == pl1) then(pl1 := none) if(sl == pl2) then(pl2 := none) end script, nearest player, sl, begin exit returning(nearest of two(sl, pl1, pl2)) end script, nearest of two, sl, sl1, sl2, begin if(sl1 == 0 && sl2 == 0) then(exit returning(0)) if(sl2 == 0) then(exit returning(sl1)) if(sl1 == 0) then(exit returning(sl2)) variable(a1, b1, c1, a2, b2, c2) a1 := abs(slice edge x(sl, edge:center) -- slice edge x(sl1, edge:center)) b1 := abs(slice edge y(sl, edge:center) -- slice edge y(sl1, edge:center)) c1 := a1^2 + b1^2 a2 := abs(slice edge x(sl, edge:center) -- slice edge x(sl2, edge:center)) b2 := abs(slice edge y(sl, edge:center) -- slice edge y(sl2, edge:center)) c2 := a2^2 + b2^2 if(c1 << c2) then(exit returning(sl1)) if(c1 >> c2) then(exit returning(sl2)) # break ties with share tog if(share tog) then( exit returning(sl1) )else( exit returning(sl2) ) end #----------------------------------------------------------------------- script, compass x, dir, begin switch(dir) do( case(up) do(exit returning(0)) case(right) do(exit returning(1)) case(down) do(exit returning(-1)) case(left) do(exit returning(0)) ) end script, compass y, dir, begin switch(dir) do( case(up) do(exit returning(1)) case(right) do(exit returning(0)) case(down) do(exit returning(0)) case(left) do(exit returning(-1)) ) end script, compass axis, dir, begin dir := dir, mod, 4 if(dir == -1) then(dir := 3) switch(dir) do( case(up) do(exit returning(1)) case(right) do(exit returning(0)) case(down) do(exit returning(1)) case(left) do(exit returning(0)) ) end script, compass sign, dir, begin switch(dir, mod, 4) do( case(up) do(exit returning(-1)) case(right) do(exit returning(1)) case(down) do(exit returning(1)) case(left) do(exit returning(-1)) ) end script, compass wall, dir, begin switch(dir) do( case(up) do(exit returning(south wall)) case(right) do(exit returning(west wall)) case(down) do(exit returning(north wall)) case(left) do(exit returning(east wall)) ) end script, compass flip, dir, begin exit returning(dir == left) end #----------------------------------------------------------------------- script, count children, sl, begin variable(n) n := 0 sl := first child(sl) while(sl) do( n += 1 sl := next sibling(sl) ) exit returning(n) end script, percent chance, p, begin exit returning(random(0, 99) << p) end script, percent chance 00, p, begin exit returning(random(0, 9999) << p) end script, randomize, n, amount, begin exit returning(random(n, n+amount)) end script, safe read pass block, x, y, begin if(x << 0) then(exit returning(0)) if(x >= map width) then(exit returning(0)) if(y << 0) then(exit returning(0)) if(y >= map height) then(exit returning(0)) exit returning(read pass block(x, y)) end script, safe read map block, x, y, layer=0, begin if(x << 0) then(exit returning(-1)) if(x >= map width) then(exit returning(-1)) if(y << 0) then(exit returning(-1)) if(y >= map height) then(exit returning(-1)) exit returning(read map block(x, y, layer)) end script, wrap read pass block, x, y, begin if(x << 0) then(x := map width -- 1) if(x >= map width) then(x := 0) if(y << 0) then(y := map height -- 1) if(y >= map height) then(y := 0) exit returning(read pass block(x, y)) end #-----------------------------------------------------------------------