-- Necklace of the Eye v5.0 roguelike frontend -- Copyright (C) 2010-2012 Zeno Rogue, see COPYING for details -- ?? and better dark blue, because it was too dark function hydrapalette() vgaset(1, 0x10F52BA) vgaset(2, 0x23C965A) vgaset(3, 0x3188484) vgaset(4, 0x4841B2D) vgaset(5, 0x5664488) vgaset(6, 0x6964B00) vgaset(7, 0x78C8C8C) vgaset(8, 0x851484F) vgaset(9, 0x971A6D2) vgaset(10, 0xA32CD32) vgaset(11, 0xB7FFFD4) --vgaset(12, 0xCE25822) vgaset(13, 0xDE164D1) vgaset(14, 0xEFFD700) vgaset(15, 0xFC0C0C0) end hydrapalette() hydrapaletteon = true function paletteswitch() hydrapaletteon = not hydrapaletteon if hydrapaletteon then hydrapalette() else vgareset() end end conssize = {x=80, y=25} -- fontsize = {x=8, y=16} mapregion = {x0=0, y0=0, x1=50, y1=22} msgbox = {x0=0, x1=80, y0=22,y1=24} function settilectr() tilectr = {x=25*fontsize.x, y=11*fontsize.y} end inhex = false spFloorH = spFree function alnumav(cc) if cc>=av("1") and cc <= av("9") then return cc - av("0") elseif cc >= av("A") and cc <= av("Z") then return cc - av("A") + 10 elseif cc == av("0") then return 10 -- only possible in the hex mode else return 0 end end function alnum(c) return alnumav(av(c)) end dofile(commondir.."hydra-png.noe") dofile(commondir.."hydra-ogg.noe") dofile(commondir.."walls-png.noe") Unseen = tilespatial(tilefill(0x181810), spFlat + spIFloor + spFloor + spCeil) OutOfMap = tilespatial(tilefill(0x202018), spFlat + spIFloor + spFloor + spCeil) function ytilefloor(M) if not M.floor then return Unseen elseif M.floor == " " then return 0 elseif M.floor == av("#") then return Wall else return Lightfloor end end function xtilefloor(C) if gp2(C) < 0 then return 0 end local ch = gch(C) local co = gco(C) if ch == " " then return Unseen elseif ch == (".") and co == vgaget(12) then return Unseen elseif ch == (".") and co == vgaget(8) then return Darkfloor elseif ch == (":") and co == vgaget(4) then return Darkfloor elseif ch == ("%") and co == vgaget(8) then return Darkfloor elseif ch == ("<") and co == vgaget(8) then return Darkfloor elseif ch == (">") and co == vgaget(8) then return Darkfloor elseif ch == ("#") then return Wall else return Lightfloor end end function ytileobj(M) local function hycolor(x) return tilerecolor(x, M.hcolor) end local out = 0 local function mergeout(x) out = tilemerge(out, x) end local function mergeoutit(x) out = tilemerge(out, tilemerge(ShadowD, tilerecolor(x, M.icolor))) end -- choose x for blade colors, y for gem colors, and z for special colors local function mergeoutbgo(x,y,z) local co = (M.icolor) if co == vgaget(8) then mergeoutit(z) elseif co == vgaget(4) or co == vgaget(1) or co == vgaget(2) or co == vgaget(5) then mergeoutit(y) else mergeoutit(x) end end -- terrain features if not Stairs then Stair = at(1,0) Stair1 = freeformparam(1,0.16,0,0.2, 0,0.2,0,0, 0,0,1,0, 0,0,0,1) Stair2 = freeformparam(1,0.32,0,0.4, 0,0.2,0,0, 0,0,1,0, 0,0,0,1) Stair3 = freeformparam(1,0.48,0,0.6, 0,0.2,0,0, 0,0,1,0, 0,0,0,1) Stair4 = freeformparam(1,0.64,0,0.8, 0,0.2,0,0, 0,0,1,0, 0,0,0,1) Stair5 = freeformparam(1,0,0,0, 0,0.2,0,0, 0,0.8,0,1, 0,0,0,1) Stair6 = freeformparam(1,0,1,0, 0,0.2,0,0, 0,0.8,0,1, 0,0,0,1) MoveDown = freeformparam(1,0,0,-1, 0,1,0,0, 0,0,1,0, 0,0,0,1) Stairs = tilemerge4( tilefreeform(Stair, Stair1), tilefreeform(Stair, Stair2), tilefreeform(Stair, Stair3), tilefreeform(Stair, Stair4) ) Stairs = tilemerge3(Stairs, tilefreeform(Stair, Stair5), tilefreeform(Stair, Stair6) ) Stairs = tilespatial(Stairs, spFree) end if M.floor == av("<") then if not uu then uu = 0 end local Ceil = tilespatial(tilerecolor(WT[4][uu], 0x181818), spCeil) mergeout(Ceil) mergeout(tilerecolor(Up, 0xFFFFFFF)) mergeout(Stairs) end if M.floor == av(">") then if not uu then uu = 0 end local Floor = tilespatial(tilerecolor(WT[4][uu], 0x181818), spFloorH) mergeout(Floor) mergeout(tilerecolor(DownF, 0xFFFFFFF)) mergeout(tilefreeform(Stairs, MoveDown)) -- this would require us to disable spFloor end -- blood drops if M.dead then mergeout(Blood); if M.dead < 0 then mergeout(Twinbody) elseif M.dead ~= vgaget(1) then mergeout(tilerecolor(Corpse, M.dead)) end end -- items local function sh(x) return tilemerge(x, ShadowD) end if M.iicon == av("!") then mergeoutit(Potion) elseif M.iicon == av("$") then mergeoutit(Rune) elseif M.iicon == av("?") then M.icolor = colormix(M.icolor, 0xFFFFFF) mergeoutit(Scroll) elseif M.iicon == av("(") then mergeoutit(Sword) elseif M.iicon == av(")") then mergeoutit(Mace) elseif M.iicon == av("/") then mergeoutit(Divisor) elseif M.iicon == av("*") then mergeoutit(Star) elseif M.iicon == av("]") then mergeoutit(Shield) elseif M.iicon == av("[") then mergeoutit(Prec) elseif M.iicon == av("{") then mergeoutit(Dance) elseif M.iicon == av("}") then mergeoutbgo(Logger,Bow,Logger) elseif M.iicon == av("&") then mergeoutit(Quake) elseif M.iicon == av("|") then mergeoutit(Mace) elseif M.iicon == av("\\") then mergeoutit(Deco) elseif M.iicon == av(";") then mergeoutit(Axe) elseif M.iicon == av("-") then mergeoutit(Wand) elseif M.iicon == av("+") then mergeoutit(Trident) elseif M.iicon == av("^") then mergeoutbgo(Erado,Pickaxe,Pickaxe) elseif M.iicon == av("o") then mergeoutbgo(Disk,Stone,Disk) end -- monsters etc local al = M.hicon and alnumav(M.hicon) local co = M.hcolor if M.gfxid then mergeout(sh(animatedhydras[M.gfxid])) elseif M.hicon == av("@") and not playeralive then mergeout(sh(SlayerDead)) elseif M.hicon == av("@") and M.hcolor == vgaget(15) then mergeout(sh(Slayer)) elseif M.hicon == av("@") and M.hcolor == vgaget(14) then mergeout(sh(SlayerNaga)) elseif M.hicon == av("@") and M.hcolor == vgaget(12) then mergeout(sh(SlayerCentaur)) elseif M.hicon == av("@") and M.hcolor == vgaget(13) then mergeout(sh(Twin)) elseif M.hicon == av(" ") then mergeout(tilerecolor(Hydra[7], 0)) elseif al and al>0 then if co == vgaget(8) then mergeout(sh(Mushroom[math.min(al,9)])) elseif co == vgaget(1) then mergeout(sh(Ettin[math.min(al,3)])) else mergeout(sh(tilerecolor(Hydra[al], co))) end end -- targets if M.target then mergeout(tilerecolor(Target, vgaget(12))) end if M.stun then GoldenStar = tilerecolor(TinyStar, vgaget(14)) for u=1,M.stun do local t = 5*os.clock()+math.pi*2*u/M.stun mergeout(tilespatial(tilexf(GoldenStar, (14 + 14 * math.sin(t))/32, (4+4* math.cos(t))/32, 5/32, 5/32, math.cos(t)/2, 0 ), spFlat + spIItem + spMonst)) end end return out end Stairs = nil function xinventory(C) local ch = gch(C) local co = gco(C) local function rec(x) return tilerecolor(x, co) end if ch == ("!") then return rec(Potion) elseif ch == ("$") then return rec(Rune) elseif ch == ("?") then return rec(Scroll) else return C end end function xtileobj(C) if gp2(C) < 0 then return 0 end local ch = gch(C) local co = gco(C) local function rec(x) return tilerecolor(x, co) end -- choose x for blade colors, y for gem colors, and z for special colors local function bgo(x,y,z) if co == vgaget(8) then return z elseif co == vgaget(4) or co == vgaget(1) or co == vgaget(2) or co == vgaget(5) then return y else return x end end al = alnum(ch); -- blood drops if ch == ("%") and co ~= vgaget(8) then return tilemerge(Blood, rec(Corpse)) elseif ch == ("@") and co == vgaget(12) then return tilemerge(Blood, Twinbody) -- 2: monsters etc elseif ch == "@" and co == vgaget(15) then return Slayer elseif ch == "@" and co == vgaget(13) then return Twin elseif ch == "@" and co == vgaget(12) then return Twinbody elseif ch == "%" then return rec(Corpse) elseif al > 0 then if co == vgaget(8) then return Mushroom[math.min(al,9)] elseif co == vgaget(2) then return rec(Mushroom[math.min(al,9)]) elseif co == vgaget(1) then return rec(Ettin[math.min(al,3)]) else return rec(Hydra[al]) end -- 3: walls etc elseif ch == ("#") and co == vgaget(12) then return rec(Target) elseif ch == (">") then return rec(Down) elseif ch == ("<") then return rec(Up) -- 4: items etc elseif ch == ("!") then return rec(Potion) elseif ch == ("$") then return rec(Rune) elseif ch == ("?") then return rec(Scroll) elseif ch == (":") then return rec(Target) elseif ch == (".") and co == vgaget(12) then return rec(Target) elseif ch == ("(") then return rec(Sword) elseif ch == (")") then return rec(Mace) elseif ch == ("/") then return rec(Divisor) elseif ch == ("*") then return rec(Star) elseif ch == ("]") then return rec(Shield) elseif ch == ("[") then return rec(Prec) elseif ch == ("{") then return rec(Dance) elseif ch == ("}") then return rec(bgo(Logger,Bow,Logger)) elseif ch == ("&") then return rec(Quake) elseif ch == ("|") then return rec(Mace) elseif ch == ("\\") then return rec(Deco) elseif ch == (";") then return rec(Axe) elseif ch == ("-") then return rec(Wand) elseif ch == ("+") then return rec(Trident) elseif ch == ("^") then return rec(bgo(Erado,Pickaxe,Pickaxe)) elseif ch == ("o") then return rec(bgo(Disk,Stone,Disk)) else return 0 end end function xtileold(C,x,y) local xtf = xtilefloor(C) uu = (x+3*y) % 5 checker = 0 -- congratulations, you have found the hidden checkerboard! -- just remove the -- from the next line -- checker = ((x+y)%2) * (0x101010) floorcolor = 0x805050 - checker if xtf == Lightfloor then xtf = tilemerge( tilespatial(tilerecolor(WT[10][uu], floorcolor), spFlat + spFloorH + spIFloor), tilespatial(tilerecolor(WT[4][uu], 0x203020), spCeil) ) elseif xtf == Darkfloor then xtf = tilespatial(tilerecolor(WT[10][uu], 0x202020 - checker/2), spFlat + spFloorH + spIFloor) -- ceiling should not be visible, so we just don't draw it elseif xtf == Wall then xtf = tilespatial(tilerecolor(WT[6][uu], 0x503030), spFlat + spWall + spIWall + spICeil) end return tilemerge(xtf, xtileobj(C)) end til = newimage(32,32) for x=0,31 do for y=0,31 do setpixel(til,x,y,0x3000003 * (x+y)) end end til = addtile(til, 0, 0, 32, 32, transAlpha) function xtile(C,x,y) if oldhydra then return xtileold(C,x,y) end local M = hydramap(x,y) if M.out == 1 then return OutOfMap end local ytf = ytilefloor(M) uu = (x+3*y) % 5 checker = 0 floorcolor = 0x504040 - checker if ytf == Lightfloor then ytf = tilemerge( tilespatial(tilerecolor(WT[10][uu], floorcolor), spFlat + spFloorH + spIFloor), tilespatial(tilerecolor(WT[4][uu], 0x203020), spCeil) ) elseif ytf == Wall then ytf = tilespatial(tilerecolor(WT[6][uu], 0x503030), spFlat + spWall + spIWall + spICeil) end if (not M.seen) and ytf ~= Unseen then ytf = tilerecolor(ytf, 0x202020) end if bAND(M.shadow, 1) > 0 then ytf = tilemerge(ytf, ShadowE) end if bAND(M.shadow, 2) > 0 then ytf = tilemerge(ytf, ShadowW) end if bAND(M.shadow, 4) > 0 then ytf = tilemerge(ytf, ShadowS) end if bAND(M.shadow, 8) > 0 then ytf = tilemerge(ytf, ShadowN) end return tilemerge(ytf, ytileobj(M)) end function xminimap(C) b = 0 local ch = gch(C) local co = gco(C) al = alnum(ch) if gp2(C) < 0 or ch == (" ") or (ch == (".") and co == vgaget(12)) then b=0x181810 elseif ch == (".") or ch == (":") then b = 0x8404040 elseif ch == ("#") then b = 0xC0C0C0 elseif ch == ("%") then b = 0x8604040 elseif al > 0 and co == vgaget(8) then b = 0x2F08000 elseif al > 0 then b = 0xFF0000 elseif ch == (">") or ch == ("<") then b = 0xFF00FF elseif ch == ("@") then b = 0xFFFFFF elseif ch == ("!") or ch == ("$") or ch == ("?") then b = 0x00FF00 else b = 0x0000FF end return tilefill(b) end function ispc(C) return gch(C) == "@" and gco(C) == vgaget(15) end playeralive = true function checkdeath() local lch = scrget(IMG, 51, 9) if gch(lch) ~= "L" then lch = scrget(IMG, 51, 10) end if gch(lch) == "L" then local lco = gco(lch) if lco == vgaget(15) then --print("alive") playeralive = true elseif lco == vgaget(12) then --print("barely") playeralive = true elseif lco == vgaget(4) then if playeralive then musichalt() end playeralive = false --print("dead") end end end do local oldcopymap = copymap function copymap() oldcopymap() checkdeath() if mapon then ininv = string.find(getline(0), "nventory") -- change to icons if ininv and mode ~= modeASCII then scrcopy(IMG, 53, 5, IMG, 53, 5, 1, 19, xinventory) end -- move hydra stats to the top left corner if mode == modeFPP and not ininv then if gch(scrget(IMG, 51, 9)) == "L" then topy = 9 else topy = 10 end scrcopy(IMG, 51, topy, IMG, 0, 0, 29, 11, eq) scrcopy(IMG, 51, 11, IMG, 0, 1, 29, 11, eq) scrfill(IMG, 51, topy, 29, 22-topy, 0) end -- we need to check if we are in the hex mode inhex = true for x=1,50 do for y=1,22 do if (x+y)%2 == 1 then local c = gch(scrget(MAP,x,y)) if av(c) ~= 0 and av(c) ~= 255 and c ~= " " and (c < "0" or c > "9") and c ~= "*" then inhex = false end end end end end end end function drawBackground() local curscr = getline(0) local curscr1 = getline(1) if string.find(curscr, "About:") then drawtile(1, Lightfloor, 0, 0, scrsize.x, scrsize.y) drawtile(1, xtileobj(scrget(S, 0, 0), 0,0), (scrsize.x-scrsize.y)/2, 0, scrsize.y, scrsize.y) return true elseif string.find(curscr, "Welcome") or string.find(curscr1, "Select your race") or string.find(curscr, "Hki") or string.find(curscr, "Hydra Slayer") or string.find(curscr, "achievement") or string.find(curscr, "Cheats") or (mode == modeMini and not mapon) then drawtile(1, HydraTitleTile, 0, 0, scrsize.x, scrsize.y) return true end return false end do local drat = drawAsciiSemitransparent function drawAsciiSemitransparent() drawBackground() drat() end end do local drat = drawAsciiTransparent function drawAsciiTransparent() if not mapon then return end if ininv then drawtile(1, tileshade(0), 50*fontsize.x, 0, 30*fontsize.x, fontsize.y*24) -- drawtile(1, tileshade(0), 50*fontsize.x, scrsize.y-3*24, scrsize.x-3*52-50*8, 344-(scrsize.y-3*24)) elseif mode == modeFPP then ysize = 1 while gch(scrget(IMG, 0, ysize)) ~= " " and av(gch(scrget(IMG, 0, ysize))) ~= 0 do ysize = ysize + 1 end drawtile(1, tileshade(0), 0, 0, 30*fontsize.x, ysize*fontsize.y) ysize = 2 while ysize < 10 and (gch(scrget(IMG, 51, ysize)) ~= " " or gch(scrget(IMG, 52, ysize)) ~= " ") do ysize = ysize + 1 end drawtile(1, tileshade(0), 50*fontsize.x, 0, 30*fontsize.x, ysize*fontsize.y) else drawtile(1, tileshade(0), 50*fontsize.x, 0, 30*fontsize.x, scrsize.y-3*24) drawtile(1, tileshade(0), 50*fontsize.x, scrsize.y-3*24, scrsize.x-3*52-50*8, 344-(scrsize.y-3*24)) end drawtile(1, tileshade(0), 0, 43*fontsize.x, scrsize.x-3*52, 56) drat() end end gotup = false lmodup = modup gotdn = false lmoddn = moddn function modup(ev) return (inhex and mapon and gotup) or lmodup(ev) end function moddn(ev) return (inhex and mapon and gotdn) or lmoddn(ev) end -- don't rotate in ISO hex! lsendrotated = sendrotated function sendrotated(ev) if ev.symbol == SDLK_F8 and ev.type == evKeyDown then paletteswitch() return end if ev.symbol == SDLK_UP or ev.symbol == SDLK_KP8 then gotup = ev.type == evKeyDown end if ev.symbol == SDLK_DOWN or ev.symbol == SDLK_KP2 then gotdn = ev.type == evKeyDown end if mode == modeISO and inhex then mode = modeASCII lsendrotated(ev) mode = modeISO else lsendrotated(ev) end end clickmouse = function (ev) end function mousesendsym(sym, msg) clickmouse = function () local ev = {} ev.type = evKeyDown ev.symbol = sym ev.chr = sym ev.mod = 0 nsendkey(ev) end mousemsg = msg end function mousenem(msg) clickmouse = function () noteyemenu() end mousemsg = msg end function mousesendskey(ch, msg) mousesendsym(av(ch), msg) end function checkmouse(ev) local d unclickmouse = function(ev) end if ev.y >= scrsize.y-16 then mousemsg = "" return end if not mapon then if string.find(getline(0), "inventory") then y = math.floor(ev.y / fontsize.y) mousesendskey("i", "Left click to use, right click for information") local ch = gch(scrget(S, 0, y)) if ch ~= "Y" and ch ~= " " then clickmouse = function (ev) ev.type = evKeyDown ev.mod = 0 if ev.button > 1 then ev.symbol = av(ch) ev.chr = av(ch) nsendkey(ev) ev.symbol = av("n") ev.chr = av("n") nsendkey(ev) ev.symbol = av("h") ev.chr = av("h") nsendkey(ev) else ev.symbol = av(ch) ev.chr = av(ch) nsendkey(ev) end end end return end if string.find(getline(0), "description") then mousesendskey(" ", "") y = math.floor(ev.y / 16) local ch = gch(scrget(S, 0, y)) if ch ~= "V" and ch ~= " " then mousesendskey(ch, "click for information") end return end if string.find(getline(0), "Welcome") then mousesendskey("z", "") y = math.floor(ev.y / fontsize.y) x = math.floor(ev.x / fontsize.x) if y == 21 and x >= 40 then mousenem("NotEye's sound and visual options") return elseif y > 21 then mousesendskey(string.char(10), "Click to start") return end while x >= 0 do local ch = gch(scrget(S, x, y)) local col = gco(scrget(S, x, y)) if col == vgaget(14) then mousesendskey(string.lower(ch), "Click to select this race") break end if gch(scrget(S, x+1, y)) == ")" then mousesendskey(string.lower(ch), "Click to select this option") break end x = x - 1 end return end if string.find(getline(0), "Hydra Slayer") then mousesendskey(" ", "") y = math.floor(ev.y / fontsize.y) x = math.floor(ev.x / fontsize.x) if y == 21 and x >= 40 then mousenem("NotEye's sound and visual options") return end local ch0 = gch(scrget(S, 0, y)) local ch1 = string.lower(gch(scrget(S, 1, y))) if ch0 == "(" then mousesendskey(ch1, "Click to select this option") end return end if(string.find(getline(0), "Cheats")) then y = math.floor(ev.y / fontsize.y) if y < 9 then mousesendskey("a", "Use Auto-attack") elseif y < 17 then mousesendskey("b", "Allow backups") elseif y < 21 then mousesendskey("c", "Cancel this menu") else mousesendskey("d", "Restart in debug mode") end end if(string.find(getline(0), "achievements")) then y = math.floor(ev.y / fontsize.y) if y < 2 then mousesendsym(SDLK_RETURN, "Exit") elseif y >= 22 then mousesendsym(SDLK_RETURN, "Exit") elseif y < 12 then mousesendsym(SDLK_PAGEUP, "page up") elseif y >=12 then mousesendsym(SDLK_PAGEDOWN, "page down") end return end if string.find(getline(0), "sort order") then -- troll inventory y = math.floor(ev.y / fontsize.y) x = math.floor(ev.x / fontsize.x) if y == 23 then local ch = gch(scrget(S, x, y)) mousesendskey(ch, "Store under "..ch) return end if y == 0 and x > 48 then local ch = gch(scrget(S, x, y)) if av(ch) >= av("A") and av(ch) <= av("Z") then mousesendsym(av(ch)-64, "Change sort order ("..ch..")") return end end while y > 0 and x >= 0 do local ch = gch(scrget(S, x,y)) if gco(scrget(S, x, y)) == vgaget(8) and gch(scrget(S,x+1,y)) == " " and gch(scrget(S,x+3,y)) == " " and gch(scrget(S,x+2,y)) ~= " " and ch ~= " " then mousesendskey(ch, "Take this item ("..ch..")") return end x = x - 1 end end -- if string.find(getline(0), 11) the if string.find(getline(11), "Enter to get help") then -- first page of Help mousesendsym(SDLK_RETURN, "Click to see the next page of Help") return end if string.find(getline(0), "Hki") then -- high scores y = math.floor(ev.y / fontsize.y) x = math.floor(ev.x / fontsize.x) mousesendskey(" ", "") if y > 0 and y < 10 then mousesendsym(SDLK_PAGEUP, "scroll up") elseif y >= 10 and y <= 18 then mousesendsym(SDLK_PAGEDOWN, "scroll down") else while x >= 0 do local ch = gch(scrget(S, x, y)) if ch ~= string.lower(ch) then mousesendskey(string.lower(ch), "Click to select option "..ch) break end x = x - 1 end end return end return end if string.find(getline(23), "(y/n)") then mousemsg = "Left click for YES, right click for NO" clickmouse = function (ev) ev.type = evKeyDown ev.mod = 0 if ev.button > 1 then ev.symbol = av("n") else ev.symbol = av("y") end ev.chr = ev.symbol nsendkey(ev) end return end if ev.x > 50 * fontsize.x and ev.y < 10 * fontsize.y then ev.type = evKeyDown ev.symbol = string.byte("1234567890", math.floor(ev.y/fontsize.y)+1) ev.chr = ev.symbol ev.mod = 0 clickmouse = function () nsendkey(ev) end mousemsg = "Click to change your weapon (digits)" return end if ev.y > fontsize.y * 22 then mousesendskey("m", "Click to view last messages ('m')") return end if ev.x > 50 * fontsize.x and mode ~= modeFPP then mousesendskey("f", "Click to get more information about hydras in sight ('f')") return end if ev.x < 30 * fontsize.x and ev.y < 1*fontsize.y then mousesendskey("f", "Click to get more information about hydras in sight ('f')") return end local d = pixeltodir(ev) if (d == 2 or d == 6) and inhex then d = -2 end if d >= 0 then ev.symbol = dirkeys[d] if mode == modeISO and not inhex then -- we need to prevent sendrotated from rotating us ev.symbol = dirkeys[(7+d)%8] end ev.chr = 0 ev.mod = 0 clickmouse = function (eva) if eva.button > 1 and hydrainfo and mode ~= modeFPP then pixeltoproc(eva) hydrainfo(eva.x, eva.y) else ev.type = evKeyDown sendrotated(ev) end end unclickmouse = function () ev.type = evKeyUp sendrotated(ev) end if mode ~= modeFPP then local dirnames = {"E ", "NE", "N ", "NW", "W ", "SW", "S ", "SE"} mousemsg = "Left click to move or attack "..dirnames[d+1]..(hydrainfo and " (or right click for info)" or "") else local dirnames = {"move right", "turn right", "go forward", "turn left", "go left", "turn left", "go backward", "turn right"} mousemsg = "Click to "..dirnames[d+1] end else clickmouse = function (ev) ev.type = evKeyDown ev.mod = 0 if ev.button > 1 and d == -2 and hydrainfo then pixeltoproc(ev) hydrainfo(ev.x, ev.y) return elseif ev.button > 1 then ev.symbol = av("g") else ev.symbol = av(".") end ev.chr = ev.symbol nsendkey(ev) end mousemsg = "Left click = wait ('.'), right = pick up / use stairs ('g')" if d == -2 and hydrainfo then mousemsg = "Left click = wait ('.'), right = info" end end end function sendmouse(ev) if ev.type == evMouseMotion then lastmm = ev elseif ev.type == evMouseDown then clickmouse(ev) elseif ev.type == evMouseUp then unclickmouse(ev) end end do local ldrawMiniMap = drawMiniMap local ldrawdisplay = drawdisplay function loadheximages() if not FloorHex then -- no need for spatial flags since hex 3D not supported yet FloorPNG = loadimage("gfx/hexfloor.png") FloorHex = addtile(FloorPNG, 0, 0, 48, 48, 0) WallPNG = loadimage("gfx/hexwall.png") WallHex = addtile(WallPNG, 0, 0, 48, 48, 0) DarkfloorHex = tilerecolor(FloorHex, 0x8202020) BlackHex = tilerecolor(WallHex, 0) FloorIsoI = newimage(48, 48) drawtile(FloorIsoI, FloorHex, 0, 24, 48, 24) FloorIso = addtile(FloorIsoI, 0, 0, 48, 48, 0) DarkFloorIsoI = newimage(48, 48) drawtile(DarkFloorIsoI, DarkfloorHex, 0, 24, 48, 24) DarkFloorIso = addtile(DarkFloorIsoI, 0, 0, 48, 48, 0) TempImg = newimage(32, 32) drawtile(TempImg, tilerecolor(WT[7][0], 0x504040), 0, 0, 32, 32) WallIsoI = newimage(48, 48) for x=0,16 do for y=0,24 do setpixel(WallIsoI, x+8, y+16+x/2, getpixel(TempImg, x*2, y*4/3)) end end drawtile(TempImg, tilerecolor(WT[7][0], 0x706060), 0, 0, 32, 32) for x=0,16 do for y=0,24 do setpixel(WallIsoI, x+8+16, y+24-x/2, getpixel(TempImg, x*2, y*4/3)) end end for x=0,48 do for y=0,24 do if getpixel(WallPNG,x,y*2) ~= 0 then setpixel(WallIsoI, x, y, 0x10101 * math.floor(16 + 16 * math.random())) end end end WallIso = addtile(WallIsoI, 0, 0, 48, 48, 0) end end function xhex(C) local c = xtilefloor(C) if c == Wall then return WallHex elseif c == Lightfloor then return FloorHex elseif c == Darkfloor then return DarkfloorHex else return BlackHex end end function yhex(M) local c = ytilefloor(M) if c == Wall then return M.seen and WallHex or tilerecolor(WallHex, 0x202020) elseif c == Lightfloor then return M.seen and FloorHex or tilerecolor(FloorHex, 0x202020) else return BlackHex end end function xiso(C) local c = xtilefloor(C) if c == Wall then return WallIso elseif c == Lightfloor then return FloorIso elseif c == Darkfloor then return DarkFloorIso else return OutOfMap end end function yiso(M) local c = ytilefloor(M) if c == Wall then return M.seen and WallIso or tilerecolor(WallIso, 0x101010) elseif c == Lightfloor then return M.seen and FloorIso or tilerecolor(FloorIso, 0x202020) else return 0 end end -- hydraget(x,y) = scrget(MAP, x, y) function hex_drawdisplayMini() drawdisplayASCII() loadheximages() fillimage(1, 0, 0, mapsize.x*fontsize.x, mapsize.y*fontsize.y, 0) playerat = { x = (playerpos.x+1) * fontsize.x, y = (playerpos.y+0.5) * fontsize.y } for x=0,mapsize.x-1 do for y=0,mapsize.y-1 do if ((x+y)%2 == 0) then drawtile(1, oldhydra and xhex(scrget(MAP, x, y)) or yhex(hydramap(x, y)), x * fontsize.x - fontsize.x/2, y * fontsize.y - fontsize.y/4, fontsize.x * 3, fontsize.y * 1.5 ) end end end for x=0,mapsize.x-1 do for y=0,mapsize.y-1 do if ((x+y)%2 == 0) then drawtile(1, oldhydra and xtileobj(scrget(MAP, x, y)) or ytileobj(hydramap(x, y)), x * fontsize.x, y * fontsize.y, fontsize.x * 2, fontsize.y ) end end end end function hex_drawdisplayTiles() -- this is useless with a 16x32 font if fontsize.x == 16 and fontsize.y == 32 and mapon then hex_drawdisplayMini() return end loadheximages() dx0 = -math.ceil((tilectr.x + 48) / 16) dx1 = math.ceil((xscrsize.x - tilectr.x) / 16) dy0 = -math.ceil((tilectr.y + 48) / 32) dy1 = math.ceil((xscrsize.y - tilectr.y) / 32) for dx=dx0,dx1 do for dy=dy0,dy1 do if((dx+dy)%2 == 0) then drawtile(1, oldhydra and xhex(scrget(MAP, playerpos.x+dx, playerpos.y+dy)) or yhex(hydramap(playerpos.x+dx, playerpos.y+dy)), tilectr.x + dx * 16 - 16, tilectr.y + dy * 32 - 8, 48, 48) end end end for dx=dx0,dx1 do for dy=dy0,dy1 do if((dx+dy)%2 == 0) then drawtile(1, oldhydra and xtileobj(scrget(MAP, playerpos.x+dx, playerpos.y+dy), dx, dy) or ytileobj(hydramap(playerpos.x+dx, playerpos.y+dy), dx, dy), tilectr.x + dx * 16 - 8, tilectr.y + dy * 32, 32, 32) end end end drawMiniAndStats() end function hex_drawdisplayISO() fillimage(Gfx, 0, 0, xscrsize.x, xscrsize.y, 0) ppy = playerpos.y -- the whole map should fit... if fontsize.y >= 16 then ppy = mapsize.y / 2 - 1 end loadheximages() dx0 = -math.ceil((tilectr.x + 48) / 16) dx1 = math.ceil((xscrsize.x - tilectr.x) / 16) dy0 = -math.ceil((tilectr.y + 48) / 16) dy1 = math.ceil((xscrsize.y - tilectr.y) / 16) for dy=dy0,dy1 do for dx=dx0,dx1 do if((dx+dy+playerpos.x+ppy)%2 == 0) then local sg = oldhydra and scrget(MAP, playerpos.x+dx, ppy+dy) or hydramap(playerpos.x+dx, ppy+dy) drawtile(1, yiso(sg), tilectr.x + dx * 16 - 16, tilectr.y + dy * 16 - 32, 48, 48) drawtile(1, ytileobj(sg, dx, dy), tilectr.x + dx * 16 - 8, tilectr.y + dy * 16 - 24, 32, 32) end end end drawMiniAndStats() end minimapborder = 0x303020 function drawMiniMap() if ininv then elseif inhex then scrcopy(MAP, 0,0, Minimap, 1,1, mapsize.x, mapsize.y, xminimap) for x=1,50 do for y=1,22 do if (x+y)%2 == 1 then scrset(Minimap, x,y, scrget(Minimap, x-1,y)) end end end drawscreen(1, Minimap, scrsize.x-2*(mapsize.x+2), scrsize.y-3*(mapsize.y+2), 2, 3) else ldrawMiniMap() end end function drawdisplay() if hydrabox then local curtime = os.clock() * 100 if not animatehydrastime then animatehydras(0) elseif animatehydrastime ~= curtime then animatehydras(curtime - animatehydrastime) end animatehydrastime = curtime end oldhydra = VIEW or SERVER if inhex and mode == modeTiles then hex_drawdisplayTiles() elseif inhex and (mode == modeMini or mode == modeMed) and mapon then hex_drawdisplayMini() elseif inhex and (mode == modeISO or mode == modeFPP) then hex_drawdisplayISO() else ldrawdisplay() end mousetooltips() drawmessage() end end function mousetooltips() mousemsg = "" if lastmm ~= nil then checkmouse(lastmm) end if mapon and lastmm ~= nil and lastmm.x > scrsize.x-168 and lastmm.y > scrsize.y-104 then drawtile(1, tilerecolor(WT[0][4], 0xC0C0C0), scrsize.x-168, scrsize.y-112, 168, 112) Icons = renewscreen(Icons, 5, 3) scrfill(Icons, 0, 0, 5, 3, 0) local iidx = 0 local widx = -1 if lastmm.x >= scrsize.x-164 and lastmm.x < scrsize.x-4 and lastmm.y >= scrsize.y-104 and lastmm.y < scrsize.y-8 then widx = math.floor((lastmm.x-(scrsize.x-164)) / 32) + 5 * math.floor((lastmm.y-(scrsize.y-104)) / 32) end function addicon(tile) scrset(Icons, iidx % 5, math.floor(iidx / 5), tile) iidx = iidx+1 return (widx+1) == iidx end if addicon(AsciiMap) then mousemsg = "Switch to ASCII map mode (Ctrl+M P)" clickmouse = function() setmode(modeASCII) end end if addicon(Slayer) then mousemsg = "(left click) tile mode (right click) mini-tile mode" clickmouse = function(ev) if ev.button == 1 then setmode(modeTiles) else setmode(modeMini) end end end if addicon(FirstPP) then clickmouse = function() setmode(modeISO) end mousemsg = "Switch to ISO mode (Ctrl+M I)" if not inhex then clickmouse = function(ev) if ev.button == 1 then setmode(modeISO) else setmode(modeFPP) end end mousemsg = "(left click) ISO mode (right click) FPP mode" end end if addicon(HelpIcon) then mousemsg = "Help" mousesendskey("?", "Get help ('?')") end if addicon(SystemMenu) then mousesendskey("S", "Main menu ('q')") end if addicon(Recycle) then mousesendskey("g", "Pick up something or use stairs ('g')") end if addicon(Potion) then mousesendskey("i", "Inventory ('i')") end if addicon(WpnInfo) then mousesendskey("v", "Information about the current weapon ('v')") end if addicon(WpnDrop) then mousesendskey("d", "Drop the current weapon ('d')") end if addicon(AutoExplore) then mousesendskey("o", "Auto-explore ('o')") end if addicon(Twin) then mousesendskey("c", "Switch twin control ('c')") end if addicon(Twin) then mousesendskey("s", "Switch twin order ('s')") end if addicon(Target) then mousesendskey("t", "Target a ranged weapon ('t')") end if addicon(Bow) then mousesendskey("T", "Turn on/off auto-fire mode (Shift+T)") end if addicon(NoteyeMenu) then clickmouse = noteyemenu mousemsg = "Go to NotEye menu (Ctrl+M)" end drawscreen(1, Icons, scrsize.x-164, scrsize.y-104, 32, 32) end if mousemsg ~= "" and not VIEW then drawtile(1, tileshade(vgaget(15)), 0, scrsize.y-fontsize.y, scrsize.x-168, fontsize.y) end Mouseline = renewscreen(Mouseline, 80, 1) scrfill(Mouseline, 0, 0, 80, 1, 0) scrwrite(Mouseline, 0, 0, mousemsg, Font, vgaget(0)) drawscreen(1, Mouseline, 0, scrsize.y-fontsize.y, fontsize.x, fontsize.y) end loadsounds() function gotgmessage(s) if volsound == 0 then return end function mac(pat, snd, vol) if string.match(s, pat) and snd and snd > 0 then playsound(snd, vol) return true end return false end lost= mac("drink", SndDrink, volsound) or mac("cut through", SndPickup, volsound) or mac("blocks your", SndPickup, volsound) or mac("Switched to ", SndPickup, volsound) or mac("to your set", SndPickup, volsound) or mac("Fire mode set", SndPickup, volsound) or mac("Dropped a weapon", SndPickup, volsound) or mac("You climb down", SndPickup, volsound) or mac("ancient Club of Hydra", SndQuake, volsound) or mac("Picked up the", SndPickup, volsound) or mac("First level completed", SndTada, volsound) or mac("No mighty hydra slaying weapons yet", SndTada, volsound) or mac("You carefully improve your armor", SndTada, volsound) or mac("You stop for a while to calmly", SndTada, volsound) or mac("You feel a strange sense", SndTada, volsound) or mac("relatively safe now", SndTada, volsound) or mac("Another pack of Hydras", SndTada, volsound) or mac("Your mission on this level is accomplished", SndTada, volsound) or mac("Such powerful Hydras slain", SndTada, volsound) or mac("something big soon.", SndTada, volsound) or mac("that was not that big", SndTada, volsound) or mac("You exchange weapons", SndPickup, volsound) or mac("You now control both twins", SndPickup, volsound) or mac("You now control on", SndPickup, volsound) or mac("You kill the Ancient Hydra", SndTada, volsound) or mac("But you can still go down for more hydra slaying!", SndTada, volsound) or mac("wakes up", SndPickup, volsound) or mac("is fully awake again!", SndPickup, volsound) or mac("suddenly grows a head!", SndRune, volsound) or mac("of its heads away", SndPhase, volsound) or mac("teleports .* heads to the", SndPhase, volsound) or mac("steals your", SndPhase, volsound) or mac("You miss the", SndPhase, volsound) or mac("The mushrooms join their", SndSplash, volsound) or mac("The mushrooms move in front of you", SndSplash, volsound) or mac("The mushroom bows to you!", SndSplash, volsound) or mac("The level shakes as you hit", SndQuake, volsound) or mac("huge shockwave", SndQuake, volsound) or mac("ground trembles", SndQuake, volsound) or mac("crush the wall", SndQuake, volsound) or mac("You raise a hydra zombie", SndRune, volsound) or mac("Your rune instantly destroys", SndRune, volsound) or mac("The mushroom grows", SndRune, volsound) or mac("You crush one of the mushroom's heads", SndSmash1, volsound) or mac("You crush the mushroom with your hands", SndSmash2, volsound) or mac("Sparks fly and the", SndRune, volsound) or mac("Your death touch kills the poor sleeping", SndRune, volsound) or mac("looks in terror as its stunned", SndRune, volsound) or mac("looks somehow normal now", SndRune, volsound) or mac("partially resists your spell", SndRune, volsound) or mac("suddenly grows some new heads", SndRune, volsound) or mac("confused", SndRune, volsound) or mac("dislike hydras", SndRune, volsound) or mac("turns into a mushroom", SndRune, volsound) or mac("turns into an otherworldly", SndRune, volsound) or mac("glows blindingly and changes both", SndRune, volsound) or mac("fingernail suddenly grows", SndRune, volsound) or mac("is reforged", SndRune, volsound) or mac("A part of", SndRune, volsound) or mac("You recognize the", SndRune, volsound) or mac("You feel the power of the Mushroom", SndDrink, volsound) or mac("You feel like a source", SndDrink, volsound) or mac("You suddenly grow a new", SndDrink, volsound) or mac("Ahh, that feels", SndDrink, volsound) or mac("You drink the", SndDrink, volsound) or mac("You activate the", SndRune, volsound) or mac("were .*bites", SndWoof, volsound) or mac("thorns at", SndWoof, volsound) or mac("turns to wood", SndWoof, volsound) or mac("chaos.*bites", SndChaos, volsound) or mac("breathes Chaos", SndChaos, volsound) or mac("wildly mutating", SndChaos, volsound) or mac("fire.*burns", SndFire, volsound) or mac("breathes fire", SndFire, volsound) or mac("consumed by flames", SndFire, volsound) or mac("swamp.*bites", SndPoison, volsound) or mac("spits poison", SndPoison, volsound) or mac("extinguishes", SndPoison, volsound) or mac("white.*bites", SndSilver, volsound) or mac("silverdust", SndSilver, volsound) or mac("bare metal", SndSilver, volsound) or mac("storm.*bites", SndStorm, volsound) or mac("zaps", SndStorm, volsound) or mac("Sparks fly", SndStorm, volsound) or mac("acid.*bites", SndSplash, volsound) or mac("spits acid", SndSplash, volsound) or mac("produce acid", SndSplash, volsound) or mac("ice.*freezes", SndIce, volsound) or mac("spits ice", SndIce, volsound) or mac("acid on your", SndIce, volsound) or mac("skeletal.*bites", SndBone, volsound) or mac("breathes Death", SndBone, volsound) or mac("bare bone", SndBone, volsound) or mac("golden.*bites", SndGold, volsound) or mac("shines blindingly", SndGold, volsound) or mac("pure gold", SndGold, volsound) or mac("alien.*cuts", SndCut, volsound) or mac("vampire.*bites", SndCut, volsound) or mac("ettin.*hits", SndSmash3, volsound) or mac("ancient.*attacks", SndSmash4, volsound) or mac("ivy.*crushes", SndSmash2, volsound) or mac("arch-.*bites", SndCut, volsound) or mac("monkey.*punches", SndSmash1, volsound) or mac("shadow.*touches", SndSmash4, volsound) or mac(" hit", SndBone, volsound) -- (ash, chaos, bone, golden) or mac(" burn", SndFire, volsound) or mac(" cut", SndCut, volsound) -- (poison, silver, meteo) or mac(" shock", SndStorm, volsound) or mac(" melt", SndSplash, volsound) or mac(" freeze", SndIce, volsound) or mac(" slam", SndSmash1, volsound) or mac(" turns green", SndSmash1, volsound) or mac(" strike", SndSmash2, volsound) or mac(" turns purple", SndSmash2, volsound) or mac(" smash", SndSmash3, volsound) or mac(" turns blue", SndSmash3, volsound) or mac(" crush", SndSmash4, volsound) or mac(" turns red", SndSmash4, volsound) or mac("kill the", SndDeath, volsound) or mac("kills the", SndDeath, volsound) end if hydramain and not externalhydra then function rungamex(cmdline) P = internal(S, Font, cmdline) hydramain(P, mainloopcyc) end end lpixeltodir = pixeltodir lpixeltoproc = pixeltoproc function pixeltodir(ev) if inhex then local ex = ev.x local ey = ev.y pixeltoproc(ev) d = vectodir(ev.x-playerpos.x, ev.y-playerpos.y, 0.8) ev.x = ex ev.y = ey return d else return lpixeltodir(ev) end end function pixeltoproc(ev) if inhex and mode == modeMed then mode = modeMini lpixeltoproc(ev) mode = modeMed elseif inhex and mode == modeTiles then ev.x = playerpos.x + math.floor((ev.x - tilectr.x + 8) / 16) ev.y = playerpos.y + math.floor((ev.y - tilectr.y) / 32) elseif inhex and mode == modeISO then ev.x = math.floor((ev.x - tilectr.x + 8) / 16) + playerpos.x ev.y = math.floor((ev.y - tilectr.y + 8) / 16) + ppy else lpixeltoproc(ev) end -- compare with 0.1 to take care about precision errors? if inhex and (ev.x+ev.y)%2 > 0.1 then ev.x = ev.x-1 end end if sethydrabox and not hydrabox then hydrabox = newimage(32*64, 32, 0x8080) hydraheads = loadimage(gfxdir.."hydraheads.png") hydraheadskey = getpixel(hydraheads, 0, 0) sethydrabox(hydrabox, hydraheads) animatedhydras = {} for u=0,63 do animatedhydras[u] = tilespatial(addtile(hydrabox, u*32, 0, 32, 32, 0x8080), spMonst + spFlat + spIItem) end end function sendquit() -- for libtcod as libnoteye user (not officially released) local id = (string.find(getline(0), "Hydra Slayer") and string.find(getline(0), "Zeno")) and av("S") or 27 nsendkey({chr=id, symbol=id, mod=0, type=evKeyDown}) end function dorotate(ev) return mapon and not string.find(getline(0), "nventory") end function yesno(x) return x and "yes" or "no" end -- do not play music after death lcheckmusic = checkmusic function checkmusic() if playeralive then lcheckmusic() end end IsoParam = isoparam(32, 24, 32, 32) setwindowtitle("Hydra Slayer "..(hydraver or "")) cmdline = caller3("Hydra Slayer", "hydra") defaultmode(2) rungame(cmdline)