Commit f967c43f0cf0db5dcfc4f8adfeb03beccb2d9c29

Authored by dg
1 parent b846861c

shhhh

git-svn-id: http://svn.net-core.org/repos/t-engine4@5354 51575b47-30f0-44d4-a5cc-537603b46e54
... ... @@ -642,6 +642,15 @@ function _M:getCharball(id_profile, uuid)
642 642 return data
643 643 end
644 644
  645 +function _M:getDLCD(name, version, file)
  646 + if not self.auth then return end
  647 + local data = nil
  648 + core.profile.pushOrder(table.serialize{o="GetDLCD", name=name, version=version, file=file})
  649 + self:waitEvent("GetDLCD", function(e) data = e.data end, 30000)
  650 + if not data then return "" end
  651 + return zlib.decompress(data)
  652 +end
  653 +
645 654 function _M:registerSaveCharball(module, uuid, data)
646 655 if not self.auth or not self.hash_valid then return end
647 656 core.profile.pushOrder(table.serialize{o="SaveCharball",
... ...
... ... @@ -164,6 +164,15 @@ table.insert(package.loaders, 2, te4_loader)
164 164 --table.insert(package.loaders, 2, function(name) return loadfile("/"..name:gsub("%.", "/")..".lua") end )
165 165 --]]
166 166
  167 +local dlcd_loader = function(name)
  168 + if not fs.exists("/"..name:gsub("%.", "/")..".stub") then return end
  169 + print("===DLCLOADER", "/"..name:gsub("%.", "/")..".stub")
  170 + local d = loadfile("/"..name:gsub("%.", "/")..".stub")()
  171 + local data = profile:getDLCD(d.name, d.version, name:gsub("%.", "/")..".lua")
  172 + return loadstring(data)
  173 +end
  174 +table.insert(package.loaders, 2, dlcd_loader)
  175 +
167 176
168 177
169 178 -- RUN engine RUN !!
... ...
... ... @@ -33,7 +33,6 @@ newBirthDescriptor{
33 33 __ALL__ = "disallow",
34 34 Summoner = "allow",
35 35 Wyrmic = "allow",
36   - ["Stone Warden"] = "allow",
37 36 Oozemancer = "allow",
38 37 },
39 38 },
... ... @@ -141,51 +140,6 @@ newBirthDescriptor{
141 140 },
142 141 }
143 142
144   -newBirthDescriptor{
145   - type = "subclass",
146   - name = "Stone Warden",
147   - locked = function() return profile.mod.allow_build.wilder_stone_warden and true or "hide" end,
148   - locked_desc = "",
149   - desc = {
150   - "Stone Wardens are dwarves trained in both the eldritch arts and the worship of nature.",
151   - "While other races are stuck in their belief that arcane forces and natural forces are meant to oppose, dwarves have found a way to combine them in harmony.",
152   - "Stone Wardens are armoured fighters, using a shield to channel many of their powers.",
153   - "#GOLD#Stat modifiers:",
154   - "#LIGHT_BLUE# * +2 Strength, +0 Dexterity, +0 Constitution",
155   - "#LIGHT_BLUE# * +4 Magic, +3 Willpower, +0 Cunning",
156   - },
157   - power_source = {nature=true, arcane=true},
158   - not_on_random_boss = true,
159   - stats = { str=2, wil=3, mag=4, },
160   - talents_types = {
161   - ["wild-gift/call"]={true, 0.2},
162   - ["wild-gift/earthen-stone"]={true, 0.3},
163   - ["wild-gift/earthen-vines"]={true, 0.3},
164   - ["spell/arcane-shield"]={true, 0.3},
165   - ["spell/earth"]={true, 0.2},
166   - ["spell/stone"]={false, 0.2},
167   - ["cunning/survival"]={true, 0},
168   - ["technique/combat-training"]={true, 0},
169   - },
170   - talents = {
171   - [ActorTalents.T_STONE_VINES] = 1,
172   - [ActorTalents.T_STONESHIELD] = 1,
173   - [ActorTalents.T_ELDRITCH_BLOW] = 1,
174   - [ActorTalents.T_ARMOUR_TRAINING] = 3,
175   - [ActorTalents.T_WEAPONS_MASTERY] = 1,
176   - },
177   - copy = {
178   - max_life = 110,
179   - resolvers.equip{ id=true,
180   - {type="weapon", subtype="mace", name="iron mace", autoreq=true, ego_chance=-1000, ego_chance=-1000},
181   - {type="armor", subtype="shield", name="iron shield", autoreq=true, ego_chance=-1000, ego_chance=-1000},
182   - {type="armor", subtype="heavy", name="iron mail armour", autoreq=true, ego_chance=-1000, ego_chance=-1000}
183   - },
184   - },
185   - copy_add = {
186   - life_rating = 2,
187   - },
188   -}
189 143
190 144 newBirthDescriptor{
191 145 type = "subclass",
... ...
1   --- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
3   ---
4   --- This program is free software: you can redistribute it and/or modify
5   --- it under the terms of the GNU General Public License as published by
6   --- the Free Software Foundation, either version 3 of the License, or
7   --- (at your option) any later version.
8   ---
9   --- This program is distributed in the hope that it will be useful,
10   --- but WITHOUT ANY WARRANTY; without even the implied warranty of
11   --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   --- GNU General Public License for more details.
13   ---
14   --- You should have received a copy of the GNU General Public License
15   --- along with this program. If not, see <http://www.gnu.org/licenses/>.
16   ---
17   --- Nicolas Casalini "DarkGod"
18   --- darkgod@te4.org
19   -
20   --- Make the 2 main forks
21   -local nb = 0
22   -local forks = {{}, {}}
23   -local m1 = forks[1]
24   -local m2 = forks[2]
25   -local tiles = math.ceil(math.sqrt(tx*tx+ty*ty))
26   -local tx = tx * engine.Map.tile_w
27   -local ty = ty * engine.Map.tile_h
28   -local breakdir = math.rad(rng.range(-8, 8))
29   -m1.bx = 0
30   -m1.by = 0
31   -m1.thick = 5
32   -m1.dir = math.atan2(ty, tx) + breakdir
33   -m1.size = math.sqrt(tx*tx+ty*ty) / 2
34   -
35   -m2.bx = m1.size * math.cos(m1.dir)
36   -m2.by = m1.size * math.sin(m1.dir)
37   -m2.thick = 5
38   -m2.dir = math.atan2(ty, tx) - breakdir
39   -m2.size = math.sqrt(tx*tx+ty*ty) / 2
40   -
41   --- Add more forks
42   -for i = 1, math.min(math.max(3, m1.size / 5), 20) do
43   - local m = rng.percent(50) and forks[1] or forks[2]
44   - if rng.percent(60) then m = rng.table(forks) end
45   - local f = {}
46   - f.thick = 2
47   - f.dir = m.dir + math.rad(rng.range(-30,30))
48   - f.size = rng.range(6, 25)
49   - local br = rng.range(1, m.size)
50   - f.bx = br * math.cos(m.dir) + m.bx
51   - f.by = br * math.sin(m.dir) + m.by
52   - forks[#forks+1] = f
53   -end
54   -
55   --- Populate the lightning based on the forks
56   -return { generator = function()
57   - local f = rng.table(forks)
58   - local a = f.dir
59   - local rad = rng.range(-3,3)
60   - local ra = math.rad(rad)
61   - local r = rng.range(1, f.size)
62   -
63   - return {
64   - life = life or 4,
65   - size = f.thick, sizev = 0, sizea = 0,
66   -
67   - x = r * math.cos(a) + 3 * math.cos(ra) + f.bx, xv = 0, xa = 0,
68   - y = r * math.sin(a) + 3 * math.sin(ra) + f.by, yv = 0, ya = 0,
69   - dir = 0, dirv = 0, dira = 0,
70   - vel = 0, velv = 0, vela = 0,
71   -
72   - r = 0xD7/255, rv = 0, ra = 0,
73   - g = 0x8E/255, gv = 0, ga = 0,
74   - b = 0x45/255, bv = 0, ba = 0,
75   - a = rng.range(230, 255)/255, av = 0, aa = 0,
76   - }
77   -end, },
78   -function(self)
79   - if nb < 4 then self.ps:emit(20*tiles) nb = nb + 1 end
80   -end,
1   --- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
3   ---
4   --- This program is free software: you can redistribute it and/or modify
5   --- it under the terms of the GNU General Public License as published by
6   --- the Free Software Foundation, either version 3 of the License, or
7   --- (at your option) any later version.
8   ---
9   --- This program is distributed in the hope that it will be useful,
10   --- but WITHOUT ANY WARRANTY; without even the implied warranty of
11   --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   --- GNU General Public License for more details.
13   ---
14   --- You should have received a copy of the GNU General Public License
15   --- along with this program. If not, see <http://www.gnu.org/licenses/>.
16   ---
17   --- Nicolas Casalini "DarkGod"
18   --- darkgod@te4.org
19   -
20   -base_size = 32
21   -
22   -return { generator = function()
23   - local ad = rng.range(0, 360)
24   - local a = math.rad(ad)
25   - local dir = math.rad(ad)
26   - local r = rng.range(8, 18)
27   -
28   - return {
29   - life = 10,
30   - size = 1, sizev = 0.3, sizea = -0.01,
31   -
32   - x = r * math.cos(a), xv = 0, xa = 0,
33   - y = r * math.sin(a), yv = 0, ya = 0,
34   - dir = 0, dirv = 0, dira = 0,
35   - vel = 0, velv = 0, vela = 0,
36   -
37   - r = 0xD7/255, rv = 0, ra = 0,
38   - g = 0x8E/255, gv = 0, ga = 0,
39   - b = 0x45/255, bv = 0, ba = 0,
40   - a = rng.range(100, 220)/255, av = 0.05, aa = 0,
41   - }
42   -end, },
43   -function(self)
44   - self.ps:emit(2)
45   -end,
... ... @@ -58,6 +58,7 @@ damDesc = function(self, type, dam)
58 58 end
59 59
60 60 Talents.damDesc = damDesc
  61 +Talents.main_env = getfenv(1)
61 62
62 63 load("/data/talents/misc/misc.lua")
63 64 load("/data/talents/techniques/techniques.lua")
... ...
1   --- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
3   ---
4   --- This program is free software: you can redistribute it and/or modify
5   --- it under the terms of the GNU General Public License as published by
6   --- the Free Software Foundation, either version 3 of the License, or
7   --- (at your option) any later version.
8   ---
9   --- This program is distributed in the hope that it will be useful,
10   --- but WITHOUT ANY WARRANTY; without even the implied warranty of
11   --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   --- GNU General Public License for more details.
13   ---
14   --- You should have received a copy of the GNU General Public License
15   --- along with this program. If not, see <http://www.gnu.org/licenses/>.
16   ---
17   --- Nicolas Casalini "DarkGod"
18   --- darkgod@te4.org
19   -
20   -newTalent{
21   - name = "Stoneshield",
22   - type = {"wild-gift/earthen-power", 1},
23   - mode = "passive",
24   - require = gifts_req1,
25   - points = 5,
26   - getValues = function(self, t)
27   - return
28   - (5 + self:getTalentLevel(t) * 2) / 100,
29   - 5 + self:getTalentLevel(t),
30   - (5 + self:getTalentLevel(t) * 1.7) / 100,
31   - 4 + self:getTalentLevel(t)
32   - end,
33   - info = function(self, t)
34   - local m, mm, e, em = t.getValues(self, t)
35   - return ([[Each time you get hit you regenerate %d%% of the damage dealt as mana (up to a maximun of %0.2f) and %d%% as equilibrium (up to %0.2f).
36   - Also makes all your melee attack also do a shield bash.]]):format(100 * m, mm, 100 * e, em)
37   - end,
38   -}
39   -
40   -newTalent{
41   - name = "Stone Fortress",
42   - type = {"wild-gift/earthen-power", 2},
43   - require = gifts_req2,
44   - points = 5,
45   - mode = "passive",
46   - info = function(self, t)
47   - return ([[When you use your Resilience of the Dwarves racial power your skin becomes so thick that it even absorbs damage from non physical attacks.
48   - Non physical damages are reduced by %d%% of your armour value (ignoring hardiness).]]):
49   - format(50 + self:getTalentLevel(t) * 10)
50   - end,
51   -}
52   -
53   -newTalent{
54   - name = "Shards",
55   - type = {"wild-gift/earthen-power", 3},
56   - require = gifts_req3,
57   - points = 5,
58   - equilibrium = 4,
59   - cooldown = 30,
60   - tactical = { ATTACK = 2 },
61   - range = 10,
62   - direct_hit = true,
63   - proj_speed = 8,
64   - action = function(self, t)
65   - local tg = {type="bolt", range=self:getTalentRange(t), display={particle="bolt_arcane"}}
66   - local x, y = self:getTarget(tg)
67   - if not x or not y then return nil end
68   - self:projectile(tg, x, y, DamageType.SLIME, self:combatTalentStatDamage(t, "dex", 30, 290), {type="slime"})
69   - game:playSoundNear(self, "talents/stone")
70   - return true
71   - end,
72   - info = function(self, t)
73   - return ([[Spit slime at your target doing %0.2f nature damage and slowing it down by 30%% for 3 turns.
74   - The damage will increase with the Dexterity stat]]):format(damDesc(self, DamageType.NATURE, self:combatTalentStatDamage(t, "dex", 30, 290)))
75   - end,
76   -}
77   -
78   -newTalent{
79   - name = "Eldritch Stone",
80   - type = {"wild-gift/earthen-power", 4},
81   - require = gifts_req4,
82   - points = 5,
83   - equilibrium = 5,
84   - cooldown = 20,
85   - tactical = { CLOSEIN = 2 },
86   - requires_target = true,
87   - range = function(self, t)
88   - return 5 + self:getTalentLevel(t)
89   - end,
90   - radius = function(self, t)
91   - return util.bound(4 - self:getTalentLevel(t) / 2, 1, 4)
92   - end,
93   - getDuration = function(self, t)
94   - return util.bound(7 - self:getTalentLevel(t) / 2, 2, 7)
95   - end,
96   - is_teleport = true,
97   - action = function(self, t)
98   - local range = self:getTalentRange(t)
99   - local radius = self:getTalentRadius(t)
100   - local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=range, radius=radius, requires_knowledge=false}
101   - local x, y = self:getTarget(tg)
102   - if not x then return nil end
103   - -- Target code does not restrict the self coordinates to the range, it lets the project function do it
104   - -- but we cant ...
105   - local _ _, x, y = self:canProject(tg, x, y)
106   - game.level.map:particleEmitter(self.x, self.y, 1, "slime")
107   - self:teleportRandom(x, y, self:getTalentRadius(t))
108   - game.level.map:particleEmitter(self.x, self.y, 1, "slime")
109   -
110   - local duration = t.getDuration(self, t)
111   -
112   - for tid, lev in pairs(self.talents) do
113   - local t = self:getTalentFromId(tid)
114   - if t.mode == "activated" and not t.innate then
115   - self.talents_cd[t.id] = duration
116   - end
117   - end
118   - game:playSoundNear(self, "talents/stone")
119   - return true
120   - end,
121   - info = function(self, t)
122   - local range = self:getTalentRange(t)
123   - local radius = self:getTalentRadius(t)
124   - local duration = t.getDuration(self, t)
125   - return ([[You extend slimy roots into the ground, follow them, and re-appear somewhere else in a range of %d with error margin of %d.
126   - The process is quite a strain on your body and all your talents will be put on cooldown for %d turns.]]):format(range, radius, duration)
127   - end,
1   --- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
3   ---
4   --- This program is free software: you can redistribute it and/or modify
5   --- it under the terms of the GNU General Public License as published by
6   --- the Free Software Foundation, either version 3 of the License, or
7   --- (at your option) any later version.
8   ---
9   --- This program is distributed in the hope that it will be useful,
10   --- but WITHOUT ANY WARRANTY; without even the implied warranty of
11   --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   --- GNU General Public License for more details.
13   ---
14   --- You should have received a copy of the GNU General Public License
15   --- along with this program. If not, see <http://www.gnu.org/licenses/>.
16   ---
17   --- Nicolas Casalini "DarkGod"
18   --- darkgod@te4.org
19   -
20   -newTalent{
21   - name = "Stone Vines",
22   - type = {"wild-gift/earthen-vines", 1},
23   - require = gifts_req1,
24   - points = 5,
25   - mode = "sustained",
26   - sustain_equilibrium = 15,
27   - cooldown = 30,
28   - tactical = { ATTACK = { PHYSICAL = 2 }, BUFF = 2, DISABLE = { pin = 2 } },
29   - radius = function(self, t) return 4 + math.ceil(self:getTalentLevel(t) / 2) end,
30   - getValues = function(self, t) return 4 + self:getTalentLevelRaw(t), self:combatTalentStatDamage(t, "wil", 3, 50) end,
31   - do_vines = function(self, t)
32   - local p = self:isTalentActive(t.id)
33   - local rad = self:getTalentRadius(t)
34   -
35   - local tgts = {}
36   - local grids = core.fov.circle_grids(self.x, self.y, rad, true)
37   - for x, yy in pairs(grids) do for y, _ in pairs(grids[x]) do
38   - local a = game.level.map(x, y, Map.ACTOR)
39   - if a and self:reactionToward(a) < 0 and not a:hasEffect(a.EFF_STONE_VINE) then
40   - tgts[#tgts+1] = a
41   - end
42   - end end
43   - if #tgts <= 0 then return end
44   -
45   - -- Randomly take targets
46   - local tg = {type="hit", range=self:getTalentRange(t), talent=t}
47   - local a, id = rng.table(tgts)
48   - local hit, chance = a:checkHit(self:combatTalentStatDamage(t, "wil", 5, 110), a:combatPhysicalResist(), 0, 95, 5)
49   - if a:canBe("pin") and hit then
50   - local turns, dam = t.getValues(self, t)
51   - a:setEffect(a.EFF_STONE_VINE, turns, {dam=dam, src=self, free=rad*2, free_chance=100-chance})
52   - game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(a.x-self.x), math.abs(a.y-self.y)), "stonevine", {tx=a.x-self.x, ty=a.y-self.y})
53   - game:playSoundNear(self, "talents/stone")
54   - end
55   - end,
56   - activate = function(self, t)
57   - return {
58   - movid = self:addTemporaryValue("movement_speed", -0.5),
59   - particle = self:addParticles(Particles.new("stonevine_static", 1, {})),
60   - }
61   - end,
62   - deactivate = function(self, t, p)
63   - self:removeTemporaryValue("movement_speed", p.movid)
64   - self:removeParticles(p.particle)
65   - return true
66   - end,
67   - info = function(self, t)
68   - local rad = self:getTalentRadius(t)
69   - local turns, dam = t.getValues(self, t)
70   - return ([[Living stone vines extend from your feet, each turn the vines will randomly target a creature in a radius of %d.
71   - Affected creatures are pinned to the ground and take %0.2f physical damage for %d turns.
72   - Targets will be free from the vines if they are at least %d grids away from you.
73   - While earthen vines are active your movement speed is reduced by 50%%.
74   - Each turn a creature entangled by the vines will have a chance to break free.
75   - The damage will increase with Willpower stats.]]):
76   - format(rad, damDesc(self, DamageType.PHYSICAL, dam), turns, rad*2)
77   - end,
78   -}
79   -
80   -newTalent{
81   - name = "Eldritch Vines",
82   - type = {"wild-gift/earthen-vines", 2},
83   - require = gifts_req2,
84   - points = 5,
85   - mode = "passive",
86   - info = function(self, t)
87   - return ([[Each time a vine deal damage to a creature it will restore %0.2f equilibrium and %0.2f mana.]])
88   - :format(self:getTalentLevel(t) / 4, self:getTalentLevel(t) / 3)
89   - end,
90   -}
91   -
92   -newTalent{
93   - name = "Rockwalk",
94   - type = {"wild-gift/earthen-vines", 3},
95   - require = gifts_req3,
96   - points = 5,
97   - equilibrium = 15,
98   - cooldown = 10,
99   - requires_target = true,
100   - range = 20,
101   - tactical = { HEAL = 2, CLOSEIN = 2 },
102   - action = function(self, t)
103   - local tg = {type="hit", range=self:getTalentRange(t)}
104   - local x, y, target = self:getTarget(tg)
105   - if not x or not y or not target then return nil end
106   - if not target:hasEffect(target.EFF_STONE_VINE) then return nil end
107   -
108   - self:attr("allow_on_heal", 1)
109   - self:heal(100 + self:combatTalentStatDamage(t, "wil", 40, 630))
110   - self:attr("allow_on_heal", -1)
111   - local tx, ty = util.findFreeGrid(x, y, 2, true, {[Map.ACTOR]=true})
112   - if tx and ty then
113   - local ox, oy = self.x, self.y
114   - self:move(tx, ty, true)
115   - if config.settings.tome.smooth_move > 0 then
116   - self:resetMoveAnim()
117   - self:setMoveAnim(ox, oy, 8, 5)
118   - end
119   - end
120   -
121   - return true
122   - end,
123   - info = function(self, t)
124   - return ([[Merge with a stone vine, travelling alongside it to reappear near an entangled creature.
125   - Merging with the stone is beneficial for you, healing %0.2f life.
126   - Healing will increase with Willpower.]])
127   - :format(100 + self:combatTalentStatDamage(t, "wil", 40, 630))
128   - end,
129   -}
130   -
131   -newTalent{
132   - name = "Rockswallow",
133   - type = {"wild-gift/earthen-vines", 4},
134   - require = gifts_req4,
135   - points = 5,
136   - equilibrium = 15,
137   - cooldown = 10,
138   - requires_target = true,
139   - range = 20,
140   - tactical = { ATTACK = { PHYSICAL = 2 }, CLOSEIN = 2 },
141   - action = function(self, t)
142   - local tg = {type="hit", range=self:getTalentRange(t)}
143   - local x, y, target = self:getTarget(tg)
144   - if not x or not y or not target then return nil end
145   - if not target:hasEffect(target.EFF_STONE_VINE) then return nil end
146   -
147   - DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, 80 + self:combatTalentStatDamage(t, "wil", 40, 330))
148   -
149   - if target.dead then return end
150   -
151   - local tx, ty = util.findFreeGrid(self.x, self.y, 2, true, {[Map.ACTOR]=true})
152   - if tx and ty then
153   - local ox, oy = target.x, target.y
154   - target:move(tx, ty, true)
155   - if config.settings.tome.smooth_move > 0 then
156   - target:resetMoveAnim()
157   - target:setMoveAnim(ox, oy, 8, 5)
158   - end
159   - end
160   -
161   - return true
162   - end,
163   - info = function(self, t)
164   - return ([[Merge your target with a stone vine, forcing it to travel alongside it to reappear near you.
165   - Merging with the stone is detrimental for the target, dealing %0.2f physical damage.
166   - Damage will increase with Willpower.]])
167   - :format(80 + self:combatTalentStatDamage(t, "wil", 40, 330))
168   - end,
... ... @@ -33,8 +33,6 @@ newTalentType{ allow_random=true, is_nature=true, type="wild-gift/fire-drake", n
33 33 newTalentType{ allow_random=true, is_nature=true, type="wild-gift/cold-drake", name = "cold drake aspect", description = "Take on the defining aspects of a Cold Drake." }
34 34 newTalentType{ allow_random=true, is_nature=true, type="wild-gift/storm-drake", name = "storm drake aspect", description = "Take on the defining aspects of a Storm Drake." }
35 35 newTalentType{ allow_random=true, is_nature=true, type="wild-gift/mindstar-mastery", name = "mindstar mastery", generic = true, description = "Learn to channel your mental power through mindstars, forming powerful psionic blades." }
36   -newTalentType{ allow_random=true, is_nature=true, type="wild-gift/earthen-power", name = "earthen power", description = "Dwarves have learned to imbue their shields with the power of stone itself." }
37   -newTalentType{ allow_random=true, is_nature=true, type="wild-gift/earthen-vines", name = "earthen vines", description = "Control the stone itself and bring it alive in the form of dreadful vines." }
38 36
39 37 -- Generic requires for gifts based on talent level
40 38 gifts_req1 = {
... ... @@ -201,6 +199,3 @@ load("/data/talents/gifts/summon-augmentation.lua")
201 199 load("/data/talents/gifts/summon-advanced.lua")
202 200
203 201 load("/data/talents/gifts/mindstar-mastery.lua")
204   -
205   -load("/data/talents/gifts/earthen-power.lua")
206   -load("/data/talents/gifts/earthen-vines.lua")
... ...
1   --- ToME - Tales of Maj'Eyal
2   --- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
3   ---
4   --- This program is free software: you can redistribute it and/or modify
5   --- it under the terms of the GNU General Public License as published by
6   --- the Free Software Foundation, either version 3 of the License, or
7   --- (at your option) any later version.
8   ---
9   --- This program is distributed in the hope that it will be useful,
10   --- but WITHOUT ANY WARRANTY; without even the implied warranty of
11   --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   --- GNU General Public License for more details.
13   ---
14   --- You should have received a copy of the GNU General Public License
15   --- along with this program. If not, see <http://www.gnu.org/licenses/>.
16   ---
17   --- Nicolas Casalini "DarkGod"
18   --- darkgod@te4.org
19   -
20   -newTalent{
21   - name = "Eldritch Blow",
22   - type = {"spell/arcane-shield", 1},
23   - require = spells_req1,
24   - points = 5,
25   - equilibrium = 3,
26   - mana = 10,
27   - cooldown = 6,
28   - range = 1,
29   - tactical = { ATTACK = { ARCANE = 2 }, DISABLE = { stun = 2 } },
30   - requires_target = true,
31   - on_pre_use = function(self, t, silent) local shield = self:hasShield() if not shield then if not silent then game.logPlayer(self, "You cannot use Eldricth Blow without a shield!") end return false end return true end,
32   - action = function(self, t)
33   - local shield = self:hasShield()
34   -
35   - local tg = {type="hit", range=self:getTalentRange(t)}
36   - local x, y, target = self:getTarget(tg)
37   - if not x or not y or not target then return nil end
38   - if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end
39   -
40   - -- First attack with both weapon & shield (since we have the Stoneshield talent)
41   - local hit = self:attackTarget(target, DamageType.ARCANE, self:combatTalentWeaponDamage(t, 0.6, (100 + self:combatTalentSpellDamage(t, 50, 300)) / 100), true)
42   -
43   - -- Try to stun !
44   - if hit then
45   - if target:canBe("stun") then
46   - target:setEffect(target.EFF_STUNNED, 2 + math.floor(self:getTalentLevel(t) / 2), {apply_power=self:combatPhysicalpower()})
47   - else
48   - game.logSeen(target, "%s resists the stun!", target.name:capitalize())
49   - end
50   - end
51   -
52   - return true
53   - end,
54   - info = function(self, t)
55   - return ([[Channel eldritch forces in your attack, hitting the target with your weapon and shield doing %d%% arcane damage.
56   - If the any of the attacks hit, the target is stunned for %d turns.
57   - The stun is considered a magical attack and thus is resisted with spell save, not physical save.]])
58   - :format(100 * self:combatTalentWeaponDamage(t, 0.6, (100 + self:combatTalentSpellDamage(t, 50, 300)) / 100), 2 + math.floor(self:getTalentLevel(t) / 2))
59   - end,
60   -}
61   -
62   -newTalent{
63   - name = "Eldritch Infusion",
64   - type = {"spell/arcane-shield", 2},
65   - require = spells_req2,
66   - points = 5,
67   - mode = "sustained",
68   - sustain_equilibrium = 15,
69   - sustain_mana = 15,
70   - cooldown = 30,
71   - tactical = { ATTACK = 3, BUFF = 2 },
72   - activate = function(self, t)
73   - local power = 5 * self:getTalentLevel(t) + (self:getWil() + self:getMag()) / 5
74   - return {
75   - onhit = self:addTemporaryValue("melee_project", {[DamageType.ARCANE]=power}),
76   - }
77   - end,
78   - deactivate = function(self, t, p)
79   - self:removeTemporaryValue("melee_project", p.onhit)
80   - return true
81   - end,
82   - info = function(self, t)
83   - return ([[Imbues your weapon with arcane power, dealing %0.2f arcane damage with each attacks.
84   - The damage will increase with Willpower and Magic stats.]]):format(damDesc(self, DamageType.ARCANE, 5 * self:getTalentLevel(t) + (self:getWil() + self:getMag()) / 5))
85   - end,
86   -}
87   -
88   -newTalent{
89   - name = "Eldritch Fury",
90   - type = {"spell/arcane-shield", 3},
91   - require = spells_req3,
92   - points = 5,
93   - equilibrium = 20,
94   - mana = 30,
95   - cooldown = 12,
96   - requires_target = true,
97   - tactical = { ATTACK = { NATURE = 3 }, DISABLE = { stun = 1 } },
98   - range = 1,
99   - on_pre_use = function(self, t, silent) local shield = self:hasShield() if not shield then if not silent then game.logPlayer(self, "You cannot use Eldricth Fury without a shield!") end return false end return true end,
100   - action = function(self, t)
101   - local shield = self:hasShield()
102   -
103   - local tg = {type="hit", range=self:getTalentRange(t)}
104   - local x, y, target = self:getTarget(tg)
105   - if not x or not y or not target then return nil end
106   - if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end
107   -
108   - -- First attack with both weapon & shield (since we have the Stoneshield talent)
109   - local hit1 = self:attackTarget(target, DamageType.NATURE, self:combatTalentWeaponDamage(t, 0.6, 1.6), true)
110   - local hit2 = self:attackTarget(target, DamageType.NATURE, self:combatTalentWeaponDamage(t, 0.6, 1.6), true)
111   - local hit3 = self:attackTarget(target, DamageType.NATURE, self:combatTalentWeaponDamage(t, 0.6, 1.6), true)
112   -
113   - -- Try to stun !
114   - if hit1 or hit2 or hit3 then
115   - if target:canBe("stun") then
116   - target:setEffect(target.EFF_DAZED, 3 + math.floor(self:getTalentLevel(t)), {apply_power=self:combatPhysicalpower(), apply_save="combatSpellResist"})
117   - else
118   - game.logSeen(target, "%s resists the dazing blows!", target.name:capitalize())
119   - end
120   - end
121   -
122   - return true
123   - end,
124   - info = function(self, t)
125   - return ([[Channel eldritch forces to speed up your attacks, hitting the target three times with your weapon and shield doing %d%% nature damage.
126   - If any of the attacks hit, the target is dazed for %d turns.
127   - The daze is considered a magical attack and thus is resisted with spell save, not physical save.]])
128   - :format(100 * self:combatTalentWeaponDamage(t, 0.6, 1.6), 3 + math.floor(self:getTalentLevel(t)))
129   - end,
130   -}
131   -
132   -newTalent{
133   - name = "Eldritch Slam",
134   - type = {"spell/arcane-shield", 4},
135   - require = spells_req4,
136   - points = 5,
137   - equilibrium = 10,
138   - mana = 30,
139   - cooldown = 20,
140   - tactical = { ATTACKAREA = { PHYSICAL = 3 } },
141   - requires_target = true,
142   - range = 1,
143   - radius = function(self, t) return 1 + self:getTalentLevelRaw(t) end,
144   - on_pre_use = function(self, t, silent) local shield = self:hasShield() if not shield then if not silent then game.logPlayer(self, "You cannot use Eldritch Slam without a shield!") end return false end return true end,
145   - action = function(self, t)
146   - local shield = self:hasShield()
147   -
148   - local tg = {type="ball", radius=self:getTalentRadius(t)}
149   - self:project(tg, self.x, self.y, function(px, py)
150   - local target = game.level.map(px, py, Map.ACTOR)
151   - if not target or target == self then return end
152   - self:attackTargetWith(target, shield.special_combat, nil, self:combatTalentWeaponDamage(t, 1.3, 2.6))
153   - end)
154   -
155   - return true
156   - end,
157   - info = function(self, t)
158   - return ([[Slam your shield on the ground, doing %d%% damage in a radius of %d.]])
159   - :format(100 * self:combatTalentWeaponDamage(t, 1.3, 2.6), self:getTalentRadius(t))
160   - end,
161   -}
... ... @@ -61,9 +61,6 @@ newTalentType{ allow_random=true, no_silence=true, is_spell=true, mana_regen=tru
61 61 newTalentType{ allow_random=true, no_silence=true, is_spell=true, mana_regen=true, type="spell/necrosis", name = "necrosis", description = "Gain control over death, eventually turning into a lich." }
62 62 newTalentType{ allow_random=true, no_silence=true, is_spell=true, mana_regen=true, type="spell/grave", name = "grave", description = "Use the rotting cold doom of the tomb to fell your foes." }
63 63
64   --- Stone Warden spells
65   -newTalentType{ allow_random=true, no_silence=true, is_spell=true, type="spell/arcane-shield", name = "arcane shield", description = "Infuse arcane forces in your shield." }
66   -
67 64 -- Generic requires for spells based on talent level
68 65 spells_req1 = {
69 66 stat = { mag=function(level) return 12 + (level-1) * 2 end },
... ... @@ -242,8 +239,6 @@ load("/data/talents/spells/fire-alchemy.lua")
242 239 load("/data/talents/spells/stone-alchemy.lua")
243 240 load("/data/talents/spells/golem.lua")
244 241
245   -load("/data/talents/spells/arcane-shield.lua")
246   -
247 242 load("/data/talents/spells/necrotic-minions.lua")
248 243 load("/data/talents/spells/advanced-necrotic-minions.lua")
249 244 load("/data/talents/spells/nightfall.lua")
... ...
... ... @@ -1267,46 +1267,6 @@ newEffect{
1267 1267 }
1268 1268
1269 1269 newEffect{
1270   - name = "STONE_VINE",
1271   - desc = "Stone Vine",
1272   - long_desc = function(self, eff) return ("A living stone vine holds the target on the ground and doing %0.2f physical damage per turn."):format(eff.dam) end,
1273   - type = "physical",
1274   - subtype = { earth=true, pin=true },
1275   - status = "detrimental",
1276   - parameters = { dam=10 },
1277   - on_gain = function(self, err) return "#Target# is grabbed by a stone vine.", "+Stone Vine" end,
1278   - on_lose = function(self, err) return "#Target# is free from the stone vine.", "-Stone Vine" end,
1279   - activate = function(self, eff)
1280   - eff.last_x = eff.src.x
1281   - eff.last_y = eff.src.y
1282   - eff.tmpid = self:addTemporaryValue("never_move", 1)
1283   - eff.particle = self:addParticles(Particles.new("stonevine_static", 1, {}))
1284   - end,
1285   - deactivate = function(self, eff)
1286   - self:removeTemporaryValue("never_move", eff.tmpid)
1287   - self:removeParticles(eff.particle)
1288   - end,
1289   - on_timeout = function(self, eff)
1290   - local severed = false
1291   - if core.fov.distance(self.x, self.y, eff.src.x, eff.src.y) >= eff.free or eff.src.dead or not game.level:hasEntity(eff.src) then severed = true end
1292   - if rng.percent(eff.free_chance) then severed = true end
1293   -
1294   - if severed then
1295   - return true
1296   - else
1297   - DamageType:get(DamageType.PHYSICAL).projector(eff.src or self, self.x, self.y, DamageType.PHYSICAL, eff.dam)
1298   - if eff.src:knowTalent(eff.src.T_ELDRITCH_VINES) then
1299   - local l = eff.src:getTalentLevel(eff.src.T_ELDRITCH_VINES)
1300   - eff.src:incEquilibrium(-l / 4)
1301   - eff.src:incMana(l / 3)
1302   - end
1303   - end
1304   - eff.last_x = eff.src.x
1305   - eff.last_y = eff.src.y
1306   - end,
1307   -}
1308   -
1309   -newEffect{
1310 1270 name = "WATERS_OF_LIFE", image = "talents/waters_of_life.png",
1311 1271 desc = "Waters of Life",
1312 1272 long_desc = function(self, eff) return ("The target purifies all diseases and poisons, turning them into healing effects.") end,
... ...
... ... @@ -442,6 +442,19 @@ function _M:orderChatChannelList(o)
442 442 end
443 443 end
444 444
  445 +function _M:orderGetDLCD(o)
  446 + self:command("DLCD", o.name, o.version, o.file)
  447 + if self:read("200") then
  448 + local _, _, size = self.last_line:find("^([0-9]+)")
  449 + size = tonumber(size)
  450 + if not size or size < 1 then return end
  451 + local body = self:receive(size)
  452 + cprofile.pushEvent(string.format("e='GetDLCD' data=%q", body))
  453 + else
  454 + cprofile.pushEvent("e='GetDLCD' data=''")
  455 + end
  456 +end
  457 +
445 458 function _M:orderPing(o)
446 459 local time = core.game.getTime()
447 460 self:command("PING")
... ...