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

controlled blink

git-svn-id: http://svn.net-core.org/repos/t-engine4@75 51575b47-30f0-44d4-a5cc-537603b46e54
parent 4ec540e2
No related branches found
No related tags found
No related merge requests found
......@@ -33,19 +33,20 @@ function _M:move(map, x, y, force)
return true
end
function _M:teleportRandom(dist)
function _M:teleportRandom(x, y, dist)
local poss = {}
for i = self.x - dist, self.x + dist do
for j = self.y - dist, self.y + dist do
for i = x - dist, x + dist do
for j = y - dist, y + dist do
if game.level.map:isBound(i, j) and
core.fov.distance(self.x, self.y, i, j) <= dist and
core.fov.distance(x, y, i, j) <= dist and
not game.level.map:checkAllEntities(i, j, "block_move") then
poss[#poss+1] = {i,j}
end
end
end
if #poss == 0 then return false end
local pos = poss[rng.range(1, #poss)]
return self:move(pos[1], pos[2], true)
end
......
......@@ -47,9 +47,11 @@ function _M:display()
local lx, ly = l()
local stopx, stopy = self.source_actor.x, self.source_actor.y
while lx and ly do
if not game.level.map.seens(lx, ly) then s = self.sr end
if self.target_type.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then s = self.sr
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then s = self.sr end
if not self.target_type.no_restrict then
if not game.level.map.seens(lx, ly) then s = self.sr end
if self.target_type.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then s = self.sr
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then s = self.sr end
end
if self.target_type.range and math.sqrt((self.source_actor.x-lx)^2 + (self.source_actor.y-ly)^2) > self.target_type.range then s = self.sr end
if s == self.sb then stopx, stopy = lx, ly end
s:toScreen(self.display_x + (lx - game.level.map.mx) * self.tile_w, self.display_y + (ly - game.level.map.my) * self.tile_h)
......@@ -62,7 +64,7 @@ function _M:display()
if self.target_type.ball then
core.fov.calc_circle(stopx, stopy, self.target_type.ball, function(self, lx, ly)
self.sg:toScreen(self.display_x + (lx - game.level.map.mx) * self.tile_w, self.display_y + (ly - game.level.map.my) * self.tile_h)
if game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then return true end
if not self.target_type.no_restrict and game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then return true end
end, function()end, self)
end
end
......@@ -78,15 +80,15 @@ function _M:getType(t)
t.range = t.range or 20
if t.friendlyfire == nil then t.friendlyfire = true end
if t.type == "hit" then
return {range=t.range, friendlyfire=t.friendlyfire}
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict}
elseif t.type == "beam" then
return {range=t.range, friendlyfire=t.friendlyfire, line=true}
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, line=true}
elseif t.type == "bolt" then
return {range=t.range, friendlyfire=t.friendlyfire, stop_block=true}
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, stop_block=true}
elseif t.type == "ball" then
return {range=t.range, friendlyfire=t.friendlyfire, ball=t.radius}
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, ball=t.radius}
elseif t.type == "cone" then
return {range=t.range, friendlyfire=t.friendlyfire, cone=t.radius}
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, cone=t.radius}
else
return {}
end
......@@ -139,3 +141,18 @@ function _M:scan(dir, radius, sx, sy)
self.target.y = self.target.entity.y
end
end
--- Returns the point at distance from the source on a line to the destination
function _M:pointAtRange(srcx, srcy, destx, desty, dist)
local l = line.new(srcx, srcy, destx, desty)
local lx, ly = l()
while lx and ly do
if core.fov.distance(srcx, srcy, lx, ly) >= dist then break end
lx, ly = l()
end
if not lx then
return destx, desty
else
return lx, ly
end
end
......@@ -22,6 +22,13 @@ function _M:block_move(x, y, e)
return true
end
--- Regenerate life, call it from your actor class act() method
function _M:regenLife()
if self.regen_life then
self.life = util.bound(self.life + self.regen_life, 0, self.max_life)
end
end
--- Remove some HP from an actor
-- If HP is reduced to 0 then remove from the level and call the die method
function _M:takeHit(value, src)
......@@ -62,9 +69,11 @@ function _M:project(t, x, y, damtype, dam)
local l = line.new(self.x, self.y, x, y)
lx, ly = l()
while lx and ly do
if typ.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then break
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then break end
if typ.range and math.sqrt((self.x-lx)^2 + (self.y-ly)^2) > typ.range then break end
if not typ.no_restrict then
if typ.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then break
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then break end
if typ.range and math.sqrt((self.x-lx)^2 + (self.y-ly)^2) > typ.range then break end
end
-- Deam damage: beam
if typ.line then addGrid(lx, ly) end
......@@ -78,7 +87,7 @@ function _M:project(t, x, y, damtype, dam)
core.fov.calc_circle(lx, ly, typ.ball, function(self, px, py)
-- Deam damage: ball
addGrid(px, py)
if game.level.map:checkEntity(px, py, Map.TERRAIN, "block_move") then return true end
if not typ.no_restrict and game.level.map:checkEntity(px, py, Map.TERRAIN, "block_move") then return true end
end, function()end, self)
addGrid(lx, ly)
elseif typ.cone then
......
......@@ -10,14 +10,16 @@ _M.resources_def = {}
-- All actors will now have :getResourcename() and :incResourcename() methods as well as a .max_resourcename and .resourcename
-- properties. It is advised to NOT access .resourcename directly and use the get/inc methods. They handle talent
-- dependencies
function _M:defineResource(name, short_name, talent, desc)
function _M:defineResource(name, short_name, talent, regen_prop, desc)
assert(name, "no resource name")
assert(short_name, "no resource short_name")
table.insert(self.resources_def, {
name = name,
short_name = short_name,
talent = talent,
regen_prop = regen_prop,
description = desc,
maxname = "max_"..short_name,
})
self.resources_def[#self.resources_def].id = #self.resources_def
self.resources_def[short_name] = self.resources_def[#self.resources_def]
......@@ -49,5 +51,17 @@ function _M:init(t)
for i, r in ipairs(_M.resources_def) do
self["max_"..r.short_name] = t["max_"..r.short_name] or 100
self[r.short_name] = t[r.short_name] or self["max_"..r.short_name]
if r.regen_prop then
self[r.regen_prop] = t[r.regen_prop] or 0
end
end
end
--- Regen resources, shout be called in your actor's act() method
function _M:regenResources()
for i, r in ipairs(_M.resources_def) do
if r.regen_prop then
self[r.short_name] = util.bound(self[r.short_name] + self[r.regen_prop], 0, self[r.maxname])
end
end
end
......@@ -36,6 +36,9 @@ end
function _M:act()
-- Cooldown talents
self:cooldownTalents()
-- Regen resources
self:regenLife()
self:regenResources()
end
function _M:move(x, y, force)
......@@ -64,8 +67,14 @@ end
function _M:levelup()
self.unused_stats = self.unused_stats + 3
self.unused_talents = self.unused_talents + 1
-- TODO: change it later, we need much less
self.unused_talents_types = self.unused_talents_types + 1
if self.level % 5 == 0 then
self.unused_talents_types = self.unused_talents_types + 1
end
-- Gain life and resources
self.max_life = self.max_life + 7
self:incMaxMana(7)
self:incMaxStamina(7)
end
--- Notifies a change of stat value
......
......@@ -43,8 +43,8 @@ function _M:run()
-- Talents
ActorTalents:loadDefinition("/data/talents.lua")
-- Actor resources
ActorResource:defineResource("Mana", "mana", ActorTalents.T_MANA_POOL, "Mana represents your reserve of magical energies. Each spell cast consumes mana and each sustained spell reduces your maximun mana.")
ActorResource:defineResource("Stamina", "stamina", ActorTalents.T_STAMINA_POOL, "Stamina represents your physical fatigue. Each physical ability used reduces it.")
ActorResource:defineResource("Mana", "mana", ActorTalents.T_MANA_POOL, "mana_regen", "Mana represents your reserve of magical energies. Each spell cast consumes mana and each sustained spell reduces your maximun mana.")
ActorResource:defineResource("Stamina", "stamina", ActorTalents.T_STAMINA_POOL, "stamina_regen", "Stamina represents your physical fatigue. Each physical ability used reduces it.")
-- Actor stats
ActorStats:defineStat("Strength", "str", 10, 1, 100, "Strength defines your character's ability to apply physical force. It increases your melee damage, damage with heavy weapons, your chance to resist physical effects, and carrying capacity.")
ActorStats:defineStat("Dexterity", "dex", 10, 1, 100, "Dexterity defines your character's ability to be agile and alert. It increases your chance to hit, your ability to avoid attacks and your damage with light weapons.")
......@@ -257,7 +257,7 @@ function _M:setupCommands()
self.player:useTalent(ActorTalents.T_FIREFLASH)
end,
_z = function()
self.player:useTalent(ActorTalents.T_PHASE_DOOR)
self.player:useTalent(ActorTalents.T_BLINK)
end,
[{"_g","shift"}] = function()
......
......@@ -8,8 +8,17 @@ 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 = {["spell/arcane"]=true,["spell/fire"]=true,["physical/1hweapon"]=true}
self.talents_types = {
["base/race"]=true,
["base/class"]=true,
["spell/arcane"]=true,
["spell/fire"]=true,
["physical/1hweapon"]=true
}
self.talents = {[self.T_MANA_POOL]=true, [self.T_STAMINA_POOL]=true}
self.mana_regen = 1
self.stamina_regen = 1
self.regen_life = 1
end
function _M:move(x, y, force)
......
......@@ -6,11 +6,11 @@ defaultProjector(function(src, x, y, type, dam)
local sx, sy = game.level.map:getTileToScreen(x, y)
if target:takeHit(dam, src) then
if src == game.player or target == game.player then
game.flyers:add(sx, sy, 30, 0.5, -3, "Kill!", {255,0,255})
game.flyers:add(sx, sy, 30, rng.range(-1,1) * 0.5, -3, "Kill!", {255,0,255})
end
else
if src == game.player or target == game.player then
game.flyers:add(sx, sy, 30, -0.5, -3, tostring(-dam), {255,0,255})
game.flyers:add(sx, sy, 30, rng.range(-1,1) * 0.5, -3, tostring(-dam), {255,0,255})
end
end
end
......
......@@ -109,15 +109,26 @@ newTalent{
}
newTalent{
name = "Phase Door",
name = "Blink",
type = {"spell/conveyance",1},
message = "@Source@ blinks.",
mana = 15,
cooldown = 9,
tactical = {
ESCAPE = 4,
},
action = function(self)
self:teleportRandom(10 + self:getMag(10))
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 }, },
......@@ -126,3 +137,13 @@ newTalent{
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,
}
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