fix: another PNG CRC error
[poca-love.git] / special.lua
blobe53a678d3dfcc6a9f0f62fcb1466af1678fa3680
1 --[[
2 This file is part of POCA - a puzzle game
4 POCA is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This software is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>.
20 function secrets_big(bigx, bigy)
21 current.painting = false -- done automatically if pencil
22 big_playfield.selectedx, big_playfield.selectedy = bigx, bigy
23 end
26 -- an unique number that depends on direction and current level
27 function secrets_arrow_number(dx, dy)
28 local direction
29 for a = 1, #directions do
30 if (dx == directions[a][1]) and (dy == directions[a][2]) then
31 direction = a - 1 / 2 -- 0 to 3
32 end
33 end
34 local slevel = game.currentlevel - level_labels['Secrets'] -- 0 to 15
35 return slevel + direction * 16
36 end
39 -- click on secrets arrow
40 -- check death or go immediately if already used
41 function secrets_arrow(dx, dy)
42 local function secrets_go(dx, dy)
43 local newx = big_playfield.selectedx + dx
44 local newy = big_playfield.selectedy + dy
45 if newx < 1 or newx > 4 or newy < 1 or newy > 4 then
46 newx = big_playfield.selectedx
47 newy = big_playfield.selectedy
48 end
49 -- return level
50 return level_labels['Secrets'] + newx - 1 + (newy - 1) * 4
51 end
52 local san = secrets_arrow_number(dx, dy)
53 -- if diagonal or used
54 if (dx ~= 0 and dy ~= 0) or game.secrets_arrows_used[san] then
55 fade_to_level(secrets_go(dx, dy)) -- go immediately
56 else
57 playfield.goto = {secrets_go(dx, dy), san} -- go if player survives
58 end
59 end
62 -- show arrows hidden in gifts, if already used
63 function secrets_check_gifts()
64 if not level_labels[game.currentlevel] == 'Secrets' then return end
65 inplayfield(function (x, y, p) if p.gift then
66 local tile = recognizeink(p.gift)
67 if (tile.kind == 'secrets_arrow') and tile.used then
68 playfield[x][y].contains = tile
69 playfield[x][y].used = tile.used
70 playfield[x][y].onclick = tile.onclick
71 end
72 end end)
73 end
76 function paint_mode(x, y)
77 -- cycles through paint modes
78 if not x then
79 if not playfield.paint_mode then playfield.paint_mode = 0 end
80 playfield.paint_mode = (playfield.paint_mode + 1) % 4
81 if playfield.paint_mode == 0 then playfield.paint_mode = nil end
82 return
83 -- ... or sets a pixel
84 else
85 if not game.painted_levels[game.currentlevel] then
86 game.painted_levels[game.currentlevel] = {}
87 end
88 local pl = game.painted_levels[game.currentlevel]
89 pl[x] = pl[x] or {}
90 if pl[x][y] == playfield.paint_mode then
91 pl[x][y] = 0
92 else
93 pl[x][y] = playfield.paint_mode
94 end
95 paint_level()
96 end
97 end
100 -- paints level_colors (4x4 canvas) according to game.painted.levels[currentlevel]
101 function paint_level()
102 if not level_colors then
103 level_colors = love.graphics.newCanvas(4, 4)
104 level_colors:setFilter('linear', 'linear')
105 else
106 level_colors:renderTo(love.graphics.clear)
108 local pl = game.painted_levels[game.currentlevel]
109 if not pl then return end
110 inplayfield(function (x, y, p)
111 local mode = 0
112 if pl[x] then mode = pl[x][y] end
113 if mode == 1 then
114 love.graphics.setColor(0,1,0, .5)
115 elseif mode == 2 then
116 love.graphics.setColor(1,0,0, .5)
117 elseif mode == 3 then
118 love.graphics.setColor(1,1,0, .5)
119 else
120 love.graphics.setColor(0,0,0, 0)
122 love.graphics.setCanvas(level_colors)
123 love.graphics.setPointSize(1)
124 love.graphics.setBlendMode('replace')
125 love.graphics.points(x - .5 , y - .5) -- should be on center of square
126 love.graphics.setBlendMode('alpha')
127 love.graphics.setCanvas()
128 end)
132 -- mark arrows according to their colors
133 function auto_paint()
134 local function get_mode(text)
135 if text == 'green' then return 1 end
136 if text == 'red' then return 2 end
137 if text == 'yellow' then return 3 end
139 game.painted_levels[game.currentlevel] = {}
140 inplayfield(function(x, y, p)
141 local mode = get_mode(p.kind)
142 if mode then
143 game.painted_levels[game.currentlevel][x] =
144 game.painted_levels[game.currentlevel][x] or {}
145 game.painted_levels[game.currentlevel][x][y] = mode
147 end)
148 paint_level()
152 function setup_wise_man_battle()
153 game.painted_levels[game.currentlevel] = nil
154 paint_level()
155 if game.solved_levels[game.currentlevel] then return end
156 if not game.wisepuzzle then
157 inplayfield(function (x, y, p)
158 p.onclick = function ()
159 change_screen('story_battle')
160 playfield.clickedx, playfield.clickedy = nil, nil
161 current.phase = nil -- will reset to play
163 if p.kind == 'wiseman' then
164 playfield.wisemanx, playfield.wisemany = x, y
166 end)
167 else -- puzzle finished
168 game.solved_levels[game.currentlevel] = true
169 game.wisepuzzle = false
170 game.shuffled = false
171 inplayfield(function (x, y, p)
172 if p.kind == 'wiseman' then
173 playfield[x][y] = recognizeink('D')
175 end)
180 function start_wise_man_battle()
181 inplayfield(function (x, y, p) p.onclick = nil end)
182 playfield[playfield.wisemanx][playfield.wisemany].onclick = function ()
183 current.died = true
184 current.showkill = true
185 draw_foreground()
187 current.symbolic = true
188 -- shuffle playfield
189 local wisemix = random_list(16)
190 local pl = game.painted_levels[game.currentlevel]
191 local plnew = { {}, {}, {}, {} }
192 game.shuffled = { {}, {}, {}, {} }
193 for x = 1, 4 do for y = 1, 4 do
194 local a = x + (y - 1) * 4
195 game.shuffled[x][y] = {}
196 local rx = (wisemix[a] - 1) % 4 + 1
197 local ry = math.floor((wisemix[a] - 1) / 4) + 1
198 game.shuffled[x][y].x = rx
199 game.shuffled[x][y].y = ry
200 if pl and pl[x] and pl[x][y] then plnew[rx][ry] = pl[x][y] end
201 end end
202 game.painted_levels[game.currentlevel] = plnew
203 paint_level()
204 change_screen('playfield')
208 function start_wise_man_puzzle()
209 inplayfield(function (x, y, p) playfield[x][y] = recognizeink() end)
210 playfield.clickedx, playfield.clickedy = nil, nil
211 playfield.wisemanx, playfield.wisemany = nil, nil
212 game.painted_levels[game.currentlevel] = nil
213 paint_level()
217 function setup_big_death()
218 playfield = small_playfield
219 setuplevel()
220 setup_big_playfield()
221 anim = {}
222 current.phase = 'play'
223 change_screen('story_big_death')
224 screen.minimap:renderTo(draw_minimap)
228 function events(e)
229 if e == 'pill on' then
230 game.underpill = true
231 setuplevel(level_labels['Knockout'])
232 elseif e == 'pill off' then
233 game.underpill = false
234 game.devil = false
235 setuplevel(level_labels['Genie'])
236 elseif e == 'devil on' then
237 game.devil = true
242 -- used in minigames
243 -- replaces functions from the main game
244 -- old functions are saved as rr.old_xx
245 function hijack(mini)
246 local h = mini.hijacked_love_functions
247 for a = 1, #h do
248 mini['old_' .. h[a]] = love[h[a]]
249 love[h[a]] = mini[h[a]]
251 local h = mini.hijacked_globals
252 if not h then return end
253 for a = 1, #h do
254 mini['old_' .. h[a]] = _G[h[a]]
255 _G[h[a]] = mini[h[a]]
260 -- restore hijacked functions and globals
261 function release(mini)
262 local h = mini.hijacked_love_functions
263 for a = 1, #h do
264 love[h[a]] = mini['old_' .. h[a]]
266 local h = mini.hijacked_globals
267 if not h then return end
268 for a = 1, #h do
269 _G[h[a]] = mini['old_' .. h[a]]
274 -- get 3 random objects from wise_man_has
275 -- exclude the last one (just donated)
276 function wise_get_offer()
277 local wmh = game.wise_man_has
278 local r = random_list(#game.wise_man_has - 1)
279 return { wmh[r[1]], wmh[r[2]], wmh[r[3]] }
283 -- remove an item from wise man's inventory
284 -- preserve order, as last item is recently donated and won't be offered
285 function wise_man_lose(trinket_name)
286 local wmh = game.wise_man_has
287 local lost = false
288 for a = 1, #wmh do
289 lost = lost or (wmh[a] == trinket_name)
290 if lost then game.wise_man_has[a] = wmh[a + 1] end
295 wise_advices = {
296 advice_yellow = {'advice on turning yellow arrows', 'There is a genie in the red box, that makes yellow arrows turn by themselves. It never rotates the same arrow twice in a row.'},
297 advice_genie = {'advice on stopping yellow arrows', 'To get rid of the genie, you\'d have to go back in time, helped by a pill.'},
298 advice_pill = {'advice on the location of the pill', 'There is a pill at the very end of this road, locked by purple arrows.'},
299 advice_purple = {'advice on the behavior of purple arrows', 'All purple arrows turn as one. To make a lasting change, seek places with odd number of purple arrows!'},
300 advice_map = {'story of the map', 'Long ago I created a map of this area. It shows passages, gates and where to unlock them. But I traded it with a certain explorer. Should you meet him, ask him about it!'},
301 advice_boxes = {'advice on the behavior of boxes', 'If you leave boxes alone, they will open at the end of the level. Otherwise, they will just disappear. Such it is also in life. Too strong a wish becomes an obstacle towards what you seek.'},
305 function draw_title()
306 local t = screen.tilesize
307 local tt = t / 8
308 hatch:send('line_transparency', .7)
309 love.graphics.setShader(hatch)
310 inplayfield(function (x, y, p)
311 draw_floor(x - .5, y - .5)
312 end)
313 playfield = big_playfield
314 inplayfield(function (x, y, p)
315 draw_image(p, x - .5, y - .5)
316 end)
317 playfield = small_playfield
318 love.graphics.setShader()
319 draw_image({name = 'po'}, 1.5, 0.5)
320 draw_image({name = 'ca'}, 1.5, 1.5)
321 draw_image({name = 'version'}, 2.5, 2.5)
322 love.graphics.setColor(1, 1, 1)
323 --love.graphics.rectangle('fill', t * 2 + tt , t * 3 + tt, t - 2 * tt, t- 2 * tt)
324 --love.graphics.setColor(.4, .4, .4)
325 love.graphics.printf('path of colored arrows',
326 t * 2, t * 3 + (t - 3 * screen.fontheight) / 2,
327 t, 'center'
329 love.graphics.setColor(1, 1, 1)