Commit a9a9b30cd8418446abba103800383317df97999f

Authored by DarkGod
2 parents 705a1be3 1659ce2f

Merge branch 'master' into cef_full

Showing 100 changed files with 306 additions and 187 deletions

Too many changes to show.

To preserve performance only 100 of 100+ files are displayed.

... ... @@ -11,4 +11,14 @@ out.avi
11 11 out.ogv
12 12 te4_log_web.txt
13 13 t-engine
14   -tengine_doc
\ No newline at end of file
  14 +tengine_doc
  15 +game/modules/pits/
  16 +game/modules/uaws/
  17 +game/modules/bare_minimum/
  18 +game/modules/bone/
  19 +game/modules/demo/
  20 +game/modules/particles_editor/
  21 +steam_appid.txt
  22 +oprofile_data/
  23 +game/modules/tome/data/gfx/ts-gfx*
  24 +game/engines/default/modules/boot/data/gfx/ts-gfx*
... ...
... ... @@ -29,12 +29,19 @@ if __SELFEXE then
29 29 print("SelfExe gave us app directory of:", dir)
30 30 fs.mount(dir..fs.getPathSeparator().."game"..fs.getPathSeparator().."thirdparty", "/", true)
31 31 fs.mount(dir..fs.getPathSeparator().."game", "/", true)
  32 + fs.setPathAllowed(dir..fs.getPathSeparator().."game", false)
32 33 else
33 34 print("No SelfExe, using basic path")
34 35 fs.mount("game"..fs.getPathSeparator().."thirdparty", "/", true)
35 36 fs.mount("game", "/", true)
36 37 end
37 38
  39 +fs.setPathAllowed(fs.getRealPath("/engines/"), false)
  40 +fs.setPathAllowed(fs.getRealPath("/thirdparty/"), false)
  41 +fs.setPathAllowed(fs.getRealPath("/addons/"), true)
  42 +if fs.getRealPath("/dlcs/") then fs.setPathAllowed(fs.getRealPath("/dlcs/"), true) end
  43 +fs.setPathAllowed(fs.getRealPath("/modules/"), true)
  44 +
38 45 -- Look for a core
39 46 function get_core(coretype, id)
40 47 coretype = coretype or "te4core"
... ...
... ... @@ -66,6 +66,16 @@ newoption {
66 66 }
67 67
68 68 newoption {
  69 + trigger = "discord",
  70 + description = "Discord integration"
  71 +}
  72 +
  73 +newoption {
  74 + trigger = "discord-nolib",
  75 + description = "Dont build discord lib"
  76 +}
  77 +
  78 +newoption {
69 79 trigger = "web-awesomium",
70 80 description = "Use awesomium embedded browser as the webcore"
71 81 }
... ...
... ... @@ -38,6 +38,7 @@ project "TEngine"
38 38 files { "../steamworks/luasteam.c", }
39 39 end
40 40 links { "physfs", "lua".._OPTIONS.lua, "fov", "luasocket", "luaprofiler", "lpeg", "tcodimport", "lxp", "expatstatic", "luamd5", "luazlib", "luabitop", "te4-bzip" }
  41 + if _OPTIONS.discord then defines { "DISCORD_TE4" } end
41 42 defines { "_DEFAULT_VIDEOMODE_FLAGS_='SDL_HWSURFACE|SDL_DOUBLEBUF'" }
42 43 defines { [[TENGINE_HOME_PATH='".t-engine"']], "TE4CORE_VERSION="..TE4CORE_VERSION }
43 44 buildoptions { "-O3" }
... ... @@ -597,3 +598,27 @@ end
597 598 if _OPTIONS.steam then
598 599 dofile("../steamworks/build/steam-code.lua")
599 600 end
  601 +
  602 +if _OPTIONS.discord and not _OPTIONS['discord-nolib'] then
  603 +project "te4-discord"
  604 + configuration "linux"
  605 + kind "SharedLib"
  606 + language "C++"
  607 + targetname "discord-rpc"
  608 + buildoptions { "-std=gnu++11" }
  609 +
  610 + includedirs { "../src/discord-rpc/include/", "../src/discord-rpc/rapidjson/", }
  611 +
  612 + defines { "DISCORD_DYNAMIC_LIB" }
  613 +
  614 + files { "../src/discord-rpc/src/discord-rpc.cpp", "../src/discord-rpc/src/rpc_connection.cpp", "../src/discord-rpc/src/serialization.cpp", }
  615 + files { "../src/discord-rpc/src/connection_unix.cpp", "../src/discord-rpc/src/discord_register_linux.cpp", }
  616 +
  617 + configuration "windows"
  618 + kind "SharedLib"
  619 + -- Empty
  620 +
  621 + configuration "macosx"
  622 + kind "SharedLib"
  623 + -- Empty
  624 +end
... ...
1 1 -- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -73,7 +73,7 @@ end
73 73 -- modules should update this as needed
74 74 _M.clone_nodes = {player=false, x=false, y=false,
75 75 fov_computed=false, fov={v={actors={}, actors_dist={}}}, distance_map={v={}},
76   - _mo=false, _last_mo=false, add_mos=false, add_displays=false,
  76 + _mo=false, _last_mo=false, add_displays=false,
77 77 shader=false, shader_args=false,
78 78 }
79 79 --- cloneActor default fields (merged by _M.cloneActor with cloneCustom)
... ... @@ -90,7 +90,15 @@ _M.clone_copy = nil
90 90 function _M:cloneActor(post_copy, alt_nodes)
91 91 alt_nodes = table.merge(alt_nodes or {}, self.clone_nodes, true)
92 92 if post_copy or self.clone_copy then post_copy = post_copy or {} table.update(post_copy, self.clone_copy or {}, true) end
93   - local a = self:cloneCustom(alt_nodes, post_copy)
  93 + -- Clone all except sub-actors which need to simply reference the same ones
  94 + local a = self:cloneCustom(alt_nodes, function(d) return not d:isClassName("mod.class.Actor") end, post_copy)
  95 + -- Handle add_displays as a special case
  96 + if self.add_displays then
  97 + a.add_displays = {}
  98 + for i, d in ipairs(self.add_displays) do
  99 + table.insert(a.add_displays, d:cloneFull())
  100 + end
  101 + end
94 102 a:removeAllMOs()
95 103 return a, post_copy
96 104 end
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -43,13 +43,17 @@ function _M:init(name, npc, player, data)
43 43
44 44 local f, err = loadfile(self:getChatFile(name))
45 45 if not f and err then error(err) end
46   - setfenv(f, setmetatable({
  46 + local env = setmetatable({
  47 + cur_chat = self,
47 48 setDialogWidth = function(w) self.force_dialog_width = w end,
48 49 newChat = function(c) self:addChat(c) end,
49   - }, {__index=data}))
  50 + setTextFont = function(font, size) self.dialog_text_font = {font, size} end,
  51 + setAnswerFont = function(font, size) self.dialog_answer_font = {font, size} end,
  52 + }, {__index=data})
  53 + setfenv(f, env)
50 54 self.default_id = f()
51 55
52   - self:triggerHook{"Chat:load", data=data}
  56 + self:triggerHook{"Chat:load", data=data, env=env}
53 57 end
54 58
55 59 --- Get chat file
... ... @@ -100,7 +104,10 @@ function _M:invoke(id)
100 104 if self.npc.onChat then self.npc:onChat() end
101 105 if self.player.onChat then self.player:onChat() end
102 106
103   - local d = engine.dialogs.Chat.new(self, id or self.default_id, self.force_dialog_width or 500)
  107 + local hd = {"Chat:invoke", id = id or self.default_id }
  108 + self:triggerHook(hd)
  109 +
  110 + local d = engine.dialogs.Chat.new(self, hd.id, self.force_dialog_width or 500)
104 111 game:registerDialog(d)
105 112 return d
106 113 end
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -32,17 +32,18 @@ frame_oy2 = 15
32 32 --- @string text
33 33 -- @int[opt=60] dur
34 34 -- @param[opt=colors.Black] color
35   -function _M:init(text, dur, color)
  35 +function _M:init(text, dur, color, font)
36 36 self.text = text
37 37 self.dur = dur or 60
38 38 self.color = color or colors.BLACK
  39 + self.use_font = font
39 40
40   - Base.init(self, {font = {"/data/font/DroidSans-Bold.ttf", 16}})
  41 + Base.init(self, {font = self.use_font or {"/data/font/DroidSans-Bold.ttf", 16}})
41 42 end
42 43
43 44 --- on loaded
44 45 function _M:loaded()
45   - Base.init(self, {font = {"/data/font/DroidSans-Bold.ttf", 16}})
  46 + Base.init(self, {font = self.use_font or {"/data/font/DroidSans-Bold.ttf", 16}})
46 47 end
47 48
48 49 --- Serialization
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -1206,6 +1206,10 @@ function _M:loadList(file, no_default, res, mod, loaded)
1206 1206 load = function(f, new_mod)
1207 1207 self:loadList(f, no_default, res, new_mod or mod, loaded)
1208 1208 end,
  1209 + loadIfNot = function(f, new_mod)
  1210 + if loaded[f] then return end
  1211 + self:loadList(f, no_default, res, new_mod or mod, loaded)
  1212 + end,
1209 1213 loadList = function(f, new_mod, list, loaded)
1210 1214 return self:loadList(f, no_default, list, new_mod or mod, loaded)
1211 1215 end,
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -475,7 +475,7 @@ function _M:addonMD5(add, base)
475 475 print("[MODULE LOADER] addon ", add.short_name, " MD5", fmd5, "computed in ", core.game.getTime() - t, vbase)
476 476
477 477 if __module_extra_info.compute_md5_only then
478   - local f = io.open(__module_extra_info.compute_md5_only, "a")
  478 + local f = fs.open(__module_extra_info.compute_md5_only, "a")
479 479 f:write(("%s : addon[%s] md5\n"):format(fmd5, add.version_name))
480 480 f:close()
481 481 end
... ... @@ -982,7 +982,7 @@ function _M:instanciate(mod, name, new_game, no_reboot, extra_module_info)
982 982 print("[MODULE LOADER] module MD5", module_md5, "computed in ", core.game.getTime() - t)
983 983
984 984 if __module_extra_info.compute_md5_only then
985   - local f = io.open(__module_extra_info.compute_md5_only, "w")
  985 + local f = fs.open(__module_extra_info.compute_md5_only, "w")
986 986 f:write(("%s : module[%s] md5\n"):format(module_md5, mod.version_string))
987 987 f:close()
988 988 end
... ... @@ -1019,6 +1019,7 @@ function _M:instanciate(mod, name, new_game, no_reboot, extra_module_info)
1019 1019 profile:incrLoadProfile(mod)
1020 1020 profile:currentCharacter(mod.full_version_string, "game did not tell us")
1021 1021
  1022 +
1022 1023 UIBase:clearCache()
1023 1024
1024 1025 -- Some requires cleanup, to correctly let modules apply settings
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -205,6 +205,9 @@ function _M:getSubtypeOrder()
205 205 return self.subtype or ""
206 206 end
207 207
  208 +--- Describe requirements flags naming
  209 +_M.requirement_flags_names = {}
  210 +
208 211 --- Describe requirements
209 212 function _M:getRequirementDesc(who)
210 213 local req = rawget(self, "require")
... ... @@ -212,6 +215,19 @@ function _M:getRequirementDesc(who)
212 215
213 216 local str = tstring{"Requires:", true}
214 217
  218 + if req.flag then
  219 + for _, flag in ipairs(req.flag) do
  220 + if type(flag) == "table" then
  221 + local name = self.requirement_flags_names[flag[1]] or flag[1]
  222 + local c = (who:attr(flag[1]) and who:attr(flag[1]) >= flag[2]) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00}
  223 + str:add(c, "- ", ("%s (level %d)"):format(name, flag[2]), {"color", "LAST"}, true)
  224 + else
  225 + local name = self.requirement_flags_names[flag] or flag
  226 + local c = who:attr(flag) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00}
  227 + str:add(c, "- ", ("%s"):format(name), {"color", "LAST"}, true)
  228 + end
  229 + end
  230 + end
215 231 if req.stat then
216 232 for s, v in pairs(req.stat) do
217 233 local c = (who:getStat(s) >= v) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00}
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -23,6 +23,7 @@ local url = require "socket.url"
23 23 local ltn12 = require "ltn12"
24 24 local Dialog = require "engine.ui.Dialog"
25 25 local UserChat = require "engine.UserChat"
  26 +local sha1 = require("sha1").sha1
26 27 require "Json2"
27 28
28 29 --- Handles the player profile, possibly online
... ... @@ -98,6 +99,12 @@ function _M:start()
98 99 self:loadGenericProfile()
99 100
100 101 if self.generic.online and self.generic.online.login and self.generic.online.pass then
  102 + -- Convert to encrypted pass
  103 + if not self.generic.online.v2 then
  104 + self.generic.online.pass = sha1(self.generic.online.pass)
  105 + self:saveGenericProfile("online", {login=self.generic.online.login, pass=self.generic.online.pass, v2=true})
  106 + end
  107 +
101 108 self.login = self.generic.online.login
102 109 self.pass = self.generic.online.pass
103 110 self:tryAuth()
... ... @@ -130,7 +137,7 @@ function _M:mountProfile(online, module)
130 137 fs.mkdir(string.format("/profiles/%s/generic/", online and "online" or "offline"))
131 138 if module then fs.mkdir(string.format("/profiles/%s/modules/%s", online and "online" or "offline", module)) end
132 139
133   - local path = engine.homepath.."/profiles/"..(online and "online" or "offline")
  140 + local path = engine.homepath..fs.getPathSeparator().."profiles"..fs.getPathSeparator()..(online and "online" or "offline")
134 141 fs.mount(path, "/current-profile")
135 142 print("[PROFILE] mounted ", online and "online" or "offline", "on /current-profile")
136 143 fs.setWritePath(path)
... ... @@ -138,7 +145,7 @@ function _M:mountProfile(online, module)
138 145 return restore
139 146 end
140 147 function _M:umountProfile(online, pop)
141   - local path = engine.homepath.."/profiles/"..(online and "online" or "offline")
  148 + local path = engine.homepath..fs.getPathSeparator().."profiles"..fs.getPathSeparator()..(online and "online" or "offline")
142 149 fs.umount(path)
143 150 print("[PROFILE] unmounted ", online and "online" or "offline", "from /current-profile")
144 151
... ... @@ -147,9 +154,9 @@ end
147 154
148 155 -- Define the fields that are sync'ed online, and how they are sync'ed
149 156 local generic_profile_defs = {
150   - firstrun = {nosync=true, {firstrun="number"}, receive=function(data, save) save.firstrun = data.firstrun end },
151   - online = {nosync=true, {login="string:40", pass="string:40"}, receive=function(data, save) save.login = data.login save.pass = data.pass end },
152   - onlinesteam = {nosync=true, {autolog="boolean"}, receive=function(data, save) save.autolog = data.autolog end },
  157 + firstrun = {nosync=true, no_sync=true, {firstrun="number"}, receive=function(data, save) save.firstrun = data.firstrun end },
  158 + online = {nosync=true, no_sync=true, {login="string:40", pass="string:40", v2="number"}, receive=function(data, save) save.login = data.login save.pass = data.pass save.v2 = data.v2 end },
  159 + onlinesteam = {nosync=true, no_sync=true, {autolog="boolean"}, receive=function(data, save) save.autolog = data.autolog end },
153 160 modules_played = { {name="index:string:30"}, {time_played="number"}, receive=function(data, save) max_set(save, data.name, data, "time_played") end, export=function(env) for k, v in pairs(env) do add{name=k, time_played=v} end end },
154 161 modules_loaded = { {name="index:string:30"}, {nb="number"}, receive=function(data, save) max_set(save, data.name, data, "nb") end, export=function(env) for k, v in pairs(env) do add{name=k, nb=v} end end },
155 162 }
... ... @@ -425,14 +432,16 @@ function _M:checkFirstRun()
425 432 end
426 433
427 434 function _M:performlogin(login, pass)
  435 + pass = sha1(pass)
  436 +
428 437 self.login=login
429 438 self.pass=pass
430 439 print("[ONLINE PROFILE] attempting log in ", self.login)
431 440 self.auth_tried = nil
432 441 self:tryAuth()
433 442 self:waitFirstAuth()
434   - if (profile.auth) then
435   - self:saveGenericProfile("online", {login=login, pass=pass})
  443 + if profile.auth then
  444 + self:saveGenericProfile("online", {login=login, pass=pass, v2=true})
436 445 self:getConfigs("generic")
437 446 self:syncOnline("generic")
438 447 end
... ... @@ -477,6 +486,9 @@ function _M:popEvent(specific)
477 486 end
478 487
479 488 function _M:waitEvent(name, cb, wait_max)
  489 + -- Dont try as it would fail and we'd fait for nothing
  490 + if config.settings.disable_all_connectivity then return end
  491 +
480 492 -- Wait anwser, this blocks thegame but cant really be avoided :/
481 493 local stop = false
482 494 local first = true
... ... @@ -509,6 +521,9 @@ function _M:noMoreAuthWait()
509 521 end
510 522
511 523 function _M:waitFirstAuth(timeout)
  524 + -- Dont try as it would fail and we'd fait for nothing
  525 + if config.settings.disable_all_connectivity then return end
  526 +
512 527 if self.no_more_wait_auth then return end
513 528 if self.auth_tried and self.auth_tried >= 1 then return end
514 529 if not self.waiting_auth then return end
... ... @@ -564,7 +579,7 @@ function _M:eventGetNews(e)
564 579 end
565 580
566 581 function _M:eventIncrLogConsume(e)
567   - local module = game.__mod_info.short_name
  582 + local module = type(game) == "table" and game.__mod_info.short_name
568 583 if not module then return end
569 584 print("[PROFILE] Server accepted our incr log, deleting")
570 585 local pop = self:mountProfile(true, module)
... ... @@ -592,6 +607,13 @@ function _M:eventGetConfigs(e)
592 607 end
593 608
594 609 function _M:eventPushCode(e)
  610 + if not config.settings.allow_online_events then
  611 + if e.return_uuid then
  612 + core.profile.pushOrder(string.format("o='CodeReturn' uuid=%q data=%q", e.return_uuid, table.serialize{error='user disabled events, refusing to load code'}))
  613 + end
  614 + return
  615 + end
  616 +
595 617 local f, err = loadstring(e.code)
596 618 if not f then
597 619 if e.return_uuid then
... ... @@ -649,6 +671,9 @@ function _M:getNews(callback, steam)
649 671 end
650 672
651 673 function _M:tryAuth()
  674 + -- Dont try as it would fail and we'd fait for nothing
  675 + if config.settings.disable_all_connectivity then return end
  676 +
652 677 print("[ONLINE PROFILE] auth")
653 678 self.auth_last_error = nil
654 679 if self.steam_token then
... ... @@ -1019,7 +1044,8 @@ function _M:isDonator(s)
1019 1044 end
1020 1045
1021 1046 function _M:allowDLC(dlc)
1022   - if core.steam then if core.steam.checkDLC(dlc[2]) then return true end end
1023   - if self.auth and self.auth.dlcs and self.auth.dlcs[dlc[1]] then return true end
1024   - return false
  1047 + -- if core.steam then if core.steam.checkDLC(dlc[2]) then return true end end
  1048 + -- if self.auth and self.auth.dlcs and self.auth.dlcs[dlc[1]] then return true end
  1049 + -- return false
  1050 + return true
1025 1051 end
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -74,6 +74,13 @@ function _M:isEnded()
74 74 if self.status == DONE or self.status == FAILED then return true else return false end
75 75 end
76 76
  77 +--- Checks if the quest is ended in success
  78 +-- @return[1] false if quest didn't end
  79 +-- @return[2] true if quest ended
  80 +function _M:isSuccess()
  81 + if self.status == DONE then return true else return false end
  82 +end
  83 +
77 84 --- Check for an quest property
78 85 -- If not a function it returns it directly, otherwise it calls the function
79 86 -- with the extra parameters
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -163,15 +163,22 @@ function _M:unregisterTalkEvents(fct)
163 163 self.on_event[fct] = nil
164 164 end
165 165
  166 +function _M:getUserColor(e)
  167 + local name = e.name
  168 + local color = colors.WHITE
  169 + if e.status == 'dev' then color = colors.CRIMSON name = "{dev} "..name
  170 + elseif e.status == 'mod' then color = colors.GOLD name = "[mod] "..name
  171 + elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
  172 + elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  173 + e.color_name = color
  174 + return color, name
  175 +end
  176 +
166 177 function _M:event(e)
167 178 if not profile.auth then return end
168 179 if e.se == "Talk" then
169 180 e.msg = e.msg:removeColorCodes():gsub("#", "##")
170   - local color = colors.WHITE
171   - if e.status == 'dev' then color = colors.CRIMSON
172   - elseif e.status == 'mod' then color = colors.GOLD
173   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
174   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  181 + local color, uname = self:getUserColor(e)
175 182
176 183 self.channels[e.channel] = self.channels[e.channel] or {users={}, log={}}
177 184 if profile and profile.auth and profile.auth.name then
... ... @@ -180,21 +187,17 @@ function _M:event(e)
180 187 e.msg = e.msg:sub(1, ni - 1).."#YELLOW##{underline}#"..profile.auth.name.."#{normal}##LAST#"..e.msg:sub(nj + 1)
181 188 end
182 189 end
183   - self:addMessage("talk", e.channel, e.login, {e.name, color}, e.msg)
  190 + self:addMessage("talk", e.channel, e.login, {uname, color}, e.msg)
184 191
185 192 if type(game) == "table" and game.logChat and self.cur_channel == e.channel then
186 193 game.logChat("#YELLOW#<%s> %s", e.name, e.msg)
187 194 end
188 195 elseif e.se == "Whisper" then
189 196 e.msg = e.msg:removeColorCodes()
190   - local color = colors.WHITE
191   - if e.status == 'dev' then color = colors.CRIMSON
192   - elseif e.status == 'mod' then color = colors.GOLD
193   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
194   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  197 + local color, uname = self:getUserColor(e)
195 198
196 199 self.channels[self.cur_channel] = self.channels[self.cur_channel] or {users={}, log={}}
197   - self:addMessage("whisper", self.cur_channel, e.login, e.name, e.msg)
  200 + self:addMessage("whisper", self.cur_channel, e.login, uname, e.msg)
198 201
199 202 if type(game) == "table" and game.logChat then
200 203 game.logChat("#GOLD#<Whisper from %s> %s", e.name, e.msg)
... ... @@ -202,11 +205,7 @@ function _M:event(e)
202 205 e.channel = self.cur_channel
203 206 elseif e.se == "Achievement" then
204 207 e.msg = e.msg:removeColorCodes()
205   - local color = colors.WHITE
206   - if e.status == 'dev' then color = colors.CRIMSON
207   - elseif e.status == 'mod' then color = colors.GOLD
208   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
209   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  208 + local color, uname = self:getUserColor(e)
210 209
211 210 local kind = "achievement_other"
212 211 if e.first then kind = "achievement_first"
... ... @@ -220,18 +219,13 @@ function _M:event(e)
220 219 if e.first then first = " for the #FIREBRICK#first time!" end
221 220
222 221 self.channels[e.channel] = self.channels[e.channel] or {users={}, log={}}
223   - self:addMessage(kind, e.channel, e.login, {e.name, color}, "#{italic}##"..acolor.."#has earned the achievement <"..e.msg..">"..first.."#{normal}#", nil, true)
  222 + self:addMessage(kind, e.channel, e.login, {uname, color}, "#{italic}##"..acolor.."#has earned the achievement <"..e.msg..">"..first.."#{normal}#", nil, true)
224 223
225 224 if type(game) == "table" and game.logChat and self.cur_channel == e.channel then
226 225 game.logChat("#"..acolor.."#%s has earned the achievement <%s>%s", e.name, e.msg, first)
227 226 end
228 227 elseif e.se == "SerialData" then
229   - local color = colors.WHITE
230   - if e.status == 'dev' then color = colors.CRIMSON
231   - elseif e.status == 'mod' then color = colors.GOLD
232   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
233   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
234   - e.color_name = color
  228 + local color, uname = self:getUserColor(e)
235 229
236 230 local data = zlib.decompress(e.msg)
237 231 if not data then return end
... ... @@ -259,8 +253,6 @@ Again, thank you, and enjoy Eyal!
259 253
260 254 #{italic}#Your malevolent local god of darkness, #GOLD#DarkGod#{normal}#]]):format(data.donated, data.donated * 10, data.items_vault_slots)
261 255 Dialog:simpleLongPopup("Thank you!", text, 600)
262   - elseif self.uc_ext then
263   - self.uc_ext:event(e)
264 256 end
265 257 elseif e.se == "SelfJoin" then
266 258 self:addMessage("join", e.channel, profile.auth.login, e.channel, "#{italic}#Joined channel#{normal}#", nil, true)
... ... @@ -272,58 +264,42 @@ Again, thank you, and enjoy Eyal!
272 264 self:updateChanList()
273 265 self:saveChannels()
274 266 elseif e.se == "Join" then
275   - local color = colors.WHITE
276   - if e.status == 'dev' then color = colors.CRIMSON
277   - elseif e.status == 'mod' then color = colors.GOLD
278   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
279   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  267 + local color, uname = self:getUserColor(e)
280 268
281 269 self.channels[e.channel] = self.channels[e.channel] or {users={}, log={}}
282 270 self.channels[e.channel].users[e.login] = {name=e.name, donator=e.donator, status=e.status, login=e.login}
283 271 self.channels_changed = true
284   - self:addMessage("join", e.channel, e.login, {e.name, color}, "#{italic}##FIREBRICK#has joined the channel#{normal}#", nil, true)
  272 + self:addMessage("join", e.channel, e.login, {uname, color}, "#{italic}##FIREBRICK#has joined the channel#{normal}#", nil, true)
285 273 if type(game) == "table" and game.logChat and e.channel == self.cur_channel then
286 274 game.logChat("#{italic}##FIREBRICK#%s has joined channel %s (press space to talk).#{normal}#", e.login, e.channel)
287 275 end
288 276 self:updateChanList()
289 277 elseif e.se == "Part" then
290   - local color = colors.WHITE
291   - if e.status == 'dev' then color = colors.CRIMSON
292   - elseif e.status == 'mod' then color = colors.GOLD
293   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
294   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  278 + local color, uname = self:getUserColor(e)
295 279
296 280 self.channels[e.channel] = self.channels[e.channel] or {users={}, log={}}
297 281 self.channels[e.channel].users[e.login] = nil
298 282 self.channels_changed = true
299   - self:addMessage("join", e.channel, e.login, {e.name, color}, "#{italic}##FIREBRICK#has left the channel#{normal}#", nil, true)
  283 + self:addMessage("join", e.channel, e.login, {uname, color}, "#{italic}##FIREBRICK#has left the channel#{normal}#", nil, true)
300 284 if type(game) == "table" and game.logChat and e.channel == self.cur_channel then
301 285 game.logChat("#{italic}##FIREBRICK#%s has left channel %s.#{normal}#", e.login, e.channel)
302 286 end
303 287 self:updateChanList()
304 288 elseif e.se == "FriendJoin" then
305   - local color = colors.WHITE
306   - if e.status == 'dev' then color = colors.CRIMSON
307   - elseif e.status == 'mod' then color = colors.GOLD
308   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
309   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  289 + local color, uname = self:getUserColor(e)
310 290
311 291 self.friends[e.login] = {name=e.name, donator=e.donator, status=e.status, login=e.login}
312 292 if not e.silent then
313   - self:addMessage("friendjoin", self.cur_channel, e.login, {e.name, color}, "#{italic}##YELLOW_GREEN#has logged in#{normal}#", nil, true)
  293 + self:addMessage("friendjoin", self.cur_channel, e.login, {uname, color}, "#{italic}##YELLOW_GREEN#has logged in#{normal}#", nil, true)
314 294 if type(game) == "table" and game.logChat then
315 295 game.logChat("#{italic}##YELLOW_GREEN#%s has logged in (press space to talk).#{normal}#", e.login, e.channel)
316 296 end
317 297 end
318 298 elseif e.se == "FriendPart" then
319   - local color = colors.WHITE
320   - if e.status == 'dev' then color = colors.CRIMSON
321   - elseif e.status == 'mod' then color = colors.GOLD
322   - elseif e.donator == "oneshot" then color = colors.LIGHT_GREEN
323   - elseif e.donator == "recurring" then color = colors.ROYAL_BLUE end
  299 + local color, uname = self:getUserColor(e)
324 300
325 301 self.friends[e.login] = nil
326   - self:addMessage("friendpart", self.cur_channel, e.login, {e.name, color}, "#{italic}##CRIMSON#has logged off#{normal}#", nil, true)
  302 + self:addMessage("friendpart", self.cur_channel, e.login, {uname, color}, "#{italic}##CRIMSON#has logged off#{normal}#", nil, true)
327 303 if type(game) == "table" and game.logChat then
328 304 game.logChat("#{italic}##CRIMSON#%s has logged off.#{normal}#", e.login, e.channel)
329 305 end
... ... @@ -351,6 +327,10 @@ Again, thank you, and enjoy Eyal!
351 327 self.channels_changed = true
352 328 end
353 329
  330 + if self.uc_ext then
  331 + self.uc_ext:event(e)
  332 + end
  333 +
354 334 for fct, _ in pairs(self.on_event) do
355 335 fct(e)
356 336 end
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -769,7 +769,8 @@ function _M:addEntity(level, e, typ, x, y, no_added)
769 769 if x and y then level.map(x, y, Map.TRIGGER, e) end
770 770 end
771 771 e:check("addedToLevel", level, x, y)
772   - e:check("on_added", level, x, y)
  772 + e:check("on_added", level, x, y) -- Sustains are activated here
  773 + e:check("on_added_final", level, x, y)
773 774 end
774 775
775 776 --- If we are loaded we need a new uid
... ... @@ -811,6 +812,7 @@ function _M:load(dynamic)
811 812 data = dynamic
812 813 ret = false
813 814 for k, e in pairs(data) do self[k] = e end
  815 + self:onLoadZoneFile(false)
814 816 self:triggerHook{"Zone:create", dynamic=dynamic}
815 817 if self.on_loaded then self:on_loaded() end
816 818 else
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -250,7 +250,7 @@ end)
250 250 -- this requires the ActorFOV interface, or an interface that provides self.fov.actors*
251 251 newAI("target_simple", function(self)
252 252 -- keep same (hostile) target 90% of the time
253   - if self.ai_target.actor and not self.ai_target.actor.dead and self:reactionToward(act) < 0 and rng.percent(90) then return true end
  253 + if self.ai_target.actor and not self.ai_target.actor.dead and self:reactionToward(self.ai_target.actor) < 0 and rng.percent(90) then return true end
254 254
255 255 -- Find closer enemy and target it
256 256 -- Get list of actors ordered by distance
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -278,11 +278,14 @@ function _M:cloneFull(post_copy)
278 278 end
279 279
280 280 --- Automatically called by cloneCustom()
281   -local function cloneCustomRecurs(clonetable, d, noclonecall, use_saveinstead, alt_nodes)
  281 +local function cloneCustomRecurs(clonetable, d, noclonecall, use_saveinstead, alt_nodes, type_checker, first)
282 282 if use_saveinstead and (d.__ATOMIC or d.__CLASSNAME) and d.__SAVEINSTEAD then
283 283 d = d.__SAVEINSTEAD
284 284 if clonetable[d] then return d, 1 end
285 285 end
  286 + if not first and type_checker and d.__CLASSNAME then
  287 + if not type_checker(d) then return d, 1 end
  288 + end
286 289
287 290 local nb = 0
288 291 local add
... ... @@ -313,11 +316,11 @@ local function cloneCustomRecurs(clonetable, d, noclonecall, use_saveinstead, al
313 316 if ne_alt ~= nil then ne = ne_alt else ne = e end
314 317
315 318 if clonetable[nk] then nk = clonetable[nk]
316   - elseif type(nk) == "table" then nk, add = cloneCustomRecurs(clonetable, nk, noclonecall, use_saveinstead, alt_nodes) nb = nb + add
  319 + elseif type(nk) == "table" then nk, add = cloneCustomRecurs(clonetable, nk, noclonecall, use_saveinstead, alt_nodes, type_checker, false) nb = nb + add
317 320 end
318 321
319 322 if clonetable[ne] then ne = clonetable[ne]
320   - elseif type(ne) == "table" and (type(nk) ~= "string" or nk ~= "__threads") then ne, add = cloneCustomRecurs(clonetable, ne, noclonecall, use_saveinstead, alt_nodes) nb = nb + add
  323 + elseif type(ne) == "table" and (type(nk) ~= "string" or nk ~= "__threads") then ne, add = cloneCustomRecurs(clonetable, ne, noclonecall, use_saveinstead, alt_nodes, type_checker, false) nb = nb + add
321 324 end
322 325
323 326 n[nk] = ne
... ... @@ -340,11 +343,12 @@ end
340 343 -- @ or nil to use the default name/ref as keys on the clone
341 344 -- @ v = the value to assign for instances of this node,
342 345 -- @ or nil to use the default assignment value
  346 +-- @param[type=function] type_checker Optional, a function that returns true if the given object is to be cloned and false if it is to be referenced
343 347 -- @param[type=table] post_copy Optional, a table to be merged (recursively) with the new object after cloning.
344 348 -- @return a reference to the clone
345   -function _M:cloneCustom(alt_nodes, post_copy)
  349 +function _M:cloneCustom(alt_nodes, type_checker, post_copy)
346 350 local clonetable = {}
347   - local n = cloneCustomRecurs(clonetable, self, nil, nil, alt_nodes)
  351 + local n = cloneCustomRecurs(clonetable, self, nil, nil, alt_nodes, type_checker, true)
348 352 if post_copy then
349 353 table.merge(n, post_copy, true)
350 354 end
... ... @@ -389,6 +393,15 @@ function _M:setCurrentHookDir(dir)
389 393 _current_hook_dir = dir
390 394 end
391 395
  396 +function _M:loadHooksFile(file)
  397 + assert(_current_hook_dir, "loadHooksFile can only be used in hooks/load.lua")
  398 +
  399 + local f, err = loadfile(_current_hook_dir.."/"..file)
  400 + if not f and err then error(err) end
  401 + setfenv(f, setmetatable({}, {__index = _G}))
  402 + f()
  403 +end
  404 +
392 405 function _M:bindHook(hook, fct)
393 406 if type(fct) == "string" and _current_hook_dir then
394 407 local f, err = loadfile(_current_hook_dir..fct..".lua")
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -46,8 +46,8 @@ function _M:init(chat, id, width)
46 46
47 47 self:generateList()
48 48
49   - self.c_desc = Textzone.new{width=self.iw - 10 - xoff, height=1, auto_height=true, text=self.text.."\n"}
50   - self.c_list = VariableList.new{width=self.iw - 10 - xoff, max_height=game.h * 0.70 - self.c_desc.h, list=self.list, fct=function(item) self:use(item) end, select=function(item) self:select(item) end}
  49 + self.c_desc = Textzone.new{font=chat.dialog_text_font, width=self.iw - 10 - xoff, height=1, auto_height=true, text=self.text.."\n"}
  50 + self.c_list = VariableList.new{font=chat.dialog_answer_font, width=self.iw - 10 - xoff, max_height=game.h * 0.70 - self.c_desc.h, list=self.list, fct=function(item) self:use(item) end, select=function(item) self:select(item) end}
51 51
52 52 local uis = {
53 53 {left=0, top=0, ui=self.c_desc},
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5 5 -- it under the terms of the GNU General Public License as published by
... ... @@ -131,7 +131,7 @@ function _M:onDownload(handlers)
131 131 local Dialog = require "engine.ui.Dialog"
132 132
133 133 handlers.on_download_request = function(downid, url, file, mime)
134   - if mime == "application/t-engine-addon" and self.allow_downloads.addons and url:find("^http://te4%.org/") then
  134 + if mime == "application/t-engine-addon" and self.allow_downloads.addons and url:find("^https://te4%.org/") then
135 135 local name = file
136 136 if self._next_download_name and os.time() - self._next_download_name.time <= 3 then name = self._next_download_name.name self._next_download_name = nil end
137 137 print("Accepting addon download to:", self.dest)
... ... @@ -140,7 +140,7 @@ function _M:onDownload(handlers)
140 140 game:registerDialog(self.download_dialog)
141 141 self.view:downloadAction(downid, self.dest)
142 142 return
143   - elseif mime == "application/t-engine-module" and self.allow_downloads.modules and url:find("^http://te4%.org/") then
  143 + elseif mime == "application/t-engine-module" and self.allow_downloads.modules and url:find("^https://te4%.org/") then
144 144 local name = file
145 145 if self._next_download_name and os.time() - self._next_download_name.time <= 3 then name = self._next_download_name.name self._next_download_name = nil end
146 146 print("Accepting module download to:", self.dest)
... ...
1 1 -- TE4 - T-Engine 4
2   --- Copyright (C) 2009 - 2017 Nicolas Casalini
  2 +-- Copyright (C) 2009 - 2018 Nicolas Casalini
3 3 --
4 4 -- This program is free software: you can redistribute it and/or modify
5