Files @ eaf92b073787
Branch filter:

Location: games/Awakening/utils.lua

Silverwing
From the ashes
--[[
	Общие утилиты для игр на Instead. Скорее всего будут повторно использоваться в следующих играх, если таковые будут.
]]

--[[
]]
ArrayUtils = {
	indexOf = function(array, item)
		for i = 1, #array do
			if (array[i] == item) then
				return i;
			end;
		end;
		return 0;
	end;
};

--[[
	
]]
PartyUtils = {
	addToParty = function(object)
		if (object.home) then 
			if (ArrayUtils.indexOf(pl.party, object.nam) == 0) then
				move(object, object.home);
				table.insert(pl.party, object.nam);
			end;
		end;
	end;
};

--[[
	functions, design to simplify some typical actions while developing Instead game
]]
EngineUtils = {
	getValue = function(source, param)
		local value = "";
		if (type(source) == "function") then
			value = source(param);
		else
			value = source;
		end;
		
		return value;
	end;
};

--[[
	internal space
]]
_kh = {
	vroom_enter = function(s)  
		local v = EngineUtils.getValue(s.where);
		if (v) then
			walk(v);
		else
			return false;
		end;
	end;
	vroom_save = function(s)
		if need then
			local t = stead.string.format("%s = kh_vroom(%s, %q, %s);\n",
				name, stead.tostring(self.disp), 
					stead.deref(self.where), stead.deref(self.nam));
			h:write(t);
		end
		stead.savemembers(h, self, name,false);
	end;
};

function kh_vway(disp, dsc, target, seen_level)
	local temp = vway(disp, dsc, target);
	temp.seen_level = seen_level;
	return temp;
end;

--[[
	vroom with additional functionality
]]
function kh_vroom(disp, target, seen_level)
	return room {
		nam = disp;
		disp = disp;
		where = target;
		enter = _kh.vroom_enter;
		seen_level = seen_level;
		--enter = _kh.vroom_enter;
		--save = _kh.vroom_save;
	};
end;

obj = inherit(obj, function(v)
	v.disable_implicit = hook(v.disable, function(f, s, ...)
		s._disabled_implicit = true;
		return f(s, unpack(arg));
	end);

	v.disable = hook(v.disable, function(f, s, ...)
		s._disabled_explicit = true;
		return f(s, unpack(arg));
	end);
	
	v.enable_implicit = hook(v.enable, function(f, s, ...)
		s._disabled_implicit = false;
		if (s._disabled_explicit) then
			return s; --mimic original enable() behavior
		else
			return f(s, unpack(arg));
		end;
	end);
	
	v.enable = hook(v.enable, function(f, s, ...)
		s._disabled_explicit = false;
		if (s._disabled_implicit) then
			return s; --mimic original enable() behavior
		else
			return f(s, unpack(arg));
		end;
	end);
	
	return v;
end);

--[[
	character object
	represents character, with whom you can interact
]]
function npc(tab)
	if (not tab.act) then
		tab.act = function(s)
			if (s.dlg) then
				walkin(s.dlg);
			else
				return s.phrases[rnd(#s.phrases)];
			end;
		end;
	end;
	
	return obj(tab);
end;

function darkroom(tab)
	local life;
	local entered;
	local left;
	if (not tab.has_light) then
		tab.has_light = false;
	end;
	if (tab.life) then
		life = tab.life;
	end;
	if (tab.entered) then
		entered = tab.entered;
	end;
	if (tab.left) then
		left = tab.left;
	end;
	tab.entered = function(s)
		lifeon(s);
		if (entered) then
			entered(s);
		end;
	end;
	tab.left = function(s)
		lifeoff(s);
		if (left) then
			left(s);
		end;
	end;
	tab.life = function(s)
		if (s.has_light) then
			-- show all objects that were not explicitly disabled(any seen_level)
			for i = 1, #objs(s) do
				objs(s)[i]:enable_implicit();
			end;
			for i = 1, #ways(s) do
				ways(s)[i]:enable_implicit();
			end;
		elseif (pl.has_light) then
			-- show all objects that were not explicitly disabled and marked as seen in halflight (seen_level = 1 or higher)
			for i = 1, #objs(s) do
				if (type(objs(s)[i].seen_level) == "number" and objs(s)[i].seen_level >= 1) then
					objs(s)[i]:enable_implicit();
				else
					objs(s)[i]:disable_implicit();
				end;
			end;
			for i = 1, #ways(s) do
				if (type(ways(s)[i].seen_level) == "number" and ways(s)[i].seen_level >= 1) then
					ways(s)[i]:enable_implicit();
				else
					ways(s)[i]:disable_implicit();
				end;
			end;
		else
			-- show all objects that were not explicitly disabled and marked as seen in darkness (seen_level = 2 or higher)
			for i = 1, #objs(s) do
				if (type(objs(s)[i].seen_level) == "number" and objs(s)[i].seen_level >= 2) then
					objs(s)[i]:enable_implicit();
				else
					objs(s)[i]:disable_implicit();
				end;
			end;
			for i = 1, #ways(s) do
				if (type(ways(s)[i].seen_level) == "number" and ways(s)[i].seen_level >= 2) then
					ways(s)[i]:enable_implicit();
				else
					ways(s)[i]:disable_implicit();
				end;
			end;
		end;
		
		if (life) then
			life(s);
		end;
	end;
	if (not tab.dsc) then
		tab.dsc = function(s)
			if (s.has_light) then
				return s.dsc_lit;
			elseif (pl.has_light) then
				return s.dsc_halflit;
			else
				return s.dsc_dark;
			end;
		end;
	end;
	
	return room(tab);
end;

--[[
	Создает комнату с полем для ввода числа длиной не более tab.maxlen
	По нажатии enter вызывает метод tab.сheck
	Приглашение для ввода: tab.label
	Вводимый текст: tab.input
]]
function input_number(tab)
	if (not tab.maxlen) then
		tab.maxlen = 2;
	end;
	tab.forcedsc = true;
	tab.noinv = true;
	tab.input = "";
	tab.dsc = function(s)
		pr(tab.label .. tab.input .. "_");
		return false;
		--return tab.label .. tab.input .. "_";
	end;
	tab.entered = function(s)
		s.input = "";
		hook_keys('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'backspace', 'return');
	end;
	tab.left = function(s)
		unhook_keys('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'backspace', 'return');
	end;
	tab.kbd = function(s, down, key)
		if (not down) then
			if (key == "return") then
				if (s.input) then
					s:check(s.input);
				end;
			elseif (key == "backspace") then
				if (s.input:len() > 0) then
					s.input = s.input:sub(1, s.input:len() - 1);
				end;
			else
				if (string.len(s.input) < s.maxlen) then
					s.input = s.input .. key;
					-- hide buttons :)
				end;
			end;
		end;
		pr("");
	end;
	tab.obj = {
		-- TODO add onscreen buttons for symbian users or losers with android 
	};

	return room(tab);
end;

--[[
	Создает obj, который добавляет другой obj на сцену при активации и становится неинтерактивным
	nam - имя объекта
	dsc_a - описание до активации
	dsc_b - описание после активации
	act_a - описание взаимодействия до активации
	act_b - описание взаимодействия после активации
	o2 - obj, добавляемый на сцену
	r - удаляет объект после активации
]]
function obscured_obj(nam, dsc_a, act_a, o2, r, dsc_b, act_b)
	return obj {
		var {
			activated = false;
		};
		nam = nam;
		dsc = function(s)
			if (s.activated) then
				return dsc_b;
			else 
				return dsc_a;
			end;
		end;
		act = function(s)
			if (s.activated) then
				return act_b;
			else
				s.activated = true;
				put(o2, here());
				if (r) then
					remove(r, here());
				end;
				return act_a;
			end;
		end;
	};
end;

_atlantis = {
	suit_menu = dlg {
		nam = "Скафандр";
		_item = nil;
		dsc = [[
			Что вы хотите сделать?
		]];
		phr = {
			{1, always = "true", "Использовать рацию", function(s)
				local val = EngineUtils.getValue(_atlantis.suit_menu._item.dlg, _atlantis.suit_menu._item);
				if (val) then
					walkin(val);
					stead.ref(val).__from__ = _atlantis.suit_menu.__from__;
				else
					back();
					return "Никто не отвечает";
				end;
			end};
			{2, always = "true", "Снять скафандр", function(s)
				if (EngineUtils.getValue(_atlantis.suit_menu._item.cantakeoff, _atlantis.suit_menu._item)) then
					drop(_atlantis.suit_menu._item);
					back();
					return "Вы снимаете скафандр";
				else
					back();
					return "Вы не можете снять скафандр сейчас";
				end;
			end};
			{3, always = "true", "Отмена", function(s)
				back();
				return "";
			end};
		};
	};
	
	suit_inv = function(s)
		_atlantis.suit_menu._item = s;
		walkin(_atlantis.suit_menu);
	end;
};

suit = function(tab)
	if (not tab.inv) then
		tab.inv = _atlantis.suit_inv;
	end;
	
	return obj(tab);
end;