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

Fixed archery when projectiles are flying during a save/reload

When the player comes back from the far east some of the zones he visited and vanquished the boss in the west will be updated with a new boss (only if the previous guardian has been killed before going east). This currently affects the Moria, Old Forest, Trollshaws and Tol Falas


git-svn-id: http://svn.net-core.org/repos/t-engine4@1554 51575b47-30f0-44d4-a5cc-537603b46e54
parent dcb85e78
No related branches found
No related tags found
No related merge requests found
Showing
with 380 additions and 7 deletions
......@@ -66,6 +66,7 @@ function _M:defaultSavedFields(t)
energy_to_act=true, energy_per_tick=true, turn=true, paused=true, save_name=true,
always_target=true, gfxmode=true, uniques=true, object_known_types=true,
current_music=true, memory_levels=true, achievement_data=true, factions=true,
state=true,
__savefile_version_tokens = true,
}
table.merge(def, t)
......
......@@ -1399,9 +1399,9 @@ function _M:getTalentFullDescription(t, addlevel)
if t.stamina or t.sustain_stamina then d:add({"color",0x6f,0xff,0x83}, "Stamina cost: ", {"color",0xff,0xcc,0x80}, ""..(t.sustain_stamina or t.stamina * (100 + self.fatigue) / 100), true) end
if t.equilibrium or t.sustain_equilibrium then d:add({"color",0x6f,0xff,0x83}, "Equilibrium cost: ", {"color",0x00,0xff,0x74}, ""..(t.equilibrium or t.sustain_equilibrium), true) end
if t.vim or t.sustain_vim then d:add({"color",0x6f,0xff,0x83}, "Vim cost: ", {"color",0x88,0x88,0x88}, ""..(t.sustain_vim or t.vim), true) end
if t.positive or t.sustain_positive then d:add({"color",0x6f,0xff,0x83}, "Positive energy cost: #GOLD#"..(t.sustain_positive or t.positive * (100 + self.fatigue) / 100), true) end
if t.negative or t.sustain_negative then d:add({"color",0x6f,0xff,0x83}, "Negative energy cost: #GREY#"..(t.sustain_negative or t.negative * (100 + self.fatigue) / 100), true) end
if t.hate or t.sustain_hate then d:add({"color",0x6f,0xff,0x83}, "Hate cost: #GREY#"..(t.hate or t.sustain_hate), true) end
if t.positive or t.sustain_positive then d:add({"color",0x6f,0xff,0x83}, "Positive energy cost: ", {"color",255, 215, 0}, ""..(t.sustain_positive or t.positive * (100 + self.fatigue) / 100), true) end
if t.negative or t.sustain_negative then d:add({"color",0x6f,0xff,0x83}, "Negative energy cost: ", {"color", 127, 127, 127}, ""..(t.sustain_negative or t.negative * (100 + self.fatigue) / 100), true) end
if t.hate or t.sustain_hate then d:add({"color",0x6f,0xff,0x83}, "Hate cost: ", {"color", 127, 127, 127}, ""..(t.hate or t.sustain_hate), true) end
if self:getTalentRange(t) > 1 then d:add({"color",0x6f,0xff,0x83}, "Range: ", {"color",0xFF,0xFF,0xFF}, ""..self:getTalentRange(t), true)
else d:add({"color",0x6f,0xff,0x83}, "Range: ", {"color",0xFF,0xFF,0xFF}, "melee/personal", true)
end
......
......@@ -33,6 +33,7 @@ local Astar = require "engine.Astar"
local DirectPath = require "engine.DirectPath"
local Shader = require "engine.Shader"
local GameState = require "mod.class.GameState"
local Store = require "mod.class.Store"
local Trap = require "mod.class.Trap"
local Grid = require "mod.class.Grid"
......@@ -125,6 +126,9 @@ function _M:newGame()
Map:setViewerActor(self.player)
self:setupDisplayMode()
-- Create the entity to store various game state things
self.state = GameState.new{}
-- Load for quick birth
local save = Savefile.new(self.save_name)
local quickbirth = save:loadQuickBirth()
......@@ -363,6 +367,9 @@ function _M:changeLevel(lev, zone, keep_old_lev, force_down)
end
self.zone:getLevel(self, lev, old_lev)
-- Check if we need to switch the current guardian
self.state:zoneCheckBackupGuardian()
-- Decay level ?
if self.level.last_turn and self.level.data.decay and self.level.last_turn + self.level.data.decay[1] * 10 < self.turn then
local nb_actor, remain_actor = self.level:decay(Map.ACTOR, function(e) return not e.unique and not e.lore and self.level.last_turn + rng.range(self.level.data.decay[1], self.level.data.decay[2]) < self.turn * 10 end)
......
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009, 2010 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.Entity"
module(..., package.seeall, class.inherit(engine.Entity))
function _M:init(t, no_default)
engine.Entity.init(self, t, no_default)
self.allow_backup_guardians = {}
end
function _M:goneEast()
self.gone_east = true
end
function _M:activateBackupGuardian(guardian, on_level, zonelevel, rumor)
if self.gone_east then return end
print("Zone guardian dead, setting up backup guardian", guardian, zonelevel)
self.allow_backup_guardians[game.zone.short_name] =
{
name = game.zone.name,
guardian = guardian,
on_level = on_level,
new_level = zonelevel,
rumor = rumor,
}
end
function _M:zoneCheckBackupGuardian()
if not self.gone_east then print("Not gone east, no backup guardian") return end
-- Adjust level of the zone
if self.allow_backup_guardians[game.zone.short_name] then
local data = self.allow_backup_guardians[game.zone.short_name]
game.zone.base_level = data.new_level
end
-- Spawn the new guardian
if self.allow_backup_guardians[game.zone.short_name] and self.allow_backup_guardians[game.zone.short_name].on_level == game.level.level then
local data = self.allow_backup_guardians[game.zone.short_name]
-- Place the guardian, we do not check for connectivity, vault or whatever, the player is suppoed to be strong enough to get there
local m = game.zone:makeEntityByName(game.level, "actor", data.guardian)
if m then
local x, y = rng.range(0, game.level.map.w - 1), rng.range(0, game.level.map.h - 1)
local tries = 0
while not m:canMove(x, y) and tries < 100 do
x, y = rng.range(0, game.level.map.w - 1), rng.range(0, game.level.map.h - 1)
tries = tries + 1
end
if tries < 100 then
game.zone:addEntity(game.level, m, "actor", x, y)
print("Backup Guardian allocated: ", data.guardian, m.uid, m.name)
end
else
print("WARNING: Backup Guardian not found: ", data.guardian)
end
self.allow_backup_guardians[game.zone.short_name] = nil
end
end
......@@ -146,7 +146,7 @@ local function archery_projectile(tx, ty, tg, self)
print("[ATTACK ARCHERY] after mult", dam)
if crit then game.logSeen(self, "%s performs a critical strike!", self.name:capitalize()) end
DamageType:get(damtype).projector(self, target.x, target.y, damtype, math.max(0, dam))
engine.DamageType:get(damtype).projector(self, target.x, target.y, damtype, math.max(0, dam))
game.level.map:particleEmitter(target.x, target.y, 1, "archery")
hitted = true
......
......@@ -511,7 +511,7 @@ newDamageType{
-- Physical damage + repulsion; checks for spell power against physical resistance
newDamageType{
name = "spellknockback", type = "SPELLKNOCKBACK",
name = "spell knockback", type = "SPELLKNOCKBACK",
projector = function(src, x, y, type, dam, tmp)
local target = game.level.map(x, y, Map.ACTOR)
if target and not tmp[target] then
......@@ -529,7 +529,7 @@ newDamageType{
-- Physical damage + repulsion; checks for mind power against physical resistance
newDamageType{
name = "mindknockback", type = "MINDKNOCKBACK",
name = "mind knockback", type = "MINDKNOCKBACK",
projector = function(src, x, y, type, dam, tmp)
local target = game.level.map(x, y, Map.ACTOR)
if target and not tmp[target] then
......
......@@ -92,6 +92,8 @@ newEntity{ define_as = "GOLBUG",
end,
on_die = function(self, who)
game.state:activateBackupGuardian("LITHFENGEL", 4, 40, "They say that after it has been confirmed orcs still inhabited the Moria, they found a mighty demon there.")
world:gainAchievement("DESTROYER_BANE", game.player:resolveSource())
game.player:setQuestStatus("orc-hunt", engine.Quest.DONE)
game.player:grantQuest("wild-wild-east")
......@@ -138,3 +140,50 @@ newEntity{ define_as = "HARNO",
game.player:setQuestStatus("orc-hunt", engine.Quest.DONE, "herald-died")
end,
}
newEntity{ define_as = "LITHFENGEL", -- Lord of Ash; backup guardian
type = "demon", subtype = "major", unique = true,
name = "Lithfengel",
display = "U", color=colors.VIOLET,
desc = [[A terrible demon of decay and atrophy, drawn to the energy of the farportal.]],
level_range = {40, 75}, exp_worth = 3,
max_life = 500, life_rating = 30, fixed_rating = true,
rank = 4,
size_category = 5,
infravision = 30,
-- The artifact he wields drains life a little, so to compensate:
life_regen = 0.3,
stats = { str=20, dex=15, cun=25, mag=25, con=20 },
poison_immune = 1,
fear_immune = 1,
instakill_immune = 1,
no_breath = 1,
move_others=true,
demon = 1,
on_melee_hit = { [DamageType.BLIGHT] = 45, },
body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 },
resolvers.equip{
{type="weapon", subtype="waraxe", defined="MALEDICTION", autoreq=true},
},
resolvers.drops{chance=100, nb=4, {ego_chance=100} },
resolvers.talents{
[Talents.T_ROTTING_DISEASE]=5,
[Talents.T_DECREPITUDE_DISEASE]=5,
[Talents.T_WEAKNESS_DISEASE]=5,
[Talents.T_CATALEPSY]=5,
[Talents.T_RUSH]=5,
[Talents.T_MORTAL_TERROR]=5,
[Talents.T_WEAPON_COMBAT]=10,
[Talents.T_WEAPONS_MASTERY]=6,
},
resolvers.sustains_at_birth(),
autolevel = "warriormage",
ai = "dumb_talented_simple", ai_state = { talent_in=2, ai_move="move_astar" },
on_die = function(self, who)
end,
}
......@@ -27,3 +27,24 @@ newEntity{ base = "BASE_SCROLL", define_as = "NOTE_FROM_MINAS_TIRITH",
game:registerDialog(require("engine.dialogs.ShowText").new(self:getName{do_color=true}, "message-minas-tirith", {playername=who.name}, game.w * 0.6))
end}
}
newEntity{ base = "BASE_WARAXE",
define_as = "MALEDICTION", rarity=false,
unided_name = "pestilent waraxe",
name = "Malediction", unique=true,
desc = [[The land withers and crumbles wherever this cursed axe rests.]],
require = { stat = { str=55 }, },
cost = 375,
combat = {
dam = 55,
apr = 15,
physcrit = 10,
dammod = {str=1},
damrange = 1.2,
},
wielder = {
life_regen = -0.3,
inc_damage = { [DamageType.BLIGHT] = 20 },
melee_project={[DamageType.BLIGHT] = 20},
},
}
......@@ -50,6 +50,8 @@ newEntity{ define_as = "OLD_MAN_WILLOW",
instakill_immune = 1,
move_others=true,
combat = { dam=27, atk=10, apr=0, dammod={str=1.2} },
resists = { [DamageType.FIRE] = -50 },
body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 },
......@@ -69,6 +71,7 @@ newEntity{ define_as = "OLD_MAN_WILLOW",
ai = "dumb_talented_simple", ai_state = { talent_in=3, ai_move="move_astar", },
on_die = function(self, who)
game.state:activateBackupGuardian("SNAPROOT", 3, 50, "Have you heard, the old forest seems to have been claimed bya new evil!")
game.player:resolveSource():grantQuest("starter-zones")
game.player:resolveSource():setQuestStatus("starter-zones", engine.Quest.COMPLETED, "old-forest")
end,
......@@ -83,3 +86,37 @@ newEntity{ base = "BASE_NPC_RODENT",
combat = { dam=50, atk=15, apr=10 },
combat_armor = 1, combat_def = 20,
}
newEntity{ define_as = "SNAPROOT", -- backup guardian
type = "giant", subtype = "ent", unique = true,
name = "Snaproot",
display = "#", color=VIOLET,
desc = [[This ancient Ent's bark is scorched almost black. It sees humanity as a scourge, to be purged.]],
level_range = {50, 75}, exp_worth = 3,
max_life = 1000, life_rating = 40, fixed_rating = true,
max_stamina = 200,
combat = { dam=100, atk=10, apr=0, dammod={str=1.2} },
stats = { str=40, dex=10, cun=15, mag=20, wil=38, con=45 },
rank = 4,
size_category = 5,
infravision = 20,
instakill_immune = 1,
stun_immune = 1,
move_others = true,
resists = { [DamageType.FIRE] = -20, [DamageType.PHYSICAL] = 50, [DamageType.COLD] = 50, [DamageType.NATURE] = 25 },
body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 },
drops = resolvers.drops{chance=100, nb=5, {ego_chance=100} },
resolvers.talents{
[Talents.T_STUN]=5,
[Talents.T_GRAB]=5,
[Talents.T_THROW_BOULDER]=5,
[Talents.T_CRUSH]=5,
},
autolevel = "warriorwill",
ai = "dumb_talented_simple", ai_state = { talent_in=3, ai_move="move_astar", },
}
......@@ -19,6 +19,8 @@
load("/data/general/objects/objects.lua")
local Stats = require "engine.interface.ActorStats"
-- Artifact, droped (and used!) by Bill the Stone Troll
newEntity{ base = "BASE_SHIELD",
......@@ -44,3 +46,19 @@ newEntity{ base = "BASE_SHIELD",
},
},
}
newEntity{ base = "BASE_GEM",
unique = true,
unided_name = "burned piece of wood",
name = "Petrified Wood", subtype = "black",
color = colors.WHITE, image="object/bloodstone.png",
level_range = {35, 45},
desc = [[A piece of the scorched wood took from the remains of Snaproot.]],
rarity = false,
cost = 100,
material_level = 5,
imbue_powers = {
resists = { [DamageType.NATURE] = 25, [DamageType.FIRE] = -10, [DamageType.COLD] = 10 },
inc_stats = { [Stats.STAT_CON] = 10, },
},
}
......@@ -25,6 +25,9 @@ load("/data/general/npcs/ghost.lua", rarity(3))
load("/data/general/npcs/all.lua", rarity(4, 35))
-- Not normaly appearing, used for the Pale Drake summons
load("/data/general/npcs/bone-giant.lua", function(e) if e.rarity then e.bonegiant_rarity = e.rarity; e.rarity = nil end end)
local Talents = require("engine.interface.ActorTalents")
-- The boss of Tol Falas, no "rarity" field means it will not be randomly generated
......@@ -88,6 +91,8 @@ newEntity{ define_as = "THE_MASTER",
ai = "dumb_talented_simple", ai_state = { talent_in=1, ai_move="move_astar", },
on_die = function(self, who)
game.state:activateBackupGuardian("PALE_DRAKE", 1, 40, "It has been month since the hero cleansed Tol Falas, yet rumours are growing: evil is back.")
world:gainAchievement("VAMPIRE_CRUSHER", game.player:resolveSource())
game.player:resolveSource():grantQuest("tol-falas")
game.player:resolveSource():setQuestStatus("tol-falas", engine.Quest.DONE)
......@@ -100,3 +105,63 @@ newEntity{ define_as = "THE_MASTER",
game:setAllowedBuild(rng.table(ud), true)
end,
}
-- The boss of Tol Falas, no "rarity" field means it will not be randomly generated
newEntity{ define_as = "PALE_DRAKE",
faction = "tol-falas",
type = "undead", subtype = "skeleton", unique = true,
name = "Pale Drake",
display = "s", color=colors.VIOLET,
desc = [[A malevolent skeleton archmage that has taken control of Tol Falas since the Master's demise.]],
level_range = {40, 50}, exp_worth = 3,
max_life = 450, life_rating = 21, fixed_rating = true,
rank = 4,
size_category = 3,
infravision = 20,
stats = { str=19, dex=19, cun=44, mag=25, con=16 },
move_others=true,
body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, NECK=1, },
equipment = resolvers.equip{
{type="weapon", subtype="staff", ego_chance=100, autoreq=true},
{type="armor", subtype="cloth", ego_chance=50, autoreq=true},
},
resolvers.drops{chance=100, nb=5, {ego_chance=100} },
resolvers.drops{chance=100, nb=1, {defined="RUNED_SKULL"} },
summon = {
{type="undead", subtype="bone giant", special_rarity="bonegiant_rarity", number=2, hasxp=true},
},
instakill_immune = 1,
blind_immune = 1,
stun_immune = 0.7,
see_invisible = 100,
undead = 1,
self_resurrect = 1,
open_door = 1,
resists = { [DamageType.FIRE] = 100, },
resolvers.talents{
[Talents.T_SUMMON]=1,
[Talents.T_WILDFIRE]=5,
[Talents.T_FLAME]=5,
[Talents.T_FLAMESHOCK]=5,
[Talents.T_INFERNO]=5,
[Talents.T_MANATHRUST]=5,
[Talents.T_CURSE_OF_DEATH]=5,
[Talents.T_CURSE_OF_VULNERABILITY]=5,
[Talents.T_BONE_SPEAR]=5,
[Talents.T_DRAIN]=5,
[Talents.T_PHASE_DOOR]=2,
},
resolvers.sustains_at_birth(),
autolevel = "caster",
ai = "dumb_talented_simple", ai_state = { talent_in=1, ai_move="move_astar", },
}
......@@ -88,3 +88,18 @@ newEntity{ base = "BASE_AMULET",
game:playSoundNear(who, "talents/spell_generic")
end },
}
newEntity{ define_as = "RUNED_SKULL",
unique = true,
type = "gem", subtype="red",
unided_name = "human skull",
name = "Runed Skull",
display = "*", color=colors.RED,
encumber = 3,
desc = [[Dull red runes are etched all over this blackened skull.]],
carrier = {
combat_spellpower = 7,
on_melee_hit = {[DamageType.FIREKNOCKBACK]=25},
},
}
......@@ -62,6 +62,60 @@ newEntity{ define_as = "TROLL_BILL",
ai = "dumb_talented_simple", ai_state = { talent_in=4, ai_move="move_astar", },
on_die = function(self, who)
game.state:activateBackupGuardian("ALUIN", 2, 35, "... and we thought the trollshaws were safer now!")
game.player:resolveSource():setQuestStatus("start-dunadan", engine.Quest.COMPLETED, "trollshaws")
end,
}
newEntity{ define_as = "ALUIN",
type = "humanoid", subtype = "human", unique = true,
name = "Aluin the Fallen",
display = "p", color=colors.VIOLET,
desc = [[His once shining armour now dull and bloodstained, this sun paladin has given in to despair.]],
level_range = {35, 40}, exp_worth = 3,
max_life = 350, life_rating = 23, fixed_rating = true,
hate_regen = 10,
stats = { str=25, dex=10, cun=8, mag=10, con=20 },
rank = 4,
size_category = 3,
infravision = 20,
instakill_immune = 1,
blind_immune = 1,
see_invisible = 30,
move_others=true,
body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 },
resolvers.equip{
{type="weapon", subtype="waraxe", ego_chance=100, autoreq=true},
{type="armor", subtype="shield", defined="SANGUINE_SHIELD", autoreq=true},
{type="armor", subtype="massive", ego_chance=100, autoreq=true},
},
resolvers.drops{chance=100, nb=3, {ego_chance=100} },
resolvers.talents{
[Talents.T_MASSIVE_ARMOUR_TRAINING]=5,
[Talents.T_WEAPON_COMBAT]=6,
[Talents.T_WEAPONS_MASTERY]=6,
[Talents.T_RUSH]=4,
[Talents.T_ENRAGE]=3,
[Talents.T_SUPPRESSION]=4,
[Talents.T_BLINDSIDE]=4,
[Talents.T_GLOOM]=4,
[Talents.T_WEAKNESS]=4,
[Talents.T_TORMENT]=4,
[Talents.T_LIFE_LEECH]=4,
[Talents.T_CHANT_OF_LIGHT]=5,
[Talents.T_SEARING_LIGHT]=5,
[Talents.T_MARTYRDOM]=5,
[Talents.T_BARRIER]=5,
[Talents.T_WEAPON_OF_LIGHT]=5,
[Talents.T_CRUSADE]=8,
[Talents.T_FIREBEAM]=7,
},
resolvers.sustains_at_birth(),
autolevel = "warriormage",
ai = "dumb_talented_simple", ai_state = { talent_in=2, ai_move="move_astar", },
}
......@@ -19,6 +19,8 @@
load("/data/general/objects/objects.lua")
local Stats = require "engine.interface.ActorStats"
-- Artifact, droped (and used!) by Bill the Stone Troll
newEntity{ base = "BASE_GREATMAUL",
......@@ -50,3 +52,24 @@ newEntity{ base = "BASE_SCROLL",
encumberance = 0,
}
end
newEntity{ base = "BASE_SHIELD",
define_as = "SANGUINE_SHIELD",
unided_name = "bloody shield",
name = "Sanguine Shield", unique=true,
desc = [["Though tarnished and spattered with blood, the emblem of the sun still manages to shine through on this shield.]],
require = { stat = { str=39 }, },
cost = 120,
special_combat = {
dam = 40,
physcrit = 9,
dammod = {str=1.2},
},
wielder = {
inc_stats = { [Stats.STAT_CON] = 5, },
fatigue = 19,
resists = { [DamageType.BLIGHT] = 25, },
life_regen = 5,
},
}
......@@ -33,5 +33,8 @@ return {
class = "engine.generator.map.Static",
map = "wilderness/arda-fareast",
},
}
},
on_enter = function()
game.state:goneEast()
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