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

movign ice storm

git-svn-id: http://svn.net-core.org/repos/t-engine4@125 51575b47-30f0-44d4-a5cc-537603b46e54
parent ad3bdbc7
No related branches found
No related tags found
No related merge requests found
......@@ -376,10 +376,12 @@ end
-- @param dir the numpad direction of the effect, 5 for a ball effect
-- @param overlay a simple display entity to draw upon the map
-- @param update_fct optional function that will be called each time the effect is updated with the effect itself as parameter. Use it to change radius, move around ....
function _M:addEffect(src, x, y, duration, damtype, dam, radius, dir, angle, overlay, update_fct)
function _M:addEffect(src, x, y, duration, damtype, dam, radius, dir, angle, overlay, update_fct, friendlyfire)
if friendlyfire == nil then friendlyfire = true end
print(friendlyfire)
table.insert(self.effects, {
src=src, x=x, y=y, duration=duration, damtype=damtype, dam=dam, radius=radius, dir=dir, angle=angle, overlay=overlay,
update_fct=update_fct,
update_fct=update_fct, friendlyfire=friendlyfire
})
self.changed = true
end
......@@ -429,7 +431,9 @@ function _M:processEffects()
-- Now display each grids
for lx, ys in pairs(grids) do
for ly, _ in pairs(ys) do
DamageType:get(e.damtype).projector(e.src, lx, ly, e.damtype, e.dam)
if e.friendlyfire or (lx ~= e.src.x and ly ~= e.src.y) then
DamageType:get(e.damtype).projector(e.src, lx, ly, e.damtype, e.dam)
end
end
end
......
......@@ -98,7 +98,7 @@ local function basicSerialize(o)
if type(o) == "number" or type(o) == "boolean" then
return tostring(o)
elseif type(o) == "function" then
return string.format("%q", string.dump(o))
return string.format("loadstring(%q)", string.dump(o))
else -- assume it is a string
return string.format("%q", o)
end
......@@ -157,6 +157,7 @@ local function deserialize(string)
local f, err = loadstring(string)
if err then print("error deserializing", string, err) end
setfenv(f, {
loadstring = loadstring,
loadObject = function(n)
-- print("wants to load",n)
return engine.Savefile.current_save:loadReal(n)
......
......@@ -37,6 +37,10 @@ function _M:init(t)
self.combat_spellspeed = 0
self.combat_spellcrit = 0
self.combat_spellpower = 0
self.combat_physresist = 0
self.combat_spellresist = 0
self.fatigue = 0
-- Default melee barehanded damage
......@@ -67,6 +71,9 @@ function _M:act()
-- 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
......
......@@ -72,11 +72,7 @@ end
function _M:newGame()
self.zone = Zone.new("ancient_ruins")
self.player = Player.new{
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, image="player.png",
move_others=true,
}
self.player = Player.new{name=self.player_name}
local birth = Birther.new(self.player, {"base", "race", "subrace", "sex", "class", "subclass" }, function()
self:changeLevel(1)
......
......@@ -11,7 +11,7 @@ end
function _M:act()
-- Do basic actor stuff
mod.class.Actor.act(self)
if not mod.class.Actor.act(self) then return end
-- Let the AI think .... beware of Shub !
self:doAI()
......
......@@ -24,10 +24,23 @@ function _M:init(t)
self.player = true
self.faction = "players"
self.display='@'
self.color_r=230
self.color_g=230
self.color_b=230
self.image="player.png"
-- Default regen
self.mana_regen = self.mana_regen or 1
self.stamina_regen = self.stamina_regen or 1
self.life_regen = self.life_regen or 0.5
self.mana_regen = 1
self.stamina_regen = 1
self.life_regen = 0.5
self.max_life=85
self.max_mana=85
self.max_stamina=85
self.unused_stats = 6
self.unused_talents = 3
self.move_others=true
self.descriptor = {}
self.hotkey = {}
......@@ -47,7 +60,7 @@ function _M:move(x, y, force)
end
function _M:act()
mod.class.Actor.act(self)
if not mod.class.Actor.act(self) then return end
game.paused = true
end
......
......@@ -72,6 +72,23 @@ function _M:attackTarget(target)
end
end
--- Computes a logarithmic chance to hit, opposing chance to hit to chance to miss
-- This will be used for melee attacks, physical and spell resistance
function _M:checkHit(atk, def, min, max, facotr)
print("checkHit", atk, def)
if atk == 0 then atk = 1 end
local hit = nil
factor = factor or 5
if atk > def then
hit = math.log10(1 + 5 * (atk - def) / atk) * 100 + 50
else
hit = -math.log10(1 + 5 * (def - atk) / atk) * 100 + 50
end
hit = util.bound(hit, min or 5, max or 95)
print("=> chance to hit", hit)
return rng.percent(hit)
end
--- Attacks with one weapon
function _M:attackTargetWith(target, weapon)
local damtype = DamageType.PHYSICAL
......@@ -79,19 +96,9 @@ function _M:attackTargetWith(target, weapon)
-- Does the blow connect? yes .. complex :/
local atk, def = self:combatAttack(weapon), target:combatDefense()
local dam, apr, armor = self:combatDamage(weapon), self:combatAPR(weapon), target:combatArmor()
print(atk, def, "::", dam, apr, armor)
if afk == 0 then atk = 1 end
local hit = nil
if atk > def then
hit = math.log10(1 + 5 * (atk - def) / atk) * 100 + 50
else
hit = -math.log10(1 + 5 * (def - atk) / atk) * 100 + 50
end
hit = util.bound(hit, 5, 95)
print("hit: ", hit, "from", atk, def)
-- If hit is over 0 it connects, if it is 0 we still have 50% chance
if rng.percent(hit) then
if self:checkHit(atk, def) then
local dam = dam - math.max(0, armor - apr)
dam = self:physicalCrit(dam, weapon)
DamageType:get(damtype).projector(self, target.x, target.y, damtype, dam)
......@@ -181,3 +188,13 @@ function _M:spellCrit(dam)
end
return dam
end
--- Computes physical resistance
function _M:combatPhysicalResist()
return self.combat_physresist + (self:getCon() + self:getStr()) * 0.5
end
--- Computes spell resistance
function _M:combatSpellResist()
return self.combat_spellresist + (self:getMag() + self:getWil()) * 0.5
end
......@@ -59,7 +59,7 @@ newBirthDescriptor{
["spell/arcane"]=true,
["spell/fire"]=true,
["spell/earth"]=true,
["spell/cold"]=true,
["spell/water"]=true,
["spell/air"]=true,
["spell/mind"]=true,
["spell/temporal"]=true,
......
......@@ -49,7 +49,7 @@ newDamageType{
local target = game.level.map(x, y, Map.ACTOR)
if target then
-- Set on fire!
target:setEffect(target.EFF_BURNING, 3, {src=src, power=dam / 2 / 3})
target:setEffect(target.EFF_BURNING, 3, {src=src, power=dam / 6})
end
end,
}
......@@ -57,3 +57,22 @@ newDamageType{
newDamageType{
name = "netherflame", type = "NETHERFLAME",
}
newDamageType{
name = "freeze", type = "FREEZE",
projector = function(src, x, y, type, dam)
local target = game.level.map(x, y, Map.ACTOR)
if target then
-- Freeze it, if we pass the test
local sx, sy = game.level.map:getTileToScreen(x, y)
if target:checkHit(src:combatSpellpower(), target:combatSpellResist(), 0, 95, 15) then
target:setEffect(target.EFF_FROZEN, dam, {src=src})
game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, "Frozen!", {0,255,155})
else
game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, "Resist!", {0,255,155})
game.logSeen(target, "%s resists!", target.name:capitalize())
end
end
end,
}
newTalent{
name = "Freeze",
type = {"spell/water", 1},
mana = 14,
cooldown = 3,
tactical = {
ATTACK = 10,
},
action = function(self)
local t = {type="hit", range=20}
local x, y = self:getTarget(t)
if not x or not y then return nil end
self:project(t, x, y, DamageType.COLD, self:spellCrit(7 + self:combatSpellpower(0.7)))
self:project(t, x, y, DamageType.FREEZE, 2)
return true
end,
require = { stat = { mag=14 }, },
info = function(self)
return ([[Condenses ambiant water on a target, freezing it for a short while.
The damage will increase with the Magic stat]]):format(7 + self:combatSpellpower(0.7))
end,
}
newTalent{
name = "Ice Storm",
type = {"spell/water",2},
mana = 45,
cooldown = 30,
tactical = {
ATTACKAREA = 20,
},
action = function(self)
local duration = 5 + self:combatSpellpower(0.25)
local radius = 3
local dam = 12 + self:combatSpellpower(0.20)
-- Add a lasting map effect
game.level.map:addEffect(self,
self.x, self.y, duration,
DamageType.COLD, dam,
radius,
5, nil,
engine.Entity.new{alpha=100, display='', color_br=30, color_bg=60, color_bb=200},
function(e)
e.x = e.src.x
e.y = e.src.y
end,
false
)
return true
end,
require = { stat = { mag=16 }, },
info = function(self)
return ([[A furious ice storm rages around the caster doing %0.2f cold damage in a radius of 3 each turns for %d turns.
The damage and duration will increase with the Magic stat]]):format(12 + self:combatSpellpower(0.20), 5 + self:combatSpellpower(0.25))
end,
}
......@@ -55,3 +55,53 @@ newEffect{
DamageType:get(DamageType.FIRE).projector(eff.src, self.x, self.y, DamageType.FIRE, eff.power)
end,
}
newEffect{
name = "FROZEN",
desc = "Frozen",
type = "magical",
status = "detrimental",
parameters = {},
on_gain = function(self, err) return "#Target# is frozen!" end,
on_lose = function(self, err) return "#Target# warms up.", "-Frozen" end,
activate = function(self, eff)
-- Change color
eff.old_r = self.color_r
eff.old_g = self.color_g
eff.old_b = self.color_b
self.color_r = 0
self.color_g = 255
self.color_b = 155
game.level.map:updateMap(self.x, self.y)
-- Frozen, cannot act
self.energy.value = 0
end,
on_timeout = function(self, eff)
-- Frozen, cannot act
self.energy.value = 0
end,
deactivate = function(self, eff)
self.color_r = eff.old_r
self.color_g = eff.old_g
self.color_b = eff.old_b
end,
}
newEffect{
name = "STUNNED",
desc = "STUN",
type = "physical",
status = "detrimental",
parameters = {},
on_gain = function(self, err) return "#Target# is stunned!", "+Stunned" end,
on_lose = function(self, err) return "#Target# is not stunned anymore.", "-Stunned" end,
activate = function(self, eff)
-- Frozen, cannot act
self.energy.value = 0
end,
on_timeout = function(self, eff)
-- Frozen, cannot act
self.energy.value = 0
end,
}
No preview for this file type
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