Commit c10fc8f2c369e1d4934bd0f6c842c62075cf536a

Authored by dg
1 parent f0a5baf9

upgraded Gurshnak pride


git-svn-id: http://svn.net-core.org/repos/t-engine4@3366 51575b47-30f0-44d4-a5cc-537603b46e54
... ... @@ -129,6 +129,7 @@ newBirthDescriptor{
129 129 "#LIGHT_BLUE# * +2 Strength, +0 Dexterity, +0 Constitution",
130 130 "#LIGHT_BLUE# * +4 Magic, +3 Willpower, +0 Cunning",
131 131 },
  132 + not_on_random_boss = true,
132 133 stats = { str=2, wil=3, mag=4, },
133 134 talents_types = {
134 135 ["wild-gift/call"]={true, 0.2},
... ...
  1 +-- ToME - Tales of Maj'Eyal
  2 +-- Copyright (C) 2009, 2010, 2011 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 +startx = 15
  21 +starty = 8
  22 +endx = 0
  23 +endy = 8
  24 +
  25 +-- defineTile section
  26 +defineTile("#", "HARDWALL")
  27 +defineTile("o", "FLOOR", nil, {entity_mod=function(e) e.make_escort = nil return e end, random_filter={type='humanoid', subtype='orc', special=function(e) return e.pride == data.pride end}})
  28 +quickEntity("g", 'o')
  29 +defineTile("+", "DOOR")
  30 +if level.level == 1 then defineTile("<", "UNDERGROUND_LADDER_UP_WILDERNESS") else defineTile("<", data.up) end
  31 +defineTile(">", data.down, nil, nil, nil, {no_teleport=true})
  32 +if level.level == 1 then defineTile("O", "FLOOR", nil, {random_filter={type='humanoid', subtype='orc', special=function(e) return e.pride == data.pride end, random_boss={nb_classes=1, loot_quality="store", loot_quantity=3, rank=3.5,}}})
  33 +else quickEntity('O', 'o') end
  34 +defineTile(".", "FLOOR")
  35 +defineTile(";", "FLOOR", nil, nil, nil, {no_teleport=true})
  36 +defineTile("*", "LEVER_DOOR", nil, nil, nil, nil, {type="lever", subtype="door"})
  37 +defineTile("&", "LEVER", nil, nil, nil, nil, {type="lever", subtype="lever"})
  38 +defineTile(" ", "FLOOR", nil, {entity_mod=function(e) e.make_escort = nil return e end, random_filter={type='humanoid', subtype='orc', special=function(e) return e.pride == data.pride end, random_boss={nb_classes=1, loot_quality="store", loot_quantity=1, no_loot_randart=true, rank=3}}}, nil, {no_teleport=true})
  39 +
  40 +-- addSpot section
  41 +
  42 +-- addZone section
  43 +
  44 +-- ASCII map section
  45 +return [[
  46 +################
  47 +################
  48 +####&.....oo####
  49 +####......oo####
  50 +######....######
  51 +####........####
  52 +###..........###
  53 +###..#o.. #..###
  54 +>O*...o.. .....<
  55 +###..#o.. #..###
  56 +###..........###
  57 +####........####
  58 +######....######
  59 +####......oo####
  60 +####&.....oo####
  61 +################]]
\ No newline at end of file
... ...
... ... @@ -19,6 +19,7 @@
19 19
20 20 -- Wild Gifts
21 21 newTalentType{ allow_random=true, type="wild-gift/call", name = "call of the wild", generic = true, description = "Be at one with nature." }
  22 +newTalentType{ allow_random=true, type="wild-gift/harmony", name = "harmony", generic = true, description = "Nature heals and cleans you." }
22 23 newTalentType{ allow_random=true, type="wild-gift/antimagic", name = "antimagic", generic = true, description = "The way to combat magic, or even nullify it.\nUsing a magical device or a spell will put all antimagic talents on cooldown for a few turns." }
23 24 newTalentType{ allow_random=true, type="wild-gift/summon-melee", name = "summoning (melee)", description = "The art of calling creatures to your aid." }
24 25 newTalentType{ allow_random=true, type="wild-gift/summon-distance", name = "summoning (distance)", description = "The art of calling creatures to your aid." }
... ... @@ -55,6 +56,7 @@ gifts_req5 = {
55 56 }
56 57
57 58 load("/data/talents/gifts/call.lua")
  59 +load("/data/talents/gifts/harmony.lua")
58 60
59 61 load("/data/talents/gifts/antimagic.lua")
60 62
... ...
  1 +-- ToME - Tales of Maj'Eyal
  2 +-- Copyright (C) 2009, 2010, 2011 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 = "Waters of Life",
  22 + type = {"wild-gift/harmony", 1},
  23 + require = gifts_req1,
  24 + points = 5,
  25 + cooldown = 30,
  26 + equilibrium = 10,
  27 + tactical = { HEAL=2 },
  28 + on_pre_use = function(self, t)
  29 + for eff_id, p in pairs(self.tmp) do
  30 + local e = self.tempeffect_def[eff_id]
  31 + if e.type == "disease" or e.type == "poison" then
  32 + return true
  33 + end
  34 + end
  35 + return false
  36 + end,
  37 + action = function(self, t)
  38 + local nb = 0
  39 + for eff_id, p in pairs(self.tmp) do
  40 + local e = self.tempeffect_def[eff_id]
  41 + if e.type == "disease" or e.type == "poison" then
  42 + nb = nb + 1
  43 + end
  44 + end
  45 + self:heal(nb * self:combatTalentStatDamage(t, "wil", 20, 60))
  46 +
  47 + self:setEffect(self.EFF_WATERS_OF_LIFE, 5 + self:getTalentLevel(t), {})
  48 +
  49 + game:playSoundNear(self, "talents/spell_generic2")
  50 + return true
  51 + end,
  52 + info = function(self, t)
  53 + return ([[The waters of life flow through you, purifying any poisons or diseases currently affecting you.
  54 + For %x turns all poisons and diseases will heal you instead of damaging you.
  55 + When activated it also heals you for %d life per diseases or poisons on you.
  56 + The healing will increase with your Willpower stat.]]):
  57 + format(5 + self:getTalentLevel(t), self:combatTalentStatDamage(t, "wil", 20, 60))
  58 + end,
  59 +}
  60 +
  61 +newTalent{
  62 + name = "Elemental Harmony",
  63 + type = {"wild-gift/harmony", 2},
  64 + require = gifts_req2,
  65 + random_ego = "defensive",
  66 + points = 5,
  67 + equilibrium = 10,
  68 + cooldown = 20,
  69 + range = 1,
  70 + requires_target = true,
  71 + no_npc_use = true,
  72 + action = function(self, t)
  73 + local tg = {default_target=self, type="hit", nowarning=true, range=self:getTalentRange(t), first_target="friend"}
  74 + local x, y, target = self:getTarget(tg)
  75 + if not x or not y or not target then return nil end
  76 + if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end
  77 + if not target.undead then
  78 + target:heal(20 + self:getWil(50) * self:getTalentLevel(t))
  79 + end
  80 + game:playSoundNear(self, "talents/heal")
  81 + return true
  82 + end,
  83 + info = function(self, t)
  84 + return ([[Touch a target (or yourself) to infuse it with Nature, healing it for %d(heal does not work on undead).
  85 + Heal will increase with your Willpower stat.]]):
  86 + format(20 + self:getWil(50) * self:getTalentLevel(t))
  87 + end,
  88 +}
  89 +
  90 +newTalent{
  91 + name = "One with Nature",
  92 + type = {"wild-gift/harmony", 3},
  93 + require = gifts_req3,
  94 + points = 5,
  95 + equilibrium = 15,
  96 + cooldown = 30,
  97 + tactical = { BUFF=2 },
  98 + on_pre_use = function(self, t) return self:hasEffect(self.EFF_INFUSION_SATURATION) end,
  99 + action = function(self, t)
  100 + self:removeEffect(self.EFF_INFUSION_SATURATION)
  101 + local tids = {}
  102 + local nb = self:getTalentLevelRaw(t)
  103 + for tid, _ in pairs(self.talents_cd) do
  104 + local tt = self:getTalentFromId(tid)
  105 + if tt.type[1] == "inscriptions/infusions" and self:isTalentCoolingDown(t) then tids[#tids+1] = tid end
  106 + end
  107 + for i = 1, nb do
  108 + if #tids == 0 then break end
  109 + local tid = rng.tableRemove(tids)
  110 + self.talents_cd[tid] = self.talents_cd[tid] - (1 + math.floor(self:getTalentLevel(t) / 2))
  111 + if self.talents_cd[tid] <= 0 then self.talents_cd[tid] = nil end
  112 + end
  113 + game:playSoundNear(self, "talents/spell_generic2")
  114 + return true
  115 + end,
  116 + info = function(self, t)
  117 + local turns = 1 + math.floor(self:getTalentLevel(t) / 2)
  118 + local nb = self:getTalentLevelRaw(t)
  119 + return ([[Commune with nature, removing the infusion saturation effect and reducing the cooldown of %d infusions by %d turns.]]):
  120 + format(nb, turns)
  121 + end,
  122 +}
  123 +
  124 +newTalent{
  125 + name = "Natural Perfection",
  126 + type = {"wild-gift/harmony", 4},
  127 + require = gifts_req4,
  128 + points = 5,
  129 + equilibrium = 20,
  130 + cooldown = 50,
  131 + range = 10,
  132 + tactical = { BUFF = 2 },
  133 + action = function(self, t)
  134 + local nb = math.ceil(self:getTalentLevel(t) + 2)
  135 + local tids = {}
  136 + for tid, _ in pairs(self.talents_cd) do
  137 + local tt = self:getTalentFromId(tid)
  138 + if tt.type[2] <= self:getTalentLevelRaw(t) and tt.type[1]:find("^wild%-gift/") then
  139 + tids[#tids+1] = tid
  140 + end
  141 + end
  142 + for i = 1, nb do
  143 + if #tids == 0 then break end
  144 + local tid = rng.tableRemove(tids)
  145 + self.talents_cd[tid] = nil
  146 + end
  147 + self.changed = true
  148 + game:playSoundNear(self, "talents/spell_generic2")
  149 + return true
  150 + end,
  151 + info = function(self, t)
  152 + return ([[Your deep link with Nature allows you to reset the cooldown of %d of your wild gifts of level %d or less.]]):
  153 + format(math.ceil(self:getTalentLevel(t) + 2), self:getTalentLevelRaw(t))
  154 + end,
  155 +}
... ...
... ... @@ -226,7 +226,9 @@ newEffect{
226 226 return old_eff
227 227 end,
228 228 on_timeout = function(self, eff)
229   - DamageType:get(DamageType.NATURE).projector(eff.src, self.x, self.y, DamageType.NATURE, eff.power)
  229 + if self:attr("purify_poison") then self:heal(eff.power)
  230 + else DamageType:get(DamageType.NATURE).projector(eff.src, self.x, self.y, DamageType.NATURE, eff.power)
  231 + end
230 232 end,
231 233 }
232 234
... ... @@ -244,7 +246,9 @@ newEffect{
244 246 eff.dur = self:updateEffectDuration(eff.dur, "pin")
245 247 end,
246 248 on_timeout = function(self, eff)
247   - DamageType:get(DamageType.NATURE).projector(eff.src, self.x, self.y, DamageType.NATURE, eff.power)
  249 + if self:attr("purify_poison") then self:heal(eff.power)
  250 + else DamageType:get(DamageType.NATURE).projector(eff.src, self.x, self.y, DamageType.NATURE, eff.power)
  251 + end
248 252 end,
249 253 deactivate = function(self, eff)
250 254 self:removeTemporaryValue("never_move", eff.tmpid)
... ... @@ -264,7 +268,9 @@ newEffect{
264 268 eff.healid = self:addTemporaryValue("healing_factor", -eff.heal_factor / 100)
265 269 end,
266 270 on_timeout = function(self, eff)
267   - DamageType:get(DamageType.NATURE).projector(eff.src, self.x, self.y, DamageType.NATURE, eff.power)
  271 + if self:attr("purify_poison") then self:heal(eff.power)
  272 + else DamageType:get(DamageType.NATURE).projector(eff.src, self.x, self.y, DamageType.NATURE, eff.power)
  273 + end
268 274 end,
269 275 deactivate = function(self, eff)
270 276 self:removeTemporaryValue("healing_factor", eff.healid)
... ... @@ -1317,7 +1323,9 @@ newEffect{
1317 1323 on_lose = function(self, err) return "#Target# is free from the rotting disease." end,
1318 1324 -- Damage each turn
1319 1325 on_timeout = function(self, eff)
1320   - DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1326 + if self:attr("purify_disease") then self:heal(eff.dam)
  1327 + else DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1328 + end
1321 1329 end,
1322 1330 -- Lost of CON
1323 1331 activate = function(self, eff)
... ... @@ -1339,7 +1347,9 @@ newEffect{
1339 1347 on_lose = function(self, err) return "#Target# is free from the decrepitude disease." end,
1340 1348 -- Damage each turn
1341 1349 on_timeout = function(self, eff)
1342   - DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1350 + if self:attr("purify_disease") then self:heal(eff.dam)
  1351 + else DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1352 + end
1343 1353 end,
1344 1354 -- Lost of CON
1345 1355 activate = function(self, eff)
... ... @@ -1361,7 +1371,9 @@ newEffect{
1361 1371 on_lose = function(self, err) return "#Target# is free from the weakness disease." end,
1362 1372 -- Damage each turn
1363 1373 on_timeout = function(self, eff)
1364   - DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1374 + if self:attr("purify_disease") then self:heal(eff.dam)
  1375 + else DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1376 + end
1365 1377 end,
1366 1378 -- Lost of CON
1367 1379 activate = function(self, eff)
... ... @@ -1383,7 +1395,9 @@ newEffect{
1383 1395 on_lose = function(self, err) return "#Target# is free from the epidemic." end,
1384 1396 -- Damage each turn
1385 1397 on_timeout = function(self, eff)
1386   - DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1398 + if self:attr("purify_disease") then self:heal(eff.dam)
  1399 + else DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
  1400 + end
1387 1401 end,
1388 1402 activate = function(self, eff)
1389 1403 eff.tmpid = self:addTemporaryValue("diseases_spread_on_blight", 1)
... ... @@ -3917,3 +3931,20 @@ newEffect{
3917 3931 eff.last_y = eff.src.y
3918 3932 end,
3919 3933 }
  3934 +
  3935 +newEffect{
  3936 + name = "WATERS_OF_LIFE",
  3937 + desc = "Waters of Life",
  3938 + long_desc = function(self, eff) return ("The target purifies all diseases and poisons, turning them into healing effects.") end,
  3939 + type = "physical",
  3940 + status = "beneficial",
  3941 + parameters = { },
  3942 + activate = function(self, eff)
  3943 + eff.poisid = self:addTemporaryValue("purify_poison", 1)
  3944 + eff.diseid = self:addTemporaryValue("purify_disease", 1)
  3945 + end,
  3946 + deactivate = function(self, eff)
  3947 + self:removeTemporaryValue("purify_poison", eff.poisid)
  3948 + self:removeTemporaryValue("purify_disease", eff.diseid)
  3949 + end,
  3950 +}
... ...
... ... @@ -32,3 +32,49 @@ newEntity{
32 32 change_level = 1,
33 33 change_zone = "slime-tunnels",
34 34 }
  35 +
  36 +newEntity{
  37 + define_as = "LEVER_DOOR",
  38 + type = "wall", subtype = "floor",
  39 + name = "sealed door", image = "terrain/granite_door1.png",
  40 + display = '+', color_r=238, color_g=154, color_b=77, back_color=colors.DARK_UMBER,
  41 + nice_tiler = { method="door3d", north_south="LEVER_DOOR_VERT", west_east="LEVER_DOOR_HORIZ" },
  42 + notice = true,
  43 + always_remember = true,
  44 + block_sight = true,
  45 + block_sense = true,
  46 + block_esp = true,
  47 + levers = 0,
  48 + force_clone = true,
  49 + door_player_stop = "This door seems to have been sealed off, you need to find a way to open it.",
  50 + door_opened = "DOOR_OPEN",
  51 +}
  52 +newEntity{ base = "LEVER_DOOR", define_as = "LEVER_DOOR_HORIZ", image = "terrain/granite_door1.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, door_opened = "DOOR_HORIZ_OPEN"}
  53 +newEntity{ base = "LEVER_DOOR", define_as = "LEVER_DOOR_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_vert.png", z=17}, class.new{image="terrain/granite_door1_vert_north.png", z=18, display_y=-1}}, door_opened = "DOOR_OPEN_VERT"}
  54 +
  55 +newEntity{
  56 + define_as = "LEVER",
  57 + type = "lever", subtype = "floor",
  58 + name = "huge lever",
  59 + display = '&', color=colors.UMBER, back_color=colors.DARK_UMBER,
  60 + notice = true,
  61 + always_remember = true,
  62 + lever = true,
  63 + force_clone = true,
  64 + block_move = function(self, x, y, e, act)
  65 + if act and e.player and self.lever then
  66 + self.lever = false
  67 + local spot = game.level:pickSpot{type="lever", subtype="door"}
  68 + if not spot then return true end
  69 + local g = game.level.map(spot.x, spot.y, engine.Map.TERRAIN)
  70 + g.levers = (g.levers or 0) + 1
  71 + if g.levers >= 2 then
  72 + game.level.map(spot.x, spot.y, engine.Map.TERRAIN, game.zone.grid_list[g.door_opened])
  73 + game.log("#VIOLET#You hear a door openning.")
  74 + else
  75 + game.log("#VIOLET#You hear a mechanism clicking.")
  76 + end
  77 + end
  78 + return true
  79 + end,
  80 +}
... ...
... ... @@ -19,11 +19,19 @@
19 19
20 20 return {
21 21 name = "Grushnak Pride",
  22 + display_name = function()
  23 + if game.level.level % 2 == 0 then return "Grushnak Pride ("..(game.level.level/2)..")"
  24 + else return "Grushnak Pride (guarded barracks)"
  25 + end
  26 + end,
  27 + variable_zone_name = true,
22 28 level_range = {35, 60},
23 29 level_scheme = "player",
24   - max_level = 5,
  30 + max_level = 10,
25 31 decay = {300, 800},
26   - actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end,
  32 + -- 10 levels but really only 5, the 5 others are just transitions
  33 + actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + math.floor(level.level / 2) + rng.range(-1,2) end,
  34 + level_adjust_level = function(zone, level) return zone.base_level + math.floor(level.level / 2) end,
27 35 width = 50, height = 50,
28 36 persistent = "zone",
29 37 -- all_remembered = true,
... ... @@ -34,6 +42,7 @@ return {
34 42 generator = {
35 43 map = {
36 44 class = "engine.generator.map.Roomer",
  45 + pride = "grushnak",
37 46 nb_rooms = 10,
38 47 lite_room_chance = 20,
39 48 rooms = {"forest_clearing", {"money_vault",5}, {"pit",7}, {"greater_vault",8}},
... ... @@ -57,18 +66,40 @@ return {
57 66 },
58 67 post_process = function(level)
59 68 -- Place a lore note on each level
60   - game:placeRandomLoreObject("GARKUL_HISTORY"..level.level)
  69 + if level.level == 2 or level.level == 4 or level.level == 6 or level.level == 8 or level.level == 10 then
  70 + game:placeRandomLoreObject("GARKUL_HISTORY"..(level.level/2))
  71 + end
61 72
62 73 for uid, e in pairs(level.entities) do e.faction="orc-pride" end
63 74 end,
64 75 levels =
65 76 {
66   - [1] = {
67   - generator = { map = {
68   - up = "UNDERGROUND_LADDER_UP_WILDERNESS",
69   - }, },
70   - },
71   - [5] = {
  77 + [1] = { generator = {
  78 + map = { class = "engine.generator.map.Static", map = "zones/prides-middle" },
  79 + actor = { nb_npc = {0, 0} },
  80 + object = { nb_object = {0, 0} },
  81 + }},
  82 + [3] = { generator = {
  83 + map = { class = "engine.generator.map.Static", map = "zones/prides-middle" },
  84 + actor = { nb_npc = {0, 0} },
  85 + object = { nb_object = {0, 0} },
  86 + }},
  87 + [5] = { generator = {
  88 + map = { class = "engine.generator.map.Static", map = "zones/prides-middle" },
  89 + actor = { nb_npc = {0, 0} },
  90 + object = { nb_object = {0, 0} },
  91 + }},
  92 + [7] = { generator = {
  93 + map = { class = "engine.generator.map.Static", map = "zones/prides-middle" },
  94 + actor = { nb_npc = {0, 0} },
  95 + object = { nb_object = {0, 0} },
  96 + }},
  97 + [9] = { generator = {
  98 + map = { class = "engine.generator.map.Static", map = "zones/prides-middle" },
  99 + actor = { nb_npc = {0, 0} },
  100 + object = { nb_object = {0, 0} },
  101 + }},
  102 + [10] = {
72 103 generator = { map = {
73 104 down = "SLIME_TUNNELS",
74 105 force_last_stair = true,
... ...