From cbc8161498ebceadb59ba993391594ba330fad16 Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Tue, 15 Dec 2009 17:09:12 +0000
Subject: [PATCH] tidal waves!

git-svn-id: http://svn.net-core.org/repos/t-engine4@126 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engine/Actor.lua                         | 20 ++++++-
 game/engine/Map.lua                           |  2 +-
 game/modules/tome/class/Actor.lua             |  4 +-
 game/modules/tome/data/damage_types.lua       | 24 +++++++++
 .../tome/data/talents/spells/water.lua        | 53 +++++++++++++++++--
 src/core_lua.c                                | 12 ++++-
 6 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index 722248b006..f775c3f900 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -34,8 +34,9 @@ end
 -- @param y coord of the destination
 -- @param force if true do not check for the presence of an other entity. *Use wisely*
 -- @return true if a move was *ATTEMPTED*. This means the actor will proably want to use energy
-function _M:move(map, x, y, force)
+function _M:move(x, y, force)
 	if self.dead then return true end
+	local map = game.level.map
 	if not force and map:checkAllEntities(x, y, "block_move", self) then return true end
 
 	if self.x and self.y then
@@ -85,6 +86,23 @@ function _M:teleportRandom(x, y, dist)
 	return self:move(pos[1], pos[2], true)
 end
 
+--- Knock back the actor
+function _M:knockBack(srcx, srcy, dist)
+	local l = line.new(srcx, srcy, self.x, self.y, true)
+	local lx, ly = l(true)
+	dist = dist - 1
+
+	while game.level.map:isBound(lx, ly) and not game.level.map:checkAllEntities(lx, ly, "block_move") and dist > 0 do
+		dist = dist - 1
+		lx, ly = l(true)
+		print("next step", lx, ly)
+	end
+
+	if game.level.map:isBound(lx, ly) and not game.level.map:checkAllEntities(lx, ly, "block_move") then
+		self:move(lx, ly, true)
+	end
+end
+
 function _M:deleteFromMap(map)
 	if self.x and self.y and map then
 		map:remove(self.x, self.y, engine.Map.ACTOR)
diff --git a/game/engine/Map.lua b/game/engine/Map.lua
index d7e45507d3..ac2268107f 100644
--- a/game/engine/Map.lua
+++ b/game/engine/Map.lua
@@ -431,7 +431,7 @@ function _M:processEffects()
 		-- Now display each grids
 		for lx, ys in pairs(grids) do
 			for ly, _ in pairs(ys) do
-				if e.friendlyfire or (lx ~= e.src.x and ly ~= e.src.y) then
+				if e.friendlyfire or not (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
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 85fb1ff4df..bd6d197f9a 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -84,7 +84,7 @@ function _M:move(x, y, force)
 		if not force and self:attr("prob_travel") and game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self) then
 			moved = self:probabilityTravel(x, y)
 		else
-			moved = engine.Actor.move(self, game.level.map, x, y, force)
+			moved = engine.Actor.move(self, x, y, force)
 		end
 		if not force and moved and not self.did_energy then self:useEnergy() end
 	end
@@ -100,7 +100,7 @@ function _M:probabilityTravel(x, y)
 		ty = ty + diry
 	end
 	if game.level.map:isBound(x, y) then
-		return engine.Actor.move(self, game.level.map, tx, ty, false)
+		return engine.Actor.move(self, tx, ty, false)
 	end
 	return true
 end
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index f4cebca9b1..7860f10d26 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -20,9 +20,11 @@ newDamageType{
 	name = "physical", type = "PHYSICAL",
 }
 
+-- Arcane is basic (usualy) unreistable damage
 newDamageType{
 	name = "arcane", type = "ARCANE",
 }
+-- The four elemental damges
 newDamageType{
 	name = "fire", type = "FIRE",
 }
@@ -35,6 +37,8 @@ newDamageType{
 newDamageType{
 	name = "lightning", type = "LIGHTNING",
 }
+
+-- Light up the room
 newDamageType{
 	name = "light", type = "LIGHT",
 	projector = function(src, x, y, type, dam)
@@ -42,6 +46,7 @@ newDamageType{
 	end,
 }
 
+-- Fire damage + DOT
 newDamageType{
 	name = "fireburn", type = "FIREBURN",
 	projector = function(src, x, y, type, dam)
@@ -54,10 +59,12 @@ newDamageType{
 	end,
 }
 
+-- Irresistible fire damage
 newDamageType{
 	name = "netherflame", type = "NETHERFLAME",
 }
 
+-- Freezes target, chcks for spellresistance
 newDamageType{
 	name = "freeze", type = "FREEZE",
 	projector = function(src, x, y, type, dam)
@@ -76,3 +83,20 @@ newDamageType{
 		end
 	end,
 }
+
+-- Cold damage + repulsion; checks for spell power against physical resistance
+newDamageType{
+	name = "wave", type = "WAVE",
+	projector = function(src, x, y, type, dam)
+		DamageType:get(DamageType.COLD).projector(src, x, y, DamageType.COLD, dam)
+		local target = game.level.map(x, y, Map.ACTOR)
+		if target then
+			if target:checkHit(src:combatSpellpower(), target:combatPhysicalResist(), 0, 95, 15) then
+				target:knockBack(src.x, src.y, 1)
+				game.logSeen(target, "%s is knocked back!", target.name:capitalize())
+			else
+				game.logSeen(target, "%s resists the wave!", target.name:capitalize())
+			end
+		end
+	end,
+}
diff --git a/game/modules/tome/data/talents/spells/water.lua b/game/modules/tome/data/talents/spells/water.lua
index a2b6540f57..94a2da14c5 100644
--- a/game/modules/tome/data/talents/spells/water.lua
+++ b/game/modules/tome/data/talents/spells/water.lua
@@ -1,3 +1,17 @@
+newTalent{
+	name = "Ent-draught",
+	type = {"spell/water", 1},
+	mana = 10,
+	cooldown = 100,
+	action = function(self)
+		return true
+	end,
+	require = { stat = { mag=10 }, },
+	info = function(self)
+		return ([[Confures some Ent-draught to fill your stomach.]])
+	end,
+}
+
 newTalent{
 	name = "Freeze",
 	type = {"spell/water", 1},
@@ -22,9 +36,42 @@ newTalent{
 }
 
 newTalent{
-	name = "Ice Storm",
+	name = "Tidal Wave",
 	type = {"spell/water",2},
-	mana = 45,
+	mana = 55,
+	cooldown = 8,
+	tactical = {
+		ATTACKAREA = 10,
+	},
+	action = function(self)
+		local duration = 5 + self:combatSpellpower(0.05)
+		local radius = 1
+		local dam = 1--12 + self:combatSpellpower(0.20)
+		-- Add a lasting map effect
+		game.level.map:addEffect(self,
+			self.x, self.y, duration,
+			DamageType.WAVE, dam,
+			radius,
+			5, nil,
+			engine.Entity.new{alpha=100, display='', color_br=30, color_bg=60, color_bb=200},
+			function(e)
+				e.radius = e.radius + 1
+			end,
+			false
+		)
+		return true
+	end,
+	require = { stat = { mag=34 }, level=25 },
+	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,
+}
+
+newTalent{
+	name = "Ice Storm",
+	type = {"spell/water",4},
+	mana = 100,
 	cooldown = 30,
 	tactical = {
 		ATTACKAREA = 20,
@@ -48,7 +95,7 @@ newTalent{
 		)
 		return true
 	end,
-	require = { stat = { mag=16 }, },
+	require = { stat = { mag=34 }, level=25 },
 	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))
diff --git a/src/core_lua.c b/src/core_lua.c
index 6d20501d6d..632a948d39 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -792,6 +792,7 @@ static int lua_line_init(lua_State *L)
 	int yFrom = luaL_checknumber(L, 2);
 	int xTo = luaL_checknumber(L, 3);
 	int yTo = luaL_checknumber(L, 4);
+	bool start_at_end = lua_toboolean(L, 5);
 
 	line_data *data = (line_data*)lua_newuserdata(L, sizeof(line_data));
 	auxiliar_setclass(L, "line{core}", -1);
@@ -822,15 +823,22 @@ static int lua_line_init(lua_State *L)
 		data->deltay *= 2;
 	}
 
+	if (start_at_end)
+	{
+		data->origx=xTo;
+		data->origy=yTo;
+	}
+
 	return 1;
 }
 
 static int lua_line_step(lua_State *L)
 {
 	line_data *data = (line_data*)auxiliar_checkclass(L, "line{core}", 1);
+	bool dont_stop_at_end = lua_toboolean(L, 2);
 
 	if ( data->stepx*data->deltax > data->stepy*data->deltay ) {
-		if ( data->origx == data->destx ) return 0;
+		if (!dont_stop_at_end && data->origx == data->destx ) return 0;
 		data->origx+=data->stepx;
 		data->e -= data->stepy*data->deltay;
 		if ( data->e < 0) {
@@ -838,7 +846,7 @@ static int lua_line_step(lua_State *L)
 			data->e+=data->stepx*data->deltax;
 		}
 	} else {
-		if ( data->origy == data->desty ) return 0;
+		if (!dont_stop_at_end && data->origy == data->desty ) return 0;
 		data->origy+=data->stepy;
 		data->e -= data->stepx*data->deltax;
 		if ( data->e < 0) {
-- 
GitLab