From f8e6733038d13dedc125b95e60fd5a4f66b1a0f5 Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Mon, 23 Nov 2009 21:34:54 +0000
Subject: [PATCH] health, ... unicode to utf8 conversion to get correct key
 presses in Key handlers

git-svn-id: http://svn.net-core.org/repos/t-engine4@22 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engine/Actor.lua                         | 12 ++++++++-
 game/engine/KeyCommand.lua                    | 26 +++++++++++++-----
 game/engine/interface/ActorLevel.lua          |  6 +++--
 game/engine/interface/ActorLife.lua           |  9 +++++++
 game/modules/tome/class/Actor.lua             | 11 +++++---
 game/modules/tome/class/Game.lua              | 24 ++++++++++++++---
 .../tome/data/zones/ancient_ruins/grids.lua   |  2 ++
 .../tome/data/zones/ancient_ruins/npcs.lua    |  4 +--
 .../tome/data/zones/ancient_ruins/zone.lua    |  1 +
 src/main.c                                    | 27 ++++++++++++++++++-
 10 files changed, 102 insertions(+), 20 deletions(-)

diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index 1013524301..37d2c82c8a 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -31,7 +31,17 @@ function _M:move(map, x, y, force)
 end
 
 function _M:deleteFromMap(map)
-	if self.x and self.y and game.level and game.level.map then
+	if self.x and self.y and map then
 		map:remove(self.x, self.y, engine.Map.ACTOR)
 	end
 end
+
+function _M:enoughEnergy(val)
+	val = val or game.energy_to_act
+	return self.energy.value >= val
+end
+
+function _M:useEnergy(val)
+	val = val or game.energy_to_act
+	self.energy.value = self.energy.value - val
+end
diff --git a/game/engine/KeyCommand.lua b/game/engine/KeyCommand.lua
index 188a5a45db..565fcdfc8a 100644
--- a/game/engine/KeyCommand.lua
+++ b/game/engine/KeyCommand.lua
@@ -11,7 +11,7 @@ end
 
 function _M:receiveKey(sym, ctrl, shift, alt, meta, unicode)
 	if not self.commands[sym] then return end
-	if ctrl or shift or alt or meta then
+	if (ctrl or shift or alt or meta) and not self.commands[sym].anymod then
 		local mods = {}
 		if alt then mods[#mods+1] = "alt" end
 		if ctrl then mods[#mods+1] = "ctrl" end
@@ -30,7 +30,7 @@ end
 -- @param sym the key to handle
 -- @param mods a table with the mod keys needed, i.e: {"ctrl", "alt"}
 -- @param fct the function to call when the key is pressed
-function _M:addCommand(sym, mods, fct)
+function _M:addCommand(sym, mods, fct, anymod)
 	if type(sym) == "string" then sym = self[sym] end
 	if not sym then return end
 
@@ -41,6 +41,7 @@ function _M:addCommand(sym, mods, fct)
 		table.sort(mods)
 		self.commands[sym][table.concat(mods,',')] = fct
 	end
+	if anymod then self.commands[sym].anymod = true end
 end
 
 --- Adds many key/command at once
@@ -57,12 +58,23 @@ end
 -- }
 
 function _M:addCommands(t)
+	local aliases = {}
 	for k, e in pairs(t) do
-		if type(k) == "string" then
-			self:addCommand(k, e)
-		elseif type(k) == "table" then
-			local sym = table.remove(k, 1)
-			self:addCommand(sym, k, e)
+		if type(e) == "function" then
+			if type(k) == "string" then
+				self:addCommand(k, e)
+			elseif type(k) == "table" then
+				local sym = table.remove(k, 1)
+				local anymod = false
+				if k[1] == "anymod" then k, e, anymod = e, nil, true end
+				self:addCommand(sym, k, e, anymod)
+			end
+		elseif e[1] == "alias" then
+			aliases[#aliases+1] = {k, e[2]}
 		end
 	end
+
+	for i, alias in ipairs(aliases) do
+		self:addCommands{[alias[1]] = self.commands[self[alias[2]]].plain}
+	end
 end
diff --git a/game/engine/interface/ActorLevel.lua b/game/engine/interface/ActorLevel.lua
index 92ba9d5df9..75397eae7e 100644
--- a/game/engine/interface/ActorLevel.lua
+++ b/game/engine/interface/ActorLevel.lua
@@ -29,6 +29,9 @@ function _M:defineExperienceChart(chart)
 	self.exp_chart = chart
 end
 
+--- Get the exp needed for the given level
+-- @param level the level to check exp for
+-- @return the exp needed, or nil if this level is not achievable
 function _M:getExpChart(level)
 	if type(self.exp_chart) == "table" then
 		return self.exp_chart[level]
@@ -40,12 +43,10 @@ end
 --- Gains some experience
 -- If a levelup happens it calls self:levelup(), modules are encourraged to rewrite it to do whatever is needed.
 function _M:gainExp(value)
-	print("gain exp",self.exp,"+",value)
 	self.exp = self.exp + value
 	while self:getExpChart(self.level + 1) and self.exp >= self:getExpChart(self.level + 1) do
 		self.level = self.level + 1
 		self.exp = self.exp - self:getExpChart(self.level)
-		print("levelup", self.level, self.exp)
 		self:levelup()
 	end
 end
@@ -56,5 +57,6 @@ function _M:worthExp()
 	return self.level * self.exp_worth
 end
 
+--- Method called when leveing up, module author rewrite it to do as you please
 function _M:levelup()
 end
diff --git a/game/engine/interface/ActorLife.lua b/game/engine/interface/ActorLife.lua
index 0fa7d2eb7a..95e6fc332f 100644
--- a/game/engine/interface/ActorLife.lua
+++ b/game/engine/interface/ActorLife.lua
@@ -1,11 +1,15 @@
 require "engine.class"
 
+--- Handles actors life and death
 module(..., package.seeall, class.make)
 
 function _M:init(t)
 	self.life = t.life or 100
 end
 
+--- Checks if something bumps in us
+-- If it happens the method attack is called on the target with the attacker as parameter.
+-- Do not touch!
 function _M:block_move(x, y, e)
 	-- Dont bump yourself!
 	if e and e ~= self then
@@ -14,6 +18,8 @@ function _M:block_move(x, y, e)
 	return true
 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)
 	self.life = self.life - value
 	if self.life <= 0 then
@@ -23,6 +29,9 @@ function _M:takeHit(value, src)
 	end
 end
 
+--- Actor is being attacked!
+-- Module authors should rewrite it to handle combat, dialog, ...
+-- @param target the actor attacking us
 function _M:attack(target)
 	game.logSeen(target, "%s attacks %s.", self.name:capitalize(), target.name:capitalize())
 	target:takeHit(10, self)
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 4c98adecea..80092ffcc0 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -13,19 +13,24 @@ end
 
 function _M:move(x, y, force)
 	local moved = false
-	if force or self.energy.value >= game.energy_to_act then
+	if force or self:enoughEnergy() then
 		moved = engine.Actor.move(self, game.level.map, x, y, force)
-		if not force then self.energy.value = self.energy.value - game.energy_to_act end
+		if not force then self:useEnergy() end
 	end
 	return moved
 end
 
 function _M:tooltip()
-	return self.name.."\n#ff0000#HP: "..self.life
+	return ("%s\n#00ffff#Level: %d\nExp: %d/%d\n#ff0000#HP: %d"):format(self.name, self.level, self.exp, self:getExpChart(self.level+1) or "---", self.life)
 end
 
 function _M:die(src)
+	-- Gives the killer some exp for the kill
 	if src then
 		src:gainExp(self:worthExp())
 	end
 end
+
+function _M:levelup()
+
+end
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 7ce7882f38..d822011de6 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -31,16 +31,21 @@ function _M:run()
 	self.log("Welcome to #00FF00#Tales of Middle Earth!")
 	self.logSeen = function(e, ...) if e and self.level.map.seens(e.x, e.y) then self.log(...) end end
 
-	self.zone:getLevel(self, 1)
-
 	self.player = Player.new{name="player", image='player.png', display='@', color_r=230, color_g=230, color_b=230}
-	self.player:move(self.level.start.x, self.level.start.y, true)
-	self.level:addEntity(self.player)
+
+	self:changeLevel(1)
 
 	-- Ok everything is good to go, activate the game in the engine!
 	self:setCurrent()
 end
 
+function _M:changeLevel(lev)
+	self.zone:getLevel(self, lev)
+	self.player:move(self.level.start.x, self.level.start.y, true)
+	self.level:addEntity(self.player)
+end
+
+
 function _M:tick()
 	engine.GameTurnBased.tick(self)
 end
@@ -137,6 +142,17 @@ function _M:setupCommands()
 				self.paused = false
 			end
 		end,
+		[{"_LESS","anymod"}] = function()
+			local e = self.level.map(self.player.x, self.player.y, Map.TERRAIN)
+			if self.player:enoughEnergy() and e.change_level then
+				-- Do not unpause, the player is allowed first move on next level
+				self:changeLevel(self.level.level + e.change_level)
+				print(self.level.level)
+			else
+				self.log("There is no way out of this level here.")
+			end
+		end,
+		_GREATER = {"alias", "_LESS"},
 	}
 	self.key:setCurrent()
 end
diff --git a/game/modules/tome/data/zones/ancient_ruins/grids.lua b/game/modules/tome/data/zones/ancient_ruins/grids.lua
index 4defc1458b..9e09dda1b8 100644
--- a/game/modules/tome/data/zones/ancient_ruins/grids.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/grids.lua
@@ -4,11 +4,13 @@ return {
 	define_as = "UP",
 	name = "previous level",
 	display = '<', color_r=255, color_g=255, color_b=0,
+	change_level = -1
 },
 {
 	define_as = "DOWN",
 	name = "next level",
 	display = '>', color_r=255, color_g=255, color_b=0,
+	change_level = 1
 },
 {
 	define_as = "FLOOR",
diff --git a/game/modules/tome/data/zones/ancient_ruins/npcs.lua b/game/modules/tome/data/zones/ancient_ruins/npcs.lua
index 7fd8183206..77e7f4464e 100644
--- a/game/modules/tome/data/zones/ancient_ruins/npcs.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/npcs.lua
@@ -3,7 +3,7 @@ return {
 {
 	name = "dragon of death",
 	display = "D", color_r=255,
-	level = 1, exp_worth = 20,
+	level = 1, exp_worth = 1,
 	life = 20,
 	mana = 1000,
 	energy = { mod=0.8 },
@@ -11,7 +11,7 @@ return {
 {
 	name = "baby dragon",
 	display = "d", color_r=128,
-	level = 1, exp_worth = 10,
+	level = 1, exp_worth = 1,
 	life = 30,
 	mana = 1000,
 	energy = { mod=0.3 },
diff --git a/game/modules/tome/data/zones/ancient_ruins/zone.lua b/game/modules/tome/data/zones/ancient_ruins/zone.lua
index 27bc2ee98d..716a0e70c5 100644
--- a/game/modules/tome/data/zones/ancient_ruins/zone.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/zone.lua
@@ -4,6 +4,7 @@ return {
 	width = 50, height = 30,
 	all_remembered = true,
 	all_lited = true,
+	level_npcs = {5, 10},
 	generator =  {
 		map = {
 			class= "engine.generator.map.Empty",
diff --git a/src/main.c b/src/main.c
index d4a5ff5a6b..c55d531872 100644
--- a/src/main.c
+++ b/src/main.c
@@ -51,7 +51,32 @@ void on_event(SGEGAMESTATE *state, SDL_Event *event)
 			lua_pushboolean(L, (event->key.keysym.mod & KMOD_SHIFT) ? TRUE : FALSE);
 			lua_pushboolean(L, (event->key.keysym.mod & KMOD_ALT) ? TRUE : FALSE);
 			lua_pushboolean(L, (event->key.keysym.mod & KMOD_META) ? TRUE : FALSE);
-			lua_pushnumber(L, event->key.keysym.unicode);
+			/* Convert unicode UCS-2 to UTF8 string */
+			if (event->key.keysym.unicode)
+			{
+				wchar_t wc = event->key.keysym.unicode;
+
+				char buf[4] = {0,0,0,0};
+				if (wc < 0x80)
+				{
+					buf[0] = wc;
+				}
+				else if (wc < 0x800)
+				{
+					buf[0] = (0xC0 | wc>>6);
+					buf[1] = (0x80 | wc & 0x3F);
+				}
+				else
+				{
+					buf[0] = (0xE0 | wc>>12);
+					buf[1] = (0x80 | wc>>6 & 0x3F);
+					buf[2] = (0x80 | wc & 0x3F);
+				}
+
+				lua_pushstring(L, buf);
+			}
+			else
+				lua_pushnil(L);
 			lua_call(L, 7, 0);
 		}
 		break;
-- 
GitLab