# Bell of Chaos -- (C)Copyright 2010 James Paige # Game data and script code is GPL # See README.txt and LICENCE.txt #----------------------------------------------------------------------- include, plotscr.hsd include, scancode.hsi include, bellchaos.hsi #----------------------------------------------------------------------- # Globals & Constants define constant(19, terminal velocity) define constant(2, gravity force) define constant(18, second) define constant(12, key timeout) define constant(3, sequence) define constant(4, checker) # preserved in saves global variable(0, save:hp) global variable(1, save:max hp) global variable(2, save:d) global variable(3, save:x) global variable(4, save:y) global variable(5, save:fx) global variable(6, save:fy) global variable(7, save:magic) global variable(8, save:max magic) #200+ for bell and chain storage # not preserved in saves global variable(500, player) global variable(501, active) global variable(502, dormant) global variable(503, create in) global variable(504, ticks) global variable(505, bell) global variable(506, hp meter) global variable(507, sleeper) global variable(508, key timer) global variable(509, key repeat) global variable(510, holding jump) global variable(511, magic meter) global variable(512, gold text) global variable(513, magic meter needs fixing) define constant(5, monster:lion beast) #----------------------------------------------------------------------- # Main scripts plotscript, main, loading=false, begin pre init if(not(loading)) then( init player name tutorial ) init if(loading) then(update load) while(true) do( do updates do collisions do forces do removals update camera(player) wait(1) ticks += 1 ) end plotscript, on load, begin variable(i) # flush globals that shouldn't be saved for(i, 500, 999) do( write global(i, 0) ) main(true) end script, pre init, begin suspend player setup key names ticks := second end script, init, begin create sleeper zone active := create container(0, 0) dormant := create container(0, 0) create in := dormant init map create hp meter create magic meter end script, init player name, begin switch(random(0, 11)) do( case(0) do($0="Anahita") # Immaculate fertility and water case(1) do($0="Arundhati") # Unrestrained night sky stars case(2) do($0="Ereshkigal") # Lady of the land of the dead case(3) do($0="Het-Heru") # of the house of Horus case(4) do($0="Rajani") # Night-Kali case(5) do($0="Al-Mah") # Nubile moon case(6) do($0="Annunaki") # of royal blood case(7) do($0="Inanna") # Source of Earth's blood case(8) do($0="Kadi") # Serpent case(9) do($0="Tirgata") # of fish case(10) do($0="Nambi") # first human woman case(11) do($0="Lahamu") # of mud ) set hero name(0, 0) rename hero(0) end plotscript, init map, begin variable(map slice) map slice := lookup slice(sl:map layer 1) set parent(active, map slice) set slice width(active, slice width(map slice)) set slice height(active, slice height(map slice)) set parent(dormant, map slice) set slice width(dormant, slice width(map slice)) set slice height(dormant, slice height(map slice)) create map things(@always) refocus screen on(player) wake up screen end script, tutorial, begin variable(b) b := create rect(320, 200) show text box(20) wait for text box wrapper free slice(b) end script, do updates, begin variable(sl) sl := first child(active) while(sl) do( universal update(sl) run update callback(sl) sl := next sibling(sl) ) end script, do collisions, begin variable(sl) sl := first child(active) while(sl) do( # for stuff that needs to happen before wall collisions pre check collisions(sl) sl := next sibling(sl) ) sl := first child(active) while(sl) do( # wall and floor collisions check collisions(sl) sl := next sibling(sl) ) sl := first child(active) while(sl) do( # for stuff that can override wall collisions post check collisions(sl) sl := next sibling(sl) ) end script, do forces, begin variable(sl) sl := first child(active) while(sl) do( apply force(sl) sl := next sibling(sl) ) end script, do removals, begin variable(sl, delete, ref) sl := first child(active) while(sl) do( if(get remove me(sl)) then(delete := sl) sl := next sibling(sl) if(delete) then( if(get held thing(delete)) then(drop thing(delete)) drop me please(delete) ref := get creator ref(delete) if(ref) then( # enable respawning set NPC extra(ref, extra 1, false) ) free slice(delete) delete := 0 ) ) end script, update camera, sl, begin variable(x, y, panning) x := slice edge x(sl, edge:center) y := slice edge y(sl, edge:bottom) if(x << camera pixel x) then(pan camera(left, 16, 20), panning := true) if(x >> camera pixel x + slice width(sprite layer)) then(pan camera(right, 16, 20), panning := true) if(y << camera pixel y) then(pan camera(up, 10, 20), panning := true) if(y >> camera pixel y + slice height(sprite layer)) then(pan camera(down, 10, 20), panning := true) if(panning) then( wait for camera wake up screen ) end script, wake up screen, begin variable(sl, nxt) create map things(@respawn far away) sl := first child(dormant) while(sl) do( nxt := next sibling(sl) if(slice collide(sl, sprite layer)) then( set parent(sl, active) ) sl := nxt ) #debug object counts sleep distant things update music #keep player above bell nag about bell end script, wake up bell, begin variable(sl) sl := bell while(sl) do( if(parent slice(sl) == dormant) then( set parent(sl, active) ) sl := get held by(sl) ) end script, nag about bell, begin if(check tag(tag:touched bell) == false) then( if(not(slice collide(bell, sleeper))) then( if(get direction(player) <> sign(slice x(bell) -- slice x(player))) then( show text box(19) wait for text box wrapper ) ) ) end script, update music, begin variable(floor, song) floor := get current floor song := 1 if(floor >> 4) then( song := 0 ) if(song <> current song) then( play song(song) ) end script, create sleeper zone, begin sleeper := create container(320 * 3, 200 * 3) realign slice(sleeper, edge:center, edge:center, edge:center, edge:center) end script, sleep distant things, begin variable(sl, nxt) sl := first child(active) while(sl) do( nxt := next sibling(sl) if(get important(sl) == false) then( if(slice collide(sl, sleeper) == false) then( set parent(sl, dormant) ) ) sl := nxt ) #debug object counts end script, debug object counts, begin $0="Active:" append number(0, child count(active)) $0+" Dormant:" append number(0, child count(dormant)) trace(0) end script, refocus screen on, sl, begin variable(x, y) x := slice edge x(sl, edge:center) / 320 * 320 y := slice edge y(sl, edge:bottom) / 200 * 200 put camera(x, y) tweak palette(-63, -63, -63) update palette wait(1) reset palette update palette end script, keep player above bell, begin # doesn't work right now variable(sl) sl := bell while(sl) do( if(player <> sl) then( move slice above(player, sl) ) sl := get held by(sl) ) end #----------------------------------------------------------------------- # Key and joystick input script, pushing up, begin exit returning(keyval(key:up) >> 0 || key is pressed(joy:y up)) end script, pushing right, begin exit returning(keyval(key:right) >> 0 || key is pressed(joy:x right)) end script, pushing down, begin exit returning(keyval(key:down) >> 0 || key is pressed(joy:y down)) end script, pushing left, begin exit returning(keyval(key:left) >> 0 || key is pressed(joy:x left)) end script, pushing jump, begin exit returning(keyval(key:Z) >> 0 || keyval(key:ctrl) >> 0 || key is pressed(joy:button 2)) end script, pushing action, begin exit returning(keyval(key:X) >> 1 || keyval(key:space) >> 1 || keyval(key:alt) >> 1 || key is pressed(joy:button 1)) end script, pushing menu, begin exit returning(keyval(key:ESC) >> 1 || keyval(key:ENTER) >> 1 || key is pressed(joy:button 3)) end # Font-specific chars for the visually displayable move string define constant(175, ascii:up) define constant(168, ascii:down) define constant(174, ascii:right) define constant(171, ascii:left) define constant(176, ascii:ul) define constant(177, ascii:ur) define constant(178, ascii:dr) define constant(179, ascii:dl) define constant(43, ascii:plus) define constant(88, ascii:X) define constant(90, ascii:Z) # must be called once per tick from the main loop script, update key sequence, begin variable(got key) while(true) do( if(pushing action) then( got key := append to sequence(ascii:X) break ) if(pushing jump && holding jump == false) then( got key := append to sequence(ascii:Z) break ) if(pushing up && not(pushing down || pushing left || pushing right)) then( got key := append to sequence(ascii:up) break ) if(pushing right && not(pushing down || pushing left || pushing up)) then( got key := append to sequence(ascii:right) break ) if(pushing down && not(pushing up || pushing left || pushing right)) then( got key := append to sequence(ascii:down) break ) if(pushing left && not(pushing down || pushing up || pushing right)) then( got key := append to sequence(ascii:left) break ) if(pushing up && pushing left && not(pushing down || pushing right)) then( got key := append to sequence(ascii:ul) break ) if(pushing up && pushing right && not(pushing down || pushing left)) then( got key := append to sequence(ascii:ur) break ) if(pushing down && pushing right && not(pushing up || pushing left)) then( got key := append to sequence(ascii:dr) break ) if(pushing down && pushing left && not(pushing up || pushing right)) then( got key := append to sequence(ascii:dl) break ) break ) if(got key) then( key timer := ticks )else( key repeat := 0 ) if(key timer + key timeout << ticks) then( $sequence="" ) #show string(sequence) end script, append to sequence, ascii, begin variable(last, rep, offset) last := ascii from string(sequence, string length(sequence)) while(last == ascii:plus) do( rep := true offset += 1 last := ascii from string(sequence, string length(sequence) -- offset) ) if(last == ascii) then( key repeat += 1 if(key repeat >> key timeout) then( $sequence+"+" key repeat := 0 exit returning(true) ) )else( append ascii(sequence, ascii) exit returning(true) ) exit returning(false) end # Chars for embedding into the checker string in the source code define constant(85, ascii:U) #up "U" u U f define constant(68, ascii:D) #down "D" B > F define constant(70, ascii:F) #forward "F" b D d define constant(66, ascii:B) #backwards "B" define constant(102, ascii:_f) #up forward "f" define constant(100, ascii:_d) #down forward "d" define constant(98, ascii:_b) #down back "b" define constant(117, ascii:_u) #up back "u" define constant(94, ascii:carrot) # any up "^" define constant(118, ascii:v) # any down "v" # examples: # $checker="DfFX" Hadoken! # $checker="FDdX" Shoryuken! # $checker="BbDdFX" Yoga Flame! # always set checker right before calling "check move" script, check move, consume keys=true, begin variable(i, ch1, ch2, diff, F, B, df, db, uf, ub) diff := string length(sequence) -- string length(checker) for(i, string length(checker), 1, -1) do( ch1 := ascii from string(checker, i) ch2 := ascii from string(sequence, i + diff) if(ch2 == 0) then(exit returning(false)) switch(ch1) do( case(ascii:U) do( if(ch2 <> ascii:up) then(exit returning(false)) ) case(ascii:D) do( if(ch2 <> ascii:down) then(exit returning(false)) ) case(ascii:X) do( if(ch2 <> ascii:X) then(exit returning(false)) ) case(ascii:F) do( if(F == 0) then( switch(ch2) do( case(ascii:left) do(F:=ascii:left, B:=ascii:right, df:=ascii:dl, db:=ascii:dr, uf:=ascii:ul, ub:=ascii:ur) case(ascii:right) do(F:=ascii:right, B:=ascii:left, df:=ascii:dr, db:=ascii:dl, uf:=ascii:ur, ub:=ascii:ul) ) ) if(ch2 <> F) then(exit returning(false)) ) case(ascii:B) do( if(F == 0) then( switch(ch2) do( case(ascii:left) do(F:=ascii:right, B:=ascii:left, df:=ascii:dr, db:=ascii:dl, uf:=ascii:ur, ub:=ascii:ul) case(ascii:right) do(F:=ascii:left, B:=ascii:right, df:=ascii:dl, db:=ascii:dr, uf:=ascii:ul, ub:=ascii:ur) ) ) if(ch2 <> B) then(exit returning(false)) ) case(ascii:_d) do( #Forward-down if(F == 0) then( switch(ch2) do( case(ascii:dl) do(F:=ascii:left, B:=ascii:right, df:=ascii:dl, db:=ascii:dr, uf:=ascii:ul, ub:=ascii:ur) case(ascii:dr) do(F:=ascii:right, B:=ascii:left, df:=ascii:dr, db:=ascii:dl, uf:=ascii:ur, ub:=ascii:ul) ) ) if(ch2 <> df) then(exit returning(false)) ) case(ascii:_b) do( #Back-down if(F == 0) then( switch(ch2) do( case(ascii:dl) do(F:=ascii:right, B:=ascii:left, df:=ascii:dr, db:=ascii:dl, uf:=ascii:ur, ub:=ascii:ul) case(ascii:dr) do(F:=ascii:left, B:=ascii:right, df:=ascii:dl, db:=ascii:dr, uf:=ascii:ul, ub:=ascii:ur) ) ) if(ch2 <> db) then(exit returning(false)) ) case(ascii:_f) do( #Forward-up if(F == 0) then( switch(ch2) do( case(ascii:ul) do(F:=ascii:left, B:=ascii:right, df:=ascii:dl, db:=ascii:dr, uf:=ascii:ul, ub:=ascii:ur) case(ascii:ur) do(F:=ascii:right, B:=ascii:left, df:=ascii:dr, db:=ascii:dl, uf:=ascii:ur, ub:=ascii:ul) ) ) if(ch2 <> uf) then(exit returning(false)) ) case(ascii:_u) do( #Back-up if(F == 0) then( switch(ch2) do( case(ascii:ul) do(F:=ascii:right, B:=ascii:left, df:=ascii:dr, db:=ascii:dl, uf:=ascii:ur, ub:=ascii:ul) case(ascii:ur) do(F:=ascii:left, B:=ascii:right, df:=ascii:dl, db:=ascii:dr, uf:=ascii:ul, ub:=ascii:ur) ) ) if(ch2 <> ub) then(exit returning(false)) ) case(ascii:v) do( #Any down if(ch2 <> ascii:dl && ch2 <> ascii:down && ch2 <> ascii:dr) then(exit returning(false)) ) case(ascii:carrot) do( #Any up if(ch2 <> ascii:ul && ch2 <> ascii:up && ch2 <> ascii:ur) then(exit returning(false)) ) ) ) if(consume keys) then( $sequence="" ) exit returning(true) end #----------------------------------------------------------------------- # User input script, player keys, sl, begin variable(fx, max, floor) if(pushing menu) then(menu handler) update key sequence fx := get force x(sl) max := get walk max(sl) floor := get touching floor(sl) if(fx >= max * -1 -- 2) then( if(pushing left) then(push force x(sl, -2)) ) if(fx <= max + 2) then( if(pushing right) then(push force x(sl, 2)) ) if(pushing down) then( try to climb down(sl) if(get climbing(sl) == false) then( set crouching(sl, true) ) ) if(not(pushing down)) then( set crouching(sl, false) ) if(pushing up) then( if(try to climb up(sl) == false) then( try to talk(sl) ) ) if(pushing jump) then( if(get climbing(sl)) then( set climbing(sl, false) ) if(floor) then( if(holding jump == false) then( holding jump := true jump or dash slide(sl) ) ) ) if(not(pushing jump)) then( #jump button must be released before it can be used again holding jump := false ) if(pushing action) then( #throw or telefetch(sl, get mobile grandholder(bell)) fling thing(sl) set using action(sl, true) ) if(not(pushing action)) then( set using action(sl, false) ) try bell tweaks(sl) try bell summon(sl) try flame bell try double jump(sl) try offering(sl) try long chain(sl) if(keyval(key:tilde) >> 0 && keyval(key:t) >> 1) then( teleport to hero pos ) end script, try to talk, sl, begin variable(find, box) find := first child(active) while(find) do( if(sl <> find && slice collide(sl, find)) then( box := get text box(find) if(box) then( show text box(box) wait for text box wrapper exit script ) ) find := next sibling(find) ) end script, try bell tweaks, sl, begin variable(dir, held) if(keyval(key:A) >> 1) then(direction change boost(sl)) # must be touching the floor and holding the chain held := get held thing(sl) if(held <> 0 && get touching floor(sl) && get special(sl) == 0) then( $checker="BF" if(check move(false)) then( direction change boost(sl) ) $checker="bd" if(check move(false)) then( direction change boost(sl) ) ) end script, direction change boost, sl, begin variable(f, spark, held, dir) set special(sl, key timeout + 2) held := get held thing(sl) dir := get last x move(sl) # impart some extra velocity to the whole chain f := 8 while(held) do( set antifriction(held, 5) push force x(held, f * dir) f += 1 held := get held thing(held) ) end script, try bell summon, sl, begin if(check tag(tag:summon bell) && get held thing(sl) == 0) then( $checker="UDUDX" if(check move) then( if(consume magic(sl, 30)) then( bell summon(sl) ) ) ) end script, try flame bell, begin if(check tag(tag:flame bell)) then( $checker="DdFX" if(check move) then( if(consume magic(player, 30)) then( set bell ablaze ) ) ) end script, try double jump, sl, begin if(get touching floor(sl) == false) then( if(check tag(tag:double jump) || check tag(tag:endless jump)) then( if(get has doublejumped(sl) == false || (check tag(tag:endless jump) && get climbing(sl) == false)) then( $checker="v^Z" if(check move) then( if(consume magic(sl, 2)) then( double jump(sl) ) ) ) ) ) end script, try offering, sl, begin if(check tag(tag:offering)) then( $checker="UDLRD" if(check move) then( create offering(player) ) ) end script, try long chain, sl, begin if(check tag(tag:long chain)) then( $checker="BuUfFX" if(check move) then( if(consume magic(sl, 90)) then( create long chain ) ) ) end script, menu handler, begin variable(mh) mh := open menu(0) play sound(sfx:little_menu_blip) wait for menu(mh) end plotscript, menu item quit, begin game over end script, setup key names, begin $1="CTRL or Z" $2="ALT or X" end script, teleport to hero pos, begin variable(sl) sl := player while(sl) do( set slice edge x(sl, edge:center, hero pixel x(0) + 10) set slice edge y(sl, edge:bottom, hero pixel y(0) + 10) sl := get held thing(sl) ) refocus screen on(player) wake up screen end #----------------------------------------------------------------------- # Saving & Loading script, update load, begin if(player == 0) then(create player(0, 0)) set slice x(player, hero pixel x(0)) set slice y(player, hero pixel y(0)) set force x(player, save:fx) set force y(player, save:fy) horiz flip sprite(first child(player), save:d) set hp(player, save:hp) set max hp(player, save:max hp) set magic(player, save:magic) set max magic(player, save:max magic) load bell refocus screen on(player) wake up screen update meters end script, load bell, begin variable(sl, i) i := 200 if(bell == 0) then(create bell(0, 0)) sl := bell while(sl) do( set slice x(sl, read global(i) + (hero pixel x(0) -- save:x)) set slice y(sl, read global(i+1) + (hero pixel y(0) -- save:y)) set force x(sl, read global(i+2)) set force y(sl, read global(i+3)) sl := get held by(sl) i += 8 ) wake up bell end plotscript, update save, begin set hero picture(0, get normal frames(player), inside battle) set hero palette(0, -1, inside battle) put hero(0, slice x(player), slice y(player)) save:x := slice x(player) save:y := slice y(player) save:d := sprite is horiz flipped(first child(player)) save:hp := get hp(player) save:max hp := get max hp(player) save:magic := get magic(player) save:max magic := get max magic(player) save bell set hero level(0, get current floor) save menu end script, save bell, begin variable(sl, i) i := 200 sl := bell while(sl) do( write global(i, slice x(sl)) write global(i+1, slice y(sl)) write global(i+2, get force x(sl)) write global(i+3, get force y(sl)) sl := get held by(sl) i += 8 ) end #----------------------------------------------------------------------- # Actions script, jump, sl, begin if(get held thing(sl)) then( # weighed down by a held object, jump 2 blocks high push force y(sl, -15) )else( # unencumbered, jump 3 block high push force y(sl, -17) ) end script, double jump, sl, begin variable(i) boring drop thing(sl) set force y(sl, 0) push force y(sl, -17) for(i, 0, 9) do( create vertical spark(sl) ) set has doublejumped(sl, true) end script, dash slide, sl, begin variable(spark) if(gettouching floor(sl) && get crouching(sl)) then( push force x(sl, 20 * get direction(sl)) set antifriction(sl, 4) spark := create magic spark(sl) set force x(spark, get direction(sl) * -1) set force y(spark, 0) ) end script, jump or dash slide, sl, begin variable(ds) ds := true if(sl == player && check tag(tag:slide) == off) then(ds := false) if(ds && get crouching(sl)) then( if(abs(get force x(sl)) >> 4) then( #dive jump if already sliding jump(sl) push force x(sl, 20 * get direction(sl)) )else( if(consume magic(sl, 2)) then( dash slide(sl) )else( # jump if you don't have the magic to slide jump(sl) ) ) )else( jump(sl) ) end script, boring drop thing, sl, begin drop thing(sl) set drop delay(sl, ticks) end script, fling thing, sl, begin variable(fling) if(get held thing(sl) == 0) then(exit script) fling := drop thing(sl) set drop delay(sl, ticks) while(fling) do( # copy the flinger's force to the flingees push force x(fling, get force x(sl)) push force y(fling, get force y(sl)) # extra forward fling push force x(fling, 5 * get direction(sl)) push force y(fling, -2) fling := get held thing(fling) ) #nullify the flinger's forces set force x(sl, 0) set force y(sl, 0) end script, bell summon, sl, begin variable(link) link := get mobile grandholder(bell) drop me please(link) while(link) do( create magic spark(link) set slice edge x(link, edge:center, slice edge x(sl, edge:center)) set slice edge y(link, edge:center, slice edge y(sl, edge:center)) create magic spark(link) link := get held thing(link) ) if(parent slice(bell) == dormant) then( wake up screen ) end script, get grandholder, sl, begin variable(cur, nxt) cur := get held by(sl) while(cur) do( nxt := get held by(cur) if(nxt == 0) then(exit returning(cur)) cur := nxt ) exit returning(cur) end script, get mobile grandholder, sl, begin variable(cur, nxt) cur := get held by(sl) while(cur) do( nxt := get held by(cur) if(nxt == 0) then(exit returning(cur)) if(get immobile(nxt)) then(exit returning(cur)) cur := nxt ) exit returning(cur) end script, throw or telefetch, sl, thing, begin if(get held thing(sl)) then( if(get using action(sl) == false) then( fling thing(sl) ) )else( telefetch(sl, thing) ) end script, telefetch, sl, thing, force=1, begin variable(fx, dx, dy, by, upforce) upforce := gravity force fx := get force x(thing) if(fx == 0) then(upforce += 1 + force) by := get held by(thing) if(by) then(drop thing(by)) dx := slice edge x(sl, edge:center) -- slice edge x(thing, edge:center) dy := slice edge y(sl, edge:center) -- slice edge y(thing, edge:center) if(abs(fx) << 4) then( push force x(thing, sign(dx) * force) ) if(dy <= 0) then( push force y(thing, sign(dy) * force -- upforce) ) set antifriction(thing, 1) end script, try to climb up, sl, begin exit returning(try to climb(sl, -2)) end script, try to climb down, sl, begin exit returning(try to climb(sl, 2)) end script, try to climb, sl, force, begin variable(fy) if(check for ladder(sl)) then( if(get climbing(sl) == false) then( if(not(is horiz tile aligned(sl))) then( force horiz tile align(sl) exit returning(true) )else( set crouching(sl, false) set force y(sl, 0) ) ) fy := get force y(sl) if(force >> 0) then( if(fy << 3) then( push force y(sl, force) force horiz tile align(sl) ) ) if(force << 0) then( if(fy >> -3) then( push force y(sl, force) force horiz tile align(sl) ) ) set climbing(sl, true) exit returning(true) ) exit returning(false) end script, check for ladder, sl, begin variable(i) if(check for ladder at spot(slice edge x(sl, edge:center), slice edge y(sl, edge:top))) then(exit returning(true)) if(check for ladder at spot(slice edge x(sl, edge:center), slice edge y(sl, edge:bottom)+2)) then(exit returning(true)) for(i, 20, slice height(sl), 20) do( if(check for ladder at spot(slice edge x(sl, edge:center), slice edge y(sl, edge:top)+i)) then(exit returning(true)) ) exit returning(false) end script, check for ladder at spot, x, y, begin variable(tile) tile := read pass block(x / 20, y / 20) if(tile, and, vehicle A) then(exit returning(true)) exit returning(false) end script, is horiz tile aligned, sl, begin variable(x) x := slice edge x(sl, edge:center) if((x, mod, 20) >= 9 && (x, mod, 20) <= 10) then(exit returning(true)) exit returning(false) end script, force horiz tile align, sl, begin variable(x, x2) x := slice edge x(sl, edge:center) x2 := x, mod, 20 if(x2 << 10) then( push force x(sl, random(1,2)) ) if(x2 >> 10) then( push force x(sl, random(-2, -1)) ) end script, avoid enemy alignment, sl, begin variable(other) if(random(1,100) << 10) then( other := find colliding slice(active, sl, 0, false) if(other) then( if(get normal frames(other) == get normal frames(sl)) then( set direction(sl, get direction(other) * -1) ) ) ) end script, advance, sl, force=2, begin push force x(sl, force * get direction(sl)) end script, advance to max, sl, force=2, begin if(abs(get force x(sl)) <= get walk max(sl)) then( advance(sl) ) end script, turn around, sl, begin set direction(sl, get direction(sl) * -1) end script, get current floor, begin exit returning((map height * 20 -- slice edge y(player, edge:bottom)) / 200) end #----------------------------------------------------------------------- # AI scripts script, ishtar angel ai, sl, begin variable(state) force of gravity(sl) if(ticks, mod, second == 0) then( set memory val(sl, random(0, 2)) if(random(1,100) << 40) then(turn around(sl)) ) state := get memory val(sl) switch(state) do( case(0) do(advance to max(sl)) case(1) do() case(2) do( face(sl, player) advance to max(sl) if(slice collide(sl, player)) then(set memory val(sl, 1)) ) ) end script, lion beast ai, sl, begin variable(fx, max) check for monster death(sl) force of gravity(sl) fx := get force x(sl) max := get walk max(sl) if(max == 3) then( if((ticks, and, second) && random(1,7) == 1) then(set walk max(sl, 2)) )else( face(sl, player) if((ticks, and, second) && random(1,7) == 1) then(set walk max(sl, 3)) ) if(fx == 0 && get touching floor(sl)) then( push force y(sl, -10) ) if(abs(fx) <= max) then( advance(sl) ) end script, beard bird ai, sl, begin check for monster death(sl) if(get force x(sl) == 0) then(turn around(sl)) set force x(sl, 2 * get direction(sl)) if(get memory val(sl) == 0) then(set memory val(sl, -1)) if(get force y(sl) == 0) then( set memory val(sl, get memory val(sl) * -1) set force y(sl, get memory val(sl)) ) end script, peon ai, sl, begin variable(fx) check for monster death(sl) force of gravity(sl) leash monster(sl, monster:lion beast) fx := get force x(sl) if(fx == 0 && get touching floor(sl)) then( turn around(sl) ) if(abs(fx) <= get walk max(sl)) then( advance(sl) ) end script, jackal ai, sl, begin variable(fx, other) check for monster death(sl) force of gravity(sl) fx := get force x(sl) if((ticks, mod, (second*6)) == 0) then(jump(sl)) if(fx == 0 && get touching floor(sl)) then( turn around(sl) ) avoid enemy alignment(sl) if(not(slice collide(sl, sprite layer))) then(face(sl, player)) advance to max(sl) end script, heavy swordsman ai, sl, begin variable(fx) check for monster death(sl) force of gravity(sl) fx := get force x(sl) if((ticks, mod, second) == 0 && random(1, 100) << 50) then( set update callback(sl, @heavy swordsman ai:slash) set memory val(sl, 0) set force x(sl, sign(get force x(sl))) exit script ) if(fx == 0 && get touching floor(sl)) then( turn around(sl) ) avoid enemy alignment(sl) if(not(slice collide(sl, sprite layer))) then(face(sl, player)) advance to max(sl) end script, heavy swordsman ai:slash, sl, begin variable(slash) if(get memory val(sl) >> 10) then( set update callback(sl, @heavy swordsman ai) set memory val(sl, 0) slash := create sword slash(0, 0) set slice edge x(slash, edge:center, slice edge x(sl, edge:center) + 25 * get direction(sl)) set slice edge y(slash, edge:center, slice edge y(sl, edge:center)) set direction(slash, get direction(sl)) advance(sl, 6) advance(slash, 7) set antifriction(sl, 1) set antifriction(slash, 3) exit script ) set memory val(sl, get memory val(sl) + 1) end script, sword slash ai, sl, begin if(get memory val(sl) >> 1) then( set remove me(sl, true) ) set memory val(sl, get memory val(sl) + 1) end script, owl pillar ai, sl, begin variable(d, fy) if(not(slice collide(sl, sprite layer))) then(exit script) d := get memory val(sl) fy := get force y(sl) if(d >> 0) then( force of gravity(sl) if(get touching floor(sl)) then( set memory val(sl, d * -1) play sound(sfx:owlbump) ) )else( if(get touching ceiling(sl)) then(set memory val(sl, d * -1)) if(abs(fy) <= get walk max(sl)) then( push force y(sl, -2) ) ) end script, trapper vine ai, sl, begin check for monster death(sl) if((ticks / second), mod, 2 == 0) then( if(get force y(sl) >> get walk max(sl) * -1) then(push force y(sl, -1)) ) if(abs(get force x(sl)) << get walk max(sl)) then( if((ticks / (second * 3 / 2)), mod, 2 == 0) then( face(sl, player) advance(sl, 1) ) push force x(sl, random(-2, 2)) ) end script, vine root ai, sl, begin force of gravity(sl) if(get held thing(sl) == 0) then(set remove me(sl, true)) end script, red bull ai, sl, begin variable(fx) check for monster death(sl) force of gravity(sl) fx := get force x(sl) if(fx == 0 && get touching floor(sl)) then( turn around(sl) ) avoid enemy alignment(sl) if(not(slice collide(sl, sprite layer))) then(face(sl, player)) advance to max(sl) end script, giant magi ai, sl, begin variable(fx) check for monster death(sl) force of gravity(sl) if(ticks, mod, (second) == 0) then( switch(random(0, 3)) do( case(0) do( face(sl, bell) advance to max(sl,3) exit script ) case(1) do(set local timer(sl, random(second/2, second))) case(2) do(continue) case(3) do( set update callback(sl, @giant magi ai:attack) set local timer(sl, random(second, second * 4 / 3)) exit script ) ) ) if(get local timer(sl) >> 0) then( # hesitate set local timer(sl, get local timer(sl) -- 1) exit script ) fx := get force x(sl) if(fx == 0 && get touching floor(sl)) then( set memory val(sl, get memory val(sl) + 1) if(get memory val(sl) >> 5) then( turn around(sl) ) )else( set memory val(sl, 0) ) avoid enemy alignment(sl) advance to max(sl) end script, giant magi ai:attack, sl, begin variable(spell, t) check for monster death(sl) force of gravity(sl) t := get local timer(sl) if(t >> 0) then( # hesitate t -= 1 set local timer(sl, t) ) if(t << 3) then( spell := create shock spell(slice edge x(sl, edge:center), slice edge y(sl, edge:center) -- 10) set force x(spell, get direction(sl) * (10 -- t)) set force y(spell, -4 + t) ) if(t <= 0) then( play sound(sfx:electric spell) set update callback(sl, @giant magi ai) ) end script, shock spell ai, sl, begin force of gravity(sl) if(get touching floor(sl)) then( if(get sprite frame(first child(sl)) == 7) then( set remove me(sl, true) ) ) end #----------------------------------------------------------------------- # Handlers script, universal update, sl, begin end script, player update, sl, begin if(get hp(sl) <= 0) then(player dies(sl), exit script) if(magic meter needs fixing) then(fix magic meter) apply climbing(sl) player keys(sl) force of gravity(sl) if(pushing left == 0 && pushing right == 0 && pushing down == 0 && pushing up == 0) then(extra friction(sl)) apply crouching(sl) regen magic(sl) try to pick up bell(sl) advance special(sl) end script, player dies, sl, begin set update callback(sl, @dying player update) set local timer(sl, second * 3) show text box(17) suspend box advance end script, dying player update, sl, begin variable(t) force of gravity(sl) set been damaged(sl, ticks) t := get local timer(sl) if(t >> 0) then( t -= 1 set local timer(sl, t) create death marker(sl) if(t == 1) then( resume box advance set slice visible(sl, false) ) )else( if(current text box == -1) then( game over ) ) end script, text box zone update, sl, begin if(slice collide(sl, player)) then( show text box(get text box(sl)) wait for text box wrapper set remove me(sl, true) ) end script, set bell ablaze, begin variable(fl) fl := create flame(bell) set attack power(bell, get attack power(fl)) # copy flame attack power to bell set local timer(bell, second) # about 1 second set update callback(bell, @burning bell update) play sound(sfx:blaze) end script, burning bell update, sl, begin variable(t) force of gravity(sl) create flame(sl) t := get local timer(sl) t -= 1 set local timer(sl, t) if(t <= 0) then( set attack power(sl, 10) # restore old attack power set update callback(sl, @dumb weight update) ) end script, dumb weight update, sl, begin force of gravity(sl) end script, ice block update, sl, begin variable(i) force of gravity(sl) if(being melted(sl)) then( for(i, 0, 8) do( create ice fragment(sl) ) set touch callback(sl, none) set remove me(sl, true) play sound(sfx:icebreak) ) end script, being melted, sl, begin variable(find) find := first child(active) while(find) do( if(get melt ice(find)) then( if(slice collide(sl, find)) then( exit returning(true) ) ) find := next sibling(find) ) exit returning(false) end script, chain holder update, sl, begin relinquish held thing(sl) try to pick up bell(sl) end script, magic chain update, sl, begin variable(t, held, holder, spark) force of gravity(sl) t := get local timer(sl) t -= 1 if(t <= 0) then( holder := get held by(sl) held := get held thing(sl) if(held) then(drop thing(sl)) if(holder) then(drop thing(holder)) if(holder && held) then( pick up thing(holder, held) ) spark := create magic spark(sl) set force x(spark, 0) set force y(spark, 2) set sprite frame(first child(spark), 3) set remove me(sl, true) ) set local timer(sl, t) end script, evaporating chain update, sl, begin force of gravity(sl) if(get held thing(sl) == 0) then(set remove me(sl, true)) if(get held by(sl) == 0) then(set remove me(sl, true)) end script, death marker update, sl, begin force of gravity(sl) if(get touching floor(sl)) then( if(get force x(sl) == 0) then( set remove me(sl, true) ) ) end script, offering ai, sl, begin variable(who, t, i) who := get memory val(sl) while(true) do( if(not(slice is valid(who))) then(break) if(not(get crouching(who))) then(break) if(abs(get force x(who)) >> 1) then(break) if(get hp(who) >= get max hp(who)) then(break) set slice edge x(sl, edge:center, slice edge x(who, edge:center) + random(-8, 8)) set slice edge y(sl, edge:center, slice edge y(who, edge:top) + random(-8, 8)) t := get local timer(sl) t -= 1 if(t <= 0) then( if(pay money(5) == false) then(break) consume magic(who, 10) t := second * 3 play sound(sfx:vibrato whistle) heal(who, random(5, 9)) for(i, 1, 5) do( create offering coin ) ) set local timer(sl, t) exit script ) create magic spark(sl) set remove me(sl, true) end script, offering coin update, sl, begin variable(t, spark) force of gravity(sl) if(get touching floor(sl)) then( if(get memory val(sl) == false) then( play sound(sfx:coin drop) push force y(sl, -5) set memory val(sl, true) exit script ) if(get force x(sl) == 0) then( spark := create vertical spark(sl) push force y(spark, -5) set remove me(sl, true) ) ) end script, coin update, sl, begin variable(t) force of gravity(sl) if(slice collide(sl, player)) then( collect money(1) create money floater(sl, 1) play sound(sfx:coin pickup) set remove me(sl, true) ) if(get touching floor(sl)) then( if(get memory val(sl) == false) then( play sound(sfx:coin drop) push force y(sl, -5) set memory val(sl, true) exit script ) if(get force x(sl) == 0) then( t := get local timer(sl) if(t <= 0) then( t := second * 5 )else( if(t == 1) then( set remove me(sl, true) ) if(t << second * 2) then( set slice visible(sl, (t,mod,2)) ) ) t -= 1 set local timer(sl, t) ) ) end script, collect money, amount, begin get money(amount) update hud text end script, health potion update, sl, begin force of gravity(sl) if(slice collide(sl, player)) then( heal(player, get attack power(sl)) set remove me(sl, true) ) end script, bell icon update, sl, begin if(get held thing(player) == 0) then( if(slice collide(sl, player)) then( if(not(slice collide(sl, bell))) then( bell summon(sl) ) ) ) end script, text floater update, sl, begin set slice y(sl, slice y(sl) -- 1) if(get memory val(sl) + second << ticks) then( set remove me(sl, true) ) end script, check for monster death, sl, begin variable(i) if(get hp(sl) <= 0) then( play sound(sfx:monstersplode) for(i, 0, small(50, slice width(sl) * slice height(sl) / 40)) do( if(random(1, 100) << 25) then( create coin(sl) )else( create death marker(sl) ) ) if(random(1,100) <= get max hp(sl)) then( create health potion(slice x(sl), slice y(sl)) ) set remove me(sl, true) ) end script, face, sl, sl2, begin set direction(sl, slice edge x(sl2, edge:center) -- slice edge x(sl, edge:center)) end script, face away, sl, sl2, begin set direction(sl, slice edge x(sl, edge:center) -- slice edge x(sl2, edge:center)) end script, leash monster, sl, pic, begin variable(mon) if(get held thing(sl)) then(exit script) mon := first child(active) while(mon) do( if(mon <> sl && slice collide(mon, sl)) then( if(get sprite set number(first child(mon)) == pic) then( if(get held by(mon) == 0) then( pick up thing(sl, mon) create chain between(sl, 5) break ) ) ) mon := next sibling(mon) ) end script, relinquish held thing, sl, begin variable(find) if(get held thing(sl) == 0) then(exit script) find := first child(active) while(find) do( if(find <> sl && slice collide(sl, find)) then( if(get can hold things(find)) then( boring drop thing(sl) exit script ) ) find := next sibling(find) ) end script, force of gravity, sl, begin if(get weightless(sl) == false && get climbing(sl) == false) then( push force y(sl, gravity force) ) end script, extra friction, sl, friction=1, begin variable(force, antifriction) antifriction := get antifriction(sl) if(antifriction >> 0) then( exit script ) force := get force x(sl) if(force >> 0) then(force -= friction, if(force << 0) then(force := 0)) if(force << 0) then(force += friction, if(force >> 0) then(force := 0)) set force x(sl, force) end script, force of friction, sl, begin variable(force, crouch, friction, antifriction) antifriction := get antifriction(sl) if(antifriction >> 0) then( set antifriction(sl, antifriction -- 1) exit script ) force := get force x(sl) friction := 1 crouch := get crouching(sl) if(crouch && abs(force) >= 4 && abs(force)) then( friction += 2 ) if(force >> 0) then(force -= friction, if(force << 0) then(force := 0)) if(force << 0) then(force += friction, if(force >> 0) then(force := 0)) set force x(sl, force) end script, apply force, sl, begin variable(fx, fy) if(can play sound(sl)) then( run sfx callback(sl) ) apply animation(sl) if(get immobile(sl)) then(exit script) fx := get force x(sl) fy := get force y(sl) set slice y(sl, slice y(sl) + fy) set slice x(sl, slice x(sl) + fx) if(fx <> 0) then(set last x move(sl, fx)) end script, apply animation, sl, begin run animation callback(sl) flash palette(sl, 0) if(being damaged(sl) || get flickering(sl)) then( flash palette(sl) )else( flash palette(sl, false) ) end script, flash palette, sl, value=1, begin if(value == 1) then(value := ticks, mod, 2) set sprite palette(first child(sl), get base palette(sl) + value) end script, pre check collisions, sl, begin run touch callback(sl) chain collision for held(sl) chain collision for holder(sl) end script, post check collisions, sl, begin if(get chain wall override(sl)) then( chain collision for held(sl, 2) ) end script, check collisions, sl, begin variable(i, first edge, second edge, fy) if(get ethereal(sl)) then(exit script) if(get standing on obstructable(sl)) then( set standing on obstructable(sl, false) set touching floor(sl, true) )else( set touching floor(sl, false) ) set touching ceiling(sl, false) head brick check(sl) fy := get force y(sl) if(fy << 0) then( if(get force x(sl) << 0 || get force y(sl) << 0) then(check point collision(sl, edge:left, edge:top)) if(get force x(sl) >> 0 || get force y(sl) << 0) then(check point collision(sl, edge:right, edge:top)) )else( if(get force x(sl) << 0 || get force y(sl) >> 0) then(check point collision(sl, edge:left, edge:bottom)) if(get force x(sl) >> 0 || get force y(sl) >> 0) then(check point collision(sl, edge:right, edge:bottom)) ) for(i, 20, slice height(sl) -- 1, 20) do( if(get force x(sl) << 0) then(check point collision(sl, edge:left, edge:top, 0, i)) if(get force x(sl) >> 0) then(check point collision(sl, edge:right, edge:top, 0, i)) ) for(i, 20, slice width(sl) -- 1, 20) do( if(get force y(sl) << 0) then(check point collision(sl, edge:left, edge:top, i, 0)) if(get force y(sl) >> 0) then(check point collision(sl, edge:left, edge:bottom, i, 0)) ) fy := get force y(sl) if(fy << 0) then( if(get force x(sl) << 0 || get force y(sl) >> 0) then(check point collision(sl, edge:left, edge:bottom)) if(get force x(sl) >> 0 || get force y(sl) >> 0) then(check point collision(sl, edge:right, edge:bottom)) )else( if(get force x(sl) << 0 || get force y(sl) << 0) then(check point collision(sl, edge:left, edge:top)) if(get force x(sl) >> 0 || get force y(sl) << 0) then(check point collision(sl, edge:right, edge:top)) ) if(get touching floor(sl)) then( force of friction(sl) ) end script, check point collision, sl, x edge, y edge, x off=0, y off=0, begin variable(i, x1, y1, x2, y2, tile1, tile2, map, checkmode, clipforce, safety, ladderstand) x1 := slice edge x(sl, x edge) + x off y1 := slice edge y(sl, y edge) + y off map := lookup slice(sl:map layer 1) safety := 0 for(checkmode, 0, 2) do( if(safety >> 12) then(break) while(true) do( if(safety >> 12) then(break) switch(checkmode) do( case(0) do( #vertical only x2 := x1 y2 := y1 + get force y(sl) ) case(1) do( #horizontal only x2 := x1 + get force x(sl) y2 := y1 ) case(2) do( #diagonal x2 := x1 + get force x(sl) y2 := y1 + get force y(sl) ) ) if(x1 / 20 == x2 / 20 && y1 / 20 == y2 / 20) then( break ) tile1 := read pass block(x1 / 20, y1 / 20) tile2 := read pass block(x2 / 20, y2 / 20) if(checkmode <> 1 && get force y(sl) >> 0) then( # down ladderstand := false if(checkmode == 0) then( ladderstand := ( (tile 2,and,vehicle A) && not(tile 1, and, vehicle A) && get climbing(sl) == false && get crouching(sl) == false ) ) if((tile 1,and,south wall) || (tile 2,and,north wall) || ladderstand || y2 >= slice height(map)) then( clipforce := (y1 + 20) / 20 * 20 -- y1 -- 1 set force y(sl, clipforce) if(y edge == edge:bottom) then( set touching floor(sl, true) set has doublejumped(sl, false) ) safety += 1 continue ) ) if(checkmode <> 1 && y edge == edge:top && (get force y(sl) << 0)) then( # up if((tile 1,and,north wall) || (tile 2,and,south wall) || y2 << 0) then( #clipforce := y1 -- y1 / 20 * 20 clipforce := y1 / 20 * 20 -- y1 set force y(sl, clipforce) if(y edge == edge:top) then(set touching ceiling(sl, true)) safety += 1 continue ) ) if(checkmode <> 0 && get force x(sl) << 0) then( # left if((tile 1,and,west wall) || (tile 2,and,east wall) || x2 << 0) then( clipforce := x1 / 20 * 20 -- x1 set force x(sl, clipforce) safety += 1 continue ) ) if(checkmode <> 0 && get force x(sl) >> 0) then( # right if((tile 1,and,east wall) || (tile 2,and,west wall) || x2 >= slice width(map)) then( clipforce := (x1 + 20) / 20 * 20 -- x1 -- 1 set force x(sl, clipforce) safety += 1 continue ) ) break ) if(i >= 100) then($0="Warning: broke out of endless loop in wall collisions", trace(0)) ) end script, chain collision for held, held, range multiplier=1, begin variable(holder, length) holder := get held by(held) if(holder) then( length := get chain length(held) * range multiplier length := get chain length(held) restrict by chain(holder, held, length, 40) ) end script, chain collision for holder, holder, begin variable(held, length, x1, y1, x2, y2) if(get immobile(holder)) then(exit script) held := get held thing(holder) if(held) then( length := large(get chain length(held), slice height(holder) / 2) restrict by chain(held, holder, length, 1) ) end script, restrict by chain, sl, sl2, length, repeat=1, begin variable(i, x1, y1, x2, y2, weightless) weightless := get weightless(sl) for(i, 1, repeat) do( x1 := slice edge x(sl, edge:center) + get force x(sl) y1 := slice edge y(sl, edge:center) + get force y(sl) x2 := slice edge x(sl2, edge:center) + get force x(sl2) y2 := slice edge y(sl2, edge:center) + get force y(sl2) if(within distance(x1, y1, x2, y2, length)) then( break ) if (x1 >> x2) then( set force x(sl2, get force x(sl2) + 1) if(weightless) then(set force x(sl, get force x(sl) -- 1)) ) if (x1 << x2) then( set force x(sl2, get force x(sl2) -- 1) if(weightless) then(set force x(sl, get force x(sl) + 1)) ) if (y1 >> y2) then( set force y(sl2, get force y(sl2) + 1) if(weightless) then(set force y(sl, get force y(sl) -- 1)) ) if (y1 << y2) then( set force y(sl2, get force y(sl2) -- 1) if(weightless) then(set force y(sl, get force y(sl) + 1)) ) ) end script, head brick check, sl, begin # up check on top edge to catch head-in-block after uncrouching if(get can crouch(sl) == false) then(exit script) variable(x, y, tile) x := slice edge x(sl, edge:center) y := slice edge y(sl, edge:top) + 1 tile := read pass block(x / 20, y / 20) if(tile,and,north wall+south wall+east wall+west wall) then( set touching ceiling(sl, true) set crouching(sl, true) ) end script, try to pick up bell, sl, begin variable(held, find, dropped) if(get can hold things(sl) == false) then(exit script) if(ticks -- second << get drop delay(sl)) then(exit script) held := get held thing(sl) if(held) then( #already holding something # look for chain links to insert find := first child(active) while(find) do( if(find <> sl && slice collide(find, sl)) then( if(get can be held(find) && get held by(find) == 0 && get is chain(find)) then( # found a chain that isn't being held # drop our previous thing dropped := drop thing(sl) # pick up the new chain link pickup thing(sl, find) # attach the old thing to the new link append thing(find, dropped) ) ) find := next sibling(find) ) )else( #not holding anything, find something find := first child(active) while(find) do( if(slice collide(find, sl)) then( if(get can be held(find) && get held by(find) == 0) then( # can be held and isn't already being held by something else pick up thing(sl, find) if(sl == player) then( # check if player picked up the bell if(get grandholder(bell) == sl) then( set tag(tag:touched bell, true) ) ) exit script ) ) find := next sibling(find) ) ) end script, pick up thing, holder, thing, begin if(thing == 0) then(exit script) set held thing(holder, thing) set held by(thing, holder) end script, append thing, holder, thing, begin if(thing == 0) then(exit script) variable(held) held := get held thing(holder) if(held) then(append thing(held, thing)) else(pick up thing(holder, thing)) end script, drop thing, holder, begin variable(thing) thing := get held thing(holder) if(thing == 0) then(exit returning(0)) set held thing(holder, 0) set held by(thing, 0) exit returning(thing) end script, drop me please, thing, begin if(get held by(thing)) then(drop thing(get held by(thing))) end script, apply crouching, sl, begin # This assumes hero-sized sprites! if (get can crouch(sl)) then( variable(old y, new y) old y := slice edge y(sl, edge:bottom) if(get crouching(sl)) then( set slice height(sl, 18) )else( set slice height(sl, 36) ) new y := slice edge y(sl, edge:bottom) set slice y(sl, slice y(sl) + (old y -- new y)) ) end script, apply climbing, sl, begin variable(fy, fx) if(get climbing(sl)) then( # check if we should stop climbing if(check for ladder(sl) == false || get touching floor(sl)) then( set climbing(sl, false) exit script ) fy := get force y(sl) fx := get force x(sl) # ladder friction if(fy) then( set force y(sl, fy -- sign(fy)) ) if(fx) then( set force x(sl, fx -- sign(fx)) ) ) end script, obstruction, sl, begin variable(obj) obj := first child(active) while(obj) do( if(obj <> sl) then( if(would collide y(sl, obj)) then( collide y with obstructable(sl, obj) ) if(would collide x(sl, obj)) then( collide x with obstructable(sl, obj) ) if(would collide(sl, obj)) then( collide with obstructable(sl, obj) ) ) obj := next sibling(obj) ) end script, would collide x, obstruct, sl, begin return(false) # try out x movement set slice x(sl, slice x(sl) + get force x(sl)) # check for collision if(slice collide(obstruct, sl)) then(return(true)) # roll back movement set slice x(sl, slice x(sl) -- get force x(sl)) end script, would collide y, obstruct, sl, begin return(false) # try out y movement set slice y(sl, slice y(sl) + get force y(sl)) # check for collision if(slice collide(obstruct, sl)) then(return(true)) # roll back movement set slice y(sl, slice y(sl) -- get force y(sl)) end script, would collide, obstruct, sl, begin return(false) # try out movement set slice x(sl, slice x(sl) + get force x(sl)) set slice y(sl, slice y(sl) + get force y(sl)) # check for collision if(slice collide(obstruct, sl)) then(return(true)) # roll back movement set slice x(sl, slice x(sl) -- get force x(sl)) set slice y(sl, slice y(sl) -- get force y(sl)) end script, collide x with obstructable, obstruct, sl, begin variable(f) f := get force x(sl) if(f >> 0) then( f := large(0, slice edge x(obstruct, edge:left) -- slice edge x(sl, edge:right) -- 1) ) if(f << 0) then( f := small(0, slice edge x(obstruct, edge:right) -- slice edge x(sl, edge:left) + 1) ) set force x(sl, f) end script, collide y with obstructable, obstruct, sl, begin variable(f) f := get force y(sl) if(f >> 0) then( f := large(0, slice edge y(obstruct, edge:top) -- slice edge y(sl, edge:bottom) -- 1) set standing on obstructable(sl, true) ) if(f << 0) then( f := small(0, slice edge y(obstruct, edge:bottom) -- slice edge y(sl, edge:top) + 1) ) set force y(sl, f) end script, collide with obstructable, obstruct, sl, begin collide y with obstructable(obstruct, sl) if(would collide x(obstruct, sl)) then( collide x with obstructable(obstruct, sl) ) end script, harmed by monsters, sl, begin variable(mon) mon := first child(active) while(mon) do( if(get is monster(mon)) then( if(sl <> mon && slice collide(sl, mon)) then( inflict damage(sl, mon) exit script ) ) mon := next sibling(mon) ) end script, harm monsters, sl, begin variable(mon) mon := first child(active) while(mon) do( if(get is monster(mon)) then( if(sl <> mon && slice collide(sl, mon)) then( inflict damage(mon, sl) exit script ) ) mon := next sibling(mon) ) end script, harmed by bell, sl, begin if(slice collide(sl, bell)) then( if(inflict velocity damage(sl, bell, false)) then( play sound(sfx:enemy_hurt) ) ) end script, being damaged, sl, begin if(ticks -- second / 2 >> get been damaged(sl)) then( exit returning(false) ) exit returning(true) end script, heal, sl, amount, begin set hp(sl, small(get max hp(sl), get hp(sl) + abs(amount))) create heal floater(sl, amount) if(sl == player) then(update hp meter) end script, inflict damage, sl, attacker, knock=true, begin variable(atk) if(not(being damaged(sl))) then( atk := get attack power(attacker) create damage floater(sl, atk) set hp(sl, get hp(sl) -- atk) set been damaged(sl, ticks) if(knock) then( knockback(sl, attacker) ) if(sl == player) then(update hp meter) ) end script, inflict velocity damage, sl, attacker, knock=true, begin variable(atk, vel) if(not(being damaged(sl))) then( vel := small(terminal velocity, abs(get force x(attacker)) + abs(get force y(attacker))) atk := (get attack power(attacker) * 100 / terminal velocity * vel + 50) / 100 if(atk >> 2) then( create damage floater(sl, atk) set hp(sl, get hp(sl) -- atk) set been damaged(sl, ticks) if(knock) then( knockback(sl, attacker) ) if(sl == player) then(update hp meter) exit returning(true) ) ) exit returning(false) end script, knockback, sl, sl2, begin if(get force y(sl2) << 0) then(push force y(sl, get force y(sl2))) push force x(sl, get force x(sl2)) push away from(sl, sl2, 4) end script, push away from, sl, sl2, amount, begin variable(d, diff) d := get direction(sl) * -1 diff := slice x(sl) -- slice x(sl2) if(diff << 0) then(d := -1) if(diff >> 0) then(d := 1) push force x(sl, amount * d) end script, create chain between, sl, link count, evaporate=true, begin variable(held, link, last, i) held := drop thing(sl) if(held == 0) then(exit script) last := sl for(i, 0, link count -- 1) do( link := create chain link(slice x(sl), slice y(sl), evaporate) set weightless(link, true) pick up thing(last, link) last := link ) pick up thing(last, held) end script, consume magic, sl, amount, begin #return true of consumed okay, return false if not enough variable(magic) magic := get magic(sl) if(magic << amount) then( flash magic meter play sound(sfx:spell fail) exit returning(false) ) magic -= amount set magic(sl, magic) if(sl == player) then(update magic meter) exit returning(true) end script, regen magic, sl, begin variable(t, magic) t := ticks, mod, second if(t == 0 || (t == 9 && get force x(sl) == 0)) then( # regen once a second when moving, twice a second when standing still magic := get magic(sl) if(magic << get max magic(sl)) then( magic += 1 set magic(sl, magic) if(sl == player) then(update magic meter) ) ) end #----------------------------------------------------------------------- # Animators script, hero animate, sl, begin variable(frame, spr, fx, fy, max, old set, new set, dmg, crouch, climb) spr := first child(sl) dmg := being damaged(sl) fx := get force x(sl) fy := get force y(sl) crouch := get crouching(sl) climb := get climbing(sl) if(not(dmg)) then( if(fx << 0) then(horiz flip sprite(spr, false)) if(fx >> 0) then(horiz flip sprite(spr, true)) ) if(climb) then( if(sl == player) then( if(fx == 0 && fy == 0) then( frame := 0 )else( frame := get sprite frame(spr) frame := (frame + (ticks,mod,2)), mod, 3 ) set sprite frame(spr, frame) ) )else( if(get touching floor(sl)) then( if(fx == 0) then( #standing still set sprite frame(spr, 0) )else( if(crouch) then( max := get walk max(sl) if(fx * 3 << max && fx * 3 >> max * -1) then( #crawling set sprite frame(spr, (ticks/2,mod,2)) )else( #sliding set sprite frame(spr, 2) ) )else( #3 frame walking cycle frame := get sprite frame(spr) frame := (frame + (ticks,mod,2)), mod, 3 set sprite frame(spr, frame) ) ) if(get special(sl) >> key timeout / 3 * 2) then( set sprite frame(spr, 6) ) )else( #jumping if(fy >> 0) then( #falling set sprite frame(spr, 4) )else( #rising set sprite frame(spr, 3) ) ) ) if(dmg) then( set sprite frame(spr, 5) ) old set := get sprite set number(spr) if(crouch) then( new set := get crouch frames(sl) )else( if(climb) then( # Only supports player right now! new set := 2 )else( new set := get normal frames(sl) ) ) if(old set <> new set) then(replace hero sprite(spr, new set)) end script, flyer animate, sl, begin variable(frame, spr, fx, fy, max, old set, new set, dmg) spr := first child(sl) dmg := being damaged(sl) fx := get force x(sl) fy := get force y(sl) if(not(dmg)) then( if(fx << 0) then(horiz flip sprite(spr, false)) if(fx >> 0) then(horiz flip sprite(spr, true)) ) #3 frame walking cycle frame := get sprite frame(spr) frame := (frame + (ticks,mod,2)), mod, 3 set sprite frame(spr, frame) if(dmg) then( set sprite frame(spr, 5) ) end script, bell animate, sl, begin variable(frame, spr, fx, fy) spr := first child(sl) fx := get force x(sl) fy := get force y(sl) if(fx << 0) then(horiz flip sprite(spr, false)) if(fx >> 0) then(horiz flip sprite(spr, true)) if(get touching floor(sl)) then( if(fx == 0) then( #standing still set sprite frame(spr, 0) )else( #3 frame walking cycle frame := get sprite frame(spr) frame := (frame + (ticks,mod,2)), mod, 3 set sprite frame(spr, frame) ) )else( #in the air while(true) do( if(fy << 0 && abs(fx) * 2 << abs(fy)) then( #vert up set sprite frame(spr, 5) break ) if(fy >> 0 && abs(fx) * 2 << abs(fy)) then( #vert down set sprite frame(spr, 7) break ) if(abs(fx) >> 0 && abs(fy) * 2 << abs(fx)) then( #sideways set sprite frame(spr, 3) break ) if(fy << 0) then( # diag down set sprite frame(spr, 4) break ) if(fy >> 0) then( #diag up set sprite frame(spr, 6) break ) if(fx == 0 && fy == 0) then( # dangle set sprite frame(spr, 5) ) break ) ) end script, magic spark animate, sl, begin variable(spr, fr) if(ticks, mod, 2 == 0) then( spr := first child(sl) fr := get sprite frame(spr) fr += 1 if(fr >= 8) then( set remove me(sl, true) )else( set sprite frame(spr, fr) ) ) end script, reward animate, sl, begin variable(spr) spr := first child(sl) set sprite frame(spr, (ticks, mod, 2)) end script, swordsman animate, sl, begin variable(frame, spr, fx, fy, dmg, val) spr := first child(sl) dmg := being damaged(sl) fx := get force x(sl) fy := get force y(sl) if(not(dmg)) then( if(fx << 0) then(horiz flip sprite(spr, false)) if(fx >> 0) then(horiz flip sprite(spr, true)) ) if(get touching floor(sl)) then( if(fx == 0) then( #standing still set sprite frame(spr, 0) )else( #3 frame walking cycle frame := get sprite frame(spr) frame := (frame + (ticks,mod,2)), mod, 3 set sprite frame(spr, frame) ) ) val := get memory val(sl) if(val >> 1) then( if(val >> 9) then( set sprite frame(spr, 4) )else( set sprite frame(spr, 3) ) ) if(dmg) then( set sprite frame(spr, 5) ) end script, trapper vine animate, sl, begin variable(spr) spr := first child(sl) set sprite frame(spr, abs((ticks, mod, 4) -- 1)) end script, giant animate, sl, begin variable(spr, set, fx, base, offset) spr := first child(sl) base := get normal frames(sl) set := get sprite set number(spr) fx := get force x(sl) if(fx == 0) then( offset := 0 )else( offset := abs(((ticks / 2), mod, 4) -- 1) ) if(get local timer(sl) >> 0) then( offset := 3 ) if(being damaged(sl)) then( offset := 5 ) if(base + offset <> set) then( replace large enemy sprite(spr, base + offset) ) end #----------------------------------------------------------------------- # Sound script, can play sound, sl, begin if(ticks >> get last sound time(sl)) then( exit returning(true) ) exit returning(false) end script, play sound for, sl, sfx id, mute ticks, begin set last sound time(sl, ticks + mute ticks) play sound(sfx id) end script, bell sfx, sl, begin # plays sounds on velocity changes variable(oldv, newv, diff) oldv := get memory val(sl) newv := abs(get force x(sl)) + abs(get force y(sl)) diff := abs(oldv -- newv) if(diff >> 16) then(play sound for(sl, random(0,4), 3)) set memory val(sl, newv) end #----------------------------------------------------------------------- # Constructors script, always, x, y, begin exit returning(true) end script, respawn far away, x, y, begin exit returning(slice collide point(sleeper, x -- camera pixel x, y -- camera pixel y) == false) end script, create map things, condition callback, begin create in := dormant variable(sl, ref, x, y, id) convert NPC pictures for (ref, -399, -1), do( if(get NPC id(ref) >= 0) then( if(npc extra(ref, extra 1) == true) then(continue) x := NPC pixel X(ref) + 10 y := NPC pixel Y(ref) + 19 id := npc extra(ref, extra 0) if(run script by id(condition callback, x, y) == false) then(continue) switch(id) do( case(1) do(sl := create chain holder(x, y)) case(2) do(sl := create lion beast(x, y)) case(4) do(sl := create beard bird(x, y)) case(5) do(sl := create player(x, y)) case(6) do(sl := create bell(x, y)) case(7) do(sl := create peon(x, y)) case(8) do(sl := create jackal(x, y)) case(9) do(sl := create health potion(x, y)) case(10) do(sl := create heavy swordsman(x, y)) case(11) do(sl := create trapper vine(x, y)) case(12) do(sl := create event zone(x, y, NPC direction(ref), read NPC(ref, NPCStat:display text))) case(14) do(sl := create ishtar angel(x, y, read NPC(ref, NPCStat:display text))) case(15) do(sl := create bell icon(x, y)) case(18) do(sl := create red bull(x, y)) case(19) do(sl := create owl pillar(x, y)) case(20) do(sl := create giant magi(x, y)) case(22) do(sl := create ice block(x, y)) else( $0="Unknown NPC picture " append number(0, read NPC(ref, npcstat:picture)) trace(0) ) ) set npc extra(ref, extra 1, true) if(sl) then( if(NPC direction(ref) == right) then(horiz flip sprite(first child(sl), true)) if(get can respawn(sl)) then( set creator ref(sl, ref) )else( destroy NPC(ref) ) )else( $0="No slice returned for ref " append number(0, ref) trace(0) ) ) ) create in := active end script, convert NPC pictures, begin variable(ref, pic) for (ref, -399, -1), do( if(get NPC id(ref) >= 0) then( pic := read NPC(ref, npcstat:picture) if(pic) then( #copy picture to extra 0 set NPC extra(ref, extra 0, pic) ) ) ) for (ref, -399, -1), do( if(get NPC id(ref) >= 0) then( # clear picture alter NPC(ref, npcstat:picture, 0) ) ) end define constant(0, thing:hero) define constant(1, thing:walkabout) define constant(2, thing:weapon) define constant(3, thing:med enemy) define constant(4, thing:large enemy) script, create thing, x, y, w, h, pic, pal=-1, type=thing:hero, begin variable(sl, spr, data, data2, data3) sl := create container(w, h) #sl := create rect(w, h, -1), set rect bg col(sl, 1) set parent(sl, create in) set slice edge x(sl, edge:center, x) set slice edge y(sl, edge:bottom, y) switch(type) do( case(thing:hero) do(spr := load hero sprite(pic, pal)) case(thing:walkabout) do(spr := load walkabout sprite(pic, pal)) case(thing:weapon) do(spr := load weapon sprite(pic, pal)) case(thing:med enemy) do(spr := load medium enemy sprite(pic, pal)) case(thing:large enemy) do(spr := load large enemy sprite(pic, pal)) ) set parent(spr, sl) set horiz anchor(spr, edge:center) set vert anchor(spr, edge:bottom) set horiz align(spr, edge:center) set vert align(spr, edge:bottom) data := create container(0,0) set slice visible(data, false) set parent(data, sl) data2 := create container(0,0) set parent(data2, data) data3 := create container(0,0) set parent(data3, data) set normal frames(sl, pic) set base palette(sl, pal) exit returning(sl) end script, create player, x, y, begin if(player <> 0) then(exit script) variable(sl, spr) sl := create thing(x, y, 18, 36, 0, 1) set crouch frames(sl, 1) set update callback(sl, @player update) set animation callback(sl, @hero animate) #set action callback(sl, @) set touch callback(sl, @harmed by monsters) set walk max(sl, 8) set can crouch(sl, true) set can hold things(sl, true) set max hp(sl, 100) set hp(sl, 100) set max magic(sl, 100) set magic(sl, 100) set important(sl, true) # uses local timer for death animation player := sl exit returning(sl) end script, create bell, x, y, begin if(bell <> 0) then(exit script) variable(sl, i, link, last) sl := create thing(x, y, 28, 19, 3) set update callback(sl, @dumb weight update) set animation callback(sl, @bell animate) set sfx callback(sl, @bell sfx) set can be held(sl, true) set chain length(sl, 10) set chain wall override(sl, true) set attack power(sl, 10) # bell uses memory val for velocity records for sfx set memory val(sl, 0) set important(sl, true) last := sl for(i, 0, 6) do( link := create chain link(x, y) set important(link, true) pick up thing(link, last) last := link ) move slice above(sl, last) set force x(sl, -2) bell := sl exit returning(sl) end script, create chain link, x, y, evaporate=false, begin variable(sl, spr) sl := create thing(x, y, 10, 10, 4, 10) if(evaporate) then( set update callback(sl, @evaporating chain update) )else( set update callback(sl, @dumb weight update) ) set animation callback(sl, @bell animate) set can be held(sl, true) set is chain(sl, true) set chain length(sl, 8) set chain wall override(sl, true) exit returning(sl) end script, create magic chain link, x, y, t, begin variable(sl) sl := create chain link(x, y) set update callback(sl, @magic chain update) set flickering(sl, true) set local timer(sl, t) # used for lifetime exit returning(sl) end script, create chain holder, x, y, begin variable(sl) sl := create thing(x, y, 20, 20, 1, -1, thing:walkabout) set update callback(sl, @chain holder update) set can hold things(sl, true) set chain length(sl, 10) set immobile(sl, true) exit returning(sl) end script, create bell icon, x, y, begin variable(sl) sl := create thing(x, y, 16, 16, 1, -1, thing:weapon) set update callback(sl, @bell icon update) set animation callback(sl, @reward animate) set immobile(sl, true) exit returning(sl) end script, create long chain, begin variable(i, sl, holder) for(i, 0, 19) do( holder := get held by(bell) sl := create magic chain link( slice edge x(holder, edge:center), slice edge y(holder, edge:center), second * i * 3 / 2 #1.5 seconds per link ) drop me please(bell) pick up thing(holder, sl) pick up thing(sl, bell) ) # try to make player immediately re-grab chain holder := get grandholder(bell) if(holder <> player) then( if(slice collide(player, holder)) then( pick up thing(player, holder) push force x(bell, get direction(player) * 5) ) ) end script, create event zone, x, y, d, box, begin variable(w, h, sl) switch(d) do( case(0) do(w := 20, h := 20) case(1) do( w := 320 h := 20 x := x / 320 * 320 + 160 ) case(2) do( w := 20 h := 200 y := y / 200 * 200 + 100 ) ) sl := create thing(x, y, w, h, 0, -1, thing:walkabout) set update callback(sl, @text box zone update) set text box(sl, box) exit returning(sl) end script, create ishtar angel, x, y, box, begin variable(sl, spr) sl := create thing(x, y, 18, 28, 11, 26) set update callback(sl, @ishtar angel ai) set animation callback(sl, @hero animate) set walk max(sl, 2) set flickering(sl, true) set text box(sl, box) #ishtar angel uses memory val for ai state set memory val(sl, 0) exit returning(sl) end script, create offering, who, begin variable(sl) sl := create thing(slice edge x(who, edge:center), slice edge y(who, edge:center), 8, 8, 3, 41, thing:weapon) set update callback(sl, @offering ai) set memory val(sl, who) # memory val keeps ref to who we are healing set local timer(sl, second / 2) # used to time healings set ethereal(sl, true) set important(sl, true) set flickering(sl, true) exit returning(sl) end script, create coin, who, begin variable(sl, h, w) h := slice width(who) / 3 w := slice height(who) / 3 sl := create thing(slice edge x(who, edge:center) + random(w*-1, w), slice edge y(who, edge:center) + random(h*-1, h), 7, 7, 2, 39, thing:weapon) set update callback(sl, @coin update) set force x(sl, get force x(who)) set force y(sl, get force y(who)) push force y(sl, random(-10, -2)) push force x(sl, random(-5, 5)) set flickering(sl, true) # uses memory val for sfx flag # uses local timer for vanishing exit returning(sl) end script, create offering coin, begin variable(sl) sl := create coin(player) set update callback(sl, @offering coin update) end script, create death marker, who, begin variable(sl, h, w) h := slice width(who) / 3 w := slice height(who) / 3 sl := create thing(slice edge x(who, edge:center) + random(w*-1, w), slice edge y(who, edge:center) + random(h*-1, h), 8, 8, 3, -1, thing:walkabout) set update callback(sl, @death marker update) set force x(sl, get force x(who)) set force y(sl, get force y(who)) push force y(sl, random(-10, -2)) push force x(sl, random(-5, 5)) exit returning(sl) end script, create magic spark, who, begin variable(sl, max) sl := create thing(slice edge x(who, edge:center), slice edge y(who, edge:center), 8, 8, 13, -1, thing:walkabout) set animation callback(sl, @magic spark animate) max := large(4, get walk max(sl)) set force x(sl, get force x(who) + random(max * -1, max)) set force y(sl, get force y(who) + random(max * -1, max)) set ethereal(sl, true) exit returning(sl) end script, create vertical spark, who, begin variable(sl, w, h) w := slice width(who) h := slice height(who) sl := create thing(slice x(who) + random(0, w), slice y(who) + random(0, h), 3, 9, 17, 30, thing:walkabout) set animation callback(sl, @magic spark animate) push force y(sl, 2) set ethereal(sl, true) exit returning(sl) end script, create flame, who, begin variable(sl, w, h) w := slice width(who) + 6 h := slice height(who) + 6 sl := create thing(slice x(who) + random(0, w), slice y(who) + random(0, h), 6, 9, 16, 28, thing:walkabout) set animation callback(sl, @magic spark animate) set touch callback(sl, @harm monsters) push force y(sl, -2) push force x(sl, random(-2, 2)) set ethereal(sl, true) set flickering(sl, true) set attack power(sl, 18) set melt ice(sl, true) exit returning(sl) end script, create shock spell, x, y, begin variable(sl, max) sl := create thing(x, y, 14, 14, 21, 35, thing:walkabout) set animation callback(sl, @magic spark animate) set update callback(sl, @shock spell ai) set is monster(sl, true) set attack power(sl, 15) set flickering(sl, true) exit returning(sl) end script, create health potion, x, y, begin variable(sl) sl := create thing(x, y, 8, 8, 0, -1, thing:weapon) set update callback(sl, @health potion update) set animation callback(sl, @reward animate) set attack power(sl, -10) exit returning(sl) end script, create damage floater, where, n, begin if(check tag(tag:show damage) == on) then(create number floater(where, n)) end script, create heal floater, where, n, begin $0="+" create number floater(where, abs(n) * -1, true, 10) end script, create money floater, where, n, begin $0="$" create number floater(where, n, true, 14) end script, create number floater, where, n, prefixed=false, color=false, begin variable(sl, text) sl := create thing(slice x(where), slice y(where), 0, 0, 0, -1, thing:walkabout) text := create text if(prefixed == false) then( $0="" ) if(color) then( set text color(text, color) ) append number(0, abs(n)) set slice text(text, 0) set outline(text, true) set horiz align(text, edge:center) set vert align(text, edge:center) set horiz anchor(text, edge:center) set vert anchor(text, edge:center) set parent(text, first child(sl)) set update callback(sl, @text floater update) # text floater uses memory val for lifetime timer set memory val(sl, ticks) exit returning(sl) end script, create lion beast, x, y, begin variable(sl, spr) sl := create thing(x, y, 20, 20, monster:lion beast, 12) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @lion beast ai) set animation callback(sl, @hero animate) set touch callback(sl, @harmed by bell) set walk max(sl, 3) set chain length(sl, 12) set max hp(sl, 28) set hp(sl, 28) set attack power(sl, 10) exit returning(sl) end script, create beard bird, x, y, begin variable(sl, spr) sl := create thing(x, y, 20, 24, 6, 14) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @beard bird ai) set animation callback(sl, @flyer animate) set touch callback(sl, @harmed by bell) set walk max(sl, 3) set max hp(sl, 10) set hp(sl, 10) set attack power(sl, 10) # beard bird uses memory val for y direction set memory val(sl, 0) exit returning(sl) end script, create peon, x, y, begin variable(sl, spr) sl := create thing(x, y, 18, 28, 7, 16) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @peon ai) set animation callback(sl, @hero animate) set touch callback(sl, @harmed by bell) set walk max(sl, 2) set max hp(sl, 20) set hp(sl, 20) set attack power(sl, 5) exit returning(sl) end script, create jackal, x, y, begin variable(sl, spr) sl := create thing(x, y, 18, 28, 8, 18) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @jackal ai) set animation callback(sl, @hero animate) set touch callback(sl, @harmed by bell) set walk max(sl, 2) set max hp(sl, 30) set hp(sl, 30) set attack power(sl, 10) exit returning(sl) end script, create heavy swordsman, x, y, begin variable(sl, spr) sl := create thing(x, y, 18, 32, 9, 20) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @heavy swordsman ai) set animation callback(sl, @swordsman animate) set touch callback(sl, @harmed by bell) set walk max(sl, 2) set max hp(sl, 30) set hp(sl, 30) set attack power(sl, 10) # heavy swordsman uses memory val for attack timer set memory val(sl, 0) exit returning(sl) end script, create sword slash, x, y, begin variable(sl, spr) sl := create thing(x, y, 48, 40, 0, -1, thing:med enemy) set update callback(sl, @sword slash ai) set is monster(sl, true) set attack power(sl, 15) # sword slash uses memory val for lifetime timer set memory val(sl, 0) exit returning(sl) end script, create owl pillar, x, y, begin variable(sl, spr) sl := create thing(x, y, 18, 50, 1, -1, thing:med enemy) set update callback(sl, @owl pillar ai) set is monster(sl, true) set attack power(sl, 50) set walk max(sl, 2) # owl pillar uses memory val for vertical direction set memory val(sl, 1) exit returning(sl) end script, create trapper vine, x, y, begin variable(sl, i, link, last) sl := create thing(x, y, 18, 18, 10, 24, thing:hero) set update callback(sl, @trapper vine ai) set animation callback(sl, @trapper vine animate) set touch callback(sl, @harmed by bell) set chain length(sl, 10) set attack power(sl, 10) set walk max(sl, 5) set max hp(sl, 15) set hp(sl, 15) set is monster(sl, true) set can respawn(sl, true) last := sl for(i, 0, 5) do( link := create chain link(x, y, true) set weightless(link, true) set is chain(link, false) set can be held(link, false) set can hold things(link, false) replace walkabout sprite(first child(link), 11) pick up thing(link, last) last := link ) #set immobile(last, true) set weightless(last, false) set update callback(last, @vine root ai) exit returning(sl) end script, create red bull, x, y, begin variable(sl, spr) sl := create thing(x, y, 68, 43, 0, 22, thing:large enemy) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @red bull ai) set animation callback(sl, @giant animate) set touch callback(sl, @harmed by bell) set walk max(sl, 2) set max hp(sl, 80) set hp(sl, 80) set attack power(sl, 10) exit returning(sl) end script, create giant magi, x, y, begin variable(sl, spr) sl := create thing(x, y, 19, 77, 6, 32, thing:large enemy) set is monster(sl, true) set can respawn(sl, true) set update callback(sl, @giant magi ai) set animation callback(sl, @giant animate) set touch callback(sl, @harmed by bell) set walk max(sl, 2) set max hp(sl, 90) set hp(sl, 90) set attack power(sl, 10) exit returning(sl) end script, create ice block, x, y, begin variable(sl, spr) sl := create thing(x, y, 38, 38, 2, 43, thing:med enemy) set slice x(sl, slice x(sl) + 10) # tile align set can respawn(sl, true) set update callback(sl, @ice block update) set touch callback(sl, @obstruction) exit returning(sl) end script, create ice fragment, who, begin variable(sl, spr) sl := create death marker(who) spr := first child(sl) replace walkabout sprite(spr, 22) set sprite palette(spr, 43) set animation callback(sl, @magic spark animate) set update callback(sl, @dumb weight update) exit returning(sl) end #----------------------------------------------------------------------- # Info display script, create hp meter, begin variable(holder, meter) holder := create rect(50, 6, 0) set horiz align(holder, edge:right) set horiz anchor(holder, edge:right) set slice x(holder, -5) set slice y(holder, 5) set padding(holder, 1) meter := create rect(0, 4, -1) set rect bg col(meter, 10) set parent(meter, holder) hp meter := meter update hp meter end script, update hp meter, begin variable(hp, max, holder) hp := get hp(player) max := get max hp(player) holder := parent slice(hp meter) set slice width(hp meter, slice width(holder) * 100 / large(1, max) * hp / 100) update hud text end script, create magic meter, begin variable(holder, meter) holder := create rect(50, 6, 0) set horiz align(holder, edge:right) set horiz anchor(holder, edge:right) set slice x(holder, -64) set slice y(holder, 5) set padding(holder, 1) meter := create rect(0, 4, -1) set rect bg col(meter, 9) set parent(meter, holder) magic meter := meter update magic meter end script, update magic meter, begin variable(magic, max, holder) magic := get magic(player) max := get max magic(player) holder := parent slice(magic meter) set slice width(magic meter, slice width(holder) * 100 / large(1, max) * magic / 100) update hud text end script, flash magic meter, begin set rect bg col(magic meter, 1) set rect bg col(parent slice(magic meter), 4) magic meter needs fixing := true end script, fix magic meter, begin set rect bg col(magic meter, 9) set rect bg col(parent slice(magic meter), 0) end script, update hud text, begin if(gold text == 0) then( gold text := create text set text color(gold text, 14) set outline(gold text, true) ) $0="$" append number(0, party money) set slice text(gold text, 0) end script, update meters, begin update hp meter update magic meter update hud text end #----------------------------------------------------------------------- # Data access script, set update callback, sl, cb, begin set slice extra(sl, extra 0, cb) end script, run update callback, sl, begin variable(cb) cb := get slice extra(sl) if(cb) then( run script by id(cb, sl) ) end script, push force y, sl, change, begin set force y(sl, get force y(sl) + change) end script, set force y, sl, value, begin variable(tv) tv := terminal velocity value := bounds(value, tv*-1, tv) set slice extra(sl, extra 1, value) end script, get force y, sl, begin exit returning(get slice extra(sl, extra 1)) end script, push force x, sl, change, begin set force x(sl, get force x(sl) + change) end script, set force x, sl, value, begin variable(tv) tv := terminal velocity value := bounds(value, tv*-1, tv) set slice extra(sl, extra 2, value) end script, get force x, sl, begin exit returning(get slice extra(sl, extra 2)) end script, get direction, sl, begin exit returning(sprite is horiz flipped(first child(sl)) * 2 -- 1) end script, set direction, sl, value, begin if(value == 0) then(exit script) horiz flip sprite(first child(sl), value >> 0) end script, get walk max, sl, begin exit returning(get slice extra(first child(sl), extra 1)) end script, set walk max, sl, value, begin set slice extra(first child(sl), extra 1, value) end script, get normal frames, sl, begin exit returning(get slice extra(first child(sl), extra 2)) end script, set normal frames, sl, value, begin set slice extra(first child(sl), extra 2, value) end script, get crouch frames, sl, begin exit returning(get slice extra(next sibling(first child(sl)), extra 0)) end script, set crouch frames, sl, value, begin set slice extra(next sibling(first child(sl)), extra 0, value) end script, run action callback, sl, begin variable(cb) cb := get slice extra(next sibling(first child(sl)), extra 1) if(cb) then(run script by id(cb, sl)) end script, set action callback, sl, value, begin set slice extra(next sibling(first child(sl)), extra 1, value) end script, get held thing, sl, begin exit returning(get slice extra(next sibling(first child(sl)), extra 2)) end script, set held thing, sl, value, begin set slice extra(next sibling(first child(sl)), extra 2, value) end script, run animation callback, sl, begin variable(cb) cb := get top padding(next sibling(first child(sl))) if(cb) then(run script by id(cb, sl)) end script, set animation callback, sl, value, begin set top padding(next sibling(first child(sl)), value) end script, get chain length, sl, begin exit returning(get right padding(next sibling(first child(sl)))) end script, set chain length, sl, value, begin set right padding(next sibling(first child(sl)), value) end script, get held by, sl, begin exit returning(get bottom padding(next sibling(first child(sl)))) end script, set held by, sl, value, begin set bottom padding(next sibling(first child(sl)), value) end script, get drop delay, sl, begin exit returning(get left padding(next sibling(first child(sl)))) end script, set drop delay, sl, value, begin set left padding(next sibling(first child(sl)), value) end script, get antifriction, sl, begin exit returning(slice x(next sibling(first child(sl)))) end script, set antifriction, sl, value, begin set slice x(next sibling(first child(sl)), value) end script, get hp, sl, begin exit returning(slice y(next sibling(first child(sl)))) end script, set hp, sl, value, begin set slice y(next sibling(first child(sl)), value) end script, run touch callback, sl, begin variable(cb) cb := slice width(next sibling(first child(sl))) if(cb) then(run script by id(cb, sl)) end script, set touch callback, sl, value, begin set slice width(next sibling(first child(sl)), value) end script, get attack power, sl, begin exit returning(slice height(next sibling(first child(sl)))) end script, set attack power, sl, value, begin set slice height(next sibling(first child(sl)), value) end script, get been damaged, sl, begin exit returning(get slice extra(first child(next sibling(first child(sl))), extra 0)) end script, set been damaged, sl, value, begin set slice extra(first child(next sibling(first child(sl))), extra 0, value) end script, get base palette, sl, begin exit returning(get slice extra(first child(next sibling(first child(sl))), extra 1)) end script, set base palette, sl, value, begin set slice extra(first child(next sibling(first child(sl))), extra 1, value) end script, run sfx callback, sl, begin variable(cb) cb := get slice extra(first child(next sibling(first child(sl))), extra 2) if(cb) then(run script by id(cb, sl)) end script, set sfx callback, sl, value, begin set slice extra(first child(next sibling(first child(sl))), extra 2, value) end script, get last sound time, sl, begin exit returning(get top padding(first child(next sibling(first child(sl))))) end script, set last sound time, sl, value, begin set top padding(first child(next sibling(first child(sl))), value) end script, get memory val, sl, begin exit returning(get right padding(first child(next sibling(first child(sl))))) end script, set memory val, sl, value, begin set right padding(first child(next sibling(first child(sl))), value) end script, get max hp, sl, begin exit returning(get bottom padding(first child(next sibling(first child(sl))))) end script, set max hp, sl, value, begin set bottom padding(first child(next sibling(first child(sl))), value) end script, get text box, sl, begin exit returning(get left padding(first child(next sibling(first child(sl))))) end script, set text box, sl, value, begin set left padding(first child(next sibling(first child(sl))), value) end script, get local timer, sl, begin exit returning(slice x(first child(next sibling(first child(sl))))) end script, set local timer, sl, value, begin set slice x(first child(next sibling(first child(sl))), value) end script, get creator ref, sl, begin exit returning(slice y(first child(next sibling(first child(sl))))) end script, set creator ref, sl, value, begin set slice y(first child(next sibling(first child(sl))), value) end script, get magic, sl, begin exit returning(get slice extra(next sibling(first child(next sibling(first child(sl)))), extra 0)) end script, set magic, sl, value, begin set slice extra(next sibling(first child(next sibling(first child(sl)))), extra 0, value) end script, get max magic, sl, begin exit returning(get slice extra(next sibling(first child(next sibling(first child(sl)))), extra 1)) end script, set max magic, sl, value, begin set slice extra(next sibling(first child(next sibling(first child(sl)))), extra 1, value) end script, get last x move, sl, begin exit returning(get slice extra(next sibling(first child(next sibling(first child(sl)))), extra 2)) end script, set last x move, sl, value, begin set slice extra(next sibling(first child(next sibling(first child(sl)))), extra 2, value) end # special is in ticks, and means: ## for the goddess, manipulating the bell's chain with her hand script, get special, sl, begin exit returning(get top padding(next sibling(first child(next sibling(first child(sl)))))) end script, set special, sl, value, begin set top padding(next sibling(first child(next sibling(first child(sl)))), value) end script, advance special, sl, begin variable(special) special := get special(sl) if(special >> 0) then( set special(sl, special -- 1) ) end #----------------------------------------------------------------------- # Slice extra as bits script, get exbit, sl, bit, begin variable(meta, n) meta := first child(sl) n := get slice extra(meta, extra 0) if(n,and,2^bit) then(exit returning(true)) exit returning(false) end script, set exbit, sl, bit, value=1, begin variable(meta, n) meta := first child(sl) n := get slice extra(meta, extra 0) if(value) then(n := n, or, 2^bit) else(n := n, and, (-1, xor, 2^bit)) set slice extra(meta, extra 0, n) end script, get touching floor, sl, begin exit returning(get exbit(sl, 0)) end script, set touching floor, sl, value, begin set exbit(sl, 0, value) end script, get touching ceiling, sl, begin exit returning(get exbit(sl, 1)) end script, set touching ceiling, sl, value, begin set exbit(sl, 1, value) end script, get crouching, sl, begin exit returning(get exbit(sl, 2)) end script, set crouching, sl, value, begin set exbit(sl, 2, value) end script, get can crouch, sl, begin exit returning(get exbit(sl, 3)) end script, set can crouch, sl, value, begin set exbit(sl, 3, value) end script, get can hold things, sl, begin exit returning(get exbit(sl, 4)) end script, set can hold things, sl, value, begin set exbit(sl, 4, value) end script, get can be held, sl, begin exit returning(get exbit(sl, 5)) end script, set can be held, sl, value, begin set exbit(sl, 5, value) end script, get is chain, sl, begin exit returning(get exbit(sl, 6)) end script, set is chain, sl, value, begin set exbit(sl, 6, value) end script, get immobile, sl, begin exit returning(get exbit(sl, 7)) end script, set immobile, sl, value, begin set exbit(sl, 7, value) end #script, get ?, sl, begin # exit returning(get exbit(sl, 8)) #end # #script, set ?, sl, value, begin # set exbit(sl, 8, value) #end script, get is monster, sl, begin exit returning(get exbit(sl, 9)) end script, set is monster, sl, value, begin set exbit(sl, 9, value) end script, get remove me, sl, begin exit returning(get exbit(sl, 10)) end script, set remove me, sl, value, begin set exbit(sl, 10, value) end script, get using action, sl, begin exit returning(get exbit(sl, 11)) end script, set using action, sl, value, begin set exbit(sl, 11, value) end script, get chain wall override, sl, begin exit returning(get exbit(sl, 12)) end script, set chain wall override, sl, value, begin set exbit(sl, 12, value) end script, get weightless, sl, begin exit returning(get exbit(sl, 13)) end script, set weightless, sl, value, begin set exbit(sl, 13, value) end script, get climbing, sl, begin exit returning(get exbit(sl, 14)) end script, set climbing, sl, value, begin set exbit(sl, 14, value) end script, get important, sl, begin exit returning(get exbit(sl, 15)) end script, set important, sl, value, begin set exbit(sl, 15, value) end script, get ethereal, sl, begin exit returning(get exbit(sl, 16)) end script, set ethereal, sl, value, begin set exbit(sl, 16, value) end script, get flickering, sl, begin exit returning(get exbit(sl, 17)) end script, set flickering, sl, value, begin set exbit(sl, 17, value) end script, get has doublejumped, sl, begin exit returning(get exbit(sl, 18)) end script, set has doublejumped, sl, value, begin set exbit(sl, 18, value) end script, get can respawn, sl, begin exit returning(get exbit(sl, 19)) end script, set can respawn, sl, value, begin set exbit(sl, 19, value) end script, get standing on obstructable, sl, begin exit returning(get exbit(sl, 20)) end script, set standing on obstructable, sl, value, begin set exbit(sl, 20, value) end script, get melt ice, sl, begin exit returning(get exbit(sl, 20)) end script, set melt ice, sl, value, begin set exbit(sl, 20, value) end #----------------------------------------------------------------------- # Utility script, small, v1, v2, begin if(v1 >> v2) then(exit returning(v2)) exit returning(v1) end script, large, v1, v2, begin if(v1 << v2) then(exit returning(v2)) exit returning(v1) end script, bounds, value, min, max, begin if(value << min) then(exit returning(min)) if(value >> max) then(exit returning(max)) exit returning(value) end script, within distance, x1, y1, x2, y2, dist, begin variable(a, b, c sq) a := x1 -- x2 b := y1 -- y2 c sq := abs(a)^2 + abs(b)^2 exit returning(c sq << dist^2) end script, wait for text box wrapper, begin suspend box advance wait(7) while(current text box >= 0) do( if(pushing action || pushing jump || pushing menu) then( advance text box wait(7) ) wait(1) ) resume box advance play sound(sfx:text box blip) end #-----------------------------------------------------------------------