Commit b9cb66bd6f15b125e85b8c7c2af264ad2ba96515
1 parent
d7961dd3
skeleton & ghoul player races
git-svn-id: http://svn.net-core.org/repos/t-engine4@554 51575b47-30f0-44d4-a5cc-537603b46e54
Showing
10 changed files
with
273 additions
and
4 deletions
... | ... | @@ -110,10 +110,15 @@ function _M:trigger(x, y, who) |
110 | 110 | str = str:gsub("@Target@", tname:capitalize()) |
111 | 111 | game.logSeen(who, "%s", str) |
112 | 112 | end |
113 | - if self:triggered(x, y, who) then | |
113 | + local known, del = self:triggered(x, y, who) | |
114 | + if known then | |
114 | 115 | self:setKnown(who, true) |
115 | 116 | game.level.map:updateMap(x, y) |
116 | 117 | end |
118 | + if del then | |
119 | + game.level.map:remove(x, y, Map.TRAP) | |
120 | + if self.removed then self:removed(x, y, who) end | |
121 | + end | |
117 | 122 | end |
118 | 123 | |
119 | 124 | --- When moving on a trap, trigger it | ... | ... |
... | ... | @@ -357,6 +357,23 @@ function _M:onTakeHit(value, src) |
357 | 357 | end |
358 | 358 | end |
359 | 359 | |
360 | + if self:attr("damage_shield") then | |
361 | + -- Absorb damage into the shield | |
362 | + if value <= self.damage_shield_absorb then | |
363 | + self.damage_shield_absorb = self.damage_shield_absorb - value | |
364 | + value = 0 | |
365 | + else | |
366 | + self.damage_shield_absorb = 0 | |
367 | + value = value - self.damage_shield_absorb | |
368 | + end | |
369 | + | |
370 | + -- If we are at the end of the capacity, release the time shield damage | |
371 | + if self.damage_shield_absorb <= 0 then | |
372 | + game.logPlayer(self, "Your shield crumbles under the damage!") | |
373 | + self:removeEffect(self.EFF_DAMAGE_SHIELD) | |
374 | + end | |
375 | + end | |
376 | + | |
360 | 377 | if self:attr("displacement_shield") then |
361 | 378 | -- Absorb damage into the displacement shield |
362 | 379 | if value <= self.displacement_shield and rng.percent(self.displacement_shield_chance) then | ... | ... |
... | ... | @@ -33,8 +33,14 @@ newBirthDescriptor{ |
33 | 33 | { |
34 | 34 | __ALL__ = "never", |
35 | 35 | Ghoul = function() return config.settings.tome.allow_build.undead_ghoul and "allow" or "never" end, |
36 | + Skeleton = function() return config.settings.tome.allow_build.undead_skeleton and "allow" or "never" end, | |
37 | + Vampire = function() return config.settings.tome.allow_build.undead_vampire and "allow" or "never" end, | |
38 | + Wight = function() return config.settings.tome.allow_build.undead_wight and "allow" or "never" end, | |
36 | 39 | }, |
37 | 40 | }, |
41 | + copy = { | |
42 | + undead = 1, | |
43 | + } | |
38 | 44 | } |
39 | 45 | |
40 | 46 | newBirthDescriptor |
... | ... | @@ -48,6 +54,7 @@ newBirthDescriptor |
48 | 54 | "- bleeding immunity", |
49 | 55 | "- stun resistance", |
50 | 56 | "- fear immunity", |
57 | + "- special ghoul talents: ghoulish leap, gnaw and retch", | |
51 | 58 | "The rotting body of ghouls also forces them to act a bit slower than most creatures.", |
52 | 59 | }, |
53 | 60 | descriptor_choices = |
... | ... | @@ -60,7 +67,7 @@ newBirthDescriptor |
60 | 67 | }, |
61 | 68 | stats = { str=3, con=5, wil=-2, mag=0, dex=1, cun=2 }, |
62 | 69 | talents_types = { |
63 | - ["undead/ghoul"]={true, 0.3}, | |
70 | + ["undead/ghoul"]={true, 0.1}, | |
64 | 71 | }, |
65 | 72 | talents = { |
66 | 73 | [ActorTalents.T_GHOUL]=1, |
... | ... | @@ -80,3 +87,47 @@ newBirthDescriptor |
80 | 87 | }, |
81 | 88 | experience = 2, |
82 | 89 | } |
90 | + | |
91 | +newBirthDescriptor | |
92 | +{ | |
93 | + type = "subrace", | |
94 | + name = "Skeleton", | |
95 | + desc = { | |
96 | + "Skeletons are animated bones, undead creatures, both strong and dextrous.", | |
97 | + "They have access to special skeleton talents and a wide range of undead abilities:", | |
98 | + "- poison immunity", | |
99 | + "- bleeding immunity", | |
100 | + "- fear immunity", | |
101 | + "- no need to breath", | |
102 | + "- special skeleton talents: ", | |
103 | + "The rotting body of ghouls also forces them to act a bit slower than most creatures.", | |
104 | + }, | |
105 | + descriptor_choices = | |
106 | + { | |
107 | + sex = | |
108 | + { | |
109 | + __ALL__ = "never", | |
110 | + Male = "allow", | |
111 | + }, | |
112 | + }, | |
113 | + stats = { str=3, con=0, wil=0, mag=0, dex=4, cun=0 }, | |
114 | + talents_types = { | |
115 | + ["undead/skeleton"]={true, 0.1}, | |
116 | + }, | |
117 | + talents = { | |
118 | + [ActorTalents.T_SKELETON]=1, | |
119 | + }, | |
120 | + copy = { | |
121 | + type = "undead", subtype="skeleton", | |
122 | + default_wilderness = {"wilderness/main", 39, 17}, | |
123 | + starting_zone = "tower-amon-sul", | |
124 | + starting_quest = "start-dunadan", | |
125 | + starting_intro = "dwarf", | |
126 | + life_rating=12, | |
127 | + poison_immune = 1, | |
128 | + cut_immune = 1, | |
129 | + fear_immune = 1, | |
130 | + no_breath = 1, | |
131 | + }, | |
132 | + experience = 2, | |
133 | +} | ... | ... |
... | ... | @@ -278,6 +278,20 @@ newDamageType{ |
278 | 278 | end, |
279 | 279 | } |
280 | 280 | |
281 | +-- Bleeding damage | |
282 | +newDamageType{ | |
283 | + name = "bleed", type = "BLEED", | |
284 | + projector = function(src, x, y, type, dam) | |
285 | + DamageType:get(DamageType.PHYSICAL).projector(src, x, y, DamageType.PHYSICAL, dam / 6) | |
286 | + dam = dam - dam / 6 | |
287 | + local target = game.level.map(x, y, Map.ACTOR) | |
288 | + if target and target:canBe("cut") then | |
289 | + -- Set on fire! | |
290 | + target:setEffect(target.EFF_CUT, 5, {src=src, power=dam / 5}) | |
291 | + end | |
292 | + end, | |
293 | +} | |
294 | + | |
281 | 295 | -- Slime damage |
282 | 296 | newDamageType{ |
283 | 297 | name = "slime", type = "SLIME", |
... | ... | @@ -404,3 +418,16 @@ newDamageType{ |
404 | 418 | end |
405 | 419 | end, |
406 | 420 | } |
421 | + | |
422 | +-- Retch: heal undead; damage living | |
423 | +newDamageType{ | |
424 | + name = "retch", type = "RETCH", | |
425 | + projector = function(src, x, y, type, dam) | |
426 | + local target = game.level.map(x, y, Map.ACTOR) | |
427 | + if target and target.undead then | |
428 | + target:heal(dam) | |
429 | + elseif target then | |
430 | + DamageType:get(DamageType.BLIGHT).projector(src, x, y, DamageType.BLIGHT, dam) | |
431 | + end | |
432 | + end, | |
433 | +} | ... | ... |
... | ... | @@ -24,11 +24,15 @@ newTalent{ |
24 | 24 | require = undeads_req1, |
25 | 25 | points = 5, |
26 | 26 | on_learn = function(self, t) |
27 | + self:incStat(self.STAT_STR, 2) | |
28 | + self:incStat(self.STAT_CON, 2) | |
27 | 29 | end, |
28 | 30 | on_unlearn = function(self, t) |
31 | + self:incStat(self.STAT_STR, -2) | |
32 | + self:incStat(self.STAT_CON, -2) | |
29 | 33 | end, |
30 | 34 | info = function(self, t) |
31 | - return ([[Improves your ghoulish body.]]):format() | |
35 | + return ([[Improves your ghoulish body, increasing strength and constitution by %d.]]):format(2 * self:getTalentLevelRaw(t)) | |
32 | 36 | end, |
33 | 37 | } |
34 | 38 | |
... | ... | @@ -110,13 +114,31 @@ newTalent{ |
110 | 114 | type = {"undead/ghoul",4}, |
111 | 115 | require = undeads_req4, |
112 | 116 | points = 5, |
117 | + cooldown = 25, | |
113 | 118 | tactical = { |
114 | 119 | DEFEND = 10, |
120 | + ATTACK = 10, | |
115 | 121 | }, |
122 | + range=1, | |
116 | 123 | action = function(self, t) |
124 | + local duration = self:getTalentLevel(t) / 2 + 4 | |
125 | + local radius = 3 | |
126 | + local dam = (2 + self:getCon(8)) * self:getTalentLevel(t) | |
127 | + local tg = {type="ball", range=self:getTalentRange(t), radius=radius} | |
128 | + -- Add a lasting map effect | |
129 | + game.level.map:addEffect(self, | |
130 | + self.x, self.y, duration, | |
131 | + DamageType.RETCH, dam, | |
132 | + radius, | |
133 | + 5, nil, | |
134 | + engine.Entity.new{alpha=100, display='', color_br=30, color_bg=180, color_bb=60}, | |
135 | + nil, self:spellFriendlyFire() | |
136 | + ) | |
137 | + game:playSoundNear(self, "talents/cloud") | |
117 | 138 | return true |
118 | 139 | end, |
119 | 140 | info = function(self, t) |
120 | - return ([[Vomit on the ground aruond you, healing any undeads in the area and damaging others.]]) | |
141 | + return ([[Vomit on the ground aruond you, healing any undeads in the area and damaging others. | |
142 | + Lasts %d turns and deals %d blight damage.]]):format(self:getTalentLevel(t) / 2 + 4, (2 + self:getCon(8)) * self:getTalentLevel(t)) | |
121 | 143 | end, |
122 | 144 | } | ... | ... |
1 | +-- ToME - Tales of Middle-Earth | |
2 | +-- Copyright (C) 2009, 2010 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 = "Skeleton", | |
22 | + type = {"undead/skeleton", 1}, | |
23 | + mode = "passive", | |
24 | + require = undeads_req1, | |
25 | + points = 5, | |
26 | + on_learn = function(self, t) | |
27 | + self:incStat(self.STAT_STR, 2) | |
28 | + self:incStat(self.STAT_DEX, 2) | |
29 | + end, | |
30 | + on_unlearn = function(self, t) | |
31 | + self:incStat(self.STAT_STR, -2) | |
32 | + self:incStat(self.STAT_DEX, -2) | |
33 | + end, | |
34 | + info = function(self, t) | |
35 | + return ([[Improves your skeletal condition, increasing strength and dexterity by %d.]]):format(2 * self:getTalentLevelRaw(t)) | |
36 | + end, | |
37 | +} | |
38 | + | |
39 | +newTalent{ | |
40 | + name = "Sharp Bones", | |
41 | + type = {"undead/skeleton", 2}, | |
42 | + require = undeads_req2, | |
43 | + points = 5, | |
44 | + cooldown = 15, | |
45 | + tactical = { | |
46 | + ATTACK = 10, | |
47 | + }, | |
48 | + range = 1, | |
49 | + action = function(self, t) | |
50 | + local x, y = self.x, self.y | |
51 | + if game.level.map(x, y, game.level.map.TRAP) then | |
52 | + game.logPlayer(self, "There is already a trap here!") | |
53 | + return | |
54 | + end | |
55 | + | |
56 | + local dam = (10 + self:getStr(20)) * self:getTalentLevel(t) | |
57 | + | |
58 | + local e = require("mod.class.Trap").new{ | |
59 | + type = "physical", subtype="sharp", id_by_type=true, unided_name = "trap", identified=true, | |
60 | + name = "sharp bones", | |
61 | + display = '^', color=colors.ANTIQUE_WHITE, | |
62 | + triggered = function(self, x, y, who) | |
63 | + self:project({type="hit",x=x,y=y}, x, y, engine.DamageType.BLEED, dam) | |
64 | + return true, true | |
65 | + end, | |
66 | + summoner_gain_exp = true, | |
67 | + summoner = self, | |
68 | + } | |
69 | + game.zone:addEntity(game.level, e, "trap", x, y) | |
70 | + | |
71 | + game:playSoundNear(self, "talents/earth") | |
72 | + return true | |
73 | + end, | |
74 | + info = function(self, t) | |
75 | + return ([[Lay down some sharpened bones to make a simple trap that will cause anyone stepping on it to bleed for %d damage.]]): | |
76 | + format((10 + self:getStr(20)) * self:getTalentLevel(t)) | |
77 | + end, | |
78 | +} | |
79 | + | |
80 | +newTalent{ | |
81 | + name = "Bone Armour", | |
82 | + type = {"undead/skeleton", 3}, | |
83 | + require = undeads_req3, | |
84 | + points = 5, | |
85 | + cooldown = 30, | |
86 | + tactical = { | |
87 | + DEFEND = 20, | |
88 | + }, | |
89 | + range = 1, | |
90 | + action = function(self, t) | |
91 | + self:setEffect(self.EFF_DAMAGE_SHIELD, 10, {power=(8 + self:getDex(20)) * self:getTalentLevel(t)}) | |
92 | + return true | |
93 | + end, | |
94 | + info = function(self, t) | |
95 | + return ([[Creates a shield of bones absorbing %d damage. Lasts for 10 turns.]]): | |
96 | + format((5 + self:getDex(20)) * self:getTalentLevel(t)) | |
97 | + end, | |
98 | +} | |
99 | + | |
100 | +newTalent{ short_name = "SKELETON_REASSEMBLE", | |
101 | + name = "Re-assemble", | |
102 | + type = {"undead/skeleton",4}, | |
103 | + require = undeads_req4, | |
104 | + points = 5, | |
105 | + cooldown = 45, | |
106 | + tactical = { | |
107 | + DEFEND = 10, | |
108 | + }, | |
109 | + range=1, | |
110 | + action = function(self, t) | |
111 | + self:heal(self:getTalentLevel(t) * self.level / 2, self) | |
112 | + game:playSoundNear(self, "talents/heal") | |
113 | + return true | |
114 | + end, | |
115 | + info = function(self, t) | |
116 | + return ([[Re-position some of your bones, healing yourself for %d. | |
117 | + At level 5 you will gain the ability to completly re-assemble your body should it be destroyed (can only be used once)]]): | |
118 | + format(self:getTalentLevel(t) * self.level / 2) | |
119 | + end, | |
120 | +} | ... | ... |
... | ... | @@ -395,6 +395,24 @@ newEffect{ |
395 | 395 | end, |
396 | 396 | } |
397 | 397 | |
398 | +newEffect{ | |
399 | + name = "DAMAGE_SHIELD", | |
400 | + desc = "Damage Shield", | |
401 | + type = "magical", | |
402 | + status = "beneficial", | |
403 | + parameters = { power=100 }, | |
404 | + on_gain = function(self, err) return "A shield forms around #target#.", "+Shield" end, | |
405 | + on_lose = function(self, err) return "The shield around #target# crumbles.", "-Shield" end, | |
406 | + activate = function(self, eff) | |
407 | + eff.tmpid = self:addTemporaryValue("damage_shield", eff.power) | |
408 | + --- Warning there can be only one time shield active at once for an actor | |
409 | + self.damage_shield_absorb = eff.power | |
410 | + end, | |
411 | + deactivate = function(self, eff) | |
412 | + self:removeTemporaryValue("damage_shield", eff.tmpid) | |
413 | + self.damage_shield_absorb = nil | |
414 | + end, | |
415 | +} | |
398 | 416 | |
399 | 417 | newEffect{ |
400 | 418 | name = "TIME_SHIELD", | ... | ... |
... | ... | @@ -134,6 +134,13 @@ function _M:use() |
134 | 134 | self:cleanActor() |
135 | 135 | self:restoreRessources() |
136 | 136 | self:resurrectBasic() |
137 | + elseif act == "skeleton" then | |
138 | + self.actor:attr("re-assembled", 1) | |
139 | + game.logPlayer(self.actor, "#YELLOW#Your bones magically come back together. You are once more able to dish pain to your foes!") | |
140 | + | |
141 | + self:cleanActor() | |
142 | + self:restoreRessources() | |
143 | + self:resurrectBasic() | |
137 | 144 | end |
138 | 145 | end |
139 | 146 | |
... | ... | @@ -142,6 +149,7 @@ function _M:generateList() |
142 | 149 | |
143 | 150 | if config.settings.tome.cheat then list[#list+1] = {name="Resurrect by cheating", action="cheat"} end |
144 | 151 | if self.actor:attr("blood_life") and not self.actor:attr("undead") then list[#list+1] = {name="Resurrect with the Blood of Life", action="blood_life"} end |
152 | + if self.actor:getTalentLevelRaw(self.actor.T_SKELETON_REASSEMBLE) >= 5 and not self.actor:attr("re-assembled") then list[#list+1] = {name="Re-assemble your bones ad resurrect (Skeleton ability)", action="skeleton"} end | |
145 | 153 | |
146 | 154 | list[#list+1] = {name="Character dump", action="dump"} |
147 | 155 | list[#list+1] = {name="Exit to main menu", action="exit"} | ... | ... |
No preview for this file type
-
Please register or login to post a comment