Skip to content
Snippets Groups Projects
Commit e1f0991e authored by dg's avatar dg
Browse files

Birther

Better AI


git-svn-id: http://svn.net-core.org/repos/t-engine4@90 51575b47-30f0-44d4-a5cc-537603b46e54
parent 9f22a1f5
No related branches found
No related tags found
No related merge requests found
Showing
with 811 additions and 247 deletions
require "engine.class"
require "engine.Dialog"
module(..., package.seeall, class.inherit(engine.Dialog))
_M.birth_descriptor_def = {}
--- Defines birth descriptors
-- Static!
function _M:loadDefinition(file)
local f, err = loadfile(file)
if not f and err then error(err) os.exit() end
setfenv(f, setmetatable({
ActorTalents = require("engine.interface.ActorTalents"),
newBirthDescriptor = function(t) self:newBirthDescriptor(t) end,
load = function(f) self:loadDefinition(f) end
}, {__index=_G}))
f()
end
--- Defines one birth descriptor
-- Static!
function _M:newBirthDescriptor(t)
assert(t.name, "no birth name")
assert(t.type, "no birth type")
t.short_name = t.short_name or t.name
t.short_name = t.short_name:upper():gsub("[ ]", "_")
assert(t.desc, "no birth description")
t.descriptor_choices = t.descriptor_choices or {}
table.insert(self.birth_descriptor_def, t)
t.id = #self.birth_descriptor_def
self.birth_descriptor_def[t.type] = self.birth_descriptor_def[t.type] or {}
self.birth_descriptor_def[t.type][t.name] = t
table.insert(self.birth_descriptor_def[t.type], t)
end
--- Instanciates a birther for the given actor
function _M:init(actor, order, at_end)
self.actor = actor
self.order = order
self.at_end = at_end
engine.Dialog.init(self, "Character Creation: "..actor.name, 600, 400)
self.descriptors = {}
self.cur_order = 1
self:next()
self:keyCommands{
_UP = function() self.sel = util.boundWrap(self.sel - 1, 1, #self.list) end,
_DOWN = function() self.sel = util.boundWrap(self.sel + 1, 1, #self.list) end,
_RETURN = function() self:next() end,
_ESCAPE = function() game:unregisterDialog(self) end,
}
self:mouseZones{
{ x=2, y=25, w=350, h=self.h, fct=function(button, x, y, xrel, yrel, tx, ty)
if ty <= self.font_h*#self.list then
self.sel = 1 + math.floor(ty / self.font_h)
if button == "left" then self:next()
elseif button == "right" then self:learn(false)
end
end
end },
}
end
function _M:selectType(type)
self.list = {}
-- Make up the list
for i, d in ipairs(self.birth_descriptor_def[type]) do
local allowed = true
for j, od in ipairs(self.descriptors) do
if od.descriptor_choices[type] then
local what = od.descriptor_choices[type][d.name] or od.descriptor_choices[type].__ALL__
if what and what == "allow" then
allowed = true
elseif what and what == "never" then
allowed = false
end
end
end
-- Check it is allowed
if allowed then
table.insert(self.list, d)
end
end
self.sel = 1
self.current_type = type
end
function _M:next()
if self.list then
table.insert(self.descriptors, self.list[self.sel])
self.cur_order = self.cur_order + 1
if not self.order[self.cur_order] then
game:unregisterDialog(self)
self:apply()
self.at_end()
return
end
end
self:selectType(self.order[self.cur_order])
if #self.list == 1 then
self:next()
end
end
--- Apply all birth options to the actor
function _M:apply()
self.actor.descriptor = {}
for i, d in ipairs(self.descriptors) do
print("[BIRTH] Applying descriptor "..d.name)
self.actor.descriptor[d.type] = d.name
-- Change stats
if d.stats then
for stat, inc in pairs(d.stats) do
self.actor:incStat(stat, inc)
end
end
if d.talents_types then
for t, v in pairs(d.talents_types) do
self.actor:learnTalentType(t, v)
print(t)
end
end
if d.talents then
for i, tid in ipairs(d.talents) do
self.actor:learnTalent(tid, true)
print(tid)
end
end
if d.experience then self.actor.exp_mod = self.actor.exp_mod * d.experience end
end
end
function _M:drawDialog(s)
if not self.list or not self.list[self.sel] then return end
-- Description part
self:drawHBorder(s, self.iw / 2, 2, self.ih - 4)
local birthhelp = ([[Keyboard: #00FF00#up key/down key#FFFFFF# to select a stat; #00FF00#right key#FFFFFF# to increase stat; #00FF00#left key#FFFFFF# to decrease a stat.
Mouse: #00FF00#Left click#FFFFFF# to increase a stat; #00FF00#right click#FFFFFF# to decrease a stat.
]]):splitLines(self.iw / 2 - 10, self.font)
for i = 1, #birthhelp do
s:drawColorString(self.font, birthhelp[i], self.iw / 2 + 5, 2 + (i-1) * self.font:lineSkip())
end
local lines = table.concat(self.list[self.sel].desc,"\n"):splitLines(self.iw / 2 - 10, self.font)
for i = 1, #lines do
s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + (i + #birthhelp + 1) * self.font:lineSkip())
end
-- Stats
s:drawColorString(self.font, "Selecting: "..self.current_type:capitalize(), 2, 2)
self:drawWBorder(s, 2, 20, 200)
self:drawSelectionList(s, 2, 25, self.font_h, self.list, self.sel, "name")
end
......@@ -3,14 +3,9 @@
newAI("move_simple", function(self)
if self.ai_target.actor then
local act = self.ai_target.actor
return self:moveDirection(act.x, act.y)
return self:moveDirection(self.ai_target.actor.x, self.ai_target.actor.y)
elseif self.ai_target.x and self.ai_target.y then
local l = line.new(self.x, self.y, self.ai_target.x, self.ai_target.y)
local lx, ly = l()
if lx and ly then
self:move(lx, ly)
end
self:move(self.ai_target.x, self.ai_target.y)
end
end)
......
......@@ -23,6 +23,7 @@ function _M:init(t)
self.level = t.level or 1
end
self.exp = t.exp or 0
self.exp_mod = t.exp_mod or 1
self.exp_worth = t.exp_worth or 1
end
......@@ -39,9 +40,9 @@ end
-- @return the exp needed, or nil if this level is not achievable
function _M:getExpChart(level)
if type(self.exp_chart) == "table" then
return self.exp_chart[level]
return self.exp_chart[level] * self.exp_mod
else
return self.exp_chart(level)
return self.exp_chart(level) * self.exp_mod
end
end
......
......@@ -44,6 +44,10 @@ end
-- @param stat the stat id to change
-- @param val the increment to add/substract
function _M:incStat(stat, val)
if type(stat) == "string" then
stat = _M.stats_def[stat].id
end
local old = self.stats[stat]
self.stats[stat] = math.max(math.min(self.stats[stat] + val, _M.stats_def[stat].max), _M.stats_def[stat].min)
if self.stats[stat] - old ~= 0 then
......
......@@ -14,6 +14,7 @@ function _M:loadDefinition(file)
DamageType = require("engine.DamageType"),
newTalent = function(t) self:newTalent(t) end,
newTalentType = function(t) self:newTalentType(t) end,
load = function(f) self:loadDefinition(f) end
}, {__index=_G}))
f()
end
......@@ -128,11 +129,13 @@ end
--- Actor learns a talent
-- @param t_id the id of the talent to learn
-- @return true if the talent was learnt, nil and an error message otherwise
function _M:learnTalent(t_id)
function _M:learnTalent(t_id, force)
local t = _M.talents_def[t_id]
local ok, err = self:canLearnTalent(t)
if not ok and err then return nil, err end
if not force then
local ok, err = self:canLearnTalent(t)
if not ok and err then return nil, err end
end
self.talents[t_id] = true
self.changed = true
......@@ -225,8 +228,9 @@ end
--- Actor learns a talent type
-- @param t_id the id of the talent to learn
-- @return true if the talent was learnt, nil and an error message otherwise
function _M:learnTalentType(tt)
self.talents_types[tt] = true
function _M:learnTalentType(tt, v)
if v == nil then v = true end
self.talents_types[tt] = v
self.changed = true
return true
end
......@@ -235,7 +239,7 @@ end
-- @param t_id the id of the talent to learn
-- @return true if the talent was unlearnt, nil and an error message otherwise
function _M:unlearnTalentType(tt)
self.talents_types[tt] = nil
self.talents_types[tt] = false
self.changed = true
return true
end
......
......@@ -32,9 +32,9 @@ function _M:init(t)
engine.interface.ActorTalents.init(self, t)
engine.interface.ActorResource.init(self, t)
self.unused_stats = 0
self.unused_talents = 0
self.unused_talents_types = 0
self.unused_stats = self.unused_stats or 0
self.unused_talents = self.unused_talents or 0
self.unused_talents_types = self.unused_talents_types or 0
end
function _M:act()
......@@ -76,9 +76,16 @@ function _M:levelup()
end
-- Gain life and resources
self.max_life = self.max_life + 7
self:incMaxMana(7)
self:incMaxStamina(7)
self.max_life = self.max_life + 10
+ (self:knowTalent(self.T_IMPROVED_HEALTH_I) and 1 or 0)
+ (self:knowTalent(self.T_IMPROVED_HEALTH_II) and 1 or 0)
+ (self:knowTalent(self.T_IMPROVED_HEALTH_III) and 1 or 0)
- (self:knowTalent(self.T_DECREASED_HEALTH_I) and 1 or 0)
- (self:knowTalent(self.T_DECREASED_HEALTH_II) and 1 or 0)
- (self:knowTalent(self.T_DECREASED_HEALTH_III) and 1 or 0)
self:incMaxMana(10)
self:incMaxStamina(10)
-- Healp up on new level
self.life = self.max_life
self.mana = self.max_mana
......
......@@ -7,6 +7,7 @@ local Zone = require "engine.Zone"
local Map = require "engine.Map"
local Target = require "engine.Target"
local Level = require "engine.Level"
local Birther = require "engine.Birther"
local Grid = require "engine.Grid"
local Actor = require "mod.class.Actor"
......@@ -72,10 +73,18 @@ end
function _M:newGame()
self.zone = Zone.new("ancient_ruins")
self.player = Player.new{
name=self.player_name, max_life=10000, display='@', color_r=230, color_g=230, color_b=230,
name=self.player_name, max_life=25, max_mana=25, max_stamina=25, display='@', color_r=230, color_g=230, color_b=230,
unused_stats = 6, unused_talents = 3,
move_others=true,
}
self:changeLevel(1)
local birth = Birther.new(self.player, {"base", "race", "subrace", "sex", "class", "subclass" }, function()
self:changeLevel(1)
local ds = LevelupStatsDialog.new(self.player)
self:registerDialog(ds)
end)
self:registerDialog(birth)
end
function _M:loaded()
......@@ -109,12 +118,14 @@ function _M:getPlayer()
end
function _M:tick()
if self.target.target.entity and not self.level:hasEntity(self.target.target.entity) then self.target.target.entity = false end
if self.level then
if self.target.target.entity and not self.level:hasEntity(self.target.target.entity) then self.target.target.entity = false end
engine.GameTurnBased.tick(self)
-- Fun stuff: this can make the game realtime, although callit 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)
engine.GameTurnBased.tick(self)
-- Fun stuff: this can make the game realtime, although callit 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
end
--- Called every game turns
......@@ -165,27 +176,6 @@ function _M:display()
self.target.target.x, self.target.target.y = tmx, tmy
end
self.old_tmx, self.old_tmy = tmx, tmy
local act = self.level.map(tmx, tmy, engine.Map.ACTOR)
if act then
local s = core.display.newSurface(16,16)
s:alpha(125)
s:erase(0,255,255)
core.fov.calc_circle(act.x, act.y, act.sight, function(self, lx, ly)
if self.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_sight") then return true end
s:toScreen(self.level.map.display_x + (lx - game.level.map.mx) * self.level.map.tile_w, self.level.map.display_y + (ly - game.level.map.my) * self.level.map.tile_h)
local dst = self.level.map(lx, ly, engine.Map.ACTOR)
if dst then
-- table.insert(self.e_distances[e.uid], {uid=dst.uid, dist=core.fov.distance(e.x, e.y, dst.x, dst.y)})
-- print("found LOS", act.uid, dst.uid)
end
end, function()end, self)
end
end
engine.GameTurnBased.display(self)
......@@ -288,6 +278,9 @@ function _M:setupCommands()
_z = function()
self.player:useTalent(ActorTalents.T_BLINK)
end,
_m = function()
self.player:listTalents()
end,
[{"_g","shift"}] = function()
local none = true
......
......@@ -9,17 +9,10 @@ function _M:init(t)
self.player = true
self.faction = "players"
self.combat = { dam=10, atk=40, apr=2, def=6, armor=4 }
self.talents_types = {
["base/race"]=true,
["base/class"]=true,
["spell/arcane"]=true,
["spell/fire"]=true,
["physical/1hweapon"]=true
}
self.talents = {[ActorTalents.T_MANA_POOL]=true, [ActorTalents.T_STAMINA_POOL]=true}
self.mana_regen = 1
self.stamina_regen = 1
self.regen_life = 1
self.mana_regen = self.mana_regen or 1
self.stamina_regen = self.stamina_regen or 1
self.regen_life = self.regen_life or 0.5
self.descriptor = {}
end
function _M:move(x, y, force)
......
......@@ -20,7 +20,7 @@ function _M:display()
local h = 0
self.surface:drawString(self.font, game.player.name, 0, h, 0, 200, 255) h = h + self.font_h
self.surface:drawString(self.font, "Human", 0, h, 0, 200, 255) h = h + self.font_h
self.surface:drawString(self.font, game.player.descriptor.race or "", 0, h, 0, 200, 255) h = h + self.font_h
h = h + self.font_h
self.surface:drawColorString(self.font, "Level: #00ff00#"..game.player.level, 0, h, 255, 255, 255) h = h + self.font_h
self.surface:drawColorString(self.font, ("Exp: #00ff00#%2d%%"):format(100 * cur_exp / max_exp), 0, h, 255, 255, 255) h = h + self.font_h
......
newBirthDescriptor{
type = "class",
name = "Warrior",
desc = {
"Simple fighters, they hack away with their trusty weapon.",
},
descriptor_choices =
{
subclass =
{
__ALL__ = "never",
Warrior = "allow",
},
},
talents = { ActorTalents.T_STAMINA_POOL, },
}
newBirthDescriptor{
type = "subclass",
name = "Warrior",
desc = {
"Simple fighters, they hack away with their trusty weapon.",
},
stats = { str=3, con=2, dex=1, },
talents_types = {
["physical/1hweapon"]=true,
["physical/2hweapon"]=true,
["physical/shield"]=true,
["physical/1hweapon"]=true,
},
}
newBirthDescriptor{
type = "class",
name = "Mage",
desc = {
"The basic spellcaster with lots of different skills",
},
descriptor_choices =
{
subclass =
{
__ALL__ = "never",
Mage = "allow",
},
},
talents = { ActorTalents.T_MANA_POOL, },
}
newBirthDescriptor{
type = "subclass",
name = "Mage",
desc = {
"Simple fighters, they hack away with their trusty weapon.",
},
stats = { mag=3, wil=2, cun=1, },
talents_types = {
["spell/arcane"]=true,
["spell/fire"]=true,
["spell/earth"]=true,
["spell/cold"]=true,
["spell/air"]=true,
["spell/conveyance"]=false,
},
talents = {
ActorTalents.T_MANATHRUST,
},
}
newBirthDescriptor{
type = "base",
name = "base",
desc = {
},
talents = {},
experience = 1.0,
}
load("/data/birth/races.lua")
load("/data/birth/subraces.lua")
load("/data/birth/sexes.lua")
load("/data/birth/classes.lua")
newBirthDescriptor{
type = "race",
name = "Human",
desc = {
"Humans are one of the youngest of the races of Arda.",
},
descriptor_choices =
{
subrace =
{
Human = "allow",
Dunadan = "allow",
Rohirrim = "allow",
Beorning = "allow",
__ALL__ = "never",
},
},
stats = { cun=1 },
talents = {},
experience = 1.0,
}
newBirthDescriptor{
type = "race",
name = "Elf",
desc = {
"Elves are the first children of Eru.",
"The first Elves awoke by Cuiviénen, the Water of Awakening in the far east of Middle-earth, long Ages before the Rising of the Sun or Moon. Unlike Men, the Elves were not subject to illness or death.",
},
descriptor_choices =
{
subrace =
{
Noldor = "allow",
Avari = "allow",
__ALL__ = "never",
},
},
stats = { wil=1, mag=1, },
talents = {
ActorTalents.T_IMPROVED_MANA_I,
},
experience = 1.05,
}
newBirthDescriptor{
type = "race",
name = "Dwarf",
desc = {
"The children of Aule, a strong but small race.",
"Miners and fighters of legend.",
"Female dwarves remain a mystery and as such may not be played."
},
descriptor_choices =
{
subrace =
{
__ALL__ = "never",
Dwarf = "allow",
},
sex =
{
__ALL__ = "never",
Male = "allow",
},
},
stats = { str=1, con=1 },
talents = {
ActorTalents.T_IMPROVED_HEALTH_I,
},
experience = 1.05,
}
newBirthDescriptor{
type = "race",
name = "Hobbit",
desc = {
"Hobbits, or halflings, are very good at ranged combat ",
"(especially with slings), throwing, and have good saving ",
"throws. They also are very good at searching, disarming, ",
"perception and stealth; so they make excellent rogues, but ",
"prefer to be called burglars. They are much weaker than ",
"humans, thus not as good at melee fighting, and also not ",
"capable of carrying as many objects. Halflings have fair ",
"infra-vision, so they can detect warm creatures at a ",
"distance. Hobbits have their dexterity sustained and in time ",
"they learn to cook a delicious meal from available ",
"ingredients. Their sturdy constitutions also allow them to ",
"resist the insidious poison of the ring-wraiths. Their feet ",
"are cover from the ankle down in brown hairy fur, preventing ",
"them from wearing boots and shoes. ",
},
descriptor_choices =
{
subrace =
{
__ALL__ = "never",
Harfoot = "allow",
Stoor = "allow",
Fallohide = "allow",
},
},
stats = { str=-2, cun=2, dex=3, con=2, },
experience = 1.1,
talents = {
ActorTalents.T_IMPROVED_HEALTH_I,
ActorTalents.T_IMPROVED_HEALTH_II,
},
}
-- Player sexes
newBirthDescriptor{
type = "sex",
name = "Female",
desc =
{
"You are a female of the species.",
"There is no in-game difference between the two sexes.",
},
data = { female=true, },
}
newBirthDescriptor{
type = "sex",
name = "Male",
desc =
{
"You are a male of the species.",
"There is no in-game difference between the two sexes.",
},
flags = { male=true, },
}
---------------------------------------------------------
-- Humans --
---------------------------------------------------------
newBirthDescriptor
{
type = "subrace",
name = "Human",
desc = {
"Humans are one of the youngest of the races of Arda.",
},
}
newBirthDescriptor
{
type = "subrace",
name = "Dunadan",
desc = {
"The greatest of the Edain, humans in all respects but",
"stronger, smarter and wiser.",
},
stats = { str=1, cun=1, dex=1, wil=1 },
experience = 1.1,
talents = { ActorTalents.T_IMPROVED_HEALTH_I },
}
--[[
newBirthDescriptor
{
type = "subrace"
name = "Rohirrim"
desc = {
"Humans from the land of Rohan, riding the great Mearas.",
}
stats = { [A_STR]=1, [A_INT]=1, [A_WIS]=0, [A_DEX]=3, [A_CON]=1, [A_CHR]=2, }
experience = 70
levels =
{
[ 1] = { SPEED=3 }
}
skills =
{
["Weaponmastery"] = { mods.add(0) , mods.add(200) }
["Riding"] = { mods.add(5000), mods.add(600) }
}
}
]]
newBirthDescriptor
{
type = "subrace",
name = "Beorning",
desc = {
"A race of men shapeshifters.",
"They have the unique power of being able to polymorph to bear form.",
},
stats = { str=2, con=2, dex=-1, cun=-3, },
experience = 1.8,
talents = {},
}
---------------------------------------------------------
-- Elves --
---------------------------------------------------------
newBirthDescriptor
{
type = "subrace",
name = "Noldor",
desc = {
"The Noldor are the second clan of Elves who came to Valinor, and ",
"are accounted as the greatest of all peoples in Middle-earth. ",
"They are masters of all skills, and are strong and intelligent. ",
"They can play all classes except rogues, and very well at that. ",
"High-elves begin their lives able to see the unseen, and resist ",
"light effects just like regular elves. However, there are few ",
"things that they have not seen already, and experience is very ",
"hard for them to gain."
},
stats = { str=1, mag=2, wil=3, cun=1, dex=1, },
experience = 1.3,
talents = {},
}
newBirthDescriptor
{
type = "subrace",
name = "Avari",
desc = {
"The Avari are those elves who refused the summons of Orome to come",
"to Valinor, and stayed behind in Middle-earth instead. While ",
"somewhat less hardy than the Noldor, they are better at magic, ",
"gain experience faster, and have an intrinsic magic missile ",
"attack. Unlike the Noldor, they are resistant to darkness attacks ",
"rather than light attacks, and gain the ability to see invisible ",
"things at a higher level, rather than starting out with it."
},
stats = { str=-1, dex=2, cun=2, mag=1, },
talents = { ActorTalents.DECREASED_HEALTH_I },
experience = 1.1,
}
---------------------------------------------------------
-- Hobbits --
---------------------------------------------------------
newBirthDescriptor
{
type = "subrace",
name = "Harfoot",
desc = {
"An old but quiet race related to humans.",
"They are small and quite weak but good at many things.",
},
}
newBirthDescriptor
{
type = "subrace",
name = "Fallohide",
desc = {
"An old but quiet race related to humans.",
"They are small and quite weak but good at many things.",
},
}
newBirthDescriptor
{
type = "subrace",
name = "Stoor",
desc = {
"An old but quiet race related to humans.",
"They are small and quite weak but good at many things.",
},
}
---------------------------------------------------------
-- Dwarves --
---------------------------------------------------------
newBirthDescriptor
{
type = "subrace",
name = "Dwarf",
desc = {
"The children of Aule, a strong but small race.",
"Miners and fighters of legend.",
},
}
---------------------------------------------------------
-- Ents --
---------------------------------------------------------
newBirthDescriptor
{
type = "subrace",
name = "Ent",
desc = {
"Guardian of the forests of Middle-earth, summoned by Yavanna before",
"even the elves awoke. It is said 'Trolls are strong, Ents are STRONGER'.",
"Ent-wives went away a long time ago and as such may not be played."
},
}
-- "classes"
newTalentType{ type="base/class", name = "class", description = "The basic talents defining a class." }
newTalentType{ type="base/race", name = "race", description = "The various racial bonuses a character can have." }
newTalent{
name = "Mana Pool",
type = {"base/class", 1},
info = "Allows you to have a mana pool. Mana is used to cast all spells.",
}
newTalent{
name = "Stamina Pool",
type = {"base/class", 1},
info = "Allows you to have a stamina pool. Stamina is used to activate special combat attacks.",
}
-- Spells
newTalentType{ type="spell/arcane", name = "arcane", description = "Arcane manipulates the raw magic energies to shape them into both offensive and defensive spells." }
newTalentType{ type="spell/fire", name = "fire", description = "Harness the power of fire to burn your foes to ashes." }
newTalentType{ type="spell/earth", name = "earth", description = "Harness the power of the earth to protect and destroy." }
newTalentType{ type="spell/cold", name = "cold", description = "Harness the power of winter to shatter your foes." }
newTalentType{ type="spell/lightning", name = "lightning", description = "Harness the power of lightnings to fry your foes." }
newTalentType{ type="spell/conveyance", name = "conveyance", description = "Conveyance is the school of travel. It allows you to travel faster and to track others." }
-- Physical combat
newTalentType{ type="physical/2hweapon", name = "two handed weapons", description = "Allows the user to be more proficient with two handed weapons." }
newTalentType{ type="physical/1hweapon", name = "one handed weapons", description = "Allows the user to be more proficient with one handed weapons." }
newTalentType{ type="physical/dualweapon", name = "dual wielding", description = "Allows the user to be more proficient with dual wielding weapons." }
newTalentType{ type="physical/shield", name = "shields", description = "Allows the user to be more proficient with shields." }
newTalent{
name = "Manathrust",
type = {"spell/arcane", 1},
mana = 10,
tactical = {
ATTACK = 10,
},
action = function(self)
local t = {type="bolt", range=20}
local x, y = self:getTarget(t)
if not x or not y then return nil end
self:project(t, x, y, DamageType.ARCANE, 10 + self:getMag())
return true
end,
require = { stat = { mag=10 }, },
info = function(self)
return ([[Conjures up mana into a powerful bolt doing %0.2f arcane damage
The damage will increase with the Magic stat]]):format(10 + self:getMag())
end,
}
newTalent{
name = "Disruption Shield",
type = {"spell/arcane",2},
mode = "sustained",
sustain_mana = 60,
tactical = {
DEFEND = 10,
},
action = function(self)
return true
end,
require = { stat = { mag=12 }, },
info = function(self)
return ([[Uses mana instead of life to take damage
The damage to mana ratio increases with the Magic stat]]):format(10 + self:getMag())
end,
}
newTalent{
name = "Globe of Light",
type = {"spell/fire",1},
mana = 5,
tactical = {
ATTACKAREA = 3,
},
action = function(self)
local t = {type="ball", range=0, friendlyfire=false, radius=5 + self:getMag(10)}
self:project(t, self.x, self.y, DamageType.LIGHT, 1)
return true
end,
require = { stat = { mag=10 }, },
info = function(self)
return ([[Creates a globe of pure light with a radius of %d that illuminates the area.
The radius will increase with the Magic stat]]):format(5 + self:getMag(10))
end,
}
newTalent{
name = "Fireflash",
type = {"spell/fire",2},
mana = 35,
cooldown = 6,
tactical = {
ATTACKAREA = 10,
},
action = function(self)
local t = {type="ball", range=15, radius=math.min(6, 3 + self:getMag(6))}
local x, y = self:getTarget(t)
if not x or not y then return nil end
self:project(t, x, y, DamageType.FIRE, 28 + self:getMag(70))
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[Conjures up a flash of fire doing %0.2f fire damage in a radius of %d.
Cooldown: 6 turns
The damage will increase with the Magic stat]]):format(8 + self:getMag(70), math.min(6, 3 + self:getMag(6)))
end,
}
newTalent{
name = "Blink",
type = {"spell/conveyance",1},
message = "@Source@ blinks.",
mana = 15,
cooldown = 9,
tactical = {
ESCAPE = 4,
},
action = function(self)
local x, y = self.x, self.y
if self:knowTalent(self.T_TELEPORT_CONTROL) then
x, y = self:getTarget{type="ball", range=10 + self:getMag(10), radius=5 - self:getMag(4)}
if not x then return nil end
-- Target code doesnot restrict the target coordinates to the range, it lets the poject function do it
-- but we cant ...
x, y = game.target:pointAtRange(self.x, self.y, x, y, 10 + self:getMag(10))
self:teleportRandom(x, y, 5 - self:getMag(4))
else
self:teleportRandom(x, y, 10 + self:getMag(10))
end
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[Teleports you randomly on a small scale range (%d)
The range will increase with the Magic stat]]):format(10 + self:getMag(10))
end,
}
newTalent{
name = "Teleport Control",
type = {"spell/conveyance",2},
require = { stat = { mag=38 }, },
info = function(self)
return ([[Allows teleport spells to specify a target area. You will blink in this radius randomly.
The radius (%d) of the target area decreases with Magic stat]]):format(5 - self:getMag(4))
end,
}
newTalent{
name = "Noxious Cloud",
type = {"spell/earth",1},
mana = 45,
cooldown = 8,
tactical = {
ATTACKAREA = 10,
},
action = function(self)
local duration = 5 + self:getMag(10)
local radius = 3
local t = {type="ball", range=15, radius=math.min(6, 3 + self:getMag(6))}
local x, y = self:getTarget(t)
if not x or not y then return nil end
x, y = game.target:pointAtRange(self.x, self.y, x, y, 15)
-- Add a lasting map effect
game.level.map:addEffect(self,
x, y, duration,
DamageType.NATURE, 4 + self:getMag(30),
radius,
5, nil,
engine.Entity.new{alpha=100, display='', color_br=30, color_bg=180, color_bb=60}
)
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[Noxious fumes raises from the ground doing %0.2f nature damage in a radius of 3 each turns for %d turns.
Cooldown: 8 turns
The damage and duration will increase with the Magic stat]]):format(4 + self:getMag(30), 5 + self:getMag(10))
end,
}
load("/data/talents/misc/misc.lua")
load("/data/talents/spells/spells.lua")
load("/data/talents/physical/physical.lua")
-- race & classes
newTalentType{ type="base/class", name = "class", hide = true, description = "The basic talents defining a class." }
newTalentType{ type="base/race", name = "race", hide = true, description = "The various racial bonuses a character can have." }
newTalent{
name = "Mana Pool",
type = {"base/class", 1},
info = "Allows you to have a mana pool. Mana is used to cast all spells.",
hide = true,
}
newTalent{
name = "Stamina Pool",
type = {"base/class", 1},
info = "Allows you to have a stamina pool. Stamina is used to activate special combat attacks.",
hide = true,
}
newTalent{
name = "Improved Health I",
type = {"base/race", 1},
info = "Improves the number of health points per levels.",
hide = true,
}
newTalent{
name = "Improved Health II",
type = {"base/race", 1},
info = "Improves the number of health points per levels.",
hide = true,
}
newTalent{
name = "Improved Health III",
type = {"base/race", 1},
info = "Improves the number of health points per levels.",
hide = true,
}
newTalent{
name = "Decreased Health I",
type = {"base/race", 1},
info = "Improves the number of health points per levels.",
hide = true,
}
newTalent{
name = "Decreased Health II",
type = {"base/race", 1},
info = "Improves the number of health points per levels.",
hide = true,
}
newTalent{
name = "Decreased Health III",
type = {"base/race", 1},
info = "Improves the number of health points per levels.",
hide = true,
}
-- Physical combat
newTalentType{ type="physical/2hweapon", name = "two handed weapons", description = "Allows the user to be more proficient with two handed weapons." }
newTalentType{ type="physical/1hweapon", name = "one handed weapons", description = "Allows the user to be more proficient with one handed weapons." }
newTalentType{ type="physical/dualweapon", name = "dual wielding", description = "Allows the user to be more proficient with dual wielding weapons." }
newTalentType{ type="physical/shield", name = "shields", description = "Allows the user to be more proficient with shields." }
-- Spells
newTalentType{ type="spell/arcane", name = "arcane", description = "Arcane manipulates the raw magic energies to shape them into both offensive and defensive spells." }
newTalentType{ type="spell/fire", name = "fire", description = "Harness the power of fire to burn your foes to ashes." }
newTalentType{ type="spell/earth", name = "earth", description = "Harness the power of the earth to protect and destroy." }
newTalentType{ type="spell/cold", name = "cold", description = "Harness the power of winter to shatter your foes." }
newTalentType{ type="spell/air", name = "air", description = "Harness the power of the air to fry your foes." }
newTalentType{ type="spell/conveyance", name = "conveyance", description = "Conveyance is the school of travel. It allows you to travel faster and to track others." }
newTalent{
name = "Manathrust",
type = {"spell/arcane", 1},
mana = 10,
tactical = {
ATTACK = 10,
},
action = function(self)
local t = {type="bolt", range=20}
local x, y = self:getTarget(t)
if not x or not y then return nil end
self:project(t, x, y, DamageType.ARCANE, 10 + self:getMag())
return true
end,
require = { stat = { mag=10 }, },
info = function(self)
return ([[Conjures up mana into a powerful bolt doing %0.2f arcane damage
The damage will increase with the Magic stat]]):format(10 + self:getMag())
end,
}
newTalent{
name = "Disruption Shield",
type = {"spell/arcane",2},
mode = "sustained",
sustain_mana = 60,
tactical = {
DEFEND = 10,
},
action = function(self)
return true
end,
require = { stat = { mag=12 }, },
info = function(self)
return ([[Uses mana instead of life to take damage
The damage to mana ratio increases with the Magic stat]]):format(10 + self:getMag())
end,
}
newTalent{
name = "Globe of Light",
type = {"spell/fire",1},
mana = 5,
tactical = {
ATTACKAREA = 3,
},
action = function(self)
local t = {type="ball", range=0, friendlyfire=false, radius=5 + self:getMag(10)}
self:project(t, self.x, self.y, DamageType.LIGHT, 1)
return true
end,
require = { stat = { mag=10 }, },
info = function(self)
return ([[Creates a globe of pure light with a radius of %d that illuminates the area.
The radius will increase with the Magic stat]]):format(5 + self:getMag(10))
end,
}
newTalent{
name = "Fireflash",
type = {"spell/fire",2},
mana = 35,
cooldown = 6,
tactical = {
ATTACKAREA = 10,
},
action = function(self)
local t = {type="ball", range=15, radius=math.min(6, 3 + self:getMag(6))}
local x, y = self:getTarget(t)
if not x or not y then return nil end
self:project(t, x, y, DamageType.FIRE, 28 + self:getMag(70))
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[Conjures up a flash of fire doing %0.2f fire damage in a radius of %d.
Cooldown: 6 turns
The damage will increase with the Magic stat]]):format(8 + self:getMag(70), math.min(6, 3 + self:getMag(6)))
end,
}
newTalent{
name = "Blink",
type = {"spell/conveyance",1},
message = "@Source@ blinks.",
mana = 15,
cooldown = 9,
tactical = {
ESCAPE = 4,
},
action = function(self)
local x, y = self.x, self.y
if self:knowTalent(self.T_TELEPORT_CONTROL) then
x, y = self:getTarget{type="ball", range=10 + self:getMag(10), radius=5 - self:getMag(4)}
if not x then return nil end
-- Target code doesnot restrict the target coordinates to the range, it lets the poject function do it
-- but we cant ...
x, y = game.target:pointAtRange(self.x, self.y, x, y, 10 + self:getMag(10))
self:teleportRandom(x, y, 5 - self:getMag(4))
else
self:teleportRandom(x, y, 10 + self:getMag(10))
end
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[Teleports you randomly on a small scale range (%d)
The range will increase with the Magic stat]]):format(10 + self:getMag(10))
end,
}
newTalent{
name = "Teleport Control",
type = {"spell/conveyance",2},
require = { stat = { mag=38 }, },
info = function(self)
return ([[Allows teleport spells to specify a target area. You will blink in this radius randomly.
The radius (%d) of the target area decreases with Magic stat]]):format(5 - self:getMag(4))
end,
}
newTalent{
name = "Noxious Cloud",
type = {"spell/earth",1},
mana = 45,
cooldown = 8,
tactical = {
ATTACKAREA = 10,
},
action = function(self)
local duration = 5 + self:getMag(10)
local radius = 3
local t = {type="ball", range=15, radius=math.min(6, 3 + self:getMag(6))}
local x, y = self:getTarget(t)
if not x or not y then return nil end
x, y = game.target:pointAtRange(self.x, self.y, x, y, 15)
-- Add a lasting map effect
game.level.map:addEffect(self,
x, y, duration,
DamageType.NATURE, 4 + self:getMag(30),
radius,
5, nil,
engine.Entity.new{alpha=100, display='', color_br=30, color_bg=180, color_bb=60}
)
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[Noxious fumes raises from the ground doing %0.2f nature damage in a radius of 3 each turns for %d turns.
Cooldown: 8 turns
The damage and duration will increase with the Magic stat]]):format(4 + self:getMag(30), 5 + self:getMag(10))
end,
}
......@@ -3,7 +3,7 @@ return {
{
name = "dragon of death",
display = "D", color_r=255,
level_range = {1, 10}, exp_worth = 1,
level_range = {1, 10}, exp_worth = 100,
autolevel = "warrior",
ai = "simple",
max_life = 20,
......@@ -18,7 +18,7 @@ return {
name = "baby dragon",
display = "d", color_r=128,
-- faction = "poorsods",
level_range = {1, 4}, exp_worth = 1,
level_range = {1, 4}, exp_worth = 100,
autolevel = "caster",
ai = "simple",
max_life = 30,
......
......@@ -7,7 +7,7 @@ return {
-- persistant = true,
generator = {
map = {
class= "engine.generator.map.Rooms",
class= "engine.generator.map.Empty",
floor = "FLOOR",
wall = "WALL",
up = "UP",
......
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