Skip to content
Snippets Groups Projects
Commit b47548a9 authored by DarkGod's avatar DarkGod
Browse files

After having played tome at least 5 hours, the New Game menu will always...

After having played tome at least 5 hours, the New Game menu will always display, to make the link to grab other modules visible
parent 615b05a5
No related branches found
No related tags found
No related merge requests found
Showing
with 11 additions and 1658 deletions
......@@ -65,7 +65,17 @@ function _M:init()
end
function _M:on_register()
if #self.list == 1 and not self.has_incompatible then
if
#self.list == 1 and
not self.has_incompatible and
(
not profile or
not profile.generic or
not profile.generic.modules_played or
not profile.generic.modules_played.tome or
profile.generic.modules_played.tome < 5 * 60 * 60
)
then
game:unregisterDialog(self)
self.list[1]:fct()
end
......
-- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
local dirs = {
[1] = {2},
[2] = {3},
[3] = {6},
[4] = {1},
[6] = {9},
[7] = {4},
[8] = {7},
[9] = {8},
}
newAI("adventurer", function(self)
-- Creature will randomly either spin or move. Chance of each can
-- be varied. Currently set based on light range, so that enemies
-- with longer ranges are more likely to turn, whilst short-sighted
-- enemies move around more.
if rng.chance(self.lite) then
self:moveDir(rng.table{1,2,3,4,6,7,8,9})
else
self.dir = rng.table(dirs[self.dir])
game.level.map.changed = true
self:useEnergy()
end
return true
end)
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
require "engine.Actor"
require "engine.Autolevel"
require "engine.interface.ActorTemporaryEffects"
require "engine.interface.ActorLife"
require "engine.interface.ActorProject"
require "engine.interface.ActorTalents"
require "engine.interface.ActorResource"
require "engine.interface.ActorFOV"
require "mod.class.interface.Combat"
local Map = require "engine.Map"
module(..., package.seeall, class.inherit(
engine.Actor,
engine.interface.ActorTemporaryEffects,
engine.interface.ActorLife,
engine.interface.ActorProject,
engine.interface.ActorTalents,
engine.interface.ActorResource,
engine.interface.ActorFOV,
mod.class.interface.Combat
))
function _M:init(t, no_default)
-- Default regen
t.max_shadow = 2
t.max_lurk = 2
engine.Actor.init(self, t, no_default)
engine.interface.ActorTemporaryEffects.init(self, t)
engine.interface.ActorLife.init(self, t)
engine.interface.ActorProject.init(self, t)
engine.interface.ActorTalents.init(self, t)
engine.interface.ActorResource.init(self, t)
engine.interface.ActorFOV.init(self, t)
self:incShadow(1000)
self:incLurk(1000)
end
function _M:act()
if not engine.Actor.act(self) then return end
self.changed = true
-- Cooldown talents
self:cooldownTalents()
-- Regen resources
self:regenLife()
self:regenResources()
-- Compute timed effects
self:timedEffects()
-- Still enough energy to act ?
if self.energy.value < game.energy_to_act then return false end
return true
end
function _M:move(x, y, force)
local moved = false
if force or self:enoughEnergy() then
moved = engine.Actor.move(self, x, y, force)
if not force and moved and not self.did_energy then self:useEnergy() end
end
self.did_energy = nil
return moved
end
function _M:tooltip()
return ([[%s%s]]):format(
self:getDisplayString(),
self.name
)
end
function _M:onTakeHit(value, src)
return value
end
function _M:die(src)
engine.interface.ActorLife.die(self, src)
game.level.map:particleEmitter(self.x, self.y, 1, "blood")
if src.player then
src.kills = src.kills + 1
if not self:attr("blind") then src.lurkkills = src.lurkkills + 1 end
src.max_shadow = math.floor((src.kills + src.lurkkills * 2) / 8) + 3
src.max_lurk = math.floor((src.kills + src.lurkkills * 2) / 10) + 2
if src.kills > 59 then src.max_lurk = src.max_lurk - 1 end
if src.kills + src.lurkkills * 2 > 50 then src.sight = 9 end
src:incShadow(2 + (self:attr("blind") and 0 or 2))
src.changed = true
end
return true
end
function _M:attack(target)
self:bumpInto(target)
end
--- Called before a talent is used
-- Check the actor can cast it
-- @param ab the talent (not the id, the table)
-- @return true to continue, false to stop
function _M:preUseTalent(ab, silent)
if not self:enoughEnergy() then print("fail energy") return false end
if ab.mode == "sustained" then
if ab.sustain_shadow and self.max_shadow < ab.sustain_shadow and not self:isTalentActive(ab.id) then
game.logPlayer(self, "You do not have enough shadow to activate %s.", ab.name)
return false
end
else
if ab.shadow and self:getShadow() < ab.shadow then
game.logPlayer(self, "You do not have enough shadow to cast %s.", ab.name)
return false
end
end
if not silent then
-- Allow for silent talents
if ab.message ~= nil then
if ab.message then
game.logSeen(self, "%s", self:useTalentMessage(ab))
end
elseif ab.mode == "sustained" and not self:isTalentActive(ab.id) then
game.logSeen(self, "%s activates %s.", self.name:capitalize(), ab.name)
elseif ab.mode == "sustained" and self:isTalentActive(ab.id) then
game.logSeen(self, "%s deactivates %s.", self.name:capitalize(), ab.name)
else
game.logSeen(self, "%s uses %s.", self.name:capitalize(), ab.name)
end
end
return true
end
--- Called before a talent is used
-- Check if it must use a turn, mana, stamina, ...
-- @param ab the talent (not the id, the table)
-- @param ret the return of the talent action
-- @return true to continue, false to stop
function _M:postUseTalent(ab, ret)
if not ret then return end
self:useEnergy()
if ab.mode == "sustained" then
if not self:isTalentActive(ab.id) then
if ab.sustain_shadow then
self.max_shadow = self.max_shadow - ab.sustain_shadow
end
else
if ab.sustain_shadow then
self.max_shadow = self.max_shadow + ab.sustain_shadow
end
end
else
if ab.shadow then
self:incShadow(-ab.shadow)
end
end
return true
end
--- Return the full description of a talent
-- You may overload it to add more data (like shadow usage, ...)
function _M:getTalentFullDescription(t)
local d = {}
if t.mode == "passive" then d[#d+1] = "#6fff83#Use mode: #00FF00#Passive"
elseif t.mode == "sustained" then d[#d+1] = "#6fff83#Use mode: #00FF00#Sustained"
else d[#d+1] = "#6fff83#Use mode: #00FF00#Activated"
end
if t.shadow or t.sustain_shadow then d[#d+1] = "#6fff83#Shadow Power cost: #7fffd4#"..(t.shadow or t.sustain_shadow) end
if self:getTalentRange(t) > 1 then d[#d+1] = "#6fff83#Range: #FFFFFF#"..self:getTalentRange(t)
else d[#d+1] = "#6fff83#Range: #FFFFFF#melee/personal"
end
if t.cooldown then d[#d+1] = "#6fff83#Cooldown: #FFFFFF#"..t.cooldown end
return table.concat(d, "\n").."\n#6fff83#Description: #FFFFFF#"..t.info(self, t)
end
--- Can the actor see the target actor
-- This does not check LOS or such, only the actual ability to see it.<br/>
-- Check for telepathy, invisibility, stealth, ...
function _M:canSee(actor, def, def_pct)
if not actor then return false, 0 end
-- Check for stealth. Checks against the target cunning and level
if actor:attr("stealth") and actor ~= self then
local def = self.level / 2 + self:getCun(25)
local hit, chance = self:checkHit(def, actor:attr("stealth") + (actor:attr("inc_stealth") or 0), 0, 100)
if not hit then
return false, chance
end
end
if def ~= nil then
return def, def_pct
else
return true, 100
end
end
--- Can the target be applied some effects
-- @param what a string describing what is being tried
function _M:canBe(what)
return true
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
require "engine.GameTurnBased"
require "engine.interface.GameTargeting"
require "engine.KeyBind"
local Savefile = require "engine.Savefile"
local DamageType = require "engine.DamageType"
local Zone = require "engine.Zone"
local Map = require "engine.Map"
local Level = require "engine.Level"
local Birther = require "engine.Birther"
local PlayerDisplay = require "mod.class.PlayerDisplay"
local Grid = require "mod.class.Grid"
local Actor = require "mod.class.Actor"
local Player = require "mod.class.Player"
local NPC = require "mod.class.NPC"
local LogFlasher = require "engine.LogFlasher"
local DebugConsole = require "engine.DebugConsole"
local FlyingText = require "engine.FlyingText"
local Tooltip = require "engine.Tooltip"
local MapMenu = require "mod.dialogs.MapMenu"
local QuitDialog = require "mod.dialogs.Quit"
module(..., package.seeall, class.inherit(engine.GameTurnBased, engine.interface.GameTargeting))
function _M:init()
engine.GameTurnBased.init(self, engine.KeyBind.new(), 1000, 100)
-- Pause at birth
self.paused = true
-- Same init as when loaded from a savefile
self:loaded()
end
function _M:run()
self.flash = LogFlasher.new(0, 0, self.w, 20, nil, nil, nil, {255,255,255}, {0,0,0})
self.player_display = PlayerDisplay.new()
self.tooltip = Tooltip.new(nil, nil, {255,255,255}, {30,30,30})
self.flyers = FlyingText.new()
self:setFlyingText(self.flyers)
self.log = function(style, ...) if type(style) == "number" then self.flash(style, ...) else self.flash(self.flash.NEUTRAL, style, ...) end end
self.logSeen = function(e, style, ...) if e and self.level.map.seens(e.x, e.y) then self.log(style, ...) end end
self.logPlayer = function(e, style, ...) if e == self.player then self.log(style, ...) end end
self.log(self.flash.GOOD, "Welcome to #GREY##{bold}#Gruesome!#{normal}#")
-- Setup inputs
self:setupCommands()
self:setupMouse()
-- Starting from here we create a new game
if not self.player then self:newGame() end
-- Setup the targetting system
engine.interface.GameTargeting.init(self)
-- Ok everything is good to go, activate the game in the engine!
self:setCurrent()
if self.level then self:setupDisplayMode() self:onTurn() end
end
function _M:newGame()
self.player = Player.new{name=self.player_name, game_ender=true}
Map:setViewerActor(self.player)
self:setupDisplayMode()
self.creating_player = true
local birth = Birther.new(nil, self.player, {"base"}, function()
self:changeLevel(20, "dungeon")
print("[PLAYER BIRTH] resolve...")
self.player:resolve()
self.player:resolve(nil, true)
self.player.energy.value = self.energy_to_act
self.paused = true
self.creating_player = false
self:onTurn()
print("[PLAYER BIRTH] resolved!")
end)
self:registerDialog(birth)
end
function _M:loaded()
engine.GameTurnBased.loaded(self)
Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", }
Map:setViewerActor(self.player)
Map:setViewPort(0, 20, self.w, math.floor(self.h * 0.80) - 20, 12, 16, "/data/font/FSEX300.ttf", 16, true)
self.key = engine.KeyBind.new()
end
function _M:setupDisplayMode()
Map:setViewPort(0, 20, self.w, math.floor(self.h * 0.80) - 20, 12, 16, "/data/font/FSEX300.ttf", 16, true)
Map:resetTiles()
Map.tiles.use_images = false
if self.level then
self.level.map:recreate()
engine.interface.GameTargeting.init(self)
self.level.map:moveViewSurround(self.player.x, self.player.y, 8, 8)
end
end
function _M:save()
return class.save(self, self:defaultSavedFields{}, true)
end
function _M:getSaveDescription()
return {
name = self.player.name,
description = ([[Exploring level %d of %s.]]):format(self.level.level, self.zone.name),
}
end
function _M:leaveLevel(level, lev, old_lev)
if level:hasEntity(self.player) then
level.exited = level.exited or {}
if lev > old_lev then
level.exited.down = {x=self.player.x, y=self.player.y}
else
level.exited.up = {x=self.player.x, y=self.player.y}
end
level.last_turn = game.turn
level:removeEntity(self.player)
end
end
function _M:changeLevel(lev, zone)
local old_lev = (self.level and not zone) and self.level.level or -1000
if zone then
if self.zone then
self.zone:leaveLevel(false, lev, old_lev)
self.zone:leave()
end
if type(zone) == "string" then
self.zone = Zone.new(zone)
else
self.zone = zone
end
end
self.zone:getLevel(self, lev, old_lev)
if lev > old_lev then
self.player:move(self.level.default_up.x, self.level.default_up.y, true)
else
self.player:move(self.level.default_down.x, self.level.default_down.y, true)
end
self.level:addEntity(self.player)
end
function _M:getPlayer()
return self.player
end
function _M:tick()
if self.level then
self:targetOnTick()
engine.GameTurnBased.tick(self)
-- Fun stuff: this can make the game realtime, although calling it in display() will make it work better
-- (since display is on a set FPS while tick() ticks as much as possible
-- engine.GameEnergyBased.tick(self)
end
-- When paused (waiting for player input) we return true: this means we wont be called again until an event wakes us
if self.paused and not savefile_pipe.saving then return true end
end
--- Called every game turns
-- Does nothing, you can override it
function _M:onTurn()
-- The following happens only every 10 game turns (once for every turn of 1 mod speed actors)
if self.turn % 10 ~= 0 then return end
-- Process overlay effects
self.level.map:processEffects()
end
function _M:display(nb_keyframe)
-- If switching resolution, blank everything but the dialog
if self.change_res_dialog then engine.GameTurnBased.display(self, nb_keyframe) return end
-- Now the map, if any
if self.level and self.level.map and self.level.map.finished then
if self.level.map.changed then
-- Clean FOV before computing it
self.level.map:cleanFOV()
self.player:playerFOV()
for uid, a in pairs(game.level.entities) do
if a ~= self.player and not a:attr("blind") then
-- Compute both the normal and the lite FOV, using cache
a:computeFOVBeam(a.lite, a.dir, a.angle, "block_sight", function(x, y, dx, dy, sqdist)
if self.level.map.seens(x, y) then
self.level.map:applyLite(x, y, 1)
if self.level.map(x, y, Map.ACTOR) == self.player then
self.player:takeHit(1, a)
end
end
end, true, false, true)
end
end
end
self.level.map:display(nil, nil, nb_keyframe)
-- Display the targetting system if active
self.target:display()
end
-- We display the player's interface
self.flash:toScreen(nb_keyframe)
self.player_display:toScreen()
if self.player then self.player.changed = false end
-- Tooltip is displayed over all else
self:targetDisplayTooltip(self.w, self.h)
engine.GameTurnBased.display(self, nb_keyframe)
end
--- Setup the keybinds
function _M:setupCommands()
-- Make targeting work
self.normal_key = self.key
self:targetSetupKey()
-- One key handled for normal function
self.key:addBinds
{
-- Movements
MOVE_LEFT = function() self.player:moveDir(4) end,
MOVE_RIGHT = function() self.player:moveDir(6) end,
MOVE_UP = function() self.player:moveDir(8) end,
MOVE_DOWN = function() self.player:moveDir(2) end,
MOVE_LEFT_UP = function() self.player:moveDir(7) end,
MOVE_LEFT_DOWN = function() self.player:moveDir(1) end,
MOVE_RIGHT_UP = function() self.player:moveDir(9) end,
MOVE_RIGHT_DOWN = function() self.player:moveDir(3) end,
MOVE_STAY = function() self.player:useEnergy() end,
RUN_LEFT = function() self.player:runInit(4) end,
RUN_RIGHT = function() self.player:runInit(6) end,
RUN_UP = function() self.player:runInit(8) end,
RUN_DOWN = function() self.player:runInit(2) end,
RUN_LEFT_UP = function() self.player:runInit(7) end,
RUN_LEFT_DOWN = function() self.player:runInit(1) end,
RUN_RIGHT_UP = function() self.player:runInit(9) end,
RUN_RIGHT_DOWN = function() self.player:runInit(3) end,
-- Hotkeys
HOTKEY_1 = function() self.player:activateHotkey(1) end,
HOTKEY_2 = function() self.player:activateHotkey(2) end,
HOTKEY_3 = function() self.player:activateHotkey(3) end,
-- Actions
CHANGE_LEVEL = function()
local e = self.level.map(self.player.x, self.player.y, Map.TERRAIN)
if self.player:enoughEnergy() and e.change_level then
self:changeLevel(e.change_zone and e.change_level or self.level.level + e.change_level, e.change_zone)
else
self.log("There is no way out of this level here.")
end
end,
USE_TALENTS = function()
self.player:useTalents()
end,
SAVE_GAME = function()
self:saveGame()
end,
-- Exit the game
QUIT_GAME = function()
self:onQuit()
end,
EXIT = function()
local menu menu = require("engine.dialogs.GameMenu").new{
"resume",
"keybinds",
"video",
"save",
"quit"
}
self:registerDialog(menu)
end,
-- Lua console, you probably want to disable it for releases
LUA_CONSOLE = function()
self:registerDialog(DebugConsole.new())
end,
LOOK_AROUND = function()
self.flash:empty(true)
self.flash(self.flash.GOOD, "Looking around... (direction keys to select interesting things, shift+direction keys to move freely)")
local co = coroutine.create(function() self.player:getTarget{type="hit", no_restrict=true, range=2000} end)
local ok, err = coroutine.resume(co)
if not ok and err then print(debug.traceback(co)) error(err) end
end,
}
self.key:setCurrent()
end
function _M:setupMouse(reset)
if reset then self.mouse:reset() end
self.mouse:registerZone(Map.display_x, Map.display_y, Map.viewport.width, Map.viewport.height, function(button, mx, my, xrel, yrel, bx, by, event)
-- Handle targeting
if self:targetMouse(button, mx, my, xrel, yrel, event) then return end
-- Handle Use menu
if button == "right" and not xrel and not yrel and event == "button" then self:mouseRightClick(mx, my) return end
-- Handle the mouse movement/scrolling
self.player:mouseHandleDefault(self.key, self.key == self.normal_key, button, mx, my, xrel, yrel, event)
end)
self.mouse:setCurrent()
end
--- Right mouse click on the map
function _M:mouseRightClick(mx, my)
local tmx, tmy = self.level.map:getMouseTile(mx, my)
self:registerDialog(MapMenu.new(mx, my, tmx, tmy))
end
--- Ask if we really want to close, if so, save the game first
function _M:onQuit()
self.player:restStop()
if not self.quit_dialog then
self.quit_dialog = QuitDialog.new()
self:registerDialog(self.quit_dialog)
end
end
--- Requests the game to save
function _M:saveGame()
-- savefile_pipe is created as a global by the engine
savefile_pipe:push(self.save_name, "game", self)
self.log("Saving game...")
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
require "engine.Grid"
local DamageType = require "engine.DamageType"
module(..., package.seeall, class.inherit(engine.Grid))
function _M:init(t, no_default)
engine.Grid.init(self, t, no_default)
end
function _M:block_move(x, y, e, act, couldpass)
-- Open doors
if self.door_opened and act then
game.level.map(x, y, engine.Map.TERRAIN, game.zone.grid_list.DOOR_OPEN)
return true
elseif self.door_opened and not couldpass then
return true
end
-- Pass walls
if e and self.can_pass and e.can_pass then
for what, check in pairs(e.can_pass) do
if self.can_pass[what] and self.can_pass[what] <= check then return false end
end
end
return self.does_block_move
end
function _M:on_move(x, y, who, forced)
if forced then return end
if who.move_project and next(who.move_project) then
for typ, dam in pairs(who.move_project) do
DamageType:get(typ).projector(who, x, y, typ, dam)
end
end
end
function _M:tooltip()
if self.show_tooltip then
local name = ((self.show_tooltip == true) and self.name or self.show_tooltip)
if self.desc then
return self:getDisplayString()..name.."\n"..self.desc
else
return self:getDisplayString()..name
end
else
return self:getDisplayString()..self.name
end
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
local ActorAI = require "engine.interface.ActorAI"
local Faction = require "engine.Faction"
require "mod.class.Actor"
module(..., package.seeall, class.inherit(mod.class.Actor, engine.interface.ActorAI))
function _M:init(t, no_default)
mod.class.Actor.init(self, t, no_default)
ActorAI.init(self, t)
self.dir = rng.table{1,2,3,4,6,7,8,9}
end
function _M:act()
-- Do basic actor stuff
if not mod.class.Actor.act(self) then return end
-- Compute FOV, if needed
-- self:computeFOV(self.sight or 20)
-- Let the AI think .... beware of Shub !
-- If AI did nothing, use energy anyway
self:doAI()
if not self.energy.used then self:useEnergy() end
end
--- Called by ActorLife interface
-- We use it to pass aggression values to the AIs
function _M:onTakeHit(value, src)
if not self.ai_target.actor and src.targetable then
self.ai_target.actor = src
end
return mod.class.Actor.onTakeHit(self, value, src)
end
function _M:tooltip()
local str = mod.class.Actor.tooltip(self)
return str..([[
Target: %s
UID: %d]]):format(
self.ai_target.actor and self.ai_target.actor.name or "none",
self.uid)
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
require "mod.class.Actor"
require "engine.interface.PlayerRun"
require "engine.interface.PlayerMouse"
require "engine.interface.PlayerHotkeys"
local Map = require "engine.Map"
local Dialog = require "engine.Dialog"
local ActorTalents = require "engine.interface.ActorTalents"
local DeathDialog = require "mod.dialogs.DeathDialog"
local Astar = require"engine.Astar"
local DirectPath = require"engine.DirectPath"
--- Defines the player
-- It is a normal actor, with some redefined methods to handle user interaction.<br/>
-- It is also able to run and use hotkeys
module(..., package.seeall, class.inherit(
mod.class.Actor,
engine.interface.PlayerRun,
engine.interface.PlayerMouse,
engine.interface.PlayerHotkeys
))
function _M:init(t, no_default)
t.player = true
t.type = t.type or "humanoid"
t.subtype = t.subtype or "player"
t.faction = t.faction or "players"
t.sight = 8
t.kills = 0
t.lurkkills = 0
mod.class.Actor.init(self, t, no_default)
engine.interface.PlayerHotkeys.init(self, t)
self.descriptor = {}
end
function _M:move(x, y, force)
if not forced then game.flash:empty() end
if not force and game.level.map.seens(x, y) == 1 then
game.logPlayer(self, "Hsss! You refuse to step near the hateful light...")
return false
end
if not force and game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move") then
game.logPlayer(self, "You snarl at the wall.%s", self.kills > 19 and " The wall looks scared!" or "")
return false
end
local moved = mod.class.Actor.move(self, x, y, force)
if moved then
game.level.map:moveViewSurround(self.x, self.y, 8, 8)
end
return moved
end
function _M:act()
if not mod.class.Actor.act(self) then return end
-- Clean log flasher
game.flash:empty()
-- Running ? Otherwise pause
if not self:runStep() and self.player then
game.paused = true
end
end
function _M:playerFOV()
-- Compute both the normal and the lite FOV, using cache
self:computeFOV(self.sight or 8, "block_sight", function(x, y, dx, dy, sqdist)
game.level.map:applyLite(x, y, 0.5)
end, true, false, true)
end
--- Called before taking a hit, overload mod.class.Actor:onTakeHit() to stop running
function _M:onTakeHit(value, src)
self:runStop("taken damage")
local ret = mod.class.Actor.onTakeHit(self, value, src)
if self.life < self.max_life * 0.3 then
local sx, sy = game.level.map:getTileToScreen(self.x, self.y)
game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, 2, "LOW HEALTH!", {255,0,0}, true)
end
return ret
end
function _M:die(src)
if self.game_ender then
engine.interface.ActorLife.die(self, src)
game.paused = true
self.energy.value = game.energy_to_act
game:registerDialog(DeathDialog.new(self))
else
mod.class.Actor.die(self, src)
end
end
function _M:setName(name)
self.name = name
game.save_name = name
end
--- Notify the player of available cooldowns
function _M:onTalentCooledDown(tid)
local t = self:getTalentFromId(tid)
local x, y = game.level.map:getTileToScreen(self.x, self.y)
game.flyers:add(x, y, 30, -0.3, -3.5, ("%s available"):format(t.name:capitalize()), {0,255,00})
game.log("#00ff00#Talent %s is ready to use.", t.name)
end
function _M:levelup()
mod.class.Actor.levelup(self)
local x, y = game.level.map:getTileToScreen(self.x, self.y)
game.flyers:add(x, y, 80, 0.5, -2, "LEVEL UP!", {0,255,255})
game.log("#00ffff#Welcome to level %d.", self.level)
end
--- Tries to get a target from the user
function _M:getTarget(typ)
return game:targetGetForPlayer(typ)
end
--- Sets the current target
function _M:setTarget(target)
return game:targetSetForPlayer(target)
end
local function spotHostiles(self)
local seen = false
-- Check for visible monsters, only see LOS actors, so telepathy wont prevent resting
core.fov.calc_circle(self.x, self.y, game.level.map.w, game.level.map.h, 20, function(_, x, y) return game.level.map:opaque(x, y) end, function(_, x, y)
local actor = game.level.map(x, y, game.level.map.ACTOR)
if actor and self:reactionToward(actor) < 0 and self:canSee(actor) and game.level.map.seens(x, y) then seen = true end
end, nil)
return seen
end
--- Can we continue running?
-- We can run if no hostiles are in sight, and if we no interesting terrains are next to us
function _M:runCheck()
if spotHostiles(self) then return false, "hostile spotted" end
-- Notice any noticeable terrain
local noticed = false
self:runScan(function(x, y)
-- Only notice interesting terrains
local grid = game.level.map(x, y, Map.TERRAIN)
if grid and grid.notice then noticed = "interesting terrain" end
end)
if noticed then return false, noticed end
self:playerFOV()
return engine.interface.PlayerRun.runCheck(self)
end
--- Move with the mouse
-- We just feed our spotHostile to the interface mouseMove
function _M:mouseMove(tmx, tmy)
return engine.interface.PlayerMouse.mouseMove(self, tmx, tmy, spotHostiles)
end
-- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
local Mouse = require "engine.Mouse"
module(..., package.seeall, class.make)
function _M:init()
self.font = core.display.newFont("/data/font/FSEX300.ttf", 16)
self.font_h = self.font:lineSkip()
self.mouse = Mouse.new()
local gw, gh = core.display.size()
self:resize(0, gh - self.font_h, gw, self.font_h)
end
--- Resize the display area
function _M:resize(x, y, w, h)
self.display_x, self.display_y = x, y
self.mouse.delegate_offset_x = x
self.mouse.delegate_offset_y = y
self.w, self.h = w, h
self.font_w = self.font:size(" ")
self.bars_x = self.font_w * 9
self.bars_w = self.w - self.bars_x - 5
self.surface = core.display.newSurface(w, h)
self.texture, self.texture_w, self.texture_h = self.surface:glTexture()
self.items = {}
end
function _M:mouseTooltip(text, w, h, x, y, click)
-- self.mouse:registerZone(x, y, w, h, function(button, mx, my, xrel, yrel, bx, by, event)
-- game.tooltip_x, game.tooltip_y = 1, 1; game.tooltip:displayAtMap(nil, nil, game.w, game.h, text)
-- if click and event == "button" and button == "left" then
-- click()
-- end
-- end)
return w, h
end
function _M:makeTexture(text, x, y, r, g, b, max_w)
local s = self.surface
s:drawColorStringBlended(self.font, text, x, y, r, g, b, true, max_w)
return self.font:size(text)
end
-- Displays the stats
function _M:display()
local player = game.player
if not player or not player.changed or not game.level then return end
self.mouse:reset()
self.items = {}
local s = self.surface
s:erase(0, 0, 0, 0)
local w = 0
w = w + self:makeTexture(("%-20s"):format(player.name), w, 0, 255, 255, 255)
w = w + self:mouseTooltip("#GOLD##{bold}#Lurk Power\n#WHITE##{normal}#Your lurking power. You can gain lurk power by standing still in the shadows.",
self:makeTexture(("LP: #GREY#%d/%d "):format(player:getLurk(), player.max_lurk), w, 0, 255, 255, 255))
w = w + self:mouseTooltip("#GOLD##{bold}#Shadow Power\n#WHITE##{normal}#Your shadow power. You can gain shadow power by eating adventurers.",
self:makeTexture(("SP: #GREY#%d/%d "):format(player:getShadow(), player.max_shadow), w, 0, 255, 255, 255))
w = w + self:mouseTooltip("#GOLD##{bold}#Meals\n#WHITE##{normal}#The total number of adventurers you ate.",
self:makeTexture(("Meals: %-4d "):format(player.kills + player.lurkkills), w, 0, 255, 255, 255))
w = w + self:mouseTooltip("#GOLD##{bold}#Turns\n#WHITE##{normal}#The total number of turns elapsed since starting.",
self:makeTexture(("Turns: %-6d "):format(game.turn / 10), w, 0, 255, 255, 255))
w = w + self:mouseTooltip("#GOLD##{bold}#Dungeon level\n#WHITE##{normal}#The current dungeon level. Reach level 1 to win!",
self:makeTexture(("Level: %d"):format(game.level.level), w, 0, 255, 255, 255))
s:updateTexture(self.texture)
end
function _M:toScreen()
self:display()
self.texture:toScreenFull(self.display_x, self.display_y, self.w, self.h, self.texture_w, self.texture_h)
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
local DamageType = require "engine.DamageType"
local Map = require "engine.Map"
local Target = require "engine.Target"
local Talents = require "engine.interface.ActorTalents"
--- Interface to add ToME combat system
module(..., package.seeall, class.make)
--- Checks what to do with the target
-- Talk ? attack ? displace ?
function _M:bumpInto(target)
local reaction = self:reactionToward(target)
if reaction < 0 then
return self:attackTarget(target)
elseif reaction >= 0 then
if self.move_others then
-- Displace
game.level.map:remove(self.x, self.y, Map.ACTOR)
game.level.map:remove(target.x, target.y, Map.ACTOR)
game.level.map(self.x, self.y, Map.ACTOR, target)
game.level.map(target.x, target.y, Map.ACTOR, self)
self.x, self.y, target.x, target.y = target.x, target.y, self.x, self.y
end
end
end
--- Makes the death happen!
function _M:attackTarget(target, mult)
if self.player then
game.logPlayer(self, "You pounce on the blind, stumbling adventurer and devour %s instantly. Yum!", target.sex)
target:die(self)
elseif target.player then
game.logPlayer(target, "The adventurer stumbles into your slavering fangs. %s", self.sex == "him" and "Gruevy..." or "Saucy...")
self:die(target)
end
-- We use up our own energy
self:useEnergy(game.energy_to_act)
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newBirthDescriptor{
type = "base",
name = "base",
desc = {
},
copy = {
type = "grue", subtype = "grue",
display = "G", color = {r=0,g=0,b=0},
max_life = 2,
max_power = 2,
},
talents = {
[ActorTalents.T_SHADOW_BALL] = 1,
[ActorTalents.T_SHADOW_WALK] = 1,
[ActorTalents.T_DARK_EYES] = 1,
},
}
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
-- The basic stuff used to damage a grid
setDefaultProjector(function(src, x, y, type, dam)
return 0
end)
newDamageType{
name = "darkness", type = "DARKNESS", text_color = "#GREY#",
projector = function(src, x, y, typ, dam)
local target = game.level.map(x, y, Map.ACTOR)
if target and not target.player then
target:attr("blind", 1)
game.logPlayer(src, "The adventurer screams in fright as %s %s is extinguished.", target.sex, target.angle < 35 and "lantern" or "torch")
end
end,
}
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newEntity{
define_as = "UP",
name = "previous level",
display = '<', color_r=255, color_g=255, color_b=0, back_color=colors.DARK_GREY,
notice = true,
always_remember = true,
change_level = -1,
}
newEntity{
define_as = "DOWN",
name = "next level",
display = '>', color_r=255, color_g=255, color_b=0, back_color=colors.DARK_GREY,
notice = true,
always_remember = true,
change_level = 1,
}
newEntity{
define_as = "FLOOR",
name = "floor", image = "terrain/marble_floor.png",
display = ' ', color_r=255, color_g=255, color_b=255, back_color=colors.DARK_GREY,
always_remember = true,
}
newEntity{
define_as = "WALL",
name = "wall", image = "terrain/granite_wall1.png",
display = '#', color_r=255, color_g=255, color_b=255, back_color=colors.DARK_GREY,
always_remember = true,
does_block_move = true,
block_sight = true,
}
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
local Talents = require("engine.interface.ActorTalents")
newEntity{
define_as = "BASE_NPC_ADVENTURER",
type = "humanoid", subtype = "adventurer",
display = "@", color=colors.WHITE,
desc = [[Tasty adventurer! Yummy!]],
name = "adventurer",
rarity = 1,
ai = "adventurer",
sex = "him",
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.DARK_BLUE,
lite = 2, angle = 25,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.DARK_GREEN,
lite = 2, angle = 40,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.TEAL,
lite = 2, angle = 60,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.RED,
lite = 3, angle = 25,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.SALMON,
lite = 3, angle = 75,
sex = "her",
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.DARK_UMBER,
lite = 3, angle = 50,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.LIGHT_GREY,
lite = 4, angle = 25,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.DARk_GREY,
lite = 4, angle = 40,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.LIGHT_BLUE,
lite = 4, angle = 55,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {1, nil},
color=colors.LIGHT_GREEN,
lite = 4, angle = 70,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {13, nil},
color=colors.AQUAMARINE,
lite = 5, angle = 25,
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {13, nil},
color=colors.LIGHT_RED,
lite = 5, angle = 35,
sex = "her",
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {13, nil},
color=colors.YELLOW,
lite = 5, angle = 50,
sex = "her",
}
newEntity{ base = "BASE_NPC_ADVENTURER",
level_range = {13, nil},
color=colors.WHITE,
lite = 5, angle = 65,
}
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
return {
base = 1000,
angle = { 0, 360 }, anglev = { 2000, 4000 }, anglea = { 200, 600 },
life = { 5, 10 },
size = { 3, 6 }, sizev = {0, 0}, sizea = {0, 0},
r = {0, 0}, rv = {0, 0}, ra = {0, 0},
g = {80, 200}, gv = {0, 10}, ga = {0, 0},
b = {0, 0}, bv = {0, 0}, ba = {0, 0},
a = {255, 255}, av = {0, 0}, aa = {0, 0},
}, function(self)
self.nb = (self.nb or 0) + 1
if self.nb < 4 then
self.ps:emit(100)
end
end
-- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
local nb = 12
local dir
local radius = radius or 6
return { generator = function()
local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2
local ad = rng.float(0, 360)
local a = math.rad(ad)
local r = 0
local x = r * math.cos(a)
local y = r * math.sin(a)
local static = rng.percent(40)
local vel = sradius * ((24 - nb * 1.4) / 24) / 12
return {
trail = 1,
life = 12,
size = 12 - (12 - nb) * 0.7, sizev = 0, sizea = 0,
x = x, xv = 0, xa = 0,
y = y, yv = 0, ya = 0,
dir = a, dirv = 0, dira = 0,
vel = rng.float(vel * 0.6, vel * 1.2), velv = 0, vela = 0,
r = rng.range(0, 40)/255, rv = 0, ra = 0,
g = rng.range(0, 40)/255, gv = 0.005, ga = 0.0005,
b = rng.range(0, 40)/255, bv = 0, ba = 0,
a = rng.range(255, 255)/255, av = static and -0.034 or 0, aa = 0.005,
}
end, },
function(self)
if nb > 0 then
local i = math.min(nb, 6)
i = (i * i) * radius
self.ps:emit(i)
nb = nb - 1
end
end,
30*radius*7*12,
"particle_cloud"
-- Gruesome - T-Engine 4 Module
-- Copyright (C) 2010 Mikolai Fajer
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
return {
base = 1000,
angle = { 0, 360 }, anglev = { 2000, 4000 }, anglea = { 200, 600 },
life = { 5, 10 },
size = { 2, 5 }, sizev = {0, 0}, sizea = {0, 0},
r = {80, 200}, rv = {0, 10}, ra = {0, 0},
g = {0, 0}, gv = {0, 0}, ga = {0, 0},
b = {0, 0}, bv = {0, 0}, ba = {0, 0},
a = {255, 255}, av = {0, 0}, aa = {0, 0},
}, function(self)
self.nb = (self.nb or 0) + 1
if self.nb < 4 then
self.ps:emit(100)
end
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
return {
[[#!!!!!!!!#]],
[[!........!]],
[[!...##...!]],
[[!........!]],
[[#!!!!!!!!#]],
}
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
return function(gen, id)
local w = rng.range(5, 12)
local h = rng.range(5, 12)
return { name="simple"..w.."x"..h, w=w, h=h, generator = function(self, x, y, is_lit)
for i = 1, self.w do
for j = 1, self.h do
if i == 1 or i == self.w or j == 1 or j == self.h then
gen.map.room_map[i-1+x][j-1+y].can_open = true
gen.map(i-1+x, j-1+y, Map.TERRAIN, gen.grid_list[gen:resolve('#')])
else
gen.map.room_map[i-1+x][j-1+y].room = id
gen.map(i-1+x, j-1+y, Map.TERRAIN, gen.grid_list[gen:resolve('.')])
end
if is_lit then gen.map.lites(i-1+x, j-1+y, true) end
end
end
end}
end
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newTalentType{ type="grue/grue", name = "grue", description = "Gruesome!" }
newTalent{
name = "Shadow Ball",
type = {"grue/grue", 1},
points = 1,
shadow = 2,
range = function(self, t)
local k = self.kills + self.lurkkills
if k <= 9 then return 1
elseif k <= 24 then return 2
elseif k <= 49 then return 3
elseif k <= 99 then return 4
else return 5
end
end,
message = "You unleash a mighty ball of shadow.",
action = function(self, t)
local tg = {type="ball", radius=self:getTalentRange(t)}
self:project(tg, self.x, self.y, DamageType.DARKNESS, 1)
game.level.map:particleEmitter(self.x, self.y, tg.radius, "ball_shadow", {radius=tg.radius})
return true
end,
info = function(self, t)
return "Unleash a ball of darkness to extinguish adventurer's lites.\nThe more your eat the bigger the radius."
end,
}
newTalent{
name = "Dark Eyes",
type = {"grue/grue", 1},
points = 1,
shadow = 1,
range = function(self, t) return 2 end,
action = function(self, t)
local tg = {type="ball", range=self:getTalentRange(t)}
self:project(tg, x, y, DamageType.DARKNESS, 1)
return true
end,
info = function(self, t)
return "Unleash a ball of darkness to extinguish adventurer's lites."
end,
}
newTalent{
name = "Shadow Walk",
type = {"grue/grue", 1},
points = 1,
range = function(self, t) return 2 end,
action = function(self, t)
local tg = {type="ball", range=self:getTalentRange(t)}
self:project(tg, x, y, DamageType.DARKNESS, 1)
return true
end,
info = function(self, t)
return "Unleash a ball of darkness to extinguish adventurer's lites."
end,
}
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009 - 2014 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
local Stats = require "engine.interface.ActorStats"
newEffect{
name = "ACIDBURN",
desc = "Burning from acid",
type = "physical",
status = "detrimental",
parameters = { power=1 },
on_gain = function(self, err) return "#Target# is covered in acid!", "+Acid" end,
on_lose = function(self, err) return "#Target# is free from the acid.", "-Acid" end,
on_timeout = function(self, eff)
DamageType:get(DamageType.ACID).projector(eff.src or self, self.x, self.y, DamageType.ACID, eff.power)
end,
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment