| -rw-r--r-- | .gitignore | 17 | ||||
| -rw-r--r-- | INSTALL | 92 | ||||
| -rw-r--r-- | Makefile | 38 | ||||
| -rw-r--r-- | content/develmanifest.lua | 10 | ||||
| -rw-r--r-- | content/scion/CombatMode.lua | 12 | ||||
| -rw-r--r-- | content/scion/Combatant.lua | 10 | ||||
| -rw-r--r-- | content/scion/ContextMenu.lua | 2 | ||||
| -rw-r--r-- | content/scion/Field.lua | 1 | ||||
| -rw-r--r-- | content/scion/LevelLoader.lua | 18 | ||||
| -rw-r--r-- | content/scion/MainMenu.lua | 4 | ||||
| -rw-r--r-- | content/scion/Preloader.lua | 4 | ||||
| -rw-r--r-- | content/scion/Slideshow.lua | 2 | ||||
| -rw-r--r-- | content/start.lua | 5 | ||||
| -rw-r--r-- | content/test/spellbench.lua | 2 | ||||
| m--------- | ult | 0 |
15 files changed, 175 insertions, 42 deletions
@@ -1,13 +1,8 @@ *~ -ult -ult.exe -/scion -scion.exe -*.pak -.build *.dll -mingw.options -userdata -stdout.txt -stderr.txt -ultwin/* +/scion +/scion.exe +/data +/stdout.txt +/stderr.txt +/userdata @@ -0,0 +1,92 @@ + +Summary +======= + +You need Lua 5.1, SDL, SDL_image, SDL_mixer, Freetype, Zlib, Zip, OpenGL. +There's no ./configure. If needed, use 'make' options or edit ult/config.mk. + +make PREFIX=/usr +sudo make install + + +Requirements +============ + +C99 compiler +Lua 5.1 - www.lua.org +SDL - www.libsdl.org +SDL_image - www.libsdl.org/projects/SDL_image +SDL_mixer - www.libsdl.org/projects/SDL_mixer +Freetype - www.freetype.org or gnuwin32.sf.net +Zlib - www.zlib.net +Zip - www.info-zip.org +OpenGL and GLU + + +Building with GNU make +====================== + +This project doesn't use autoconf and automake. A custom configure script +was used for some time, but it was abandoned in favor of simple Makefiles. +See ult/config.mk for rationale and information. + +To compile the package, use: + +make OPTION1=value1 OPTION2=value2 ... + +A list of options and their default values is in ult/config.mk. If it +exists, ult/myconfig.mk will be read instead. You can specify another +config file with 'make CONFIG=file.mk'. The default ult/config.mk uses +pkg-config and similar tools to provide good cross-platform defaults, +so you probably won't have to provide any options. + +To install the program, use: + +make install + +Installing is optional - the software looks for data files in the current +directory as well. You can use DESTDIR=/alternate/root for staged installs. + + +Building with MinGW and MSYS +============================ + +To build this under MinGW, you need +(1) required libraries installed in /mingw, +(2) .dll files copied to the project directory, +(3) MinGW-specific compile flags (e.g. -lopengl32 instead of -lGL), + +You can run ult/mingw-get-libs.sh to download and install all libraries. +Then, compile with the config file 'make CONFIG=ult/mingw.mk', which takes +care of (2) and (3). You may want to do 'cp ult/mingw.mk ult/myconfig.mk' to +make the choice persistent. + + +Manual build +============ + +Here's what to do when using another build system. + +The software uses Lua to generate C source code. Run these commands in ult/: + +lua lgllib.lua -I/header/path/to/SDL_opengl.h/ -I/and/GL.h/ -I/and/GLU.h/ +lua lsdllib.lua -I/path/to/SDL.h/ -I/and/SDL_image.h/ -I/and/SDL_mixer.h/ +# omit datadir=... and the program will look for data in ./data/ +# line wrapped for clarity +lua generate.lua launcher datadir=/data/files/location/ \ + product=Scion <launcher.lua >chunks.h +lua generate.lua FS <FS.lua >>chunks.h +# when linking with LuaJIT, run this too: +#lua generate.lua jit.opt <.../LuaJIT/lib/opt.lua >>chunks.h +#lua generate.lua jit.opt_inline <.../LuaJIT/lib/opt_inline.lua >>chunks.h + +Compile all *.c files in ult/ (including generated ones) and all required +libraries (see above) into a single binary named 'scion'. + +Then, using the binary, run this in the top-level directory: + +./scion --userdir=. --datadir=. --run=content.makedata + +To install the software, copy the binary to /usr/bin and data/ to +/data/files/location/. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..70d37a2 --- a/dev/null +++ b/Makefile @@ -0,0 +1,38 @@ + +all: scion data/scion.pak + +export DATADIR = $(PREFIX)/share/games/scion + +# using $(abspath) allows including CONFIG from ult/Makefile +override CONFIG := $(abspath $(or $(CONFIG),$(wildcard ult/myconfig.mk),ult/config.mk)) +include $(CONFIG) + +scion: + $(MAKE) -C ult target=../scion product=Scion CONFIG=$(CONFIG) + +data/manifest.lua data/scion.pak: scion content/makedata.lua + ./scion --userdir=. --datadir=. --run=content.makedata + +install: all + $(INSTALL) -d $(DESTDIR)$(BINDIR) + $(INSTALL) -m755 scion $(DESTDIR)$(BINDIR) + $(INSTALL) -d $(DESTDIR)$(DATADIR) + $(INSTALL) -m644 data/scion.pak $(DESTDIR)$(DATADIR) + [ -f data/music.pak ] && $(INSTALL) -m644 data/music.pak $(DESTDIR)$(DATADIR) + $(INSTALL) -m644 data/manifest.lua $(DESTDIR)$(DATADIR) + +uninstall: + $(RM) $(DESTDIR)$(BINDIR)/scion + -rmdir $(DESTDIR)$(BINDIR) + $(RM) $(DESTDIR)$(DATADIR)/scion.pak + $(RM) $(DESTDIR)$(DATADIR)/music.pak + $(RM) $(DESTDIR)$(DATADIR)/manifest.lua + -rmdir $(DESTDIR)$(DATADIR) + +clean distclean: + -$(RM) stdout.txt stderr.txt data/manifest.lua data/scion.pak data/music.pak + -rmdir data + $(MAKE) -C ult target=../scion CONFIG=$(CONFIG) $@ + +.PHONY: all scion install uninstall clean distclean + diff --git a/content/develmanifest.lua b/content/develmanifest.lua new file mode 100644 index 0000000..c0bdc1a --- a/dev/null +++ b/content/develmanifest.lua @@ -0,0 +1,10 @@ +function FS.runConfig(fname, body) + local chunk = assert(loadstring(body or assert(FS.load(fname):read()), '@'..fname)) + local env = {} + _G.setfenv(chunk, env) + chunk() + return env +end + +FS.DataDirectory:new{ id = 'ult', path = 'ult/content' }:appendToActiveList() +require 'test.compat' diff --git a/content/scion/CombatMode.lua b/content/scion/CombatMode.lua index 20dd504..ff6fa84 100644 --- a/content/scion/CombatMode.lua +++ b/content/scion/CombatMode.lua @@ -118,7 +118,7 @@ function CombatMode:inserted() v.layer = L_ENEMIES; v.position = i; self:addChild(v) end self:addChild(StatusMessage:new{ frames = 5 }) - self:addChild(Overlay:new{ layer = L_INTERFACE, texture = 'scion/gfx/caveoverlay.png{^2}' }) + self:addChild(Overlay:new{ layer = L_INTERFACE, texture = 'gfx/caveoverlay.png{^2}' }) self:addChild(Overlay:new{ layer = L_BACKGROUND, texture = self.bg_texture }) self:addChild(InputGrid:new{}) self:addChild(_G.scion.Cursor:new{}) @@ -247,7 +247,7 @@ function SpellAnim:initialize() _G.Node.initialize(self) assert(self.name) local _; self.anim = {} - for i,v in ipairs(_G.FS.matchFiles('^/scion/gfx/spells/'..self.name..'/..')) do + for i,v in ipairs(_G.FS.matchFiles('^/gfx/spells/'..self.name)) do _, self.anim[i] = Textures.bind(v..'{^2}') end self.w, self.h = self.anim[1].origw, self.anim[1].origh @@ -337,7 +337,7 @@ function InputIcon:displayContent() local active = (action == 'attack' or action == 'defend' or self.parent.parent.queue[1].words[action] or (action == 'heal' and _G.PERSISTENT.plants > 0)) - Textures.bind('scion/gfx/words'..(active and '' or '_inactive')..'.png'.. + Textures.bind('gfx/words'..(active and '' or '_inactive')..'.png'.. '{'..((self.x-1)*32)..','..((self.y-1)*32)..',32,32}') drawQuad{ x = self.draw_x, y = self.draw_y, vert = { 2, 2, 34, 34 } } self:displayChildren() @@ -399,7 +399,7 @@ InputGrid.isInput = true InputGrid.layer = L_INTERFACE function InputGrid:inserted() - self:addChild(Overlay:new{ texture = 'scion/gfx/battleoverlay.png{^2}' }) + self:addChild(Overlay:new{ texture = 'gfx/battleoverlay.png{^2}' }) for y = 1, 3 do for x = 1, 5 do self:addChild(InputIcon:new{ x = x, y = y }) end end end @@ -407,7 +407,7 @@ end function InputGrid:displayContent() -- spell icons if self.showSpell then - Textures.bind('scion/gfx/words.png{'..((self.showSpell[1]-1)*32)..','..((self.showSpell[2]-1)*32)..',32,32}') + Textures.bind('gfx/words.png{'..((self.showSpell[1]-1)*32)..','..((self.showSpell[2]-1)*32)..',32,32}') drawQuad{ x = _G.WIDTH/2 + (5*36)/2 + 36*2, y = 0, vert = { 0, 0, 32, 32 } } gl.Translate(32, 0, 0) gl.Color(0.8, 0.8, 0.8) @@ -417,7 +417,7 @@ function InputGrid:displayContent() gl.Vertex(0, 16); gl.Vertex(16, 16) gl.End() gl.Translate(16, 0, 0) - Textures.bind('scion/gfx/words.png{'..((self.showSpell[3]-1)*32)..','..((self.showSpell[4]-1)*32)..',32,32}') + Textures.bind('gfx/words.png{'..((self.showSpell[3]-1)*32)..','..((self.showSpell[4]-1)*32)..',32,32}') drawQuad{ vert = { 0, 0, 32, 32 } } end diff --git a/content/scion/Combatant.lua b/content/scion/Combatant.lua index 6a6fa39..913870d 100644 --- a/content/scion/Combatant.lua +++ b/content/scion/Combatant.lua @@ -113,7 +113,7 @@ Combatant.attack_frame_damage = nil EnemyData = {} _G.setmetatable(EnemyData, { __index = function (t, enemy) - EnemyData[enemy] = _G.assert(_G.FS.runConfig('scion/enemies/'..enemy..'.lua')) + EnemyData[enemy] = _G.assert(_G.FS.runConfig('enemies/'..enemy..'.lua')) return EnemyData[enemy] end }) @@ -131,7 +131,7 @@ end function Combatant:initialize() _G.Node.initialize(self) - local path = '/scion/gfx/'..(self.isEnemy and 'enemies/' or '')..(self.shape or self.name) + local path = '/gfx/'..(self.isEnemy and 'enemies/' or '')..(self.shape or self.name) if self.isEnemy then _G.assert(self.resistance) if not self.attack_frame_damage then self.attack_frame_damage = 4 end @@ -350,7 +350,7 @@ function Combatant:displayContent() gl.End() if self.protected and not self.eff_anim.parent then - Textures.bind'scion/gfx/spells/protect/04.png' + Textures.bind'gfx/spells/protect/04.png' gl.Begin(gl.QUADS) gl.TexCoord(0, 0); gl.Vertex(0, 0) gl.TexCoord(0, 1); gl.Vertex(0, 64) @@ -359,7 +359,7 @@ function Combatant:displayContent() gl.End() end if self.invincible and not self.eff_anim.parent then - Textures.bind'scion/gfx/spells/invincibility/04.png' + Textures.bind'gfx/spells/invincibility/04.png' gl.Begin(gl.QUADS) gl.TexCoord(0, 0); gl.Vertex(0, 0) gl.TexCoord(0, 1); gl.Vertex(0, 64) @@ -368,7 +368,7 @@ function Combatant:displayContent() gl.End() end if self.autolife and not self.eff_anim.parent then - local _, td = Textures.bind'scion/gfx/spells/autolife/03.png{^2}' + local _, td = Textures.bind'gfx/spells/autolife/03.png{^2}' gl.Color(1, 1, 1, 0.4) gl.Begin(gl.QUADS) gl.TexCoord(0, 0); gl.Vertex(0, 0) diff --git a/content/scion/ContextMenu.lua b/content/scion/ContextMenu.lua index e43a01c..a9c5e46 100644 --- a/content/scion/ContextMenu.lua +++ b/content/scion/ContextMenu.lua @@ -183,7 +183,7 @@ function ContextMenu:inserted() color = {1,1,1,0.8}, isOffset = false, x = x, y = yWords }) for wx = 1, 4 do for wy = 1, 3 do local word = _G.scion.CombatMode.GridActions[wy][wx+1] - local function getTexid() return Textures.bind('scion/gfx/words'.. + local function getTexid() return Textures.bind('gfx/words'.. (character.words[word] and '' or '_inactive')..'.png'.. '{'..((wx+1-1)*32)..','..((wy-1)*32)..',32,32}') end self:addChild(IconButton:new{ wx = wx, wy = wy, charid = charid, diff --git a/content/scion/Field.lua b/content/scion/Field.lua index 537b513..acb8ac0 100644 --- a/content/scion/Field.lua +++ b/content/scion/Field.lua @@ -15,6 +15,7 @@ local math = math local SDL, gl = SDL, gl local MainLoop, Controls, CombatMode, Combatant, TextInput = MainLoop, scion.Controls, scion.CombatMode, scion.Combatant, TextInput +local Textures = Textures module(...) diff --git a/content/scion/LevelLoader.lua b/content/scion/LevelLoader.lua index bfd9f4f..4abe52a 100644 --- a/content/scion/LevelLoader.lua +++ b/content/scion/LevelLoader.lua @@ -11,7 +11,7 @@ local function loadChar(dname, animations, chartexid) -- TODO cleanup hardcoded parts if dname == 'ged' then for _,d in ipairs({1, 2, 10, 11, 12, 20, 21, 22}) do - local base = 'scion/gfx/'..dname..'/'..('%03d'):format(d) + local base = 'gfx/'..dname..'/'..('%03d'):format(d) local animid = Textures.bind(base..'walk1.png{^2}') chartexid[d] = Textures.bind(base..'.png{^2}') chartexid[d+100] = animid @@ -25,14 +25,14 @@ local function loadChar(dname, animations, chartexid) end elseif dname == 'ship' then for _,d in ipairs({1, 2, 10, 11, 12, 20, 21, 22}) do - local base = 'scion/gfx/'..dname..'/'..('%03d'):format(d) + local base = 'gfx/'..dname..'/'..('%03d'):format(d) chartexid[d] = Textures.bind(base..'.png{^2}') chartexid[d+100] = Textures.bind(base..'.png{^2}') end chartexid.w, chartexid.h = 32, 32 else for _,d in ipairs({1, 2, 10, 11, 12, 20, 21, 22}) do - local base = 'scion/gfx/'..dname..'/'..('%03d'):format(d) + local base = 'gfx/'..dname..'/'..('%03d'):format(d) local animid = Textures.bind(base..'s1.png{^2}') chartexid[d] = animid chartexid[d+100] = Textures.bind(base..'walk1.png{^2}') @@ -50,7 +50,7 @@ end -- TODO: (maybe) cache loaded levels? function load(proto) - local map = _G.assert(_G.FS.runConfig('scion/maps/'..proto.mapname..'.lua')).map + local map = _G.assert(_G.FS.runConfig('maps/'..proto.mapname..'.lua')).map local W, H = map.width, map.height for k,v in _G.pairs(map.properties or {}) do proto[k] = _G.tonumber(v) or v end @@ -62,12 +62,12 @@ function load(proto) for _,ts in ipairs(map.tilesets) do local firstgid = ts.firstgid if ts.source then - ts = _G.assert(_G.FS.runConfig('scion/maps/'..ts.source:sub(1, -5)..'.lua')).map.tilesets[1] + ts = _G.assert(_G.FS.runConfig('maps/'..ts.source:sub(1, -5)..'.lua')).map.tilesets[1] ts.firstgid = firstgid end local image = nil for j,v in ipairs(ts) do - if v.label == 'image' then image = 'scion/gfx/'..v.source end + if v.label == 'image' then image = 'gfx/'..v.source end if v.label == 'tile' then tileprop[firstgid+v.id] = v.properties end end _G.assert(image) @@ -111,7 +111,7 @@ function load(proto) local finfo = proto.fields[y][x] if texids[gid] then finfo.display = texids[gid] end if (tileprop[gid] or {}).noaccess then finfo.access = false end - if (tileprop[gid] or {}).plant then finfo.plant = Textures.bind('scion/gfx/'..tileprop[gid].plant) end + if (tileprop[gid] or {}).plant then finfo.plant = Textures.bind('gfx/'..tileprop[gid].plant) end if (tileprop[gid] or {}).stairs then finfo.stairs = true; finfo.access = false end x = x + 1; if x >= W then x = 0; y = y + 1 end end @@ -131,9 +131,9 @@ function load(proto) end end proto.texid_overlay = (proto.overlay and - Textures.bind('scion/gfx/'..proto.overlay..'{^2}')) + Textures.bind('gfx/'..proto.overlay..'{^2}')) - proto.battlebg = 'scion/gfx/'..(proto.battlebg or 'bbg_ow.png')..'{^2}' + proto.battlebg = 'gfx/'..(proto.battlebg or 'bbg_ow.png')..'{^2}' local defGroupSize = nil local wildlife = proto.wildlife or 'C0' diff --git a/content/scion/MainMenu.lua b/content/scion/MainMenu.lua index ad78c6e..83ee595 100644 --- a/content/scion/MainMenu.lua +++ b/content/scion/MainMenu.lua @@ -46,7 +46,7 @@ MainMenu.logo_speed = 0.5 MainMenu.initialized_lines = false -MainMenu.music_list = { _G.FS.lookupFile('/music/field/song5.ogg') and '/music/field/song5.ogg' } +MainMenu.music_list = { _G.FS.listFiles('/music/field')['song5.ogg'] and '/music/field/song5.ogg' } function MainMenu:initialize() MainLoop.initialize(self) @@ -139,7 +139,7 @@ function MainMenu:display() gl.Clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT) gl.LoadIdentity() - local _, tinfo = Textures.bind'scion/gfx/menubg.png{^2}' + local _, tinfo = Textures.bind'gfx/menubg.png{^2}' gl.Color(1, 1, 1) gl.Begin(gl.QUADS) gl.TexCoord(0, 0); gl.Vertex(0, 0) diff --git a/content/scion/Preloader.lua b/content/scion/Preloader.lua index 84ad2e5..8f2121b 100644 --- a/content/scion/Preloader.lua +++ b/content/scion/Preloader.lua @@ -30,10 +30,10 @@ function Preloader:initialize() self.font = _G.Fonts['fonts/BROOKLNN.ttf:26'] self:setString("načítava sa...") - local images = _G.FS.matchFiles('^/scion/gfx/spells/.*%.') + local images = _G.FS.matchFiles('^/gfx/spells/.*%.') local music = _G.FS.matchFiles('^/music/.*%.') self.preload = {} - for i,v in _G.ipairs(_G.FS.matchFiles('^/scion/gfx/spells/.*%.')) do + for i,v in _G.ipairs(_G.FS.matchFiles('^/gfx/spells/.*%.')) do _G.table.insert(self.preload, { f=_G.Textures.bind, v..'{^2}' }) end for i,v in _G.ipairs(_G.FS.matchFiles('^/music/.*%.')) do diff --git a/content/scion/Slideshow.lua b/content/scion/Slideshow.lua index 76bb5f0..7f6b917 100644 --- a/content/scion/Slideshow.lua +++ b/content/scion/Slideshow.lua @@ -26,7 +26,7 @@ Slideshow.pressedEsc = false function Slideshow:initialize() MainLoop.initialize(self) if not self.slides then - self.slides = _G.FS.matchFiles('scion/gfx/'..self.name) + self.slides = _G.FS.matchFiles('gfx/'..self.name) _G.table.sort(self.slides) end end diff --git a/content/start.lua b/content/start.lua index 6219c02..d7342f6 100644 --- a/content/start.lua +++ b/content/start.lua @@ -2,9 +2,6 @@ require 'strict' require 'extlib' -if (_ARG[1] or ''):sub(1,5) == 'test.' then return require(_ARG[1]) end -if _ARG[1] == 'karel' then return require'karel.Main' end - require 'scion.Preloader' require 'scion.MainMenu' @@ -40,5 +37,5 @@ gl.Ortho(0, WIDTH, 0, HEIGHT, -1, 1) gl.MatrixMode(gl.MODELVIEW); gl.LoadIdentity() PERSISTENT = {} -if _ARG[1] == '--pdebug' then return scion.MainMenu:new{}:run() end +if arg[1] == '--pdebug' then return scion.MainMenu:new{}:run() end scion.Preloader:new{}:run() diff --git a/content/test/spellbench.lua b/content/test/spellbench.lua index 5e05166..5307d11 100644 --- a/content/test/spellbench.lua +++ b/content/test/spellbench.lua @@ -1,4 +1,4 @@ require'test.nehe.nehelib'; initScreen() --[[ to be able to use gl.* ]] -local G,A,S,T,t=SDL.GetTicks,FS.matchFiles'^/scion/gfx/spells.*%.',0 +local G,A,S,T,t=SDL.GetTicks,FS.matchFiles'^/gfx/spells.*%.',0 T=G(); for i,v in ipairs(A) do t=G(); Textures.bind(v..'{^2}') t=G()-t; S=S+t; print(t, v) end; print(S, G()-T) diff --git a/ult b/ult -Subproject 957ab96c21fbe5d4ade91b4805232f4c0189be2 +Subproject 3efeb57caea4d4389f12061fef475a7e95c0d6e |
