-- Color multipler local COLOR_MUL = love._version >= "11.0" and 1 or 255 function gradientMesh(dir, ...) -- Check for direction local isHorizontal = true if dir == "vertical" then isHorizontal = false elseif dir ~= "horizontal" then error("bad argument #1 to 'gradient' (invalid value)", 2) end -- Check for colors local colorLen = select("#", ...) if colorLen < 2 then error("color list is less than two", 2) end -- Generate mesh local meshData = {} if isHorizontal then for i = 1, colorLen do local color = select(i, ...) local x = (i - 1) / (colorLen - 1) meshData[#meshData + 1] = {x, 1, x, 1, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)} meshData[#meshData + 1] = {x, 0, x, 0, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)} end else for i = 1, colorLen do local color = select(i, ...) local y = (i - 1) / (colorLen - 1) meshData[#meshData + 1] = {1, y, 1, y, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)} meshData[#meshData + 1] = {0, y, 0, y, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)} end end -- Resulting Mesh has 1x1 image size return love.graphics.newMesh(meshData, "strip", "static") end local black_gradient = gradientMesh("vertical", {0,0,0,0.8}, {0,0,0,0.8}, {0,0,0,0.8}, {0,0,0,0.6}, {0,0,0,0.0}) local white_gradient = gradientMesh("vertical", {1,1,1,0.8}, {1,1,1,0.8}, {1,1,1,0.8}, {1,1,1,0.0}) local blue_gradient = gradientMesh("vertical", {0,0.1,0.6,0.8}, {0,0.1,0.6,0.8}, {0,0.1,0.6,0.8}, {0,0.1,0.6,0.0}) local yellow_gradient = gradientMesh("vertical", {0.6,0.6,0,0.8}, {0.6,0.6,0,0.8}, {0.6,0.6,0,0.8}, {0.6,0.6,0,0.0}) local red_gradient = gradientMesh("vertical", {0.6,0.1,0,0.8}, {0.6,0.1,0,0.8}, {0.6,0.1,0,0.8}, {0.6,0.1,0,0.0}) local console = require ("lovedebug") local DEBUG = true and false local draw_ui = true and false local w = 1280 local h = 720 local aspect_ratio = 16/9 local GabrielaRegular36 = love.graphics.newFont("assets/fonts/Gabriela-Regular.ttf",36) local OpenGOST36 = love.graphics.newFont("assets/fonts/OpenGostTypeA-Regular.ttf",36) local OpenGOST72 = love.graphics.newFont("assets/fonts/OpenGostTypeA-Regular.ttf",72) local world_scale = 1 local ROM local wall_texture = {"master.png"} -- ONE per "level" local wall_model = {"path", "bottomless", "topless"} local wall_textures = {} -- will contain actual images; for production can be image data Kappa local models = {} local torch_strength = 0.5 local torch_color = {1,0.7,0} local object_models = {} local view_distance = 6 local current_location = {x = 0, y = 0, z = 0, dirx = 0, dirz = -1} local door_timer local just_stopped = true -- this breaks current_location if set to false, need to sync that with stating_pos local level_name_timer = 0 --local color = {1,1,1} -- party torch light color local color = {1,0.7,0} -- party torch light color local ambientcolor = {1,1,1} -- global ambient color local ambient_strength = 0.1 -- global ambient strength local hand_torch_strength = 4 local match = string.match function string.trim(s) return match(s,'^()%s*$') and '' or match(s,'^%s*(.*%S)') end function to_number(value) return value and 1 or 0 end function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end ----------- local image_cache = {} local dfont = love.graphics.getFont() local ogni = love.graphics.newImage function love.graphics.newImage(filename,t) local file if type(filename) == "userdata" then file = true else file = love.filesystem.getInfo(filename or "easteregg.png") end if file then if not image_cache[filename] then image_cache[filename] = ogni(filename) end return image_cache[filename] end local canvas = love.graphics.newCanvas(128,128) local font = love.graphics.getFont() love.graphics.setCanvas(canvas) love.graphics.setFont(dfont) love.graphics.setColor(math.max(0,math.random()-0.2), math.max(0,math.random()-0.2), math.max(0,math.random()-0.2)) --if t then love.graphics.setColor(0,0,1) print ("test") end love.graphics.rectangle("fill",0,0,128,128) love.graphics.setColor(0,0,0) love.graphics.print( filename or "no texture", 128, 10, 0,1,2) love.graphics.setColor(1,1,1) love.graphics.print( filename or "no texture", 128, 10, 0,1,2) love.graphics.setCanvas() love.graphics.setFont(font) return canvas end ----------- local g3d local canvas = love.graphics.newCanvas() local current_level = {} local moving = nil --local OGL = require("OGL") local inspect = require "inspect" local enemies = require("data.enemies") local items = require("data.items") local objects = require("data.objects") local encounter_rate = 0.2 local state = "dungeon" local enemies3d = {} for i in ipairs(items) do items[i].icon = love.graphics.newImage("assets/items/".. i .. ".png") end --local xbrz = require("xbrz") --xbrz.scaleXBRZ(obj) local menu_level = 0 -- A adds a level -- B subtracts a level -- can move only with 4 == 0 -- on picking target the menu level goes to 0 local menu_selected_index = 0 local menu_option_mode = nil local menu_type_selecor = {village = 1, dungeon = 2, battle = 3, shop = 4, smith = 5, church=6} local menu = {} -- a thing to draw local menu_system = { name = "base menu", [1] = {name = "Village menu", id = 1, [1] = {name = "Enter", id = 1, }, -- enters a building [4] = {name = "Magic", id = 4, }, -- opens up magic menu (pick user) [2] = {name = "Items", id = 2, -- opens up inventory (pick user) [1] = {name = "Use" , id = 1,}, [4] = {name = "Give" , id = 4,}, [2] = {name = "Equip", id = 2,}, [3] = {name = "Drop", id = 3,}, }, [3] = {name = "Status", id = 3, action = "person status"}, -- opens up status window (pick user) -- can R1 L1 }, [2] = {name = "Stanby menu", id = 1, [1] = {name = "Search", id = 1, }, -- searches the place in front of you, opens chests, gives info on items (do I need this?) [4] = {name = "Magic", id = 4, }, -- opens up magic menu (same cast thing, but magic should be labeled: "out_of_battle_use = true") [2] = {name = "Items", id = 2, -- opens up items menu (same as regular menu) [1] = {name = "Use", id = 1, action = "item drop"}, [4] = {name = "Give", id = 4, action = "person give"}, [2] = {name = "Equip", id = 2, action = "person equip"}, [3] = {name = "Drop", id = 3, action = "item drop"}, }, [3] = {name = "Status", id = 3, action = "person status"}, -- same status window, can r1 l1 }, [3] = {name = "Battle menu", id = 1, -- if in battle you have to set a target. Can't heal enemies [1] = {name = "Attack", id = 1, action = "enemy group pick"}, -- pick whom, if counter<3 then show the same menu [4] = {name = "Magic", id = 4, action = "magic person pick"}, -- pick what, then whom [2] = {name = "Items", id = 2, action = "item pick"}, -- picks an item [3] = {name = {[1]="Run", [2]="Defend", [3]="Defend",}, id = 3,}, }, [4] = {name = "Shop menu", id = 1, [1] = {name = "Buy", id = 1,}, [4] = {name = "Deals", id = 4,}, [2] = {name = "Sell", id = 2,}, [3] = {name = "-", id = 3,}, -- should be exit, but.. }, [5] = {name = "Blacksmith menu", id = 1, [1] = {name = "", id = 1,}, [4] = {name = "Forge", id = 4,}, [2] = {name = "Fix", id = 2,}, [3] = {name = "", id = 3,}, }, [6] = {name = "Priest menu", id = 1, [1] = {name = "Revive", id = 1,}, [4] = {name = "Cure", id = 4,}, [2] = {name = "Promote", id = 2,}, [3] = {name = "Status", id = 3,}, }, } for i=1, 6 do menu_system[i].parent = menu_system for j = 1, 4 do menu_system[i][j].parent = menu_system[i] for k = 1, 4 do ((menu_system[i][j] or {})[k] or {}).parent = menu_system[i][j] end end end -- HalOO VennOh -- Hallo Venner -- Hallo Kompiser function menu_control(dt) -- do nothing if below zero, preserve no menu if menu_lock then return end if menu_level<=0 then menu_level = 0 menu = {} menu_option_mode = nil end -- controls selection of 4 options: if not menu_option_mode then local og_menu = menu if menu_level>0 then --print(type(menu[menu_selected_index]), menu_last_change, menu.name, (menu.parent or {name="stub"}).name) if menu.name then if menu_last_change < 0 then menu_selected_index = menu.id or 1 menu = (menu.parent or {}) print(menu.id, 1) else -- going INTO a menu menu = (menu or menu_system)[menu_selected_index] local item = (menu or menu_system)[menu_selected_index] if item == nil then print('There are better ways to do this, but screw that!') print('Will be checking for what to do RIGHT in here.') print('Probably still be polling the "action" field,') print('but all the functions will be called from here (open_inventory, open_magiclist, etc)') menu_lock = true -- will prevent choosing stuff until needed -- THIS branch crashes the game ATM prev_state = state state = menu.action min_menu_level = menu_level print(prev_state, state) end menu_selected_index = 1 end else menu = menu_system[menu_type_selecor[state]] menu_selected_index = 1 end else menu = {} -- end if menu ~= og_menu then menu_option_mode = true end end menu_selection_cooldown = 0.2 -- controls auto menu pop-up if state == "battle" and old_state~="battle" then print("into battle") menu_level = 1 menu = menu_system[3] menu_option_mode = true end if state ~= "battle" and old_state=="battle" then print("outta battle") menu = {} menu_level = 0 menu_option_mode = nil end -- print(menu.name, menu_level, menu_last_change or "") old_state = state end menu_level = 0 state = "dungeon" local party = {} local character = { name = "", level = 1, magic = {}, items = {}, -- equipped ones here as well exp = 0, max_hp = 0, max_mp = 0, hp = 0, mp = 0, iq = 0, speed = 0, luck = 0, attack = 0, defence = 0, weapon = 0, -- use these 2 to sum up weapon & armor stats armor = 0, -- will be neat to use during rendering of statistics } function check_level_gain(c) if c.level == 99 then return 0 end -- MY GOD, how STUPID it was to forget c.!!! COuldn't get levels ONLY if I'm in level99 labirynth local counter = 0 local threshold = c.exp_table[c.level+1] while c.exp >= threshold do counter = counter + 1 end return counter end function create_character(data) local tmp = {} for k,v in pairs(character) do --print(k,v, data[k], counter) tmp[k] = data[k] or v -- make sure I can use named AND unnames params end local counter = 0 for k,v in pairs(data) do counter = counter + 1 --print(k,v, data[k], counter) tmp[k] = data[k] or data[counter] or v -- make sure I can use named AND unnames params end table.insert(party,tmp) --print("----------") return tmp end function update_character(c, data) local counter = 0 for k,v in pairs(c) do counter = counter + 1 c[k] = data[k] or data[counter] or v -- override stat if needed, will usualy be like update_character(c, {weapon = c.attack+item.attack}) end return tmp end function get_forward(direction) -- direction is needed if we press "back" and walk local direction = direction or 1 local xtobe = (g3d.camera.position[1] + world_scale*6*direction*math.sin(g3d.camera.direction))/(world_scale*6) local ztobe = (g3d.camera.position[3] + world_scale*6*direction*math.cos(g3d.camera.direction))/(world_scale*6) -- grey magic return math.floor(xtobe+0.5), math.floor(ztobe+0.5), xtobe, ztobe end function check_forward(direction) local free = true local direction = direction or 1 local xtobe, ztobe = get_forward(direction) local cell = (current_level.layout[ztobe] or {})[xtobe] or 192 local block = (current_level[ztobe] or {})[xtobe] or {} --print((block.model_info or {}).door) if cell == 192 or ((block.model_info or {}).door and direction < 0) or (cell == 132 and direction < 0) or (cell == 133 and direction < 0) then free = nil end return DEBUG or free, cell end function get_closest_door(x,z) local res local distance = math.huge for _, door in ipairs(current_level.layout.doors) do current_distance = math.sqrt((door[1]-x)*(door[1]-x)+(door[2]-z)*(door[2]-z)) --print(door[1],door[2], current_distance, distance) if current_distance < distance then distance = current_distance res = door end end return res, distance end function update_doors(dt) local opened_door_count = 0 local x, z = current_location.x, current_location.z local fx, fz = get_forward() for _, door in ipairs(current_level.layout.doors) do local xoffset, zoffset = door[1], door[2] local door_instance = (current_level[zoffset] or {})[xoffset] if door_instance then if (fx == door[1] and fz == door[2]) or (x == door[1] and z == door[2]) then door_instance.door_timer_grow = -1 else --if door_instance.opened then -- dump ROM data, edit it? put all keys into KEY items door_instance.door_timer_grow = 1 --end end -- print(_, door[1], door[2], door_instance.door_timer_grow or 1) door_instance.door_timer = (door_instance.door_timer or 0) - dt* door_instance.door_timer_grow if door_instance.door_timer <= 0 then door_instance.door_timer = 0 elseif door_instance.door_timer >= 1.95 then door_instance.door_timer = 1.95 else if not ((x == door[1] and z == door[2])) then opened_door_count = opened_door_count + 1 end end if not ((fx == door[1] and fz == door[2]) or (x == door[1] and z == door[2])) then -- increase opened doors counter for ONLY those which are not directly ahead or at the same position end end end return opened_door_count end function math.sign(number) if number > 0 then return 1 elseif number < 0 then return -1 else return 0 end end function update_controls(dt) -- can't go anywhere untill ALL of the doors are closed , except the one ahead of you and the one you're standing in ------- engine controls if love.keyboard.isScancodeDown("q") then menu_lock = false end ------- battle controls if state == "battle" then ----------- auto-resets battles state = "dungeon" menu_level = 0 --------- if love.keyboard.isScancodeDown("e") then state = "dungeon" menu_level = 0 print("--") end end local opened_doors_count = update_doors(dt) --print("opened doors:",opened_doors_count, state) if opened_doors_count > 0 then return end ------- move controls if moving or state == "battle" or menu_level>0 then return end if love.keyboard.isScancodeDown("w") or love.keyboard.isScancodeDown("up") then moving = {dir = 1, dist = world_scale*6} -- dir +/-1 + dist on movement, dir +/-1 + angle on turning if not check_forward() then moving = nil end end if love.keyboard.isScancodeDown("s") or love.keyboard.isScancodeDown("down") then moving = {dir = -1, dist = world_scale*6} -- dir +/-1 + dist on movement, dir +/-1 + angle on turning if not check_forward(-1) then print("nope") moving = nil end end if love.keyboard.isScancodeDown("a") or love.keyboard.isScancodeDown("left") then moving = {dir = -1, angle = math.pi/2} -- dir +/-1 + dist on movement, dir +/-1 + angle on turning end if love.keyboard.isScancodeDown("d") or love.keyboard.isScancodeDown("right") then moving = {dir = 1, angle = math.pi/2} -- dir +/-1 + dist on movement, dir +/-1 + angle on turning end end function love.keypressed(k,s,r) console.keypressed(key, scancode, isrepeat) if s == "f12" then if not screenshot_timer then love.graphics.captureScreenshot(os.date("%m %d %Y @ %H-%M ")..".png") --love.graphics.captureScreenshot("test.png") screenshot_timer = 0.2 end end if k == "space" then g3d.camera.position[2] = g3d.camera.position[2] - 1 g3d.camera.lookInDirection(g3d.camera.position[1],g3d.camera.position[2],g3d.camera.position[3]) end if k == "lshift" then g3d.camera.position[2] = g3d.camera.position[2] + 1 g3d.camera.lookInDirection(g3d.camera.position[1],g3d.camera.position[2],g3d.camera.position[3]) end if not menu_lock then if love.keyboard.isScancodeDown("w") then menu_selected_index = 1 elseif love.keyboard.isScancodeDown("a") then menu_selected_index = 4 elseif love.keyboard.isScancodeDown("s") then menu_selected_index = 3 elseif love.keyboard.isScancodeDown("d") then menu_selected_index = 2 end if love.keyboard.isScancodeDown("left") then menu_level = menu_level - 1 menu_option_mode = nil menu_last_change = -1 end if love.keyboard.isScancodeDown("down") then menu_level = menu_level + 1 menu_option_mode = nil menu_last_change = 1 end else -- NOT main menu, but still some sort of a menu if state == "person status" then if old_state ~= state then menu_selected_index = 1 end if love.keyboard.isScancodeDown("left") then menu_level = menu_level -1 print(min_menu_level, menu_level) if min_menu_level == menu_level +1 then menu_option_mode = nil menu_last_change = -1 menu_lock = nil state = prev_state prev_state = nil end end if love.keyboard.isScancodeDown("down") then state = "person status show" person = menu_selected_index -- this needs to stop any other menu interaction but going back. -- regardless of what is to be pressed end if love.keyboard.isScancodeDown("w") then menu_selected_index = menu_selected_index - 1 print("-1") end if love.keyboard.isScancodeDown("s") then menu_selected_index = menu_selected_index + 1 print("+1") end if menu_selected_index <1 then menu_selected_index = #party print("max") end if menu_selected_index >#party then menu_selected_index = 1 print("one") end print(menu_selected_index) elseif state == "person status show" then if s~="f12" then state = "person status" end end end end function guess_rotation(layout,x,y) -- return a NUMBER -- left, right, top, bottom holes are: -- 1 2 4 8 local holes = 0 if (layout[x] or {})[y] ~=192 then -- we're in a corridor (or something) if ((layout[x] or {})[y-1] or 192) ~= 192 then holes = holes + 4 end if ((layout[x] or {})[y+1] or 192) ~= 192 then holes = holes + 8 end if ((layout[x-1] or {})[y] or 192) ~= 192 then holes = holes + 1 end if ((layout[x+1] or {})[y] or 192) ~= 192 then holes = holes + 2 end --[[ local holes = 0 if layout[x][y] >0 then if (layout[x][y-1] or 0) > 0 then holes = holes + 1 end if (layout[x][y+1] or 0) > 0 then holes = holes + 2 end if ((layout[x-1] or {})[y] or 0) > 0 then holes = holes + 4 end if ((layout[x+1] or {})[y] or 0) > 0 then holes = holes + 8 end ]] --[[ HOLES (passages, North = top): 1 left cc0000 2 right 008000 3 left right cc8000 4 top 0000cc 5 left top cc00cc 6 right top 0080cc 7 left right top cc80cc 8 bottom 333333 9 left bottom ff3333 10 right bottom 33b333 11 left right bottom ffb333 12 top bottom 3333ff 13 left top bottom ff33ff 14 right top bottom 33b3ff 15 left right top bottom ffb3ff --strangely enough, something BROKE and now lef-right is cc7Foo :/ -- had to add math.ceil to fix it. -- but then b2 turned into b3 -- on one hand it's better to avoid more math.* -- on the other - consistency matters, and it DID break once, so.. -- it's loading time only and not THAT bad anyway ]] end return holes end function holes_to_submodel(holes) local submodel, rotation = 0, {0,0,0} -- defaults to full box w/o rotation if holes == 01 then submodel = 1 rotation = {0, math.pi/1, 0} end if holes == 02 then submodel = 1 rotation = {0, 0, 0} end if holes == 03 then submodel = 2 rotation = {0, 0, 0} end if holes == 04 then submodel = 1 rotation = {0, -math.pi/2, 0} end if holes == 05 then submodel = 5 rotation = {0, math.pi/1, 0} end if holes == 06 then submodel = 5 rotation = {0, -math.pi/2, 0} end if holes == 07 then submodel = 3 rotation = {0, math.pi/1, 0} end if holes == 08 then submodel = 1 rotation = {0, math.pi/2, 0} end if holes == 09 then submodel = 5 rotation = {0, math.pi/2, 0} end if holes == 10 then submodel = 5 rotation = {0, 0, 0} end if holes == 11 then submodel = 3 rotation = {0, 0, 0} end if holes == 12 then submodel = 2 rotation = {0, math.pi/2, 0} end if holes == 13 then submodel = 3 rotation = {0, math.pi/2, 0} end if holes == 14 then submodel = 3 rotation = {0, -math.pi/2, 0} end if holes == 15 then submodel = 4 rotation = {0, 0, 0} end return submodel, rotation end function load_textures() -- stores ALL wall textures wall_textures = {} for i=1, #ROM.maps do wall_textures[i] = love.graphics.newImage("assets/textures/".. (wall_texture[i] or wall_texture[1])) -- at least ONE should be specified end end function load_models() for model_id, model_path in ipairs(wall_model) do models[model_id] = {} -- assume path models have 6 variants for i = 0, 5 do -- i = # of holes -- order is: orange, purple, blue, red, top, bottom -- for some objects some of the models are irrelevant -- EVERY model SHOULD share THE SAME orientation, thus THE SAME rotation, guessed from the level layout data -- right now, DESPITE having multiple versions of a tile, rotation and model are hardcoded in the level data :( -- -Y up, Z = forward local filler = "" if i>0 then filler = "."..string.rep("0",3-string.len(i)) .. i end local model = "assets/models/"..model_path.. filler .. ".obj" local info = love.filesystem.getInfo(model) -- still, check if file really exists. Dunno what to do if it isn't, but oh, well... if info then models[model_id][i] = g3d.newModel(model, nil, nil, nil, {world_scale*3,world_scale*2,world_scale*3}, nil, true) models[model_id][i].name = model_path models[model_id][i]:makeNormals() end end end end function load_object_models() for object_id, model_info in pairs(objects) do -- store ALL info from "objects.lua" in object_models[object_id] -- model = model_info, REAL vertices are in model_info.model model_info.id = object_id model_info.center = model_info.center or 2.3 object_models[object_id] = object_models[object_id] or model_info object_models[object_id].id = object_id local model_path = model_info.model --[[ 0-5 holes determine orientation, but I don't know it here, just preparing (model_info.count or 1) shows if model shoud be loaded twice and mirrored... can I do this in Lua? by moving all points as needed? meh, just load those twice >:) ]] for i = 0, 5 do -- I'll ALLWAYS have 5 models (or copies/proxies/pointers/whatever) -- ok, let's ASSUME there's IS ".obj" part in model_info.model -- if will be the same for all 6 variants object_models[object_id][i] = {} local full_model_path = "assets/models/"..model_path local full_texture_path = "assets/textures/"..model_info.texture --print(full_texture_path) -- but if it's not there, replace old path with a new one(s) if not model_path:find(".obj") then local filler = "" if i>0 then filler = "."..string.rep("0",3-string.len(i)) .. i end full_model_path = "assets/models/"..model_path.. filler .. ".obj" end -- now I have the correct path local info = love.filesystem.getInfo(full_model_path) -- check if it's there and load if info then -- welp, I CAN load a model, but what if it's paired? -- Dang... -- let's load it ONCE, but store new positions/rotations/scales... it'll work, right? model_info.translation = model_info.translation or {model_info.x, model_info.y, model_info.z} local model3d = g3d.newModel(full_model_path, full_texture_path, model_info.translation, model_info.rotation, {world_scale*3*(model_info.scale or 1), world_scale*2*(model_info.scale or 1), world_scale*3*(model_info.scale or 1)}, model_info.flipU or false, model_info.flipV or true) if model_info.invert_normales then model3d:makeNormals(true) end -- now model3d stores the model we can rotate etc -- actually, if it's not paired, then just assign -_- -- also, I need only ONE of the couple if 2 0 then cell3d.box = cell3d.box or models[cell][submodel] cell3d.rotation = cell3d.rotation or rotation --cell3d.box.mesh:setTexture(wall_textures[id]) cell3d.holes = holes -- can be used for orienting other object via simple table lookup cell3d.submodel = submodel -- can be used for orienting other object via simple table lookup end end end print() -- ADD OBJECT MODELS FROM objects!!! print(level.layout.name .. " has ".. objects_total .. " objects total") print(level.layout.name .. " has ".. point_light_count .. " light sources total") local shader = love.filesystem.read("lighting.frag") -- reserve 10 more point lights than needed, just in case shader = shader:gsub("#define LIGHTS ", "#define LIGHTS ".. point_light_count+10) -- store the shader in the level var local lightingShader = love.graphics.newShader("g3d/g3d.vert", shader) level.lightingShader = lightingShader local light_source = 1 -- and iteraet AGAIN to set static point lights for object_type_id, objects_ in pairs(level.layout.objects) do if type(objects_) == "table" then -- I have some other fields there which are numbers -_- for object_id, object in ipairs(objects_) do if object_models[object_type_id] then -- I don't have ALL the models (and I won't, cause I don't need thoes seeThing ones) local x, y = object[2], object[1] local cell = level[x][y] local model_info = object_models[object_type_id] local second_model_info = object_models[-object_type_id] local required_box = model_info.requires or 1 local submodel = cell.submodel or 0 local couples = {} local holes = cell.holes local center = model_info.center or 2.3 --local holes = level[object[2]][object[1]].holes --print(inspect(couples)) if object_id == 132 then -- print(x,y) end cell.box = models[required_box][submodel] cell.model_info = model_info cell.model = model_info[submodel] --cell.model_info.model if second_model_info then cell.second_model = second_model_info[submodel] end if (model_info.count or 1) > 1 then -- "holes" contain the correct rotation. -- so.. I can use that to rotate both models in the couple accordingly -- and rotate each accordingly -- I DON'T NEED any processing in load_object_models, that would be innacurate anyway -- meaning THIS v CAN BE SIMPLIFIED local pos1 = {x=model_info.x or 0, y=model_info.y or 0, z=model_info.z or 0} local pos2 = {x=model_info.x or 0, y=model_info.y or 0, z=model_info.z or 0} local rot1 = {x=model_info.rotation_x or 0, y=model_info.rotation_y or 0, z=model_info.rotation_z or 0} local rot2 = {x=model_info.rotation_x or 0, y=model_info.rotation_y or 0, z=model_info.rotation_z or 0} if holes == 0 then elseif holes == 1 or holes == 2 or holes == 3 then -- left & right pos1.x = pos1.x - center pos2.x = pos2.x + center rot1.y = rot1.y - math.pi/2 rot2.y = rot2.y + math.pi/2 elseif holes == 4 or holes == 8 or holes == 12 then -- top pos1.z = pos1.z - center pos2.z = pos2.z + center rot1.y = rot1.y + math.pi rot2.y = rot2.y + 0 elseif holes == 5 then -- left & top pos1.z = pos1.z + center pos2.x = pos2.x + center rot1.y = rot1.y + 0--0 rot2.y = rot2.y + math.pi/2 elseif holes == 6 then -- right & top pos1.z = pos1 .z - center pos2.x = pos2.x + center rot1.y = rot1.y + math.pi rot2.y = rot2.y + math.pi/2 elseif holes == 7 then -- left & right & top pos1.x = pos1.x + center pos2.x = math.huge rot1.y = rot1.y + math.pi/2 --(may be -rot) rot2.y = rot2.y + 0--0 elseif holes == 8 then -- bottom pos1.x = pos1.x - center pos2.x = pos2.x + center rot1.y = rot1.y + 0--0 rot2.y = rot2.y + 0--rot2.y + math.pi elseif holes == 9 then -- left & bottom pos1.x = pos1.x - center pos2.z = pos2.z + center rot1.y = rot1.y - math.pi/2 rot2.y = rot2.y + 0--0 elseif holes == 10 then -- right & bottom pos1.x = pos1.x - center pos2.z = pos2.z - center rot1.y = rot1.y - math.pi/2 rot2.y = rot2.y - math.pi elseif holes == 11 then -- left & right & bottom pos1.x = pos1.x - center pos2.x = math.huge rot1.y = rot1.y - math.pi/2 rot2.y = rot2.y + 0--0 elseif holes == 12 then -- top & bottom pos1.x = pos1.x - center pos2.x = pos2.x + center rot1.y = rot1.y + 0--0 rot2.y = rot2.y + 0--rot2.y + math.pi ? elseif holes == 13 then -- left & top & bottom pos1.z = pos1.z + center pos2.x = math.huge rot1.y = rot1.y + 0--0 rot2.y = rot2.y + 0--0 elseif holes == 14 then -- right & top & bottom pos1.z = pos1.z - center pos2.x = math.huge rot1.y = rot1.y + math.pi rot2.y = rot2.y + 0--0 elseif holes == 15 then -- letf & right & top & bottom pos1.x = math.huge pos2.x = math.huge rot1.y = rot1.y + 0--0 rot2.y = rot2.y + 0--0 end couples.pos1 = pos1 couples.pos2 = pos2 couples.rot1 = rot1 couples.rot2 = rot2 cell.couples = couples --print(inspect(cell.couples)) end --print(light_source) if object_type_id == 14 then -- puddles are lit lightingShader:send("pointLights[" .. light_source .. "].position", {y*world_scale*6, 1.5, x*world_scale*6}) lightingShader:send("pointLights[" .. light_source .. "].color", {0.5,0.5,1}) lightingShader:send("pointLights[" .. light_source .. "].strength", 2) lightingShader:send("pointLights[" .. light_source .. "].max_distance", 4) light_source = light_source + 1 elseif object_type_id == 143 then -- fountains are lit lightingShader:send("pointLights[" .. light_source .. "].position", {y*world_scale*6, 0, x*world_scale*6}) lightingShader:send("pointLights[" .. light_source .. "].color", {0.5,0.5,1}) lightingShader:send("pointLights[" .. light_source .. "].strength", 2) lightingShader:send("pointLights[" .. light_source .. "].max_distance", 4) light_source = light_source + 1 elseif object_type_id == 144 then -- GOLD fountains are lit lightingShader:send("pointLights[" .. light_source .. "].position", {y*world_scale*6, 0, x*world_scale*6}) lightingShader:send("pointLights[" .. light_source .. "].color", {1,1,0.5}) lightingShader:send("pointLights[" .. light_source .. "].strength", 2) lightingShader:send("pointLights[" .. light_source .. "].max_distance", 4) light_source = light_source + 1 elseif object_type_id == 28 or object_type_id == 29 then -- print(model_info.name .. " requires ".. (model_info.requires or 1), x, y, world_scale, y*world_scale*6) local pos1 = {x = y*world_scale*6+cell.couples.pos1.x, y = 0+cell.couples.pos1.y-1, z = cell.couples.pos1.z+x*world_scale*6} local pos2 = {x = y*world_scale*6+cell.couples.pos2.x, y = 0+cell.couples.pos2.y-1, z = cell.couples.pos2.z+x*world_scale*6} --print(table.concat({pos1.x/6, pos1.y, pos1.z/6},",")) lightingShader:send("pointLights[" .. light_source .. "].position", {pos1.x, pos1.y, pos1.z}) lightingShader:send("pointLights[" .. light_source .. "].color", torch_color) lightingShader:send("pointLights[" .. light_source .. "].strength", torch_strength/2) lightingShader:send("pointLights[" .. light_source .. "].max_distance", 18) light_source = light_source + 1 lightingShader:send("pointLights[" .. light_source .. "].position", {pos2.x, pos2.y, pos2.z}) lightingShader:send("pointLights[" .. light_source .. "].color", torch_color) lightingShader:send("pointLights[" .. light_source .. "].strength", torch_strength/2) lightingShader:send("pointLights[" .. light_source .. "].max_distance", 18) light_source = light_source + 1 end end end end end level_name_timer_on = 1 return level end function love.load(arg) ROM = require("sitd") ROM:load("assets/OG_ROM/SHININGD_UE.GEN") ROM.font1 = ROM:generate_font1() ROM.font1:setFilter("nearest") love.graphics.setDefaultFilter("nearest", "nearest", 16) g3d = require "g3d" --test_models() g3d.camera.up = {0,-1, 0} create_character( require ("data/characters/Hiro") ) create_character( require ("data/characters/Milo") ) create_character( require ("data/characters/Pyra") ) party[1].hp = 1 party[2].hp = 0 -- I need this to change things via effects.lua party.camera = g3d.camera love.window.setMode(w, h, {depth=16}) love.window.setVSync( false )-- yeah, don't forget this, cause 98% on 1660S in NOT good XD g3d.camera.aspectRatio = aspect_ratio g3d.camera.updateProjectionMatrix() g3d.camera.direction = - math.pi/2 + 4* math.pi load_textures() load_models() load_object_models() current_level = load_level(1) for i = 1, #enemies do enemies3d[i] = g3d.newModel("assets/models/".."enemy_plane.obj", "assets/upscaled_sitd/"..i..".png", {0,0,0}) end Timer = 0 --print(current_level.start_pos[1], current_level.start_pos[2], current_level.start_pos[1]*6, current_level.start_pos[2]*6, get_forward()) --os.exit() g3d.camera.lookInDirection(current_level.start_pos[1]*world_scale*6, 0, current_level.start_pos[2]*world_scale*6, -math.pi/2) print( love.graphics.getRendererInfo( )) end function math.sign(number) return number >= 0 and 1 or -1 end function handle_stairs(dt) for id, stair in ipairs(ROM.stairs) do local x, z = math.floor(current_location.x+0.5), math.floor(current_location.z +0.5) local floor = current_level.id --print(table.concat(stair, ", "), x, stair[2], z, stair[3], floor, stair[1] == floor, x == stair[2], z == stair[3]) if stair[1] == floor and x == stair[2] and z == stair[3] then print(id) moving = nil if floor ~= stair[4] then current_level = load_level(stair[4]) end print(inspect(stair), current_level.name or floor, id) --print(stair[5]+current_location.dirz, 0, stair[6]+current_location.dirx) -- +current_location.dirx -- +current_location.dirz --[[ local xtb, ztb = get_forward() local block_ahead = (current_level.layout[ztb] or {})[xtb] while block_ahead == 192 do g3d.camera.direction = g3d.camera.direction + math.pi/2 xtb, ztb = get_forward() block_ahead = (current_level.layout[ztb] or {})[xtb] current_location = {x=math.ceil(g3d.camera.position[1]/6 -0.5), y=math.ceil(g3d.camera.position[2]/4 -0.5), z=math.ceil(g3d.camera.position[3]/6 -0.5)} current_location.dirx = xtb - current_location.x current_location.dirz = ztb - current_location.z end ]] --g3d.camera.lookInDirection((stair[5]+current_location.dirx)*world_scale*6, 0, (stair[6]+current_location.dirz)*world_scale*6) print("teleporting to level", stair[4], "to", stair[5]+current_location.dirx,stair[6]+current_location.dirz) g3d.camera.lookInDirection((stair[5]+current_location.dirx)*world_scale*6, 0, (stair[6]+current_location.dirz)*world_scale*6) if block_ahead == 192 then moving = {dir = 1, angle = math.pi/2} end break end end end function love.update(dt) Timer = Timer + dt if state == "battle" then --print("battle") else if just_stopped then local xtb, ztb = get_forward() current_location = {x=math.ceil(g3d.camera.position[1]/6 -0.5), y=math.ceil(g3d.camera.position[2]/4 -0.5), z=math.ceil(g3d.camera.position[3]/6 -0.5)} current_location.dirx = xtb - current_location.x current_location.dirz = ztb - current_location.z local door, dist = get_closest_door(current_location.x,current_location.z) local block_ahead = (current_level.layout[ztb] or {})[xtb] local block_afoot = (current_level.layout[current_location.z] or {})[current_location.x] local object_ahead = objects[block_ahead] or {} local object_afoot = objects[block_afoot] or {} if object_ahead.door then object_ahead.door_timer = 1 end if object_afoot.door then object_afoot.door_timer = 1 end -- now, we need to update ALL doors every tick and make them CLOSE depending on the timer -- maybe even disabling any input untill the door has closed --print(door[1], door[2], dist, current_location.x,current_location.z) handle_stairs() --just_stopped = false -- ? end if moving then if moving.dist then -- means we're walking local speed = 15 local dist = math.min(moving.dist, dt * speed) g3d.camera.position[1] = g3d.camera.position[1] + dist*moving.dir*math.sin(g3d.camera.direction) g3d.camera.position[3] = g3d.camera.position[3] + dist*moving.dir*math.cos(g3d.camera.direction) g3d.camera.lookInDirection(g3d.camera.position[1],g3d.camera.position[2],g3d.camera.position[3]) moving.dist = moving.dist - dist if moving.dist <=0 then moving = nil just_stopped = true if moving == nil then --print("moving = nil") if check_forward() then chance = math.random() --print("ch") if chance math.pi*4 then g3d.camera.direction = g3d.camera.direction - math.pi*2 end if g3d.camera.direction < math.pi*2 then g3d.camera.direction = g3d.camera.direction + math.pi*2 end g3d.camera.lookInDirection(nil,nil,nil, g3d.camera.direction) if moving.angle <=0 then moving = nil just_stopped = true if moving == nil then --print("moving = nil") if check_forward() then chance = math.random() --print("ch") if chance