Comment: | many bug fixers, some minor refactoring, allow non-drinkable potions to be empowered in various ways, allow gods to be petitioned for recipes (next up: cookbooks!) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c71731cf588f3c6b783992fc2455d645 |
User & Date: | lexi on 2021-07-03 02:25:42 |
Other Links: | manifest | tags |
2021-07-04
| ||
20:27 | add cool and informative visuals for taps, add more capacity to rune forge, many bug fixes, fixed some bugs, and fixed some bugs check-in: 94064fe5c9 user: lexi tags: trunk | |
2021-07-03
| ||
02:25 | many bug fixers, some minor refactoring, allow non-drinkable potions to be empowered in various ways, allow gods to be petitioned for recipes (next up: cookbooks!) check-in: c71731cf58 user: lexi tags: trunk | |
2021-06-28
| ||
18:31 | defuckulate markdown check-in: fa442a5d6a user: lexi tags: trunk | |
Modified altar.lua from [a7a1197203] to [080406f8d2].
1 2 3 4 5 6 7 8 9 10 11 .. 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 ... 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 ... 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
local altar_item_offset = { x = 0, y = -0.3, z = 0 } local log = function(...) sorcery.log('altar',...) end local range = function(min, max) local span = max - min local val = math.random() * span return val + min end ................................................................................ after_place_node = function(pos, placer, stack, pointat) local meta = minetest.get_meta(pos) local stackmeta = stack:get_meta() meta:set_int('favor', stackmeta:get_int('favor')) meta:set_string('last_sacrifice', stackmeta:get_string('last_sacrifice')) minetest.get_node_timer(pos):start(60) end; drop = { -- for some idiot reason this is necessary for -- preserve_metadata to work right max_items = 1; items = { ................................................................................ -- we pick a random gift and roll against its rarity -- to determine if the god is feeling generous local gift = sorcery.lib.tbl.pick(god.gifts) local data = god.gifts[gift] local value, rarity = data[1], data[2] if value <= divine_favor and math.random(rarity) == 1 then bestow(gift) log(god.name .. ' has produced ' .. gift .. ' upon an altar as a gift') if math.random(god.generosity) == 1 then -- unappreciated gifts may incur divine -- irritation divine_favor = divine_favor - 1 end end end ................................................................................ goto refresh end end -- loop through the list of things this god will consecrate and -- check whether the item on the altar is any of them for s, cons in pairs(god.consecrate) do local cost, tx = cons[1], cons[2] if type(tx) == "table" then tx = tx[math.random(#tx)] end -- preserve wear local gift = ItemStack(tx) local wear = stack:get_wear() if wear > 0 then gift:set_wear(wear) end -- preserve meta gift:get_meta():from_table(stack:get_meta():to_table()) -- reflash enchantments to ensure label is accurate local ench = sorcery.enchant.get(gift) if #ench.spells > 0 then -- add a bit of energy as a gift? if math.random(math.ceil(god.stinginess * 0.5)) == 1 then local max = 0.05 * god.generosity ench.energy = ench.energy * range(0.7*max,max) end sorcery.enchant.set(gift,ench) end if itemname == s then if divine_favor >= cost then bestow(gift) divine_favor = divine_favor - cost print(god.name..'has consecrated ' ..s.. ' into ' ..tx.. ', for the cost of ' ..cost.. ' points of divine favor') goto refresh end end end end ::refresh:: |
| | | > | | > | > > > > > > > > | | > > | > | | | | | > > > | > > > | | | | | | | | | | < > | |
1 2 3 4 5 6 7 8 9 10 11 .. 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 ... 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 ... 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
local altar_item_offset = { x = 0, y = -0.3, z = 0 } local log = sorcery.logger('altar') local range = function(min, max) local span = max - min local val = math.random() * span return val + min end ................................................................................ after_place_node = function(pos, placer, stack, pointat) local meta = minetest.get_meta(pos) local stackmeta = stack:get_meta() meta:set_int('favor', stackmeta:get_int('favor')) meta:set_string('last_sacrifice', stackmeta:get_string('last_sacrifice')) minetest.get_node_timer(pos):start(1) end; drop = { -- for some idiot reason this is necessary for -- preserve_metadata to work right max_items = 1; items = { ................................................................................ -- we pick a random gift and roll against its rarity -- to determine if the god is feeling generous local gift = sorcery.lib.tbl.pick(god.gifts) local data = god.gifts[gift] local value, rarity = data[1], data[2] if value <= divine_favor and math.random(rarity) == 1 then bestow(gift) log.act(god.name .. ' has produced ' .. gift .. ' upon an altar as a gift') if math.random(god.generosity) == 1 then -- unappreciated gifts may incur divine -- irritation divine_favor = divine_favor - 1 end end end ................................................................................ goto refresh end end -- loop through the list of things this god will consecrate and -- check whether the item on the altar is any of them for s, cons in pairs(god.consecrate) do if itemname == s then local cost, tx if type(cons) == "table" then cost, tx = cons[1], cons[2] tx = tx[math.random(#tx)] elseif type(cons) == 'function' then cost, tx = cons { favor = divine_favor; pos = pos; altar = altarmeta; idol = idolmeta; god = god; } end -- preserve wear local gift if type(tx) == 'string' then gift = ItemStack(tx) else gift = tx end local wear = stack:get_wear() if wear > 0 then gift:set_wear(wear) end -- preserve meta local gm = gift:get_meta() gm:from_table( sorcery.lib.tbl.merge( stack:get_meta():to_table(), gm:to_table() ) ) -- oof -- reflash enchantments to ensure label is accurate local ench = sorcery.enchant.get(gift) if #ench.spells > 0 then -- add a bit of energy as a gift? if math.random(math.ceil(god.stinginess * 0.5)) == 1 then local max = 0.05 * god.generosity ench.energy = ench.energy * range(0.7*max,max) end sorcery.enchant.set(gift,ench) end if divine_favor >= cost then bestow(gift) divine_favor = divine_favor - cost log.act(god.name, 'has consecrated', s, 'into', tx, 'for the cost of', cost, 'points of divine favor') goto refresh end end end end ::refresh:: |
Modified astrolabe.lua from [a9316d6c59] to [cc031237ac].
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
local r = {}
for i,v in ipairs(k) do
r[i] = {
id = k[i];
name = sorcery.data.calendar.styles[v].name;
}
end
print(dump(r))
return r
end
local astrolabe_formspec = function(pos)
local m = minetest.get_meta(pos)
local i = m:get_inventory()
local datestamp = minetest.get_day_count()
local date = sorcery.calendar.date(datestamp)
|
< |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
local r = {} for i,v in ipairs(k) do r[i] = { id = k[i]; name = sorcery.data.calendar.styles[v].name; } end return r end local astrolabe_formspec = function(pos) local m = minetest.get_meta(pos) local i = m:get_inventory() local datestamp = minetest.get_day_count() local date = sorcery.calendar.date(datestamp) |
Modified cookbook.lua from [e643a56c3c] to [aae72d93b8].
1 2 3 4 5 6 7 8 9 10 11 12 13 .. 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 ... 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 ... 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 ... 400 401 402 403 404 405 406 407 408 409 410 411 412 413 ... 464 465 466 467 468 469 470 471 472 473 474 475 476 477 |
-- by use of the enchanter, it is possible to reveal a random -- recipe and enscribe it on a sheet of paper. these sheets of -- paper can then bound together into books, combining like -- recipes sorcery.cookbook = {} local constants = { -- do not show recipes for items in these groups exclude_groups = { }; exclude_names = { 'stairs'; 'slab'; ................................................................................ return {} end local modofname = function(id) local sep = string.find(id,':') if sep == nil then return nil end -- uh oh return string.sub(id, 1, sep - 1) end local pick_builtin = function(kind) return function(restrict) -- ow ow ow ow ow ow ow local names = {} for k in pairs(minetest.registered_items) do local rec = minetest.get_craft_recipe(k) if rec.items ~= nil and (rec.method == kind or (rec.method == 'shapeless' and kind == 'normal')) then -- is this last bit necessary? local excluded = false for _,n in pairs(constants.exclude_names) do if string.find(k,n) ~= nil then excluded = true break end end if not excluded then for _,g in pairs(constants.exclude_groups) do if minetest.get_item_group(k, g) > 0 then excluded = true break end end end local props = minetest.registered_items[k]._sorcery local module = modofname(k) if not (excluded or sorcery.lib.tbl.has(constants.blacklist_mods,module) or (props and props.recipe and props.recipe.secret) or (restrict and ( (restrict.mod and module ~= restrict.mod) or (restrict.group and (minetest.get_item_group(k, restrict.group) == 0)) ))) then names[#names + 1] = k end end end return names[math.random(#names)] end end local find_builtin = function(method,kind) return function(out) local rec = {} ................................................................................ chance = 4; slots = { {0,0}; {0,1}; }; pick = function(restrict) -- TODO make sure affinity restrictions match return sorcery.register.infusions.db[math.random(#sorcery.register.infusions.db)].output end; title = function(output) for _,i in pairs(sorcery.register.infusions.db) do if i.output == output then if i._proto and i._proto.name then return i._proto.name else break end ................................................................................ name = 'Milling Guide'; node = 'sorcery:mill'; booksuf = 'Manual'; chance = 1; w = 1, h = 2; pick = function(restrict) cache:populate_grindables() local i = cache.grindables[math.random(#cache.grindables)] local pd = sorcery.itemclass.get(i, 'grindable') return pd.powder end; props = props_builtin; slots = { {0,1}, {0,0}; }; find = function(out) ................................................................................ end if kind == nil then -- oh well, we tried local rks = sorcery.lib.tbl.keys(recipe_kinds) kind = rks[math.random(#rks)] end end return recipe_kinds[kind].pick(restrict), kind end local render_recipe = function(kind,ingredients,result,notes_right) local k = recipe_kinds[kind] local t = '' local props = k.props(result) ................................................................................ local ing = rec.find(out) return render_recipe(kind,ing,out,notes_right), rec.w, rec.h end sorcery.cookbook.setrecipe = function(stack,k,r,restrict) local meta = stack:get_meta() if not r then r,k = sorcery.cookbook.pickrecipe(k,restrict) end local t = recipe_kinds[k] meta:set_string('recipe_kind', k) meta:set_string('recipe_name', r) meta:set_string('description', (t.title and t.title(r) or desc_builtin(r)) .. ' ' .. t.name) end |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < < | > > > > > > > > > > > > > > | > > > > > > > > > > > | | | > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 .. 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 ... 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 ... 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 ... 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 ... 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 |
-- by use of the enchanter, it is possible to reveal a random -- recipe and enscribe it on a sheet of paper. these sheets of -- paper can then bound together into books, combining like -- recipes sorcery.cookbook = {} local log = sorcery.logger('cookbook') local constants = { -- do not show recipes for items in these groups exclude_groups = { }; exclude_names = { 'stairs'; 'slab'; ................................................................................ return {} end local modofname = function(id) local sep = string.find(id,':') if sep == nil then return nil end -- uh oh return string.sub(id, 1, sep - 1) end local item_restrict_eval = function(name, restrict) for _,n in pairs(constants.exclude_names) do if string.find(name,n) ~= nil then return false end end for _,g in pairs(constants.exclude_groups) do if minetest.get_item_group(name, g) > 0 then return false end end local props = minetest.registered_items[name]._sorcery local module = modofname(name) return not (excluded or sorcery.lib.tbl.has(constants.blacklist_mods,module) or (props and props.recipe and props.recipe.secret) or (restrict and ( (restrict.pred and restrict.pred { mod = module, item = name, props = props } ~= true) or (restrict.mod and module ~= restrict.mod) or (restrict.group and (minetest.get_item_group(name, restrict.group) == 0)) ))) end local pick_builtin = function(kind) return function(restrict) -- ow ow ow ow ow ow ow local names = {} for k in pairs(minetest.registered_items) do local rec = minetest.get_craft_recipe(k) if rec.items ~= nil and (rec.method == kind or (rec.method == 'shapeless' and kind == 'normal')) then -- is this last bit necessary? if item_restrict_eval(k, restrict) then names[#names + 1] = k end end end return names[math.random(#names)] end end local find_builtin = function(method,kind) return function(out) local rec = {} ................................................................................ chance = 4; slots = { {0,0}; {0,1}; }; pick = function(restrict) -- TODO make sure affinity restrictions match if restrict then local t = {} for _, i in pairs(sorcery.register.infusions.db) do if item_restrict_eval(i.output, restrict) and not ( -- conditions which cause failure of restriction test (restrict.ipred and restrict.ipred { mod = module; infusion = i; output = i.output; } ~= true) ) then t[#t+1] = i.output end end return select(2, sorcery.lib.tbl.pick(t)) else return sorcery.register.infusions.db[math.random(#sorcery.register.infusions.db)].output end end; title = function(output) for _,i in pairs(sorcery.register.infusions.db) do if i.output == output then if i._proto and i._proto.name then return i._proto.name else break end ................................................................................ name = 'Milling Guide'; node = 'sorcery:mill'; booksuf = 'Manual'; chance = 1; w = 1, h = 2; pick = function(restrict) cache:populate_grindables() if restrict then local t = {} for _, i in pairs(cache.grindables) do local pd = sorcery.itemclass.get(i, 'grindable') if item_restrict_eval(pd.powder, restrict) then t[#t+1] = pd.powder end end return select(2, sorcery.lib.tbl.pick(t)) else local gd = cache.grindables[math.random(#cache.grindables)] local pd = sorcery.itemclass.get(gd, 'grindable') return pd.powder end end; props = props_builtin; slots = { {0,1}, {0,0}; }; find = function(out) ................................................................................ end if kind == nil then -- oh well, we tried local rks = sorcery.lib.tbl.keys(recipe_kinds) kind = rks[math.random(#rks)] end end if not recipe_kinds[kind] then log.fatalf('attempted to pick recipe of unknown kind "%s"', kind) end return recipe_kinds[kind].pick(restrict), kind end local render_recipe = function(kind,ingredients,result,notes_right) local k = recipe_kinds[kind] local t = '' local props = k.props(result) ................................................................................ local ing = rec.find(out) return render_recipe(kind,ing,out,notes_right), rec.w, rec.h end sorcery.cookbook.setrecipe = function(stack,k,r,restrict) local meta = stack:get_meta() if not r then r,k = sorcery.cookbook.pickrecipe(k,restrict) end if not r then return false end local t = recipe_kinds[k] meta:set_string('recipe_kind', k) meta:set_string('recipe_name', r) meta:set_string('description', (t.title and t.title(r) or desc_builtin(r)) .. ' ' .. t.name) end |
Modified data/draughts.lua from [ab3b6e4e1b] to [0a84465667].
6 7 8 9 10 11 12 13 14 15 16 17 18 19 .. 27 28 29 30 31 32 33 34 35 36 37 38 39 40 .. 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 .. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 .. 85 86 87 88 89 90 91 92 93 94 95 96 97 98 ... 108 109 110 111 112 113 114 115 116 117 118 119 120 121 ... 129 130 131 132 133 134 135 136 137 138 139 140 141 142 ... 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 ... 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
style = 'sparkle'; desc = "A potion that amps up your body's natural\nhealing abilities, causing you to heal rapidly\neven if you're starving"; infusion = 'sorcery:blood'; basis = 'sorcery:potion_luminous'; duration = function(self,meta) return 10 + meta:get_int('duration')*2 end; effect = function(self, user, proto) local meta = self:get_meta() local force = 1 + meta:get_int('force') late.new_effect(user, { duration = proto:duration(meta); raise = 4; fall = 4; impacts = { ................................................................................ color = {79,228,243}; style = 'sparkle'; basis = 'sorcery:potion_luminous'; desc = "Conserve your precious supply of oxygen when diving down into the ocean's depths"; infusion = 'sorcery:extract_kelp'; duration = function(self,meta) return 20 + meta:get_int('duration')*30 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 1 + 2 * (meta:get_int('force')) late.new_effect(user, { duration = proto:duration(meta); raise = 2; fall = 5; impacts = { ................................................................................ }) end; }; heal = { name = 'Healing'; color = {243,44,58}; style = 'sparkle'; no_duration = true; desc = 'This blood-red liquid glitters with an enchantment that rapidly knits torn flesh and broken bones'; infusion = 'sorcery:oil_sanguine'; basis = 'sorcery:potion_luminous'; effect = function(self, user) local meta = self:get_meta() user:set_hp(user:get_hp() + (2 * (2 + meta:get_int('force')))) end; ................................................................................ stealth = { name = 'Stealth'; color = {184,106,224}; style = 'sparkle'; infusion = 'default:coal_lump'; basis = 'sorcery:potion_soft'; desc = 'Drinking this dark, swirling draught will shelter you from the power of mortal perception for a time, even rendering you entirely invisible at full strength.'; duration = function(self,meta) return 30 + meta:get_int('duration')*30 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 1 + 1 * (meta:get_int('force')) local opacity = 1.0 - (1.0 * (force / 4)) ................................................................................ nightsight = { name = 'Nightsight'; color = {91,0,200}; style = 'sparkle'; desc = 'While this potion flows through your veins, your vision will be strengthened against the darkness of the night'; maxforce = 3; infusion = 'sorcery:oil_dawn'; basis = 'sorcery:potion_soft'; duration = function(self,meta) return 50 + meta:get_int('duration')*70 end; effect = function(self,user,proto) --TODO ensure it can only be drunk at night --TODO ensure it can't last more than one night local meta = self:get_meta() ................................................................................ }; antigravity = { name = 'Antigravity'; color = {240,59,255}; style = 'sparkle'; desc = 'Loosen the crushing grip of the earth upon your tender mortal form with a few sips from this glittering phial'; infusion = 'sorcery:oil_stone'; basis = 'sorcery:potion_soft'; duration = function(self,meta) return 20 + meta:get_int('duration')*25 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 1 - 0.3 * (meta:get_int('force') + 1) late.new_effect(user, { ................................................................................ }; gale = { name = 'Gale'; color = {187,176,203}; desc = 'Move and strike with the speed of a hurricane as this enchanted fluid courses through your veins'; infusion = 'sorcery:grease_storm'; basis = 'sorcery:potion_soft'; duration = function(self,meta) return 10 + meta:get_int('duration')*15 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 2 + 0.7 * (meta:get_int('force')) late.new_effect(user, { ................................................................................ obsidian = { name = 'Obsidian'; infusion = 'default:obsidian_shard'; color = {76,0,121}; style = 'sparkle'; desc = 'Walk untroubled through volleys of arrows and maelstroms of swinging blades, for all will batter uselessly against skin protected by spellwork mightier than the doughtiest armor'; infusion = 'default:obsidian_shard'; basis = 'sorcery:potion_luminous'; no_force = true; duration = function(self,meta) return 5 + meta:get_int('duration')*7 end; }; lavabreathing = { name = 'Lavabreathing'; color = {243,118,79}; style = 'sparkle'; glow = 12; basis = 'sorcery:potion_soft'; desc = "Wade through seas of roiling lava as easily as though it were but a babbling brook"; }; -- mighty = { -- name = 'Mighty'; -- color = {255,0,119}; style = 'sparkle'; glow = 5; -- infusion = 'sorcery:grease_war'; -- basis = 'sorcery:potion_soft'; -- desc = 'Amplify the power of your blows and crack steel armor with the force of your bare hands'; -- }; resilient = { name = 'Resilient'; color = {124,124,124}; style = 'dull'; basis = 'sorcery:potion_soft'; desc = 'Withstand greater damage and hold your ground even in face of tremendous force'; }; hover = { name = 'Hover'; color = {164,252,55}; style = 'sparkle'; desc = 'Rise into the air for a time and stay there until the potion wears off'; basis = 'sorcery:potion_soft'; }; flight = { name = 'Flight'; color = {143,35,255}; style = 'sparkle'; desc = 'Free yourself totally from the shackles of gravity and soar through the air however you should will'; basis = 'sorcery:potion_soft'; infusion = 'sorcery:grease_lift'; no_force = true; duration = function(self,meta) return 40 + meta:get_int('duration')*55 end; effect = function(self,user,proto) late.new_effect(user, { duration = proto:duration(self:get_meta()); impacts = { ................................................................................ }; leap = { name = 'Leap'; color = {164,252,55}; desc = 'Soar high into the air each time you jump (but may risk damage if used without a Feather Potion)'; infusion = 'sorcery:oil_wind'; basis = 'sorcery:potion_soft'; duration = function(self,meta) return 5 + meta:get_int('duration')*7 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 2 + (0.5 * meta:get_int('force')) late.new_effect(user, { |
> > | > > > > | > > > | > |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 .. 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 .. 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 .. 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 .. 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 ... 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 ... 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 ... 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 ... 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
style = 'sparkle'; desc = "A potion that amps up your body's natural\nhealing abilities, causing you to heal rapidly\neven if you're starving"; infusion = 'sorcery:blood'; basis = 'sorcery:potion_luminous'; duration = function(self,meta) return 10 + meta:get_int('duration')*2 end; quals = { force = true, duration = true }; effect = function(self, user, proto) local meta = self:get_meta() local force = 1 + meta:get_int('force') late.new_effect(user, { duration = proto:duration(meta); raise = 4; fall = 4; impacts = { ................................................................................ color = {79,228,243}; style = 'sparkle'; basis = 'sorcery:potion_luminous'; desc = "Conserve your precious supply of oxygen when diving down into the ocean's depths"; infusion = 'sorcery:extract_kelp'; duration = function(self,meta) return 20 + meta:get_int('duration')*30 end; quals = { force = true, duration = true }; effect = function(self,user,proto) local meta = self:get_meta() local force = 1 + 2 * (meta:get_int('force')) late.new_effect(user, { duration = proto:duration(meta); raise = 2; fall = 5; impacts = { ................................................................................ }) end; }; heal = { name = 'Healing'; color = {243,44,58}; style = 'sparkle'; quals = { force = true }; desc = 'This blood-red liquid glitters with an enchantment that rapidly knits torn flesh and broken bones'; infusion = 'sorcery:oil_sanguine'; basis = 'sorcery:potion_luminous'; effect = function(self, user) local meta = self:get_meta() user:set_hp(user:get_hp() + (2 * (2 + meta:get_int('force')))) end; ................................................................................ stealth = { name = 'Stealth'; color = {184,106,224}; style = 'sparkle'; infusion = 'default:coal_lump'; basis = 'sorcery:potion_soft'; desc = 'Drinking this dark, swirling draught will shelter you from the power of mortal perception for a time, even rendering you entirely invisible at full strength.'; quals = { force = true, duration = true }; duration = function(self,meta) return 30 + meta:get_int('duration')*30 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 1 + 1 * (meta:get_int('force')) local opacity = 1.0 - (1.0 * (force / 4)) ................................................................................ nightsight = { name = 'Nightsight'; color = {91,0,200}; style = 'sparkle'; desc = 'While this potion flows through your veins, your vision will be strengthened against the darkness of the night'; maxforce = 3; infusion = 'sorcery:oil_dawn'; basis = 'sorcery:potion_soft'; quals = { force = true, duration = true }; duration = function(self,meta) return 50 + meta:get_int('duration')*70 end; effect = function(self,user,proto) --TODO ensure it can only be drunk at night --TODO ensure it can't last more than one night local meta = self:get_meta() ................................................................................ }; antigravity = { name = 'Antigravity'; color = {240,59,255}; style = 'sparkle'; desc = 'Loosen the crushing grip of the earth upon your tender mortal form with a few sips from this glittering phial'; infusion = 'sorcery:oil_stone'; basis = 'sorcery:potion_soft'; quals = { force = true, duration = true }; duration = function(self,meta) return 20 + meta:get_int('duration')*25 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 1 - 0.3 * (meta:get_int('force') + 1) late.new_effect(user, { ................................................................................ }; gale = { name = 'Gale'; color = {187,176,203}; desc = 'Move and strike with the speed of a hurricane as this enchanted fluid courses through your veins'; infusion = 'sorcery:grease_storm'; basis = 'sorcery:potion_soft'; quals = { force = true, duration = true }; duration = function(self,meta) return 10 + meta:get_int('duration')*15 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 2 + 0.7 * (meta:get_int('force')) late.new_effect(user, { ................................................................................ obsidian = { name = 'Obsidian'; infusion = 'default:obsidian_shard'; color = {76,0,121}; style = 'sparkle'; desc = 'Walk untroubled through volleys of arrows and maelstroms of swinging blades, for all will batter uselessly against skin protected by spellwork mightier than the doughtiest armor'; infusion = 'default:obsidian_shard'; basis = 'sorcery:potion_luminous'; quals = { duration = true }; duration = function(self,meta) return 5 + meta:get_int('duration')*7 end; }; lavabreathing = { name = 'Lavabreathing'; color = {243,118,79}; style = 'sparkle'; glow = 12; basis = 'sorcery:potion_soft'; desc = "Wade through seas of roiling lava as easily as though it were but a babbling brook"; quals = { duration = true }; }; -- mighty = { -- name = 'Mighty'; -- color = {255,0,119}; style = 'sparkle'; glow = 5; -- infusion = 'sorcery:grease_war'; -- basis = 'sorcery:potion_soft'; -- desc = 'Amplify the power of your blows and crack steel armor with the force of your bare hands'; -- }; resilient = { name = 'Resilient'; color = {124,124,124}; style = 'dull'; basis = 'sorcery:potion_soft'; desc = 'Withstand greater damage and hold your ground even in face of tremendous force'; quals = { force = true, duration = true }; }; hover = { name = 'Hover'; color = {164,252,55}; style = 'sparkle'; desc = 'Rise into the air for a time and stay there until the potion wears off'; basis = 'sorcery:potion_soft'; quals = { force = true, duration = true }; }; flight = { name = 'Flight'; color = {143,35,255}; style = 'sparkle'; desc = 'Free yourself totally from the shackles of gravity and soar through the air however you should will'; basis = 'sorcery:potion_soft'; infusion = 'sorcery:grease_lift'; quals = { duration = true }; duration = function(self,meta) return 40 + meta:get_int('duration')*55 end; effect = function(self,user,proto) late.new_effect(user, { duration = proto:duration(self:get_meta()); impacts = { ................................................................................ }; leap = { name = 'Leap'; color = {164,252,55}; desc = 'Soar high into the air each time you jump (but may risk damage if used without a Feather Potion)'; infusion = 'sorcery:oil_wind'; basis = 'sorcery:potion_soft'; quals = { force = true, duration = true }; duration = function(self,meta) return 5 + meta:get_int('duration')*7 end; effect = function(self,user,proto) local meta = self:get_meta() local force = 2 + (0.5 * meta:get_int('force')) late.new_effect(user, { |
Modified data/elixirs.lua from [b08a2041a5] to [ba37716134].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
return { Force = { color = {255,165,85}; flag = 'force'; apply = function(potion, kind) local meta = potion:get_meta() meta:set_int('force', meta:get_int('force') + 1) end; describe = function(potion) return 'good', 'empowered', "The strength of this potion's effect has been alchemically amplified" end; infusion = 'sorcery:grease_thunder'; }; Longevity = { color = {255,85,216}; flag = 'duration'; apply = function(potion, kind) local meta = potion:get_meta() meta:set_int('duration', meta:get_int('duration') + 1) end; describe = function(potion) return 'good', 'prolonged', 'The effects of this potion will last longer than normal' end; infusion = 'sorcery:grease_pine'; }; } |
| < < | | < > | > > > > > > | | < < < > > > > > > > | > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
local inc = function(prop, val) return function(potion, kind) local meta = potion:get_meta() meta:set_int(prop, meta:get_int(prop) + (val or 1)) end end return { Force = { color = {255,165,85}; qual = 'force'; apply = inc('force'); describe = function(potion) return 'good', 'empowered', "The strength of this potion's effect has been alchemically amplified" end; infusion = 'sorcery:grease_thunder'; }; Longevity = { color = {255,85,216}; qual = 'duration'; apply = inc('duration'); describe = function(potion) return 'good', 'prolonged', 'The effects of this potion will last longer than normal' end; infusion = 'sorcery:grease_pine'; }; Rapidity = { color = {183,28,238}; qual = 'speed'; apply = inc('speed'); describe = function(potion) return 'good', 'Quickened', 'This potion will take effect more quiclkly and easily' end; infusion = 'sorcery:liquid_sap_acacia_bottle'; }; Purity = { color = {244,255,255}; qual = 'purity'; apply = inc('purity'); describe = function(potion) return 'good', 'purified', 'This potion\'s impurities and undesirable side effects are diminished or eliminated' end; infusion = 'sorcery:oil_purifying'; }; Beauty = { color = {255,20,226}; qual = 'beauty'; apply = inc('beauty'); describe = function(potion) return 'good', 'beautified', 'The effects of this potion will be more vivid and spectacular than normal' end; infusion = 'sorcery:liquid_sap_apple_bottle'; }; -- Glory? -- Clarity? } |
Modified data/gods.lua from [4ff6f034b6] to [fc9658990d].
1 2 3 4 5 6 7 8 9 10 11 12 13 .. 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ... 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
return { harvest = { name = "Irix Irimentari" --[[ an old Elerian harvest goddess, Irix Irimentari has watched vigilantly over the fields of her worshippers since before the Second Age. she favors alcoholic beverages as tribute, and has been known to perform blessings for sorcerers when sufficiently inebriated. she harbors a particular hatred of daemons and those who spill the blood of farmers. legend says that a barbarian lord high on opium once wandered into a temple of Irix and left the severed head of a local shepherd on the her altar. this desecration so enraged the goddess that the barbarian's entire tribe soon starved horribly to death, their crops refusing to take root, and their stolen breads turning to ash in their mouths. ]]; laziness = 5; stinginess = 3; generosity = 10; color = {214, 255, 146}; idol = { desc = "Harvest Idol"; ................................................................................ "flowerpot:flowers_chrysanthemum_green"; "flowerpot:flowers_dandelion_white"; "flowerpot:flowers_dandelion_yellow"; }}; ["sorcery:dagger"] = {17, "sorcery:dagger_consecrated"}; ["sorcery:oil_mystic"] = {9, "sorcery:oil_purifying"}; ["sorcery:potion_water"] = {4, "sorcery:holy_water"}; -- ["default:steel_ingot"] = {15, "sorcery:holy_token_harvest"}; }; sacrifice = { -- beattitudes ["farming:straw" ] = 1; ["farming:bread_slice" ] = 1; ["farming:bread" ] = 2; ................................................................................ Force = {favor=50, cost=5, chance=7}; Longevity = {favor=65, cost=7, chance=3}; }; tools = { rend = {favor=80, cost=15, chance=20}; }; }; generosity = 4; stinginess = 9; idol = { desc = "Blood Idol"; width = 0.7; height = 1.3; tex = { |
> > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 .. 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 ... 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
local L = sorcery.lib return { harvest = { name = "Irix Irimentari" --[[ an old Elerian harvest goddess, Irix Irimentari has watched vigilantly over the fields of her worshippers since before the Second Age. she favors alcoholic beverages as tribute, and has been known to perform blessings for sorcerers when sufficiently inebriated. she harbors a particular hatred of daemons and those who spill the blood of farmers. legend says that a barbarian lord high on opium once wandered into a temple of Irix and left the severed head of a local shepherd on the her altar. this desecration so enraged the goddess that the barbarian's entire tribe soon starved horribly to death, their crops refusing to take root, and their stolen breads turning to ash in their mouths. in the mystic arts, she is the patron of Alchemy. it is said that Irix Irimentari herself invented alchemy when she brewed the first mead. ]]; laziness = 5; stinginess = 3; generosity = 10; color = {214, 255, 146}; idol = { desc = "Harvest Idol"; ................................................................................ "flowerpot:flowers_chrysanthemum_green"; "flowerpot:flowers_dandelion_white"; "flowerpot:flowers_dandelion_yellow"; }}; ["sorcery:dagger"] = {17, "sorcery:dagger_consecrated"}; ["sorcery:oil_mystic"] = {9, "sorcery:oil_purifying"}; ["sorcery:potion_water"] = {4, "sorcery:holy_water"}; ["default:paper"] = function(ctx) local stack = ItemStack('sorcery:recipe') local mode = select(2,L.tbl.pick{'cook','craft','infuse','grind'}) sorcery.cookbook.setrecipe(stack, mode, nil, { pred = function(c) local me = ctx.god if c.mod == 'farming' or minetest.get_item_group(c.item, 'sorcery_potion') ~= 0 or minetest.get_item_group(c.item, 'sorcery_oil') ~= 0 or minetest.get_item_group(c.item, 'sorcery_grease') ~= 0 or minetest.get_item_group(c.item, 'sorcery_extract') ~= 0 or me.sacrifice [c.item] or me.consecrate[c.item] then print(' !! accepted') return true end print(' -- rejected') end; }) return 1, stack end; -- ["default:steel_ingot"] = {15, "sorcery:holy_token_harvest"}; }; sacrifice = { -- beattitudes ["farming:straw" ] = 1; ["farming:bread_slice" ] = 1; ["farming:bread" ] = 2; ................................................................................ Force = {favor=50, cost=5, chance=7}; Longevity = {favor=65, cost=7, chance=3}; }; tools = { rend = {favor=80, cost=15, chance=20}; }; }; laziness = 2; generosity = 4; stinginess = 9; idol = { desc = "Blood Idol"; width = 0.7; height = 1.3; tex = { |
Modified data/spells.lua from [2d770c6227] to [f6d0b8e638].
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
if div.restrict and not div.restrict(ctx) then
return false
end
local dst
local bonus = math.floor(ctx.stats.power or 1)
if div.mode == 'any' then
local lst = sorcery.lib.tbl.cshuf(div.give)
dst = function(i) return lst[i] end
elseif div.mode == 'random' then
dst = function() return tblroll(bonus,div.give) end
elseif div.mode == 'set' then
dst = function(i) return div.give[i] end
elseif div.mode == 'all' then
dst = function() return div.give end
|
| |
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
if div.restrict and not div.restrict(ctx) then
return false
end
local dst
local bonus = math.floor(ctx.stats.power or 1)
if div.mode == 'any' then
local lst = sorcery.lib.tbl.scramble(div.give)
dst = function(i) return lst[i] end
elseif div.mode == 'random' then
dst = function() return tblroll(bonus,div.give) end
elseif div.mode == 'set' then
dst = function(i) return div.give[i] end
elseif div.mode == 'all' then
dst = function() return div.give end
|
Modified entities.lua from [5b6d6366ce] to [76a0b3b59c].
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
::collcheck:: do
-- if no collision then return end
-- local nname = minetest.get_node(pos).name
-- if nname == 'air' or minetest.registered_nodes[nname].walkable ~= true then return
-- elseif nname == 'ignore' then goto destroy end
-- else fall through to explode
if collision then -- since 5.3 only!!
print('collision detected!',dump(collision))
if collision.collides == false then return end
if #collision.collisions > 0 then
local col = collision.collisions[1]
if col.node_pos then
pos = col.node_pos
elseif col.object then
pos = col.object:get_pos()
|
< |
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
::collcheck:: do -- if no collision then return end -- local nname = minetest.get_node(pos).name -- if nname == 'air' or minetest.registered_nodes[nname].walkable ~= true then return -- elseif nname == 'ignore' then goto destroy end -- else fall through to explode if collision then -- since 5.3 only!! if collision.collides == false then return end if #collision.collisions > 0 then local col = collision.collisions[1] if col.node_pos then pos = col.node_pos elseif col.object then pos = col.object:get_pos() |
Modified infuser.lua from [6c01c64259] to [0b21397e89].
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 ... 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 ... 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
end local elixir_can_apply = function(elixir, potion) -- accepts an elixir def and potion def if elixir == nil or potion == nil then return false end if elixir.apply and potion.on_use then -- the ingredient is an elixir and at least one potion -- is a fully enchanted, usable potion if elixir.flag and potion._proto and potion._proto['no_' .. elixir.flag] == true then -- does the elixir have a property used to denote -- compatibility? if so, check the potion to see if it's -- marked as incompatible return false else return true end ................................................................................ return false end local effects_table = function(potion) local meta = potion:get_meta() local tbl = {} for k,v in pairs(sorcery.data.elixirs) do if not v.flag then goto skip end local val = meta:get_int(v.flag) if val > 0 then local aff, title, desc = v.describe(potion) if val > 3 then title = title .. ' x' .. val elseif val == 3 then title = 'thrice-' .. title elseif val == 2 then title = 'twice-' .. title end tbl[#tbl + 1] = { ................................................................................ sorcery.alchemy.elixir_apply = function(elixir, potion) if not potion then return end local pdef = potion:get_definition() if elixir_can_apply(elixir, pdef) then elixir.apply(potion, pdef._proto) potion:get_meta():set_string('description', sorcery.lib.ui.tooltip { title = pdef._proto.name .. ' Draught'; desc = pdef._proto.desc; color = sorcery.lib.color(pdef._proto.color):readable(); props = effects_table(potion); }); end return potion end ................................................................................ elseif r.enhance then if fx.onenhance then out = fx.onenhance { pos = pos; stack = out; potion = r.proto; elixir = r.elixir; } end log.act(dump(r)) log.act(string.format('an infuser at %s has enhanced a %s potion with a %s elixir', minetest.pos_to_string(pos), out:get_name(), infusion[1]:get_name())) end inv:set_stack('potions',i,discharge(out)) end inv:set_stack('infusion',1,residue) |
| | | | < | | | < |
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 ... 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 ... 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 ... 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
end local elixir_can_apply = function(elixir, potion) -- accepts an elixir def and potion def if elixir == nil or potion == nil then return false end if elixir.apply and potion._proto and potion._proto.quals then -- the ingredient is an elixir and at least one potion has a -- quality that can be enhanced if elixir.qual and potion._proto and not potion._proto.quals[elixir.qual] then -- does the elixir have a property used to denote -- compatibility? if so, check the potion to see if it's -- marked as incompatible return false else return true end ................................................................................ return false end local effects_table = function(potion) local meta = potion:get_meta() local tbl = {} for k,v in pairs(sorcery.data.elixirs) do if not v.qual then goto skip end local val = meta:get_int(v.qual) if val > 0 then local aff, title, desc = v.describe(potion) if val > 3 then title = title .. ' x' .. val elseif val == 3 then title = 'thrice-' .. title elseif val == 2 then title = 'twice-' .. title end tbl[#tbl + 1] = { ................................................................................ sorcery.alchemy.elixir_apply = function(elixir, potion) if not potion then return end local pdef = potion:get_definition() if elixir_can_apply(elixir, pdef) then elixir.apply(potion, pdef._proto) potion:get_meta():set_string('description', sorcery.lib.ui.tooltip { title = string.format('%s %s', pdef._proto.name, pdef._proto.kind.label); desc = pdef._proto.desc; color = sorcery.lib.color(pdef._proto.color):readable(); props = effects_table(potion); }); end return potion end ................................................................................ elseif r.enhance then if fx.onenhance then out = fx.onenhance { pos = pos; stack = out; potion = r.proto; elixir = r.elixir; } end log.act(string.format('an infuser at %s has enhanced a %s potion with a %s elixir', minetest.pos_to_string(pos), out:get_name(), infusion[1]:get_name())) end inv:set_stack('potions',i,discharge(out)) end inv:set_stack('infusion',1,residue) |
Modified init.lua from [58ff591804] to [3b59932455].
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
argjoin(arg, nxt, ...) if arg and not nxt then return tostring(arg) end if not arg then return "(nil)" end return tostring(arg) .. ' ' .. argjoin(nxt, ...) end local logger = function(module) local emit = function(lvl) return function(...) if module then minetest.log(lvl,string.format('[%s :: %s] %s',selfname,module,argjoin(...))) else minetest.log(lvl,string.format('[%s] %s',selfname,argjoin(...))) end end end return { info = emit('info'); warn = emit('warning'); err = emit('error'); act = emit('action'); } end; local stage = function(s,...) logger().info('entering stage',s) local f = sorcery.cfg(s .. '.lua') if test(f) then return loadfile(f)(...) or true end return false |
| | | | | | | | | | | | | | | > > > > > |
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
argjoin(arg, nxt, ...) if arg and not nxt then return tostring(arg) end if not arg then return "(nil)" end return tostring(arg) .. ' ' .. argjoin(nxt, ...) end local logger = function(module) local lg = {} local setup = function(fn, lvl) lvl = lvl or fn local function emit(...) local call = (fn == 'fatal') and error or function(str) minetest.log(lvl, str) end if module then call(string.format('[%s :: %s] %s',selfname,module,argjoin(...))) else call(string.format('[%s] %s',selfname,argjoin(...))) end end lg[fn ] = function(...) emit(...) end lg[fn .. 'f'] = function(...) emit(string.format(...)) end -- convenience fn end setup('info') setup('warn','warning') setup('err','error') setup('act','action') setup('fatal') return lg end; local stage = function(s,...) logger().info('entering stage',s) local f = sorcery.cfg(s .. '.lua') if test(f) then return loadfile(f)(...) or true end return false |
Modified keg.lua from [7838002de4] to [5c653d450d].
185 186 187 188 189 190 191 192 193 194 195 196 197 |
}) minetest.register_craft { output = "sorcery:keg"; recipe = { {'','screwdriver:screwdriver',''}; {'sorcery:screw_bronze', 'sorcery:tap', 'sorcery:screw_bronze'}; {'', 'xdecor:barrel', ''}; }; replacements = { {'screwdriver:screwdriver', 'screwdriver:screwdriver'}; }; } |
| |
185 186 187 188 189 190 191 192 193 194 195 196 197 |
}) minetest.register_craft { output = "sorcery:keg"; recipe = { {'','screwdriver:screwdriver',''}; {'sorcery:screw_bronze', 'sorcery:tap', 'sorcery:screw_bronze'}; {'sorcery:screw_bronze', 'xdecor:barrel', 'sorcery:screw_bronze'}; }; replacements = { {'screwdriver:screwdriver', 'screwdriver:screwdriver'}; }; } |
Modified lib/node.lua from [d8278e1811] to [087023acf7].
315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
if n.name == 'ignore' then minetest.load_area(sum) n = minetest.get_node(sum) end fn(sum, n) end end; force = force; -- when items have already been removed; notify cannot be relied on -- to reach the entire network; this function accounts for the gap notifyneighbors = function(pos) sorcery.lib.node.forneighbor(pos, sorcery.ley.txofs, function(sum,node) |
> > |
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
if n.name == 'ignore' then
minetest.load_area(sum)
n = minetest.get_node(sum)
end
fn(sum, n)
end
end;
amass = amass;
force = force;
-- when items have already been removed; notify cannot be relied on
-- to reach the entire network; this function accounts for the gap
notifyneighbors = function(pos)
sorcery.lib.node.forneighbor(pos, sorcery.ley.txofs, function(sum,node)
|
Modified lib/tbl.lua from [990a6e8caf] to [0fb14e1ea3].
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
for i = #list, 2, -1 do local j = math.random(i) list[i], list[j] = list[j], list[i] end return list end fn.cshuf = function(list) return fn.shuffle(table.copy(list)) end fn.urnd = function(min,max) local r = {} for i=min,max do r[1 + (i - min)] = i end fn.shuffle(r) ................................................................................ hash[v] = true new[#new+1] = v end end return new end fn.scramble = function(list) local new = table.copy(list) fn.shuffle(new) return new end fn.copy = function(t) local new = {} for i,v in pairs(t) do new[i] = v end setmetatable(new,getmetatable(t)) return new end |
|
<
<
<
<
<
<
|
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
for i = #list, 2, -1 do local j = math.random(i) list[i], list[j] = list[j], list[i] end return list end fn.scramble = function(list) return fn.shuffle(table.copy(list)) end fn.urnd = function(min,max) local r = {} for i=min,max do r[1 + (i - min)] = i end fn.shuffle(r) ................................................................................ hash[v] = true new[#new+1] = v end end return new end fn.copy = function(t) local new = {} for i,v in pairs(t) do new[i] = v end setmetatable(new,getmetatable(t)) return new end |
Modified liquid.lua from [04ca2e071b] to [6a40bd16e3].
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
sorcery.liquid.mktrough = function(liq) -- troughs are used for collecting liquid from the environment, -- like rainwater and tree sap. they hold twice as much as a bucket local Q = constants.glasses_per_bottle local trough_mkid = function(l,i) if type(l) == 'string' then l = sorcery.register.liquid.db[l] end if not l or not i then return 'sorcery:trough' end return string.format('%s:trough_%s_%u', l.mod,l.sid,i) end local lid = function(l) return trough_mkid(liq, l) end local M = constants.bottles_per_trough local mkbox = function(lvl) local pxl = function(tbl) -- for mapping to txcoords ................................................................................ end end sorcery.liquid.mktrough() sorcery.liquid.measure_default = function(amt) return string.format('%s drams', amt*constants.drams_per_glass) end sorcery.liquid.register = function(liq) local fmt = string.format local Q = constants.glasses_per_bottle liq.sid = liq.sid or liq.id:gsub('^[^:]+:','') liq.mod = liq.mod or liq.id:gsub('^([^:]+):.*','%1') if not liq.measure then liq.measure = sorcery.liquid.measure_default |
|
>
>
>
>
>
>
>
>
>
>
|
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
sorcery.liquid.mktrough = function(liq) -- troughs are used for collecting liquid from the environment, -- like rainwater and tree sap. they hold twice as much as a bucket local Q = constants.glasses_per_bottle local trough_mkid = function(l,i) if type(l) == 'string' then l = sorcery.register.liquid.db[l] end if (not l) or (not i) or i < 1 then return 'sorcery:trough' end return string.format('%s:trough_%s_%u', l.mod,l.sid,i) end local lid = function(l) return trough_mkid(liq, l) end local M = constants.bottles_per_trough local mkbox = function(lvl) local pxl = function(tbl) -- for mapping to txcoords ................................................................................ end end sorcery.liquid.mktrough() sorcery.liquid.measure_default = function(amt) return string.format('%s drams', amt*constants.drams_per_glass) end sorcery.liquid.container = function(liq, ctr) return liq.containers[({ bottle = 'vessels:glass_bottle'; glass = 'vessels:drinking_glass'; keg = 'sorcery:keg'; trough = 'sorcery:trough'; })[ctr] or ctr] end sorcery.liquid.register = function(liq) local fmt = string.format local Q = constants.glasses_per_bottle liq.sid = liq.sid or liq.id:gsub('^[^:]+:','') liq.mod = liq.mod or liq.id:gsub('^([^:]+):.*','%1') if not liq.measure then liq.measure = sorcery.liquid.measure_default |
Modified potions.lua from [a4fa9f9b09] to [0b54227d82].
52 53 54 55 56 57 58 59 60 61 62 63 64 65 ... 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 ... 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 ... 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 ... 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 ... 302 303 304 305 306 307 308 309 310 |
sorcery.register_oil = function(name,label,desc,color,imgvariant,extra) local image = 'xdecor_bowl.png^(sorcery_oil_' .. (imgvariant or 'dull') .. '.png^[colorize:'..tostring(color)..':140)' sorcery.register.residue.link('sorcery:' .. name, 'xdecor:bowl') extra.description = label; extra.inventory_image = image; if not extra.groups then extra.groups = {} end minetest.register_craftitem('sorcery:' .. name, extra) end sorcery.register_potion('blood', 'Blood', 'A bottle of sacrificial blood, imbued with stolen (or perhaps donated) life force', u.color(219,19,14), nil, nil, { _sorcery = { life_store = 4; container = { ................................................................................ output = 'sorcery:' .. id; _proto = proto; } end end -- for n,v in pairs(sorcery.data.potions) do sorcery.register.potions.foreach('sorcery:mknodes',{},function(n,v) local color = u.color(v.color) local kind = v.style local glow = v.glow local id = 'potion_' .. string.lower(n) local desc = 'A ' .. ((glow and 'glowing ') or '') .. 'bottle of ' .. string.lower(n) .. ((kind == 'sparkle' and ', fiercely bubbling') or '') .. ' liquid' local fullname = n .. ' Potion' sorcery.register.liquid.link('sorcery:'..id, { name = 'Serene Potion'; color = v.color; proto = v; kind = 'sorcery:potion'; measure = function(amt) return string.format('%s draughts', amt / 3) end; containers = { ['vessels:glass_bottle'] = 'sorcery:' .. id; }; }) sorcery.register_potion(id, fullname, desc, color, kind, glow, { groups = { sorcery_potion = 1; sorcery_magical = 1; }; _proto = v; _sorcery = { ................................................................................ }; }; }) create_infusion_recipe(id,v,'sorcery:potion_serene',{data=v,name=fullname}) end) -- for n,potion in pairs(sorcery.data.draughts) do sorcery.register.draughts.foreach('sorcery:mknodes',{},function(n,potion) local name = 'draught_' .. n local behavior = { _proto = potion; groups = { sorcery_potion = 2; sorcery_draught = 1; sorcery_magical = 1; sorcery_usable_magic = 1; ................................................................................ potion.style or 'dull', potion.glow or 0, behavior) create_infusion_recipe(name,potion,'sorcery:potion_luminous',{data=potion,name=fullname}) end) -- for n,elixir in pairs(sorcery.data.elixirs) do sorcery.register.elixirs.foreach('sorcery:mknodes',{},function(n,elixir) local color = u.color(elixir.color) local id = 'elixir_' .. string.lower(n) local fullname = 'Elixir of ' .. n sorcery.register_potion(id, fullname, nil, color, 'dull', false, { _proto = elixir; groups = { sorcery_elixir = 1; sorcery_magical = 1; }; }) ................................................................................ local kind = v.style sorcery.register_oil('grease_' .. n, u.str.capitalize(n) .. ' Grease', nil, color, kind, { groups = { sorcery_grease = 1 } }) end) -- for n,v in pairs(sorcery.data.philters) do sorcery.register.philters.foreach('sorcery:mknodes',{},function(n,v) local color = u.color(v.color) local id = 'philter_' .. n local name = v.name or u.str.capitalize(n) local fullname = name .. ' Philter' sorcery.register_potion(id, fullname, v.desc, color, 'sparkle',v.glow or 4, { _proto = v; _protoname = n; groups = { sorcery_magical = 1; sorcery_philter = 1; }; }) create_infusion_recipe(id,v,'sorcery:potion_viscous',{data=v,name=fullname}) end) -- for n,v in pairs(sorcery.data.extracts) do sorcery.register.extracts.foreach('sorcery:mknodes',{},function(n,v) local item = v[1] local color = u.color(v[2]) ................................................................................ {"farming:mortar_pestle", "farming:mortar_pestle"}; }; } end -- need a relatively pure alcohol for this, tho other alcohols can be used -- for potionmaking in other ways add_alcohol('farming:bottle_ethanol') add_alcohol('wine:glass_vodka') end) |
> > > > > | > > > > > > > > > > > > > > > > > > > | | > |
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 ... 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 ... 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 ... 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 ... 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 ... 325 326 327 328 329 330 331 332 333 334 335 |
sorcery.register_oil = function(name,label,desc,color,imgvariant,extra) local image = 'xdecor_bowl.png^(sorcery_oil_' .. (imgvariant or 'dull') .. '.png^[colorize:'..tostring(color)..':140)' sorcery.register.residue.link('sorcery:' .. name, 'xdecor:bowl') extra.description = label; extra.inventory_image = image; if not extra.groups then extra.groups = {} end extra.groups.sorcery_oil = 1 minetest.register_craftitem('sorcery:' .. name, extra) end sorcery.register_potion('blood', 'Blood', 'A bottle of sacrificial blood, imbued with stolen (or perhaps donated) life force', u.color(219,19,14), nil, nil, { _sorcery = { life_store = 4; container = { ................................................................................ output = 'sorcery:' .. id; _proto = proto; } end end -- for n,v in pairs(sorcery.data.potions) do local kind_potion = { label = 'Potion'; kind = 'A mystical liquid crucial to the art of alchemy'; } sorcery.register.potions.foreach('sorcery:mknodes',{},function(n,v) local color = u.color(v.color) local kind = v.style local glow = v.glow local id = 'potion_' .. string.lower(n) local desc = 'A ' .. ((glow and 'glowing ') or '') .. 'bottle of ' .. string.lower(n) .. ((kind == 'sparkle' and ', fiercely bubbling') or '') .. ' liquid' local fullname = n .. ' Potion' sorcery.register.liquid.link('sorcery:'..id, { name = fullname; color = v.color; proto = v; kind = 'sorcery:potion'; measure = function(amt) return string.format('%s draughts', amt / 3) end; containers = { ['vessels:glass_bottle'] = 'sorcery:' .. id; }; }) v.kind = kind_potion; sorcery.register_potion(id, fullname, desc, color, kind, glow, { groups = { sorcery_potion = 1; sorcery_magical = 1; }; _proto = v; _sorcery = { ................................................................................ }; }; }) create_infusion_recipe(id,v,'sorcery:potion_serene',{data=v,name=fullname}) end) -- for n,potion in pairs(sorcery.data.draughts) do local kind_draught = { label = 'Draught'; desc = 'A drink that will suffuse your body and spirit with mystic energies'; } sorcery.register.draughts.foreach('sorcery:mknodes',{},function(n,potion) local name = 'draught_' .. n potion.kind = kind_draught local behavior = { _proto = potion; groups = { sorcery_potion = 2; sorcery_draught = 1; sorcery_magical = 1; sorcery_usable_magic = 1; ................................................................................ potion.style or 'dull', potion.glow or 0, behavior) create_infusion_recipe(name,potion,'sorcery:potion_luminous',{data=potion,name=fullname}) end) -- for n,elixir in pairs(sorcery.data.elixirs) do local kind_elixir = { label = 'Elixir'; desc = 'A special kind of potion that enhances the particular qualities of other alchemical brews'; } sorcery.register.elixirs.foreach('sorcery:mknodes',{},function(n,elixir) local color = u.color(elixir.color) local id = 'elixir_' .. string.lower(n) local fullname = 'Elixir of ' .. n elixir.kind = kind_elixir; sorcery.register_potion(id, fullname, nil, color, 'dull', false, { _proto = elixir; groups = { sorcery_elixir = 1; sorcery_magical = 1; }; }) ................................................................................ local kind = v.style sorcery.register_oil('grease_' .. n, u.str.capitalize(n) .. ' Grease', nil, color, kind, { groups = { sorcery_grease = 1 } }) end) -- for n,v in pairs(sorcery.data.philters) do local kind_philter = { label = 'Philter'; desc = 'A special kind of potion that wooden rods can be soaked in to imbue them with special powers and transform them into wands'; } sorcery.register.philters.foreach('sorcery:mknodes',{},function(n,v) local color = u.color(v.color) local id = 'philter_' .. n local name = v.name or u.str.capitalize(n) if not v.name then v.name = name end local fullname = name .. ' Philter' v.kind = kind_philter sorcery.register_potion(id, fullname, v.desc, color, 'sparkle',v.glow or 4, { _proto = v; _protoname = n; groups = { sorcery_magical = 1; sorcery_philter = 1; }; }) v.quals = {force = true}; create_infusion_recipe(id,v,'sorcery:potion_viscous',{data=v,name=fullname}) end) -- for n,v in pairs(sorcery.data.extracts) do sorcery.register.extracts.foreach('sorcery:mknodes',{},function(n,v) local item = v[1] local color = u.color(v[2]) ................................................................................ {"farming:mortar_pestle", "farming:mortar_pestle"}; }; } end -- need a relatively pure alcohol for this, tho other alcohols can be used -- for potionmaking in other ways add_alcohol('farming:bottle_ethanol') if minetest.get_modpath('wine') then add_alcohol('wine:glass_vodka') end end) |
Modified runeforge.lua from [69ba246df3] to [65aa0a1ed6].
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 .. 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 ... 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 ... 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
}; supreme = {grade = 6, name = 'Supreme'; infusion = 'sorcery:powder_levitanium'; dist = { Fragile = 0, Weak = 0, Ordinary = 1, Pristine = 0.7, Sublime = 0.4 }; }; }; } local calc_phial_props = function(phial) --> mine interval: float, time factor: float local g = phial:get_definition()._proto.data.grade local i = constants.rune_mine_interval local fac = (g-1) / 5 return i - ((i*0.5) * fac), 0.5 * fac end sorcery.register.runes.foreach('sorcery:generate',{},function(name,rune) local id = 'sorcery:rune_' .. name rune.image = rune.image or string.format('sorcery_rune_%s.png',name) rune.item = id local c = sorcery.lib.color(rune.tone) ................................................................................ short_description = rune.name .. ' Rune'; inventory_image = rune.image; stack_max = 1; groups = { sorcery_rune = 1; not_in_creative_inventory = 1; }; _proto = { id = name, data = rune; }; }) end) for name,p in pairs(constants.phial_kinds) do local f = string.format local color = sorcery.lib.color(142,232,0) local fac = p.grade / 6 local id = f('phial_%s', name); sorcery.register_potion_tbl { name = id; label = f('%s Phial',p.name); desc = "A powerful liquid consumed in the operation of a rune forge. Its quality determines how fast new runes can be constructed and how much energy is required by the process, and affects your odds of getting a high-quality rune."; color = color:brighten(1 + fac*0.5); imgvariant = (fac >= 5) and 'sparkle' or 'dull'; glow = 5+p.grade; extra = { groups = { sorcery_phial = p.grade }; _proto = { id = name, data = p }; }; } sorcery.register.infusions.link { infuse = p.infusion; into = 'sorcery:potion_subtle'; output = 'sorcery:'..id; } ................................................................................ local pow_min = l.self.powerdraw >= l.self.minpower local pow_max = l.self.powerdraw >= l.self.maxpower local has_phial = function() return not i:is_empty('phial') end if time and has_phial() and pow_min and not probe.disjunction then -- roll for runes local phial = i:get_stack('phial',1) local int, powerfac = calc_phial_props(phial) local rolls = math.floor(time/int) local newrunes = {} for _=1,rolls do local choices = {} for name,rune in pairs(sorcery.data.runes) do -- print('considering',name) -- print('-- power',rune.minpower,(rune.minpower*powerfac)*time,'//',l.self.powerdraw,l.self.powerdraw/time,'free',l.freepower,'max',l.maxpower) if (rune.minpower*powerfac)*time <= l.self.powerdraw and math.random(rune.rarity) == 1 then choices[#choices + 1] = rune end end if #choices > 0 then -- if multiple runes were rolled up, be nice to the player -- and pick the rarest one to give them local rare, choice = 0 ................................................................................ local wrench if not inv:is_empty('wrench') then wrench = inv:get_stack('wrench',1):get_definition()._proto end if fl == 'cache' then if probe.disjunction then return 0 end if tl == 'cache' then return 1 end if tl == 'active' and inv:is_empty('active') then print(dump(wrench)) if wrench and wrench.powers.imbue and not inv:is_empty('amulet') then local amulet = inv:get_stack('amulet',1) local rune = inv:get_stack(fl,fi) local runeid = rune:get_definition()._proto.id local runegrade = rune:get_meta():get_int('rune_grade') if sorcery.data.runes[runeid].amulets[amulet:get_definition()._sorcery.amulet.base] then local spell do -- haaaack |
> > | > > > > > > > | < > | > | < |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 .. 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 ... 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 ... 501 502 503 504 505 506 507 508 509 510 511 512 513 514 |
}; supreme = {grade = 6, name = 'Supreme'; infusion = 'sorcery:powder_levitanium'; dist = { Fragile = 0, Weak = 0, Ordinary = 1, Pristine = 0.7, Sublime = 0.4 }; }; }; } local calc_phial_props = function(phial) --> mine interval: float, time factor: float local m = phial:get_meta() local g = phial:get_definition()._proto.data.grade local i = constants.rune_mine_interval local fac = (g-1) / 5 fac = fac + 0.4 * m:get_int('speed') return i - ((i*0.5) * fac), 0.5 * fac end sorcery.register.runes.foreach('sorcery:generate',{},function(name,rune) local id = 'sorcery:rune_' .. name rune.image = rune.image or string.format('sorcery_rune_%s.png',name) rune.item = id local c = sorcery.lib.color(rune.tone) ................................................................................ short_description = rune.name .. ' Rune'; inventory_image = rune.image; stack_max = 1; groups = { sorcery_rune = 1; not_in_creative_inventory = 1; }; _proto = { id = name, data = rune }; }) end) local phkind = { label = 'Phial'; desc = 'An alchemical substance which rune forges consume while coalescing new runes'; } for name,p in pairs(constants.phial_kinds) do local f = string.format local color = sorcery.lib.color(142,232,0) local fac = p.grade / 6 local id = f('phial_%s', name); local fname = f('%s Phial',p.name); local desc = "A powerful liquid consumed in the operation of a rune forge. Its quality determines how fast new runes can be constructed and how much energy is required by the process, and affects your odds of getting a high-quality rune." sorcery.register_potion_tbl { name = id; label = fname; desc = desc; color = color:brighten(1 + fac*0.5); imgvariant = (fac >= 5) and 'sparkle' or 'dull'; glow = 5+p.grade; extra = { groups = { sorcery_phial = p.grade }; _proto = { id = name, desc = desc, name = p.name, kind = phkind, data = p, quals = {force = true, speed = true}, color = color }; }; } sorcery.register.infusions.link { infuse = p.infusion; into = 'sorcery:potion_subtle'; output = 'sorcery:'..id; } ................................................................................ local pow_min = l.self.powerdraw >= l.self.minpower local pow_max = l.self.powerdraw >= l.self.maxpower local has_phial = function() return not i:is_empty('phial') end if time and has_phial() and pow_min and not probe.disjunction then -- roll for runes local phial = i:get_stack('phial',1) local int, powerfac = calc_phial_props(phial) local pf = phial:get_meta():get_int('force') local rolls = math.floor(time/int) local newrunes = {} for _=1,rolls do local choices = {} for name,rune in pairs(sorcery.data.runes) do -- print('considering',name) -- print('-- power',rune.minpower,(rune.minpower*powerfac)*time,'//',l.self.powerdraw,l.self.powerdraw/time,'free',l.freepower,'max',l.maxpower) if (rune.minpower*powerfac)*time <= l.self.powerdraw and math.random(rune.rarity - pf) == 1 then choices[#choices + 1] = rune end end if #choices > 0 then -- if multiple runes were rolled up, be nice to the player -- and pick the rarest one to give them local rare, choice = 0 ................................................................................ local wrench if not inv:is_empty('wrench') then wrench = inv:get_stack('wrench',1):get_definition()._proto end if fl == 'cache' then if probe.disjunction then return 0 end if tl == 'cache' then return 1 end if tl == 'active' and inv:is_empty('active') then if wrench and wrench.powers.imbue and not inv:is_empty('amulet') then local amulet = inv:get_stack('amulet',1) local rune = inv:get_stack(fl,fi) local runeid = rune:get_definition()._proto.id local runegrade = rune:get_meta():get_int('rune_grade') if sorcery.data.runes[runeid].amulets[amulet:get_definition()._sorcery.amulet.base] then local spell do -- haaaack |
Modified sorcery.md from [5a3ebfda49] to [17b053c9d3].
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
* if you need to travel quickly between two distant places, and you're wealthy enough to afford it, you can build yourself one of the most powerful and complex of magitech devices — the **Teleporter**. it's no mean feat: even the smallest teleporter requires a teleport pad with a reflector above it and a portal node connected to one or the other. the teleporter will then need to be connected to its destination with cables or conduits, and if where you're travelling is very far away, you'll have to build two separate ley nets and bridge them by using an **Attunement Wand** on a pair of **Raycasters** — or perhaps even **Farcasters**. the power required to operate all of these devices is not trivial, and while a Farcaster's signal can pierce through any substance and cross any distance to reach its destination, the farther away each is from the other, the more power each side will consume. and casters can't send current, they can only send signals, so you may need a sizable power plant on both sides of the portal. * if all you need to do is send small items, of course, a **Displacer** is much cheaper, and more flexible. if you're feeling particularly ambitious, you could use a Displacer net to connect your whole kingdom with instantaneous package service. * stop your foes in their tracks by flipping a switch to turn on your **Force Field Emitters**, generating an impenetrable barrier wherever they aim. * who needs elevators when you have **Gravitators**? float gently up a vast borehole, bring attackers crashing down to earth, or slow a fatal plunge to a soft and easy landing. * build graven **Idols** to your gods and set sacrifices to them upon an altar. if they're feeling generous, they might start sending you presents of their own, or consecrating your offerings. but beware: different gods have different tastes (and different powers), and get bored quickly with repetitive offerings. * to bend the ultimate arcane forces of the cosmos to your will, you'll need a **Rune Forge**. with a strong ley-current and a steady supply of **Phials** from an Infuser, a Rune Forge will crystallize thaumic impurities into Runes that can you can imbue into a gemstone **Amulet** with a **Rune Wrench**. each amulet can only be used once before it loses its charge, and it may be a long time before the same kind of rune happens to coalesce in your forge again, but the spells they unleash are unique and priceless boons — or weapons. teleport without a teleporter! purge your environs of all spellcraft no matter how fearsomely potent! surround yourself with a shimmering Disjunction Field that, for a short while, will snuff out any spell it touches and, rendering enemy mages utterly helpless and piercing otherwise impenetrable defenses! stride through solid stone like open air! carve huge tunnels deep into the rock with only a snap of your fingers! rain obliteration down upon a target of your choosing! send forth a titanic bolt of flame with the power to blast open mountainsides! tear the very life force straight from an enemy's body and use it to fortify your being! all this and more can be done with the power of rune magic. there's more as well. i have yet to figure out how i want to go about introducing users to the lore, but for now there's some information on the wiki and some things you can glean from creative mode; otherwise you'll have to read the source code. # lore `sorcery` supplies a default system of lore (that is, the arbitrary objects that the basic principles of the setting operate over) but this can be augmented or replaced on a per-world basis. for instance, you can substitute your own gods for the Harvest Goddess, Blood God, change their names, and so on, or simply make your own additions to the pantheon. since lore overrides are stored outside the minetest tree, it can be updated without destroying your changes. lore is stored separately from the rest of the game logic, in the 'data' directory of the `sorcery` mod. it is arranged in a hierarchy of thematically-organized tables. for instance, the table of gods can be found in `data/gods.lua`. ideally, lore tables should contain plain data, though they can also contain lambdas if necessary. lore files are evaluated in the second stage of the init process, after library code has been loaded but before any game logic has been instantiated. lore can thus depend on libraries where reasonable (though e.g. colors should be stored as 3-tuples rather than `sorcery.lib.color` objects, and images as texture strings, unless there is a very good reason to do otherwise). lore files should never depend on functions in the `minetest` or `core` namespace! if you really need such functionality, gate it off with an if statement and be sure to return something useful in the event that the namespace isn't defined. *lore is just data:* as a general principle, non-minetest code should be able to evaluate and make use of the lore files, for instance to produce an HTML file tabulating the various potions and how to create them. lore should also not mutate the global environment: while there is currently nothing preventing it from doing so, steps will likely be taken in the future to give each lore module a clean environment to keep it from contaminating the global namespace. right now, all functions and variables declared in a lore file should be defined `local`. the only job of a lore file is to return a table. |
| |
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
* if you need to travel quickly between two distant places, and you're wealthy enough to afford it, you can build yourself one of the most powerful and complex of magitech devices — the **Teleporter**. it's no mean feat: even the smallest teleporter requires a teleport pad with a reflector above it and a portal node connected to one or the other. the teleporter will then need to be connected to its destination with cables or conduits, and if where you're travelling is very far away, you'll have to build two separate ley nets and bridge them by using an **Attunement Wand** on a pair of **Raycasters** — or perhaps even **Farcasters**. the power required to operate all of these devices is not trivial, and while a Farcaster's signal can pierce through any substance and cross any distance to reach its destination, the farther away each is from the other, the more power each side will consume. and casters can't send current, they can only send signals, so you may need a sizable power plant on both sides of the portal.
* if all you need to do is send small items, of course, a **Displacer** is much cheaper, and more flexible. if you're feeling particularly ambitious, you could use a Displacer net to connect your whole kingdom with instantaneous package service.
* stop your foes in their tracks by flipping a switch to turn on your **Force Field Emitters**, generating an impenetrable barrier wherever they aim.
* who needs elevators when you have **Gravitators**? float gently up a vast borehole, bring attackers crashing down to earth, or slow a fatal plunge to a soft and easy landing.
* build graven **Idols** to your gods and set sacrifices to them upon an altar. if they're feeling generous, they might start sending you presents of their own, or consecrating your offerings. but beware: different gods have different tastes (and different powers), and get bored quickly with repetitive offerings.
* to bend the ultimate arcane forces of the cosmos to your will, you'll need a **Rune Forge**. with a strong ley-current and a steady supply of **Phials** from an Infuser, a Rune Forge will crystallize thaumic impurities into Runes that can you can imbue into a gemstone **Amulet** with a **Rune Wrench**. each amulet can only be used once before it loses its charge, and it may be a long time before the same kind of rune happens to coalesce in your forge again, but the spells they unleash are unique and priceless boons — or weapons. teleport without a teleporter! purge your environs of all spellcraft no matter how fearsomely potent! surround yourself with a shimmering Disjunction Field that, for a short while, will snuff out any spell it touches and, rendering enemy mages utterly helpless and piercing otherwise impenetrable defenses! stride through solid stone like open air! carve huge tunnels deep into the rock with only a snap of your fingers! rain obliteration down upon a target of your choosing! send forth a titanic bolt of flame with the power to blast open mountainsides! tear the very life force straight from an enemy's body and use it to fortify your being! all this and more can be done with the power of rune magic.
there's more as well. i have yet to figure out how i want to go about introducing users to the lore (although you can occasionally find random recipes in dungeon chests, and gods can be coaxed to bestow recipes and cookbooks), but for now there's some information on the wiki and some things you can glean from creative mode; otherwise you'll have to read the source code.
# lore
`sorcery` supplies a default system of lore (that is, the arbitrary objects that the basic principles of the setting operate over) but this can be augmented or replaced on a per-world basis. for instance, you can substitute your own gods for the Harvest Goddess, Blood God, change their names, and so on, or simply make your own additions to the pantheon. since lore overrides are stored outside the minetest tree, it can be updated without destroying your changes.
lore is stored separately from the rest of the game logic, in the 'data' directory of the `sorcery` mod. it is arranged in a hierarchy of thematically-organized tables. for instance, the table of gods can be found in `data/gods.lua`. ideally, lore tables should contain plain data, though they can also contain lambdas if necessary. lore files are evaluated in the second stage of the init process, after library code has been loaded but before any game logic has been instantiated. lore can thus depend on libraries where reasonable (though e.g. colors should be stored as 3-tuples rather than `sorcery.lib.color` objects, and images as texture strings, unless there is a very good reason to do otherwise).
lore files should never depend on functions in the `minetest` or `core` namespace! if you really need such functionality, gate it off with an if statement and be sure to return something useful in the event that the namespace isn't defined. *lore is just data:* as a general principle, non-minetest code should be able to evaluate and make use of the lore files, for instance to produce an HTML file tabulating the various potions and how to create them. lore should also not mutate the global environment: while there is currently nothing preventing it from doing so, steps will likely be taken in the future to give each lore module a clean environment to keep it from contaminating the global namespace. right now, all functions and variables declared in a lore file should be defined `local`. the only job of a lore file is to return a table.
|
Modified spell.lua from [92125c4f2c] to [4f39d5643f].
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 ... 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 ... 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
-- disjunction is cast on one of them, they will be removed from the -- table. each entry should have at least a 'player' field; they can -- also contain any other data useful to the spell. if a subject has -- a 'disjoin' field it must be a function called when they are removed -- from the list of spell targets. -- * caster is the individual who cast the spell, if any. a disjunction -- against their person will totally disrupt the spell. local log = function(...) sorcery.log('spell',...) end -- FIXME saving object refs is iffy, find a better alternative sorcery.spell = { active = {} } local get_spell_positions = function(spell) ................................................................................ local t if type(when) == 'number' then t = s.duration * when else t = (s.duration * (when.whence or 0)) + when.secs end if t then return math.min(s.duration,math.max(0,t)) end log('invalid timespec ' .. dump(when)) return 0 end s.queue = function(when,fn) local elapsed = s.starttime and minetest.get_server_uptime() - s.starttime or 0 local timepast = interpret_timespec(when) if not timepast then timepast = 0 end local timeleft = s.duration - timepast local howlong = (s.delay + timepast) - elapsed if howlong < 0 then log('cannot time-travel! queue() called with `when` specifying timepoint that has already passed') howlong = 0 end s.jobs[#s.jobs+1] = minetest.after(howlong, function() -- this is somewhat awkward. since we're using a non-polling approach, we -- need to find a way to account for a caster or subject walking into an -- existing antimagic field, or someone with an existing antimagic aura -- walking into range of the anchor. so every time a spell effect would ................................................................................ termqueued = true s.queue(1,function(s,...) what(s,...) if s.terminate then s:terminate() end sorcery.spell.active[myid] = nil end) else log('multiple final timeline events not possible, ignoring') end elseif when == 0 and s.disjunction then startqueued = true s.queue(when_raw,function(...) perform_disjunction_calls() what(...) end) |
| | | | |
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 ... 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 ... 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
-- disjunction is cast on one of them, they will be removed from the -- table. each entry should have at least a 'player' field; they can -- also contain any other data useful to the spell. if a subject has -- a 'disjoin' field it must be a function called when they are removed -- from the list of spell targets. -- * caster is the individual who cast the spell, if any. a disjunction -- against their person will totally disrupt the spell. local log = sorcery.logger 'spell' -- FIXME saving object refs is iffy, find a better alternative sorcery.spell = { active = {} } local get_spell_positions = function(spell) ................................................................................ local t if type(when) == 'number' then t = s.duration * when else t = (s.duration * (when.whence or 0)) + when.secs end if t then return math.min(s.duration,math.max(0,t)) end log.err('invalid timespec ' .. dump(when)) return 0 end s.queue = function(when,fn) local elapsed = s.starttime and minetest.get_server_uptime() - s.starttime or 0 local timepast = interpret_timespec(when) if not timepast then timepast = 0 end local timeleft = s.duration - timepast local howlong = (s.delay + timepast) - elapsed if howlong < 0 then log.err('cannot time-travel! queue() called with `when` specifying timepoint that has already passed') howlong = 0 end s.jobs[#s.jobs+1] = minetest.after(howlong, function() -- this is somewhat awkward. since we're using a non-polling approach, we -- need to find a way to account for a caster or subject walking into an -- existing antimagic field, or someone with an existing antimagic aura -- walking into range of the anchor. so every time a spell effect would ................................................................................ termqueued = true s.queue(1,function(s,...) what(s,...) if s.terminate then s:terminate() end sorcery.spell.active[myid] = nil end) else log.warn('multiple final timeline events not possible, ignoring') end elseif when == 0 and s.disjunction then startqueued = true s.queue(when_raw,function(...) perform_disjunction_calls() what(...) end) |
Modified tap.lua from [7b8c107461] to [17fb78473a].
1 2 3 4 5 6 7 8 9 10 11 12 |
local log = sorcery.logger('tap') minetest.register_node('sorcery:tap',{ description = 'Tree Tap'; drawtype = 'mesh'; mesh = 'sorcery-tap.obj'; tiles = { 'default_copper_block.png'; 'default_steel_block.png'; }; groups = { dig_immediate = 2; attached_node = 1; |
> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
local log = sorcery.logger('tap')
minetest.register_node('sorcery:tap',{
description = 'Tree Tap';
drawtype = 'mesh';
mesh = 'sorcery-tap.obj';
inventory_image = 'sorcery_tap_inv.png';
tiles = {
'default_copper_block.png';
'default_steel_block.png';
};
groups = {
dig_immediate = 2;
attached_node = 1;
|
Added textures/sorcery_tap_inv.png version [0ade756825].
cannot compute difference between binary files