diff --git a/game/engines/default/engine/Map.lua b/game/engines/default/engine/Map.lua index 74f64bcc3d2542babd3f7254fad08a3d5dc8438a..0655da93d2a8d89766f8ea06ca7f198a99ed91e6 100644 --- a/game/engines/default/engine/Map.lua +++ b/game/engines/default/engine/Map.lua @@ -1112,7 +1112,7 @@ function _M:displayParticles(nb_keyframes) e = next(self.particles, e) end - for i = 1, #del do self.particles[del[i]] = nil end + for i = 1, #del do self.particles[del[i]] = nil if del[i].on_remove then del[i]:on_remove() end end end ------------------------------------------------------------- diff --git a/game/engines/default/engine/UserChat.lua b/game/engines/default/engine/UserChat.lua index d079361587903f35b21f92360682d9be2135c151..255673ea097988f9250d7ee37e5d141ad6f7b072 100644 --- a/game/engines/default/engine/UserChat.lua +++ b/game/engines/default/engine/UserChat.lua @@ -419,10 +419,6 @@ function _M:mouseEvent(button, x, y, xrel, yrel, bx, by, event) local item = self.dlist[i] if item.dh and by >= item.dh - self.mouse.delegate_offset_y then citem = self.dlist[i].src ci=i break end end - for i = 1, #self.dlist do - local item = self.dlist[i] - if item.dh then print("===", y, by, item.dh - self.mouse.delegate_offset_y, ci==i and "*****" or "") end - end self.on_mouse(citem and citem.login and self.channels[self.cur_channel].users[citem.login], citem and citem.login and citem, button, event, x, y, xrel, yrel, bx, by) end end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index dd95edff7d4d5c793262764ff524ffa271b6a490..d1148ab955ecfaae9672275e5df7f51d51cc96f3 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -1207,10 +1207,11 @@ function _M:setupCommands() end end, [{"_g","ctrl"}] = function() if config.settings.cheat then -- self:registerDialog(require("mod.dialogs.DownloadCharball").new()) - local f, err = loadfile("/data/general/events/old-battle-field.lua") + local f, err = loadfile("/data/general/events/meteor.lua") print(f, err) setfenv(f, setmetatable({level=self.level, zone=self.zone}, {__index=_G})) print(pcall(f)) + end end, [{"_f","ctrl"}] = function() if config.settings.cheat then self.player.quests["love-melinda"] = nil diff --git a/game/modules/tome/class/uiset/Minimalist.lua b/game/modules/tome/class/uiset/Minimalist.lua index ef749f4ba5fab368fd3d0c441fbf60b0e9110654..bd00e18f9ff1516fde1de2c5ed21c20ccf28404b 100644 --- a/game/modules/tome/class/uiset/Minimalist.lua +++ b/game/modules/tome/class/uiset/Minimalist.lua @@ -1802,7 +1802,6 @@ function _M:setupMouse(mouse) -- Chat tooltips profile.chat:onMouse(function(user, item, button, event, x, y, xrel, yrel, bx, by) local mx, my = core.mouse.get() - print(">>??", item, user, item and item.faded) if not item or not user or item.faded == 0 then game.mouse:delegate(button, mx, my, xrel, yrel, nil, nil, event, "playmap") return end local str = tstring{{"color","GOLD"}, {"font","bold"}, user.name, {"color","LAST"}, {"font","normal"}, true} diff --git a/game/modules/tome/data/general/events/groups/outdoor-fareast-generic.lua b/game/modules/tome/data/general/events/groups/outdoor-fareast-generic.lua new file mode 100644 index 0000000000000000000000000000000000000000..c9765aa8b27b2fe4799d5c1dad16a8b172d3453b --- /dev/null +++ b/game/modules/tome/data/general/events/groups/outdoor-fareast-generic.lua @@ -0,0 +1,22 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011, 2012 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 { + {name="meteor", percent=7}, +} diff --git a/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua b/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua index a8465c86a4ad2e8e97a69b02b8076c530f52998d..6d4fe32e0a8d15889fd9aa15dd847fc9eb979f9c 100644 --- a/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua +++ b/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua @@ -20,4 +20,5 @@ return { {name="damp-cave", percent=10}, {name="drake-cave", percent=5}, + {name="meteor", percent=7}, } diff --git a/game/modules/tome/data/general/events/meteor.lua b/game/modules/tome/data/general/events/meteor.lua new file mode 100644 index 0000000000000000000000000000000000000000..c1893ba08b4f6d9655afcd486914e12972ebabd3 --- /dev/null +++ b/game/modules/tome/data/general/events/meteor.lua @@ -0,0 +1,91 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011, 2012 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 function canEventGrid(level,x,y) return not level.map.attrs(x, y, "no_teleport") and not level.map:checkAllEntities("change_level") end + +local function check(x, y) + local list = {} + for i = -2, 2 do for j = -2, 2 do + if not canEventGrid(level, x+i, y+j) then return false end + list[#list+1] = {x=x+i, y=y+j} + end end + if not game.state:canEventGrid(level, x, y) then return false end -- Check the center is also accessible + + if #list < 5 then return false + else return list end +end + +local x, y = rng.range(3, level.map.w - 4), rng.range(3, level.map.h - 4) +local tries = 0 +while not check(x, y) and tries < 100 do + x, y = rng.range(3, level.map.w - 4), rng.range(3, level.map.h - 4) + tries = tries + 1 +end +if tries >= 100 then return false end + +level.data.meteor_x = x +level.data.meteor_y = y + +game.zone.meteor_event_levels = game.zone.meteor_event_levels or {} +game.zone.meteor_event_levels[level.level] = true + +if not game.zone.meteor_event_on_turn then game.zone.meteor_event_on_turn = game.zone.on_turn or function() end end +game.zone.on_turn = function() + if game.zone.meteor_event_on_turn then game.zone.meteor_event_on_turn() end + + if game.turn % 10 ~= 0 or not game.zone.meteor_event_levels[game.level.level] then return end + + local p = game:getPlayer(true) + if core.fov.distance(p.x, p.y, game.level.data.meteor_x, game.level.data.meteor_y) > 3 then return end + + game.zone.meteor_event_levels[game.level.level] = nil + + game.level.map:particleEmitter(game.level.data.meteor_x, game.level.data.meteor_y, 10, "meteor").on_remove = function() + local x, y = game.level.data.meteor_x, game.level.data.meteor_y + game.level.map:particleEmitter(x, y, 10, "ball_fire", {radius=5}) + game:playSoundNear(game.player, "talents/fireflash") + + local terrains = mod.class.Grid:loadList("/data/general/grids/lava.lua") + local npcs = mod.class.NPC:loadList("/data/general/npcs/losgoroth.lua") + + for i = x-2, x+2 do for j = y-2, y+2 do + if core.fov.distance(x, y, i, j) <= 1 or rng.percent(40) then + local g = terrains.LAVA_FLOOR:clone() + g:resolve() g:resolve(nil, true) + game.zone:addEntity(game.level, g, "terrain", i, j) + + if rng.percent(30) and not game.level.map(i, j, engine.Map.ACTOR) then + local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true) + if m then + m.resists = m.resists or {} + m.resists[engine.DamageType.FIRE] = 100 + game.zone:addEntity(game.level, m, "actor", i, j) + end + end + end + end end + for i = x-2, x+2 do for j = y-2, y+2 do + game.nicer_tiles:updateAround(game.level, i, j) + end end + + require("engine.ui.Dialog"):simplePopup("Meteor!", "As you walk you notice a huge rock falling from the sky, it crashes right near you!") + end +end + +return true diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua index 834da5633fb5350c643a5b2a380821a76f031960..ee35842b9c61f9e38dacf864de9be33094035891 100644 --- a/game/modules/tome/data/talents/misc/npcs.lua +++ b/game/modules/tome/data/talents/misc/npcs.lua @@ -1700,7 +1700,6 @@ newTalent{ end, } - newTalent{ name = "Frost Hands", image = "talents/shock_hands.png", type = {"spell/other", 3}, @@ -1731,3 +1730,78 @@ newTalent{ format(damDesc(self, DamageType.COLD, icedamage), icedamageinc, self:getTalentLevel(t) / 3) end, } + +newTalent{ + name = "Meteor Rain", + type = {"spell/other", 3}, + points = 5, + cooldown = 30, + mana = 70, + tactical = { ATTACKAREA = { FIRE=2, PHYSICAL=2 } }, + getDamage = function(self, t) return self:combatTalentSpellDamage(t, 15, 250) end, + getNb = function(self, t) return 3 + math.floor(self:getTalentLevel(t) / 3) end, + radius = 2, + range = 5, + target = function(self, t) return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false, talent=t} end, + action = function(self, t) + local tg = self:getTalentTarget(t) + local x, y = self:getTarget(tg) + if not x or not y then return nil end + + local terrains = mod.class.Grid:loadList("/data/general/grids/lava.lua") + local meteor = function(src, x, y, dam) + game.level.map:particleEmitter(x, y, 10, "meteor", {x=x, y=y}).on_remove = function(self) + local x, y = self.args.x, self.args.y + game.level.map:particleEmitter(x, y, 10, "ball_fire", {radius=2}) + game:playSoundNear(game.player, "talents/fireflash") + + for i = x-1, x+1 do for j = y-1, y+1 do + if (core.fov.distance(x, y, i, j) < 1 or rng.percent(40)) and (game.level.map:checkEntity(i, j, engine.Map.TERRAIN, "dig") or game.level.map:checkEntity(i, j, engine.Map.TERRAIN, "grow")) then + local g = terrains.LAVA_FLOOR:clone() + g:resolve() g:resolve(nil, true) + g.temporary = 8 + g.x = i g.y = j + g.canAct = false + g.energy = { value = 0, mod = 1 } + g.old_feat = game.level.map(i, j, engine.Map.TERRAIN) + g.useEnergy = mod.class.Trap.useEnergy + g.act = function(self) + self:useEnergy() + self.temporary = self.temporary - 1 + if self.temporary <= 0 then + game.level.map(self.x, self.y, engine.Map.TERRAIN, self.old_feat) + game.level:removeEntity(self) + game.nicer_tiles:updateAround(game.level, self.x, self.y) + end + end + game.zone:addEntity(game.level, g, "terrain", i, j) + game.level:addEntity(g) + end + end end + for i = x-1, x+1 do for j = y-1, y+1 do + game.nicer_tiles:updateAround(game.level, i, j) + end end + + src:project({type="ball", radius=2, selffire=src:spellFriendlyFire()}, x, y, engine.DamageType.FIRE, dam/2) + src:project({type="ball", radius=2, selffire=src:spellFriendlyFire()}, x, y, engine.DamageType.PHYSICAL, dam/2) + end + end + + local grids = {} + self:project(tg, x, y, function(px, py) grids[#grids+1] = {x=px, y=py} end) + + for i = 1, t.getNb(self, t) do + local g = rng.tableRemove(grids) + meteor(self, g.x, g.y, t.getDamage(self, t)) + end + + return true + end, + info = function(self, t) + local dam = t.getDamage(self, t) + return ([[Uses arcane forces to summon %d meteors that fall on the ground, smashing all around in a radius 2 for %0.2f fire and %0.2f physical damage. + The hit zone will also turn into lava for 8 turns. + The effects will increase with your Spellpower.]]): + format(t.getNb(self, t), damDesc(self, DamageType.FIRE, dam), damDesc(self, DamageType.PHYSICAL, dam)) + end, +} diff --git a/game/modules/tome/data/zones/eruan/events.lua b/game/modules/tome/data/zones/eruan/events.lua index 4454fe11bf13bbad0dd058b33d1345a8a88b62f6..24b629160cf9ab1a9c80f00f5a815a823cdf1ac8 100644 --- a/game/modules/tome/data/zones/eruan/events.lua +++ b/game/modules/tome/data/zones/eruan/events.lua @@ -19,4 +19,5 @@ return { one_per_level=true, {group="fareast-generic", percent_factor=1.5}, + {group="outdoor-fareast-generic", percent_factor=1.5}, } diff --git a/ideas/class-uber-points.ods b/ideas/class-uber-points.ods index 19adfa748048b570f0c273fc7edb2ae82a08d9c3..76ea4e38a5dd22aef70588910d37aa759271500e 100644 Binary files a/ideas/class-uber-points.ods and b/ideas/class-uber-points.ods differ diff --git a/ideas/events b/ideas/events index de7f09a4f2d5ba2756dbd44848ddda2fedab2c8b..bb92a7ef938b56308a270f5c7673b6a735ca16dd 100644 --- a/ideas/events +++ b/ideas/events @@ -1,12 +1,15 @@ ++ fearscape invasion portal: demons pouring out: enter the demon gate; end up in orbit on a fearscape bit of land floating in space and destroy the master demon there ++ naga invasion portal: nagas pouring out: enter the water portal; end up in a water cave (provide air bubbles) and defeat the naga leader ++ 3 pedesrals, stay on each for 3 turns; each time a rare pops; when all 3 dead a portal pops and a randboss pops from it -* 7 neutral cultists are spread on the level with a back stone nearby; when one is killed a timer starts, if all killed before timer is out a stair to a secret cave is revealed with an artifact inside ++ a few tombstones that can be interraced with; if disturbed a random undead (rare or randboss) may pop ++ old battle field: many tombs in close space, if disturbed the player falls into the ground into a small cave; for 100 turns undeads pop faster and faster, if survived a pile of treasure is generated ++ damp cave: filled with thieves & bandits with some rares; uses building generator; hosts a pile of gems +++ drake "nest", a few hatclings around a stair; inside is a cave with wyrms +++ hole in the ground with rats around it, inside are undead rats with their boss the ratlich +++ level wide thunderstorm, reducing sight/lite/.. range by half; making the level dark; random lighting strike the ground, sometimes poping an elemental +++ a huge meteor falls near the player, destroying anything and poping losgoroths +* 7 neutral cultists are spread on the level with a back stone nearby; when one is killed a timer starts, if all killed before timer is out a stair to a secret cave is revealed with an artifact inside * a necromancer starts on the other side of the level (not on boss levels); kills npcs, when enough killed he makes a huge bone golem rare -* a huge meteor falls near the player, destroying anything and poping losgoroths * zone appropriate battle fields: yeachs vs. yeeks; zigur vs corrupters, ... * abandonned sher'tul ruin, full of horrors; sometimes a half working farportal (requires the orb to use, not an exploratory one) which connects to somewhere * crystalized forest: only in forests; take a groove and replace trees with crystals, when entered crytals npcs keep poping up from the walls @@ -14,8 +17,5 @@ * sismic danger: paches of lava & volcanos have poped in the level, someimes fire elementals errupt from it * space fissure: enter it and you get in a temporal mess, with paradox mages & temporal wardens fighting an ever growing number of gwel/telugoroths; after X turns they are saved and give you a reward; or you are all dead * abandonned alchemist camp: inactive golems & gems; when picking up gems tthe golems all awaken -++ drake "nest", a few hatclings around a stair; inside is a cave with wyrms * worldmap: a "town", full of normal npcs, but hey all have a hidden diease, after X turns tthey turn into ghouls and all come on the player -++ hole in the ground with rats around it, inside are undead rats with their boss the ratlich * elven tomb, with mummies -++ level wide thunderstorm, reducing sight/lite/.. range by half; making the level dark; random lighting strike the ground, sometimes poping an elemental