docs
This commit is contained in:
parent
658c28538a
commit
53701da01c
|
@ -157,27 +157,27 @@ If the attribute or handler is laid out as a function, then the first argument o
|
|||
If you know lua, you can simplify:
|
||||
<code>
|
||||
function sw(v, a, b)
|
||||
if v then
|
||||
return a;
|
||||
end
|
||||
return b
|
||||
if v then
|
||||
return a;
|
||||
end
|
||||
return b
|
||||
end
|
||||
|
||||
aple = obj {
|
||||
nam = function(s)
|
||||
return sw(not s._seen, 'unknown','apple');
|
||||
end,
|
||||
dsc = function(s)
|
||||
return sw(not s._seen,'There is {something} on the table.', 'There is an {apple} on the table.');
|
||||
end,
|
||||
act = function(s)
|
||||
if s._seen then
|
||||
return 'It\'s an apple!';
|
||||
else
|
||||
s._seen = true;
|
||||
return 'Hm... But it\'s an apple!';
|
||||
end
|
||||
end,
|
||||
nam = function(s)
|
||||
return sw(not s._seen, 'unknown','apple');
|
||||
end,
|
||||
dsc = function(s)
|
||||
return sw(not s._seen,'There is {something} on the table.', 'There is an {apple} on the table.');
|
||||
end,
|
||||
act = function(s)
|
||||
if s._seen then
|
||||
return 'It\'s an apple!';
|
||||
else
|
||||
s._seen = true;
|
||||
return 'Hm... But it\'s an apple!';
|
||||
end
|
||||
end,
|
||||
};
|
||||
</code>
|
||||
And then always use “sw” or some other auxiliary function.
|
||||
|
@ -189,7 +189,7 @@ Warning!!! The variables outside any of the following object types: room, object
|
|||
From version 0.8.9 you can define a function “isForSave(k)”, which is called to determine whether to save a variable to a savegame file. By default it is defined this way:
|
||||
<code>
|
||||
function isForSave(k)
|
||||
return string.find(k, '_') == 1 or string.match(k,'^%u')
|
||||
return string.find(k, '_') == 1 or string.match(k,'^%u')
|
||||
end
|
||||
</code>
|
||||
|
||||
|
@ -198,20 +198,20 @@ There are two extra parameters for isForSave() (for instead versions > 1.0.0). v
|
|||
Sometimes we need a handler that would do something without showing any description, e.g.:
|
||||
<code>
|
||||
button = obj {
|
||||
nam = "button",
|
||||
dsc = "There is a big red {button} on the room wall.",
|
||||
act = function (s)
|
||||
here()._dynamic_dsc = [[The room transformed after I pressed the button.
|
||||
The book-case disappeared along with the table and the chest, and a strange
|
||||
looking device took its place.]];
|
||||
return true;
|
||||
end,
|
||||
nam = "button",
|
||||
dsc = "There is a big red {button} on the room wall.",
|
||||
act = function (s)
|
||||
here()._dynamic_dsc = [[The room transformed after I pressed the button.
|
||||
The book-case disappeared along with the table and the chest, and a strange
|
||||
looking device took its place.]];
|
||||
return true;
|
||||
end,
|
||||
}
|
||||
r12 = room {
|
||||
nam = 'room',
|
||||
_dynamic_dsc = 'I am in the room.',
|
||||
dsc = function (s) return s._dynamic_dsc end,
|
||||
obj = {'button'}
|
||||
nam = 'room',
|
||||
_dynamic_dsc = 'I am in the room.',
|
||||
dsc = function (s) return s._dynamic_dsc end,
|
||||
obj = {'button'}
|
||||
}
|
||||
</code>
|
||||
In this case ''act'' handler is used to change room description but it is not supposed to add any description of its own. To achieve this we need to return true from the handler. It means the action is done successfully but does not require to diplay any additional description.
|
||||
|
@ -271,7 +271,7 @@ room2 = room {
|
|||
};
|
||||
</code>
|
||||
|
||||
“exit” and “enter” may be functions. Then the first parameter is the object itself (as usual) and the second parameter is a reference to the room where the player is heading (for “exit”) or which he is leaving (for “enter”). For example:
|
||||
“exit” and “enter” may be functions. Then the first parameter is the object itself (as usual) and the second parameter is a reference to the room where the player is heading (for “exit”) or which he is leaving (for “enter”). For example:
|
||||
<code>
|
||||
room2 = room {
|
||||
enter = function(s, f)
|
||||
|
@ -325,7 +325,7 @@ knife = obj {
|
|||
inv = 'Sharp!',
|
||||
tak = 'I took the knife!',
|
||||
use = function(s, w)
|
||||
if w ~= 'tabl'
|
||||
if w ~= 'tabl' then
|
||||
return 'I don\'t want to cut this.', false
|
||||
else
|
||||
return 'You incise your initials on the table.';
|
||||
|
@ -340,9 +340,9 @@ You can use the knife only on the table.
|
|||
In STEAD the player is represented by the object “pl”. The object type is “player”. In the engine it's created thie way:
|
||||
<code>
|
||||
pl = player {
|
||||
nam = "Incognito",
|
||||
where = 'main',
|
||||
obj = { }
|
||||
nam = "Incognito",
|
||||
where = 'main',
|
||||
obj = { }
|
||||
};
|
||||
</code>
|
||||
The “obj” attribute represents the player's inventory.
|
||||
|
@ -352,17 +352,17 @@ The “obj” attribute represents the player's inventory.
|
|||
The game is also represented by the object “game” of type “game”. In the engine it is defined this way:
|
||||
<code>
|
||||
game = game {
|
||||
nam = "INSTEAD -- Simple Text Adventure interpreter v"..version.." '2009 by Peter Kosyh",
|
||||
dsc = [[
|
||||
nam = "INSTEAD -- Simple Text Adventure interpreter v"..version.." '2009 by Peter Kosyh",
|
||||
dsc = [[
|
||||
Commands:^
|
||||
look(or just enter), act <on what> (or just what), use <what> [on what], go <where>,^
|
||||
back, inv, way, obj, quit, save <fname>, load <fname>.]],
|
||||
pl ='pl',
|
||||
showlast = true,
|
||||
pl ='pl',
|
||||
showlast = true,
|
||||
};
|
||||
</code>
|
||||
As we can see, the object keeps the reference to the current player ('pl') and some parameters. For example at the start of your game you can set the encoding the following way:
|
||||
<code> game.codepage="UTF-8"; </code>
|
||||
<code>game.codepage="UTF-8"; </code>
|
||||
|
||||
The support of arbitrary encodings is present in every UNIX version of the interpreter and in windows versions from 0.7.7.
|
||||
|
||||
|
@ -469,11 +469,11 @@ end
|
|||
|
||||
move(o, w) — moves an object from the current scene to another:
|
||||
|
||||
<code> move('mycat','inmycar');</code>
|
||||
<code>move('mycat','inmycar');</code>
|
||||
|
||||
If you want to move an object from an arbitrary scene, you'll have to delete it from the original scene with the “del” method. To create objects, that move in complex ways, you'll have to write a method that would save the object's position in the object itself and delete it from the original scene. You can set the initial position (room) as the third parameter of “move”.
|
||||
|
||||
<code> move('mycat','inmycar', 'forest'); </code>
|
||||
<code>move('mycat','inmycar', 'forest'); </code>
|
||||
|
||||
From version 0.8 there is a “movef” function similar to “move”, but adding the object to the start of the list.
|
||||
|
||||
|
@ -509,11 +509,11 @@ change_pl(p) — switch to another player (with one's own inventory and position
|
|||
|
||||
<code>
|
||||
mycar = obj {
|
||||
nam = 'my car',
|
||||
dsc = 'In front of the cabin there is my old Toyota {pickup}.',
|
||||
act = function(s)
|
||||
return goto('inmycar');
|
||||
end
|
||||
nam = 'my car',
|
||||
dsc = 'In front of the cabin there is my old Toyota {pickup}.',
|
||||
act = function(s)
|
||||
return goto('inmycar');
|
||||
end
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -530,42 +530,42 @@ par(...) — returns the string, concatenating argument strings split by the fir
|
|||
Dialogs are scenes with phrase objects. The simplest dialog may look like this:
|
||||
<code>
|
||||
povardlg = dlg {
|
||||
nam = 'in the kitchen',
|
||||
dsc = 'I see a fat face of a lady cook wearing a white hat with a tired look...',
|
||||
obj = {
|
||||
[1] = phr('“Those green, please... Yeah, and beans too!”', '“Enjoy!”'),
|
||||
[2] = phr('“Fried potato with lard, please!”', '“Bon appetit!”'),
|
||||
[3] = phr('“Two helpings of garlic sooup!!!”', '“Good choice!”'),
|
||||
[4] = phr('“Something light, please, I've got an ulcer...”', '“Oatmeal!”'),
|
||||
},
|
||||
nam = 'in the kitchen',
|
||||
dsc = 'I see a fat face of a lady cook wearing a white hat with a tired look...',
|
||||
obj = {
|
||||
[1] = phr('“Those green, please... Yeah, and beans too!”', '“Enjoy!”'),
|
||||
[2] = phr('“Fried potato with lard, please!”', '“Bon appetit!”'),
|
||||
[3] = phr('“Two helpings of garlic sooup!!!”', '“Good choice!”'),
|
||||
[4] = phr('“Something light, please, I've got an ulcer...”', '“Oatmeal!”'),
|
||||
},
|
||||
};
|
||||
</code>
|
||||
|
||||
“phr” creates a phrase. A phrase contains a question, an answer and a reaction (the example has no reaction). When the player picks one of the phrases, it is disabled. When all phrases are disabled, the dialog is over. Reaction is a line of lua code, which is executed when the phrase is disabled. E.g.:
|
||||
<code>
|
||||
food = obj {
|
||||
nam = 'food',
|
||||
inv = function (s)
|
||||
inv():del('food');
|
||||
return 'I eat.';
|
||||
end
|
||||
nam = 'food',
|
||||
inv = function (s)
|
||||
inv():del('food');
|
||||
return 'I eat.';
|
||||
end
|
||||
};
|
||||
|
||||
gotfood = function(w)
|
||||
inv():add('food');
|
||||
food._num = w;
|
||||
return back();
|
||||
inv():add('food');
|
||||
food._num = w;
|
||||
return back();
|
||||
end
|
||||
|
||||
povardlg = dlg {
|
||||
nam = 'in the kitchen',
|
||||
dsc = 'I see a fat face of a lady cook wearing a white hat with a tired look...',
|
||||
obj = {
|
||||
[1] = phr('“Those green, please... Yeah, and beans too!”', '“Enjoy!”', [[pon(1); return gotfood(1);]]),
|
||||
[2] = phr('“Fried potato with lard, please!”', '“Bon appetit!”', [[pon(2); return gotfood(2);]]),
|
||||
[3] = phr('“Two helpings of garlic sooup!!!”', '“Good choice!”', [[pon(3);return gotfood(3);]]),
|
||||
[4] = phr('“Something light, please, I've got an ulcer...”', '“Oatmeal!”', [[pon(4); return gotfood(4);]]),
|
||||
},
|
||||
nam = 'in the kitchen',
|
||||
dsc = 'I see a fat face of a lady cook wearing a white hat with a tired look...',
|
||||
obj = {
|
||||
[1] = phr('“Those green, please... Yeah, and beans too!”', '“Enjoy!”', [[pon(1); return gotfood(1);]]),
|
||||
[2] = phr('“Fried potato with lard, please!”', '“Bon appetit!”', [[pon(2); return gotfood(2);]]),
|
||||
[3] = phr('“Two helpings of garlic sooup!!!”', '“Good choice!”', [[pon(3);return gotfood(3);]]),
|
||||
[4] = phr('“Something light, please, I've got an ulcer...”', '“Oatmeal!”', [[pon(4); return gotfood(4);]]),
|
||||
},
|
||||
};
|
||||
</code>
|
||||
In the example the player chooses his dinner. After getting the food (recording the choice in the “food._num” variable) he returns back to the scene from where he got in the dialog.
|
||||
|
@ -591,23 +591,23 @@ You can pass from one dialog to another, organizing hierarchic dialogs.
|
|||
You can also hide some phrases when initializing the dialog and show them under certain conditions.
|
||||
<code>
|
||||
facectrl = dlg {
|
||||
nam = 'фэйсконтроль',
|
||||
dsc = 'I see an unpleasant face of a fat guard.',
|
||||
obj = {
|
||||
[1] = phr('“I came to the Belin's lecture...”',
|
||||
'“I do not know who you are,” he smiles, “but I have orders to let in only decent people.”',
|
||||
[[pon(2);]]),
|
||||
[2] = _phr('“I\'ve got an invitation!”',
|
||||
'“And I don\'t care! Look at yourself in a mirror!!! You\'ve come to listen to Belin himself — the right hand of...” he made a respectful pause. “So get lost...”', [[pon(3,4)]]),
|
||||
[3] = _phr(' “I\'m gonna kick your ass!”', '“I\'ve had enough...” Strong arms push me out to the corridor...',
|
||||
[[poff(4)]]),
|
||||
[4] = _phr('“You, boar! I\'ve told you, I\'ve got an invitation!”',
|
||||
'“Whaaat?” The guard\'s eyes start getting bloodshot... A powerful kick sends me out to the corridor...',
|
||||
[[poff(3)]]),
|
||||
},
|
||||
exit = function(s,w)
|
||||
s:pon(1);
|
||||
end,
|
||||
nam = 'facecontrol',
|
||||
dsc = 'I see an unpleasant face of a fat guard.',
|
||||
obj = {
|
||||
[1] = phr('“I came to the Belin's lecture...”',
|
||||
'“I do not know who you are,” he smiles, “but I have orders to let in only decent people.”',
|
||||
[[pon(2);]]),
|
||||
[2] = _phr('“I\'ve got an invitation!”',
|
||||
'“And I don\'t care! Look at yourself in a mirror!!! You\'ve come to listen to Belin himself — the right hand of...” he made a respectful pause. “So get lost...”', [[pon(3,4)]]),
|
||||
[3] = _phr(' “I\'m gonna kick your ass!”', '“I\'ve had enough...” Strong arms push me out to the corridor...',
|
||||
[[poff(4)]]),
|
||||
[4] = _phr('“You, boar! I\'ve told you, I\'ve got an invitation!”',
|
||||
'“Whaaat?” The guard\'s eyes start getting bloodshot... A powerful kick sends me out to the corridor...',
|
||||
[[poff(3)]]),
|
||||
},
|
||||
exit = function(s,w)
|
||||
s:pon(1);
|
||||
end,
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -620,19 +620,19 @@ You can enable/disable phrases not only of the current put of any arbitrary dial
|
|||
Sometimes a scene has to be filled with decorations with a limited functionality to add variety to the game. For that lightweight objects can be used. For example:
|
||||
<code>
|
||||
sside = room {
|
||||
nam = 'southern side',
|
||||
dsc = [[I am near the southern wall of an institute building. ]],
|
||||
act = function(s, w)
|
||||
if w == 1 then
|
||||
ways():add('stolcorridor');
|
||||
return "I walked to the porch. The sign on the door read 'Canteen'. Hm... should I get in?";
|
||||
end
|
||||
if w == 2 then
|
||||
return 'The ones going out look happier...';
|
||||
end
|
||||
end,
|
||||
obj = { vobj(1, "porch", "There is a small {porch} by the eastern corner."),
|
||||
vobj(2, "people", "From time to time the porch door slams letting {people} in and out..")},
|
||||
nam = 'southern side',
|
||||
dsc = [[I am near the southern wall of an institute building. ]],
|
||||
act = function(s, w)
|
||||
if w == 1 then
|
||||
ways():add('stolcorridor');
|
||||
return "I walked to the porch. The sign on the door read 'Canteen'. Hm... should I get in?";
|
||||
end
|
||||
if w == 2 then
|
||||
return 'The ones going out look happier...';
|
||||
end
|
||||
end,
|
||||
obj = { vobj(1, "porch", "There is a small {porch} by the eastern corner."),
|
||||
vobj(2, "people", "From time to time the porch door slams letting {people} in and out..")},
|
||||
};
|
||||
</code>
|
||||
As you see, “vobj” allows to create a lightweight version of a static object, with which it will still be possible to interact (defining an “act” handler in the scene an analyzing the object key). “vobj” also calls the “used” method with the third parameter being the object which acts on the virtual object.
|
||||
|
@ -649,7 +649,7 @@ There is a modification of “vobj” object — “vway”. It creates a refere
|
|||
You can dynamically fill the scene with “vobj” and “vway” objects. Use methods “add” and “del”. For example:
|
||||
|
||||
<code>
|
||||
home.objs:add(vway("next", "{Next}.", 'next_room');
|
||||
home.objs:add(vway("next", "{Next}.", 'next_room'));
|
||||
-- some code here
|
||||
home.objs:del("next");
|
||||
</code>
|
||||
|
@ -666,32 +666,32 @@ Syntax: vroom(passage name, destination scene). For example:
|
|||
You can define handlers, that would execute every time when the game time increments by 1. E.g.:
|
||||
<code>
|
||||
mycat = obj {
|
||||
nam = 'Barsik',
|
||||
lf = {
|
||||
[1] = 'Barsik is moving in my bosom.',
|
||||
[2] = 'Barsik peers out of my bosom.',
|
||||
[3] = 'Barsik purrs in my bosom.',
|
||||
[4] = 'Barsik shivers in my bosom.',
|
||||
[5] = 'I feel Barsik's warmth in my bosom.',
|
||||
[6] = 'Barsik leans out of my bosom and looks around.',
|
||||
},
|
||||
life = function(s)
|
||||
local r = rnd(6);
|
||||
if r > 2 then
|
||||
return;
|
||||
end
|
||||
r = rnd(6);
|
||||
return s.lf[r];
|
||||
end,
|
||||
nam = 'Barsik',
|
||||
lf = {
|
||||
[1] = 'Barsik is moving in my bosom.',
|
||||
[2] = 'Barsik peers out of my bosom.',
|
||||
[3] = 'Barsik purrs in my bosom.',
|
||||
[4] = 'Barsik shivers in my bosom.',
|
||||
[5] = 'I feel Barsik's warmth in my bosom.',
|
||||
[6] = 'Barsik leans out of my bosom and looks around.',
|
||||
},
|
||||
life = function(s)
|
||||
local r = rnd(6);
|
||||
if r > 2 then
|
||||
return;
|
||||
end
|
||||
r = rnd(6);
|
||||
return s.lf[r];
|
||||
end,
|
||||
....
|
||||
|
||||
profdlg2 = dlg {
|
||||
nam = 'Belin',
|
||||
dsc = 'Belin is pale. He absently looks at the shotgun.',
|
||||
obj = {
|
||||
[1] = phr('“I came for my cat.”',
|
||||
'I snatch Barsik from Belin's hand and put in my bosom.',
|
||||
[[inv():add('mycat'); lifeon('mycat')]]),
|
||||
nam = 'Belin',
|
||||
dsc = 'Belin is pale. He absently looks at the shotgun.',
|
||||
obj = {
|
||||
[1] = phr('“I came for my cat.”',
|
||||
'I snatch Barsik from Belin's hand and put in my bosom.',
|
||||
[[inv():add('mycat'); lifeon('mycat')]]),
|
||||
....
|
||||
</code>
|
||||
Any object or scene may have their “life” handler, which is called every time the game time advances, if the object or the scene have been added to the list of living objects with “lifeon”. Don't forget to remofe living objects from the list with “lifeoff”, when you no longer need them. You can do this, for example, in the “exit” handler or some other way.
|
||||
|
@ -709,9 +709,9 @@ Graphic interpreter analyzes the scene “pic” attribute and treats it as a pa
|
|||
|
||||
<code>
|
||||
home = room {
|
||||
pic = 'gfx/home.png',
|
||||
nam = 'at home',
|
||||
dsc = 'I am at home',
|
||||
pic = 'gfx/home.png',
|
||||
nam = 'at home',
|
||||
dsc = 'I am at home',
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -724,7 +724,7 @@ From version 0.9.2 graphics can be embedded everywhere in text or inventory with
|
|||
|
||||
<code>
|
||||
knife = obj {
|
||||
nam = 'Knife'..img('img/knife.png'),
|
||||
nam = 'Knife'..img('img/knife.png'),
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -733,12 +733,12 @@ The interpreter cycles the current music defined by the function ”set_music(mu
|
|||
For example:
|
||||
<code>
|
||||
street = room {
|
||||
pic = 'gfx/street.png',
|
||||
enter = function()
|
||||
set_music('mus/rain.ogg');
|
||||
end,
|
||||
nam = 'on the street',
|
||||
dsc = 'It is raining outside.',
|
||||
pic = 'gfx/street.png',
|
||||
enter = function()
|
||||
set_music('mus/rain.ogg');
|
||||
end,
|
||||
nam = 'on the street',
|
||||
dsc = 'It is raining outside.',
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -771,8 +771,8 @@ txtl() - left align;
|
|||
For example:
|
||||
<code>
|
||||
main = room {
|
||||
nam = 'Intro',
|
||||
dsc = txtc('Welcome!'),
|
||||
nam = 'Intro',
|
||||
dsc = txtc('Welcome!'),
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -785,8 +785,8 @@ txtu() - underline;
|
|||
For example:
|
||||
<code>
|
||||
main = room {
|
||||
nam = 'Intro',
|
||||
dsc = 'You are in the room: '..txtb('main')..'.',
|
||||
nam = 'Intro',
|
||||
dsc = 'You are in the room: '..txtb('main')..'.',
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -795,8 +795,8 @@ Since the version 1.1.0 you can create unwrapped strings by using txtnb();
|
|||
For example:
|
||||
<code>
|
||||
main = room {
|
||||
nam = 'Intro',
|
||||
dsc = 'You are in the room '..txtb('main')..'.',
|
||||
nam = 'Intro',
|
||||
dsc = 'You are in the room '..txtb('main')..'.',
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -804,33 +804,33 @@ main = room {
|
|||
You can do menus in the inventory area, using menu constructor. Menu handler will be called after single mouse click. If handler have no return string the state of game will no change. For example, here is pocket realisation:
|
||||
<code>
|
||||
pocket = menu {
|
||||
State = false,
|
||||
nam = function(s)
|
||||
if s.State then
|
||||
return txtu('pocket');
|
||||
end
|
||||
return 'pocket';
|
||||
end,
|
||||
gen = function(s)
|
||||
if s.State then
|
||||
s:enable_all();
|
||||
else
|
||||
s:disable_all();
|
||||
end
|
||||
end,
|
||||
menu = function(s)
|
||||
if s.State then
|
||||
s.State = false;
|
||||
else
|
||||
s.State = true;
|
||||
end
|
||||
s:gen();
|
||||
end,
|
||||
State = false,
|
||||
nam = function(s)
|
||||
if s.State then
|
||||
return txtu('pocket');
|
||||
end
|
||||
return 'pocket';
|
||||
end,
|
||||
gen = function(s)
|
||||
if s.State then
|
||||
s:enable_all();
|
||||
else
|
||||
s:disable_all();
|
||||
end
|
||||
end,
|
||||
menu = function(s)
|
||||
if s.State then
|
||||
s.State = false;
|
||||
else
|
||||
s.State = true;
|
||||
end
|
||||
s:gen();
|
||||
end,
|
||||
};
|
||||
|
||||
knife = obj {
|
||||
nam = 'knife',
|
||||
inv = 'This is knife',
|
||||
nam = 'knife',
|
||||
inv = 'This is knife',
|
||||
};
|
||||
|
||||
inv():add(pocket);
|
||||
|
@ -838,7 +838,7 @@ put(knife, pocket);
|
|||
pocket:gen();
|
||||
|
||||
main = room {
|
||||
nam = 'test',
|
||||
nam = 'test',
|
||||
};
|
||||
</code>
|
||||
==== Player status ====
|
||||
|
@ -849,9 +849,9 @@ pl.Life = 10;
|
|||
pl.Power = 10;
|
||||
|
||||
status = obj {
|
||||
nam = function(s)
|
||||
return 'Life: '..pl.Life..',Power: '..pl.Power
|
||||
end
|
||||
nam = function(s)
|
||||
return 'Life: '..pl.Life..',Power: '..pl.Power
|
||||
end
|
||||
};
|
||||
inv():add('status');
|
||||
status.object_type = false
|
||||
|
@ -863,9 +863,9 @@ pl.Life = 10;
|
|||
pl.Power = 10;
|
||||
|
||||
status = stat {
|
||||
nam = function(s)
|
||||
return 'Life: '..pl.Life..',Power: '..pl.Power
|
||||
end
|
||||
nam = function(s)
|
||||
return 'Life: '..pl.Life..',Power: '..pl.Power
|
||||
end
|
||||
};
|
||||
inv():add('status');
|
||||
</code>
|
||||
|
@ -875,8 +875,9 @@ inv():add('status');
|
|||
If you use “goto” from the “exit” handler, you get stack overflow, because goto would call “exit” again and again. You can prevent it by aadding a check that breaks the recursioon. For example:
|
||||
<code>
|
||||
exit = function(s, t)
|
||||
if t == 'dialog' then return; end
|
||||
return goto('dialog');
|
||||
if t == 'dialog' then return; end
|
||||
return goto('dialog');
|
||||
end
|
||||
</code>
|
||||
|
||||
From version 0.9.1 this is done by stead engine.
|
||||
|
@ -895,27 +896,27 @@ home.obj:del('Road');
|
|||
The “srch” method can check if the reference is present in the scene.
|
||||
<code>
|
||||
if not home.obj:srch('Road') then
|
||||
home.obj:add(vway('Road', 'I noticed a {road} going into the forest...', 'forest'));
|
||||
home.obj:add(vway('Road', 'I noticed a {road} going into the forest...', 'forest'));
|
||||
end
|
||||
</code>
|
||||
It's convenient to create dynamic references either in the “enter” handler, or in the arbitrary place in the game code, where they are required. If the reference is created in the current scene, the example can be simplified:
|
||||
<code>
|
||||
if not seen('Road') then
|
||||
objs():add(vway('Road', 'I noticed a {road} going into the forest...', 'forest'));
|
||||
objs():add(vway('Road', 'I noticed a {road} going into the forest...', 'forest'));
|
||||
end
|
||||
</code>
|
||||
Or you can just enable and disable references with “enable()” and “disable()”, for example:
|
||||
<code>
|
||||
objs()[1]:disable();
|
||||
objs()[1]:disable();
|
||||
</code>
|
||||
|
||||
Creating disabled “vobj” and “vway”:
|
||||
<code>
|
||||
obj = {vway('Road', 'I noticed a {road} going into the forest...', 'forest'):disable()},
|
||||
obj = {vway('Road', 'I noticed a {road} going into the forest...', 'forest'):disable()},
|
||||
</code>
|
||||
And then enabling them by their index in the “obj” array:
|
||||
<code>
|
||||
objs()[1]:enable();
|
||||
objs()[1]:enable();
|
||||
</code>
|
||||
|
||||
==== Encoding game sources (from version 0.9.3) ====
|
||||
|
@ -937,21 +938,21 @@ You can create a game with several characters and switch between them from time
|
|||
==== Using the first parameter of a handler ====
|
||||
Code example.
|
||||
<code>
|
||||
knife = obj {
|
||||
nam = 'stone',
|
||||
dsc = 'There is a {stone} at the edge.',
|
||||
act = function()
|
||||
objs():del('knife');
|
||||
return 'I pushed the stone, it fell and flew down...';
|
||||
end
|
||||
stone = obj {
|
||||
nam = 'stone',
|
||||
dsc = 'There is a {stone} at the edge.',
|
||||
act = function()
|
||||
objs():del('stone');
|
||||
return 'I pushed the stone, it fell and flew down...';
|
||||
end
|
||||
</code>
|
||||
|
||||
The “act” handler could look simpler:
|
||||
<code>
|
||||
act = function(s)
|
||||
objs():del(s);
|
||||
return 'I pushed the stone, it fell and flew down...';
|
||||
end
|
||||
act = function(s)
|
||||
objs():del(s);
|
||||
return 'I pushed the stone, it fell and flew down...';
|
||||
end
|
||||
</code>
|
||||
|
||||
==== Using “set_music” ====
|
||||
|
@ -962,20 +963,20 @@ You can write your own music player, creating it from a live object, e.g:
|
|||
-- plays tracks in random order, starting from 2-nd
|
||||
tracks = {"mus/astro2.mod", "mus/aws_chas.xm", "mus/dmageofd.xm", "mus/doomsday.s3m"}
|
||||
mplayer = obj {
|
||||
nam = 'плеер',
|
||||
life = function(s)
|
||||
local n = get_music();
|
||||
local v = get_music_loop();
|
||||
if not n or not v then
|
||||
set_music(tracks[2], 1);
|
||||
elseif v == -1 then
|
||||
local n = get_music();
|
||||
while get_music() == n do
|
||||
n = tracks[rnd(4)]
|
||||
end
|
||||
set_music(n, 1);
|
||||
end
|
||||
end,
|
||||
nam = 'media player',
|
||||
life = function(s)
|
||||
local n = get_music();
|
||||
local v = get_music_loop();
|
||||
if not n or not v then
|
||||
set_music(tracks[2], 1);
|
||||
elseif v == -1 then
|
||||
local n = get_music();
|
||||
while get_music() == n do
|
||||
n = tracks[rnd(4)]
|
||||
end
|
||||
set_music(n, 1);
|
||||
end
|
||||
end,
|
||||
};
|
||||
lifeon('mplayer');
|
||||
</code>
|
||||
|
@ -984,20 +985,20 @@ You can use “get_music_loop” and “get_music” functions to remember the l
|
|||
|
||||
<code>
|
||||
function save_music(s)
|
||||
s.OldMusic = get_music();
|
||||
s.OldMusicLoop = get_music_loop();
|
||||
s.OldMusic = get_music();
|
||||
s.OldMusicLoop = get_music_loop();
|
||||
end
|
||||
|
||||
function restore_music(s)
|
||||
set_music(s.OldMusic, s.OldMusicLoop);
|
||||
set_music(s.OldMusic, s.OldMusicLoop);
|
||||
end
|
||||
|
||||
-- ....
|
||||
enter = function(s)
|
||||
save_music(s);
|
||||
save_music(s);
|
||||
end,
|
||||
exit = function(s)
|
||||
restore_music(s);
|
||||
restore_music(s);
|
||||
end,
|
||||
-- ....
|
||||
|
||||
|
@ -1009,14 +1010,14 @@ From version 0.8.5 functions “save_music” and “restore_music” are alread
|
|||
If your hero needs a friend, one of the ways is the “life” method of that character, that would always bring the object to the player's location:
|
||||
<code>
|
||||
horse = obj {
|
||||
nam = 'horse',
|
||||
dsc = 'A {horse} is standing next to me.',
|
||||
life = function(s)
|
||||
if not seen('horse') then
|
||||
move('horse', here(), s.__where);
|
||||
s.__where = pl.where;
|
||||
end
|
||||
end,
|
||||
nam = 'horse',
|
||||
dsc = 'A {horse} is standing next to me.',
|
||||
life = function(s)
|
||||
if not seen('horse') then
|
||||
move('horse', here(), s.__where);
|
||||
s.__where = pl.where;
|
||||
end
|
||||
end,
|
||||
};
|
||||
lifeon('horse');
|
||||
</code>
|
||||
|
@ -1032,17 +1033,17 @@ Timer controls through the ''timer'' object.
|
|||
Timer function can return a ''stead'' interface command that have to be invoked after the callback execution. For example:
|
||||
<code>
|
||||
timer.callback = function(s)
|
||||
main._time = main._time + 1;
|
||||
return "look";
|
||||
main._time = main._time + 1;
|
||||
return "look";
|
||||
end
|
||||
timer:set(100);
|
||||
main = room {
|
||||
_time = 1,
|
||||
force_dsc = true,
|
||||
nam = 'Timer',
|
||||
dsc = function(s)
|
||||
return 'Example: '..tostring(s._time);
|
||||
end
|
||||
_time = 1,
|
||||
force_dsc = true,
|
||||
nam = 'Timer',
|
||||
dsc = function(s)
|
||||
return 'Example: '..tostring(s._time);
|
||||
end
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -1055,26 +1056,26 @@ Handler can return a ''stead'' interface command. In this case the interpreter d
|
|||
For example:
|
||||
<code>
|
||||
input.key = function(s, pr, key)
|
||||
if not pr or key == "escape"then
|
||||
return
|
||||
elseif key == 'space' then
|
||||
key = ' '
|
||||
elseif key == 'return' then
|
||||
key = '^';
|
||||
end
|
||||
if key:len() > 1 then return end
|
||||
main._txt = main._txt:gsub('_$','');
|
||||
main._txt = main._txt..key..'_';
|
||||
return "look";
|
||||
if not pr or key == "escape"then
|
||||
return
|
||||
elseif key == 'space' then
|
||||
key = ' '
|
||||
elseif key == 'return' then
|
||||
key = '^';
|
||||
end
|
||||
if key:len() > 1 then return end
|
||||
main._txt = main._txt:gsub('_$','');
|
||||
main._txt = main._txt..key..'_';
|
||||
return "look";
|
||||
end
|
||||
|
||||
main = room {
|
||||
_txt = '_',
|
||||
force_dsc = true,
|
||||
nam = 'Keyboard',
|
||||
dsc = function(s)
|
||||
return 'Example: '..tostring(s._txt);
|
||||
end
|
||||
_txt = '_',
|
||||
force_dsc = true,
|
||||
nam = 'Keyboard',
|
||||
dsc = function(s)
|
||||
return 'Example: '..tostring(s._txt);
|
||||
end
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -1151,10 +1152,10 @@ delete(n)
|
|||
''new'' treats its string argument as an object constructor. The constructor must return an object. Thus, the string argument usually contains a constructor function call. For example:
|
||||
<code>
|
||||
function myconstructor()
|
||||
local v = {}
|
||||
v.nam = 'test object',
|
||||
v.act = 'test feedback',
|
||||
return obj(v);
|
||||
local v = {}
|
||||
v.nam = 'test object',
|
||||
v.act = 'test feedback',
|
||||
return obj(v);
|
||||
end
|
||||
</code>
|
||||
The object created will be saved every time the game is saved. ''new()'' returns a real object; to get its name you can use ''deref'' function:
|
||||
|
@ -1167,24 +1168,26 @@ delete(o_name);
|
|||
Sometimes the we need to form event handler output from several parts depending on some conditions. In this case ''p()'' and ''pn()'' functions can be useful. These functions add text to the internal buffer of the handler. The content of this buffer is returned from the handler.
|
||||
<code>
|
||||
dsc = function(s)
|
||||
p "There is a {barrel} standing on the floor."
|
||||
if s._opened then
|
||||
p "The barrel lid lies nearby."
|
||||
end
|
||||
p "There is a {barrel} standing on the floor."
|
||||
if s._opened then
|
||||
p "The barrel lid lies nearby."
|
||||
end
|
||||
end
|
||||
</code>
|
||||
''pn()'' function adds line feed to the text and outputs the result to the buffer. ''p()'' does almost the same thing but adds a space instead of line feed.
|
||||
|
||||
There is a function ''pr()'' in versions 1.1.6 and later, that does not add anything at end of output.
|
||||
|
||||
To clear the buffer you can use ''pclr()''. To return the status of the action along with the text, use ''pget()''.
|
||||
<code>
|
||||
use = function(s, w)
|
||||
if w == 'apple' then
|
||||
p 'I peeled the apple';
|
||||
apple._peeled = true
|
||||
return
|
||||
end
|
||||
p 'You cannot use it this way!'
|
||||
return pget(), false
|
||||
if w == 'apple' then
|
||||
p 'I peeled the apple';
|
||||
apple._peeled = true
|
||||
return
|
||||
end
|
||||
p 'You cannot use it this way!'
|
||||
return pget(), false
|
||||
end
|
||||
</code>
|
||||
|
||||
|
|
|
@ -153,27 +153,27 @@ apple = obj {
|
|||
Зная lua, можно упростить запись:
|
||||
<code>
|
||||
function sw(v, a, b)
|
||||
if v then
|
||||
return a;
|
||||
end
|
||||
return b
|
||||
if v then
|
||||
return a;
|
||||
end
|
||||
return b
|
||||
end
|
||||
|
||||
apple = obj {
|
||||
nam = function(s)
|
||||
return sw(not s._seen, 'нечто','яблоко');
|
||||
end,
|
||||
dsc = function(s)
|
||||
return sw(not s._seen,'На столе {что-то} лежит.', 'На столе лежит {яблоко}.');
|
||||
end,
|
||||
act = function(s)
|
||||
if s._seen then
|
||||
return 'Это яблоко!';
|
||||
else
|
||||
s._seen = true;
|
||||
return 'Гм... Это же яблоко!';
|
||||
end
|
||||
end,
|
||||
nam = function(s)
|
||||
return sw(not s._seen, 'нечто','яблоко');
|
||||
end,
|
||||
dsc = function(s)
|
||||
return sw(not s._seen,'На столе {что-то} лежит.', 'На столе лежит {яблоко}.');
|
||||
end,
|
||||
act = function(s)
|
||||
if s._seen then
|
||||
return 'Это яблоко!';
|
||||
else
|
||||
s._seen = true;
|
||||
return 'Гм... Это же яблоко!';
|
||||
end
|
||||
end,
|
||||
};
|
||||
</code>
|
||||
И в дальнейшем всегда использовать функцию sw (или какую-либо другую, вспомогательную функцию).
|
||||
|
@ -185,7 +185,7 @@ apple = obj {
|
|||
Начиная с версии 0.8.9 вы можете определить функцию isForSave(k), которая вызывается для определения необходимости записи переменной в файл сохранения. По умолчанию, функция определена следующим образом:
|
||||
<code>
|
||||
function isForSave(k)
|
||||
return string.find(k, '_') == 1 or string.match(k,'^%u')
|
||||
return string.find(k, '_') == 1 or string.match(k,'^%u')
|
||||
end
|
||||
</code>
|
||||
|
||||
|
@ -194,20 +194,20 @@ end
|
|||
Иногда может понадобиться обработчик, который совершал бы некоторое действие, но не выводил никакого описания. Например:
|
||||
<code>
|
||||
button = obj {
|
||||
nam = "кнопка",
|
||||
dsc = "На стене комнаты видна большая красная {кнопка}.",
|
||||
act = function (s)
|
||||
here()._dynamic_dsc = [[После того как я нажал на кнопку, комната преобразилась.
|
||||
Книжный шкаф куда-то исчез вместе со столом и комодом, а на его месте
|
||||
появился странного вида аппарат.]];
|
||||
return true;
|
||||
end,
|
||||
nam = "кнопка",
|
||||
dsc = "На стене комнаты видна большая красная {кнопка}.",
|
||||
act = function (s)
|
||||
here()._dynamic_dsc = [[После того как я нажал на кнопку, комната преобразилась.
|
||||
Книжный шкаф куда-то исчез вместе со столом и комодом, а на его месте
|
||||
появился странного вида аппарат.]];
|
||||
return true;
|
||||
end,
|
||||
}
|
||||
r12 = room {
|
||||
nam = 'комната',
|
||||
_dynamic_dsc = 'Я нахожусь в комнате.',
|
||||
dsc = function (s) return s._dynamic_dsc end,
|
||||
obj = {'button'}
|
||||
nam = 'комната',
|
||||
_dynamic_dsc = 'Я нахожусь в комнате.',
|
||||
dsc = function (s) return s._dynamic_dsc end,
|
||||
obj = {'button'}
|
||||
}
|
||||
</code>
|
||||
В данном случае обработчик `act` нужен для того, чтобы поменять описание комнаты, и не нужно, чтобы чтобы он выводил результат действия. Для отключения результата можно вернуть из обработчика значение true -- это будет означать, что действие успешно выполнено, но не требует дополнительного описания.
|
||||
|
@ -323,12 +323,12 @@ knife = obj {
|
|||
inv = 'Острый!',
|
||||
tak = 'Я взял нож!',
|
||||
use = function(s, w)
|
||||
if w ~= 'tabl'
|
||||
if w ~= 'tabl' then
|
||||
return 'Не хочу это резать.', false
|
||||
else
|
||||
return 'Вы вырезаете на столе свои инициалы.';
|
||||
end
|
||||
end
|
||||
end
|
||||
};
|
||||
</code>
|
||||
Нож можно использовать только на стол.
|
||||
|
@ -338,9 +338,9 @@ knife = obj {
|
|||
Игрок в STEAD представлен объектом pl. Тип объекта -- player. В движке объект создается следующим образом:
|
||||
<code>
|
||||
pl = player {
|
||||
nam = "Incognito",
|
||||
where = 'main',
|
||||
obj = { }
|
||||
nam = "Incognito",
|
||||
where = 'main',
|
||||
obj = { }
|
||||
};
|
||||
</code>
|
||||
Атрибут obj представляет собой инвентарь игрока.
|
||||
|
@ -350,13 +350,13 @@ pl = player {
|
|||
Игра также представлена объектом game с типом game. В движке он определяется следующим образом:
|
||||
<code>
|
||||
game = game {
|
||||
nam = "INSTEAD -- Simple Text Adventure interpreter v"..version.." '2009 by Peter Kosyh",
|
||||
dsc = [[
|
||||
nam = "INSTEAD -- Simple Text Adventure interpreter v"..version.." '2009 by Peter Kosyh",
|
||||
dsc = [[
|
||||
Commands:^
|
||||
look(or just enter), act <on what> (or just what), use <what> [on what], go <where>,^
|
||||
back, inv, way, obj, quit, save <fname>, load <fname>.]],
|
||||
pl ='pl',
|
||||
showlast = true,
|
||||
pl ='pl',
|
||||
showlast = true,
|
||||
};
|
||||
</code>
|
||||
Как видим, объект хранит в себе указатель на текущего игрока ('pl') и некоторые параметры. Например, вы можете указать в начале своей игры кодировку текста следующим образом:
|
||||
|
@ -465,19 +465,19 @@ end
|
|||
</code>
|
||||
move(o, w) -- переносит объект из текущей сцены в другую:
|
||||
|
||||
<code> move('mycat','inmycar');</code>
|
||||
<code>move('mycat','inmycar');</code>
|
||||
|
||||
Если вы хотите перенести объект из произвольной сцены, вам придется удалить его из старой сцены с помощью метода del. Для создания сложно перемещающихся объектов, вам придется написать свой метод, который будет сохранять текущую позицию объекта в самом объекте и делать удаление объекта из старой сцены. Вы можете указать исходную позицию (комнату) объекта в качестве третьего параметра move.
|
||||
|
||||
<code> move('mycat','inmycar', 'forest'); </code>
|
||||
<code>move('mycat','inmycar', 'forest'); </code>
|
||||
|
||||
Начиная с версии 0.8 присутствует также функция movef, аналогичная move, но добавляющая объект в начало списка.
|
||||
|
||||
seen(o) -- если объект присутствует в текущей сцене:
|
||||
<code>
|
||||
if seen('mycat') then
|
||||
move('mycat','inmycar');
|
||||
end
|
||||
if seen('mycat') then
|
||||
move('mycat','inmycar');
|
||||
end
|
||||
</code>
|
||||
Начиная с 0.8.6 -- необязательный второй параметр -- сцена.
|
||||
|
||||
|
@ -505,11 +505,11 @@ change_pl(p) -- переключиться на другого игрока (с
|
|||
|
||||
<code>
|
||||
mycar = obj {
|
||||
nam = 'моя машина',
|
||||
dsc = 'Перед хижиной стоит мой старенький {пикап} Toyota.',
|
||||
act = function(s)
|
||||
return goto('inmycar');
|
||||
end
|
||||
nam = 'моя машина',
|
||||
dsc = 'Перед хижиной стоит мой старенький {пикап} Toyota.',
|
||||
act = function(s)
|
||||
return goto('inmycar');
|
||||
end
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -526,41 +526,41 @@ par(...) -- возвращает строку -- склейку строк-ар
|
|||
Диалоги это сцены, содержащие объекты -- фразы. Например, простейший диалог может выглядеть следующим образом.
|
||||
<code>
|
||||
povardlg = dlg {
|
||||
nam = 'на кухне',
|
||||
dsc = 'Передо мной полное лицо женщины - повара в белом колпаке и усталым взглядом...',
|
||||
obj = {
|
||||
[1] = phr('Мне вот-этих зелененьких... Ага -- и бобов!', 'На здоровье!'),
|
||||
[2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!'),
|
||||
[3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!'),
|
||||
[4] = phr('Мне что-нибудь легонькое, у меня язва...', 'Овсянка!'),
|
||||
},
|
||||
nam = 'на кухне',
|
||||
dsc = 'Передо мной полное лицо женщины - повара в белом колпаке и усталым взглядом...',
|
||||
obj = {
|
||||
[1] = phr('Мне вот-этих зелененьких... Ага -- и бобов!', 'На здоровье!'),
|
||||
[2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!'),
|
||||
[3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!'),
|
||||
[4] = phr('Мне что-нибудь легонькое, у меня язва...', 'Овсянка!'),
|
||||
},
|
||||
};
|
||||
</code>
|
||||
phr -- создание фразы. Фраза содержит вопрос, ответ и реакцию (реакция в данном примере отсутствует). Когда игрок выбирает одну из фраз, фраза отключается. Когда все фразы отключатся диалог заканчивается. Реакция -- это строка кода на lua который выполнится после отключения фразы. Например:
|
||||
<code>
|
||||
food = obj {
|
||||
nam = 'еда',
|
||||
inv = function (s)
|
||||
inv():del('food');
|
||||
return 'Я ем.';
|
||||
end
|
||||
nam = 'еда',
|
||||
inv = function (s)
|
||||
inv():del('food');
|
||||
return 'Я ем.';
|
||||
end
|
||||
};
|
||||
|
||||
gotfood = function(w)
|
||||
inv():add('food');
|
||||
food._num = w;
|
||||
return back();
|
||||
inv():add('food');
|
||||
food._num = w;
|
||||
return back();
|
||||
end
|
||||
|
||||
povardlg = dlg {
|
||||
nam = 'на кухне',
|
||||
dsc = 'Передо мной полное лицо женщины - повара в белом колпаке и усталым взглядом...',
|
||||
obj = {
|
||||
[1] = phr('Мне вот-этих зелененьких... Ага -- и бобов!', 'На здоровье!', [[pon(1); return gotfood(1);]]),
|
||||
[2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!', [[pon(2); return gotfood(2);]]),
|
||||
[3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!', [[pon(3);return gotfood(3);]]),
|
||||
[4] = phr('Мне что-нибудь легонькое, у меня язва...', 'Овсянка!', [[pon(4); return gotfood(4);]]),
|
||||
},
|
||||
nam = 'на кухне',
|
||||
dsc = 'Передо мной полное лицо женщины - повара в белом колпаке и усталым взглядом...',
|
||||
obj = {
|
||||
[1] = phr('Мне вот-этих зелененьких... Ага -- и бобов!', 'На здоровье!', [[pon(1); return gotfood(1);]]),
|
||||
[2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!', [[pon(2); return gotfood(2);]]),
|
||||
[3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!', [[pon(3);return gotfood(3);]]),
|
||||
[4] = phr('Мне что-нибудь легонькое, у меня язва...', 'Овсянка!', [[pon(4); return gotfood(4);]]),
|
||||
},
|
||||
};
|
||||
</code>
|
||||
В данном примере, игрок выбирает еду. Получае ее (запомнив выбор в переменной food._num) и возвращается обратно (в ту сцену откуда попал в диалог).
|
||||
|
@ -586,23 +586,23 @@ povar = obj {
|
|||
Также, вы можете прятать некоторые фразы при инициализации диалога и показывать их при некоторых условиях.
|
||||
<code>
|
||||
facectrl = dlg {
|
||||
nam = 'фэйсконтроль',
|
||||
dsc = 'Я вижу перед собой неприятное лицо полного охранника.',
|
||||
obj = {
|
||||
[1] = phr('Я пришел послушать лекцию Белина...',
|
||||
'-- Я не знаю кто вы -- ухмыляется охранник -- но мне велели пускать сюда только приличных людей.',
|
||||
[[pon(2);]]),
|
||||
[2] = _phr('У меня есть приглашение!',
|
||||
'-- А мне плевать! Посмотри на себя в зеркало!!! Ты пришел слушать самого Белина -- правую руку самого... -- охранник почтительно помолчал -- Так что пошел вон..', [[pon(3,4)]]),
|
||||
[3] = _phr('Сейчас я дам тебе по роже!', '-- Ну все... Мощные руки выталкивают меня в коридор...',
|
||||
[[poff(4)]]),
|
||||
[4] = _phr('Ты, кабан! Я же тебе сказал -- у меня есть приглашение!',
|
||||
'-- Чтоооооо? Глаза охранника наливаются кровью... Мощный пинок отправляет меня в коридор...',
|
||||
[[poff(3)]]),
|
||||
},
|
||||
exit = function(s,w)
|
||||
s:pon(1);
|
||||
end,
|
||||
nam = 'фэйсконтроль',
|
||||
dsc = 'Я вижу перед собой неприятное лицо полного охранника.',
|
||||
obj = {
|
||||
[1] = phr('Я пришел послушать лекцию Белина...',
|
||||
'-- Я не знаю кто вы -- ухмыляется охранник -- но мне велели пускать сюда только приличных людей.',
|
||||
[[pon(2);]]),
|
||||
[2] = _phr('У меня есть приглашение!',
|
||||
'-- А мне плевать! Посмотри на себя в зеркало!!! Ты пришел слушать самого Белина -- правую руку самого... -- охранник почтительно помолчал -- Так что пошел вон..', [[pon(3,4)]]),
|
||||
[3] = _phr('Сейчас я дам тебе по роже!', '-- Ну все... Мощные руки выталкивают меня в коридор...',
|
||||
[[poff(4)]]),
|
||||
[4] = _phr('Ты, кабан! Я же тебе сказал -- у меня есть приглашение!',
|
||||
'-- Чтоооооо? Глаза охранника наливаются кровью... Мощный пинок отправляет меня в коридор...',
|
||||
[[poff(3)]]),
|
||||
},
|
||||
exit = function(s,w)
|
||||
s:pon(1);
|
||||
end,
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -615,19 +615,19 @@ facectrl = dlg {
|
|||
Иногда, сцену нужно наполнить декорациями, которые обладают ограниченной функциональностью, но делают игру разнообразней. Для этого можно использовать облегченный объект. Например:
|
||||
<code>
|
||||
sside = room {
|
||||
nam = 'южная сторона',
|
||||
dsc = [[Я нахожусь у южной стены здания института. ]],
|
||||
act = function(s, w)
|
||||
if w == 1 then
|
||||
ways():add('stolcorridor');
|
||||
return "Я подошел к подъезду. На двери подъезда надпись -- 'Столовая'. Хм -- зайти внутрь?";
|
||||
end
|
||||
if w == 2 then
|
||||
return 'Те, кто выходят, выглядят более довольными...';
|
||||
end
|
||||
end,
|
||||
obj = { vobj(1, "подъезд", "У восточного угла находится небольшой {подъезд}."),
|
||||
vobj(2, "люди", "Время от времени дверь подъезда хлопает впуская и выпуская {людей}.")},
|
||||
nam = 'южная сторона',
|
||||
dsc = [[Я нахожусь у южной стены здания института. ]],
|
||||
act = function(s, w)
|
||||
if w == 1 then
|
||||
ways():add('stolcorridor');
|
||||
return "Я подошел к подъезду. На двери подъезда надпись -- 'Столовая'. Хм -- зайти внутрь?";
|
||||
end
|
||||
if w == 2 then
|
||||
return 'Те, кто выходят, выглядят более довольными...';
|
||||
end
|
||||
end,
|
||||
obj = { vobj(1, "подъезд", "У восточного угла находится небольшой {подъезд}."),
|
||||
vobj(2, "люди", "Время от времени дверь подъезда хлопает впуская и выпуская {людей}.")},
|
||||
};
|
||||
</code>
|
||||
Как видим, vobj позволяет сделать легкую версию статического объекта, с которым тем не менее можно взаимодействовать (за счет определения обработчика act в сцене и анализа ключа объекта). vobj также вызывает метод used, при этом в качестве третьего параметра передается объект, воздействующий на виртуальный объект.
|
||||
|
@ -644,8 +644,8 @@ sside = room {
|
|||
Вы можете динамически заполнять сцену объектами vobj или vway с помощью методов add и del. Например:
|
||||
|
||||
<code>
|
||||
home.objs:add(vway("next", "{Дальше}.", 'next_room');
|
||||
-- some code here
|
||||
home.objs:add(vway("next", "{Дальше}.", 'next_room'));
|
||||
-- здесь какой-нибудь код
|
||||
home.objs:del("next");
|
||||
</code>
|
||||
|
||||
|
@ -661,32 +661,32 @@ sside = room {
|
|||
Вы можете определять обработчики, которые выполняются каждый раз, когда время игры увеличивается на 1. Например:
|
||||
<code>
|
||||
mycat = obj {
|
||||
nam = 'Барсик',
|
||||
lf = {
|
||||
[1] = 'Барсик шевелится у меня за пазухой.',
|
||||
[2] = 'Барсик выглядывает из за пазухи.',
|
||||
[3] = 'Барсик мурлычит у меня за пазухой.',
|
||||
[4] = 'Барсик дрожит у меня за пазухой.',
|
||||
[5] = 'Я чувствую тепло Барсика у себя за пазухой.',
|
||||
[6] = 'Барсик высовывает голову из за пазухи и осматривает местность.',
|
||||
},
|
||||
life = function(s)
|
||||
local r = rnd(6);
|
||||
if r > 2 then
|
||||
return;
|
||||
end
|
||||
r = rnd(6);
|
||||
return s.lf[r];
|
||||
end,
|
||||
nam = 'Барсик',
|
||||
lf = {
|
||||
[1] = 'Барсик шевелится у меня за пазухой.',
|
||||
[2] = 'Барсик выглядывает из-за пазухи.',
|
||||
[3] = 'Барсик мурлычит у меня за пазухой.',
|
||||
[4] = 'Барсик дрожит у меня за пазухой.',
|
||||
[5] = 'Я чувствую тепло Барсика у себя за пазухой.',
|
||||
[6] = 'Барсик высовывает голову из-за пазухи и осматривает местность.',
|
||||
},
|
||||
life = function(s)
|
||||
local r = rnd(6);
|
||||
if r > 2 then
|
||||
return;
|
||||
end
|
||||
r = rnd(6);
|
||||
return s.lf[r];
|
||||
end,
|
||||
....
|
||||
|
||||
profdlg2 = dlg {
|
||||
nam = 'Белин',
|
||||
dsc = 'Белин бледен. Он смотрит на дробовик рассеянным взглядом.',
|
||||
obj = {
|
||||
[1] = phr('Я пришел за своим котом.',
|
||||
'Я выхватываю Барсика из руки Белина и засовываю себе за пазуху.',
|
||||
[[inv():add('mycat'); lifeon('mycat')]]),
|
||||
nam = 'Белин',
|
||||
dsc = 'Белин бледен. Он смотрит на дробовик рассеянным взглядом.',
|
||||
obj = {
|
||||
[1] = phr('Я пришел за своим котом.',
|
||||
'Я выхватываю Барсика из руки Белина и засовываю себе за пазуху.',
|
||||
[[inv():add('mycat'); lifeon('mycat')]]),
|
||||
....
|
||||
</code>
|
||||
Любой объект или сцена могут иметь свой обработчик life, который вызывается каждый раз при смене текущего времени игры, если объект или сцена были добавлены в список живых объектов с помощью lifeon. Не забывайте удалять живые объекты из списка с помощью lifeoff, когда они больше не нужны. Это можно сделать, например, в обработчике exit, или любым другим способом.
|
||||
|
@ -705,9 +705,9 @@ return 'В комнату вошел охранник.', true
|
|||
|
||||
<code>
|
||||
home = room {
|
||||
pic = 'gfx/home.png',
|
||||
nam = 'дома',
|
||||
dsc = 'Я у себя дома',
|
||||
pic = 'gfx/home.png',
|
||||
nam = 'дома',
|
||||
dsc = 'Я у себя дома',
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -719,7 +719,7 @@ home = room {
|
|||
Начиная с версии 0.9.2 вы можете встраивать графические изображения в текст или в инвентарь с помощью функции img. Например:
|
||||
<code>
|
||||
knife = obj {
|
||||
nam = 'Нож'..img('img/knife.png'),
|
||||
nam = 'Нож'..img('img/knife.png'),
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -734,12 +734,12 @@ set_music(имя музыкального файла).
|
|||
Например:
|
||||
<code>
|
||||
street = room {
|
||||
pic = 'gfx/street.png',
|
||||
enter = function()
|
||||
set_music('mus/rain.ogg');
|
||||
end,
|
||||
nam = 'на улице',
|
||||
dsc = 'На улице идет дождь.',
|
||||
pic = 'gfx/street.png',
|
||||
enter = function()
|
||||
set_music('mus/rain.ogg');
|
||||
end,
|
||||
nam = 'на улице',
|
||||
dsc = 'На улице идет дождь.',
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -764,8 +764,8 @@ is_music() позволяет узнать, проигрывается ли му
|
|||
Например:
|
||||
<code>
|
||||
main = room {
|
||||
nam = 'Intro',
|
||||
dsc = txtc('Добро пожаловать!'),
|
||||
nam = 'Intro',
|
||||
dsc = txtc('Добро пожаловать!'),
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -778,8 +778,8 @@ main = room {
|
|||
Например:
|
||||
<code>
|
||||
main = room {
|
||||
nam = 'Intro',
|
||||
dsc = 'Вы находитесь в комнате '..txtb('main')..'.',
|
||||
nam = 'Intro',
|
||||
dsc = 'Вы находитесь в комнате '..txtb('main')..'.',
|
||||
}
|
||||
|
||||
Начиная с версии 1.1.0 вы также можете создавать неразрываемые строки с помощью: txtnb();
|
||||
|
@ -789,33 +789,33 @@ main = room {
|
|||
Вы можете делать меню в области инвентаря, определяя объекты с типом menu. При этом, обработчик меню будет вызван после одного клика мыши. Если обработчик не возвращает текст, то состояние игры не изменяется. Например, реализация кармана:
|
||||
<code>
|
||||
pocket = menu {
|
||||
State = false,
|
||||
nam = function(s)
|
||||
if s.State then
|
||||
return txtu('карман');
|
||||
end
|
||||
return 'карман';
|
||||
end,
|
||||
gen = function(s)
|
||||
if s.State then
|
||||
s:enable_all();
|
||||
else
|
||||
s:disable_all();
|
||||
end
|
||||
end,
|
||||
menu = function(s)
|
||||
if s.State then
|
||||
s.State = false;
|
||||
else
|
||||
s.State = true;
|
||||
end
|
||||
s:gen();
|
||||
end,
|
||||
State = false,
|
||||
nam = function(s)
|
||||
if s.State then
|
||||
return txtu('карман');
|
||||
end
|
||||
return 'карман';
|
||||
end,
|
||||
gen = function(s)
|
||||
if s.State then
|
||||
s:enable_all();
|
||||
else
|
||||
s:disable_all();
|
||||
end
|
||||
end,
|
||||
menu = function(s)
|
||||
if s.State then
|
||||
s.State = false;
|
||||
else
|
||||
s.State = true;
|
||||
end
|
||||
s:gen();
|
||||
end,
|
||||
};
|
||||
|
||||
knife = obj {
|
||||
nam = 'нож',
|
||||
inv = 'Это нож',
|
||||
nam = 'нож',
|
||||
inv = 'Это нож',
|
||||
};
|
||||
|
||||
inv():add(pocket);
|
||||
|
@ -823,7 +823,7 @@ put(knife, pocket);
|
|||
pocket:gen();
|
||||
|
||||
main = room {
|
||||
nam = 'test',
|
||||
nam = 'test',
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -835,9 +835,9 @@ pl.Life = 10;
|
|||
pl.Power = 10;
|
||||
|
||||
status = obj {
|
||||
nam = function(s)
|
||||
return 'Жизнь: '..pl.Life..',Сила: '..pl.Power
|
||||
end
|
||||
nam = function(s)
|
||||
return 'Жизнь: '..pl.Life..',Сила: '..pl.Power
|
||||
end
|
||||
};
|
||||
inv():add('status');
|
||||
status.object_type = false
|
||||
|
@ -849,9 +849,9 @@ pl.Life = 10;
|
|||
pl.Power = 10;
|
||||
|
||||
status = stat {
|
||||
nam = function(s)
|
||||
return 'Жизнь: '..pl.Life..',Сила: '..pl.Power
|
||||
end
|
||||
nam = function(s)
|
||||
return 'Жизнь: '..pl.Life..',Сила: '..pl.Power
|
||||
end
|
||||
};
|
||||
inv():add('status');
|
||||
</code>
|
||||
|
@ -861,8 +861,9 @@ inv():add('status');
|
|||
Если вы выполните goto из обработчика exit, то получите переполнение стека, так как goto снова и снова будет вызывать метод exit. Вы можете избавиться от этого, если вставите проверку, разрушающую рекурсию. Например:
|
||||
<code>
|
||||
exit = function(s, t)
|
||||
if t == 'dialog' then return; end
|
||||
return goto('dialog');
|
||||
if t == 'dialog' then return; end
|
||||
return goto('dialog');
|
||||
end
|
||||
</code>
|
||||
Начиная с версии 0.9.1 движок сам разрывает рекурсию.
|
||||
|
||||
|
@ -880,27 +881,27 @@ home.obj:del('Дорога');
|
|||
Для определения наличия ссылки в сцене -- метод srch.
|
||||
<code>
|
||||
if not home.obj:srch('Дорога') then
|
||||
home.obj:add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
|
||||
home.obj:add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
|
||||
end
|
||||
</code>
|
||||
Динамические ссылки удобно создавать в обработчике enter, или по мере необходимости в любом месте кода игры. Если ссылки создаются в текущей сцене, то последний пример можно упростить:
|
||||
<code>
|
||||
if not seen('Дорога') then
|
||||
objs():add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
|
||||
objs():add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
|
||||
end
|
||||
</code>
|
||||
Кроме того, вы можете просто включать и выключать ссылки с помощью enable(), disable(), например:
|
||||
<code>
|
||||
objs()[1]:disable();
|
||||
objs()[1]:disable();
|
||||
</code>
|
||||
|
||||
Вы можете создавать выключенные vobj и vway следующим образом:
|
||||
<code>
|
||||
obj = {vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'):disable()},
|
||||
obj = {vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'):disable()},
|
||||
</code>
|
||||
И затем включать их по индексу в массиве obj:
|
||||
<code>
|
||||
objs()[1]:enable();
|
||||
objs()[1]:enable();
|
||||
</code>
|
||||
|
||||
==== Кодирование исходного кода игры (начиная с версии 0.9.3) ====
|
||||
|
@ -922,22 +923,23 @@ doencfile("game");
|
|||
==== Использование первого параметра обработчика ====
|
||||
Пример кода.
|
||||
<code>
|
||||
knife = obj {
|
||||
nam = 'камень',
|
||||
dsc = 'На краю лежит {камень}.',
|
||||
act = function()
|
||||
objs():del('knife');
|
||||
return 'Я толкнул камень, он сорвался и улетел вниз...';
|
||||
end
|
||||
stone = obj {
|
||||
nam = 'камень',
|
||||
dsc = 'На краю лежит {камень}.',
|
||||
act = function()
|
||||
objs():del('stone');
|
||||
return 'Я толкнул камень, он сорвался и улетел вниз...';
|
||||
end
|
||||
</code>
|
||||
|
||||
Обработчик act мог бы выглядеть проще:
|
||||
<code>
|
||||
act = function(s)
|
||||
objs():del(s);
|
||||
return 'Я толкнул камень, он сорвался и улетел вниз...';
|
||||
end
|
||||
act = function(s)
|
||||
objs():del(s);
|
||||
return 'Я толкнул камень, он сорвался и улетел вниз...';
|
||||
end
|
||||
</code>
|
||||
|
||||
==== Использование set_music ====
|
||||
Вы можете использовать set_music для проигрывания звуков, задавая второй параметр -- счетчик циклов проигрывания звукового файла.
|
||||
|
||||
|
@ -946,20 +948,20 @@ knife = obj {
|
|||
-- играет треки в случайном порядке, начиная со 2-го
|
||||
tracks = {"mus/astro2.mod", "mus/aws_chas.xm", "mus/dmageofd.xm", "mus/doomsday.s3m"}
|
||||
mplayer = obj {
|
||||
nam = 'плеер',
|
||||
life = function(s)
|
||||
local n = get_music();
|
||||
local v = get_music_loop();
|
||||
if not n or not v then
|
||||
set_music(tracks[2], 1);
|
||||
elseif v == -1 then
|
||||
local n = get_music();
|
||||
while get_music() == n do
|
||||
n = tracks[rnd(4)]
|
||||
end
|
||||
set_music(n, 1);
|
||||
end
|
||||
end,
|
||||
nam = 'плеер',
|
||||
life = function(s)
|
||||
local n = get_music();
|
||||
local v = get_music_loop();
|
||||
if not n or not v then
|
||||
set_music(tracks[2], 1);
|
||||
elseif v == -1 then
|
||||
local n = get_music();
|
||||
while get_music() == n do
|
||||
n = tracks[rnd(4)]
|
||||
end
|
||||
set_music(n, 1);
|
||||
end
|
||||
end,
|
||||
};
|
||||
lifeon('mplayer');
|
||||
</code>
|
||||
|
@ -968,20 +970,20 @@ lifeon('mplayer');
|
|||
|
||||
<code>
|
||||
function save_music(s)
|
||||
s.OldMusic = get_music();
|
||||
s.OldMusicLoop = get_music_loop();
|
||||
s.OldMusic = get_music();
|
||||
s.OldMusicLoop = get_music_loop();
|
||||
end
|
||||
|
||||
function restore_music(s)
|
||||
set_music(s.OldMusic, s.OldMusicLoop);
|
||||
set_music(s.OldMusic, s.OldMusicLoop);
|
||||
end
|
||||
|
||||
-- ....
|
||||
enter = function(s)
|
||||
save_music(s);
|
||||
save_music(s);
|
||||
end,
|
||||
exit = function(s)
|
||||
restore_music(s);
|
||||
restore_music(s);
|
||||
end,
|
||||
-- ....
|
||||
|
||||
|
@ -993,17 +995,18 @@ end,
|
|||
Если вашему герою нужен друг, одним из способов может стать метод life этого персонажа, который всегда переносит объект в локацию игрока:
|
||||
<code>
|
||||
horse = obj {
|
||||
nam = 'лошадь',
|
||||
dsc = 'Рядом со мной стоит {лошадь}.',
|
||||
life = function(s)
|
||||
if not seen('horse') then
|
||||
move('horse', here(), s.__where);
|
||||
s.__where = pl.where;
|
||||
end
|
||||
end,
|
||||
nam = 'лошадь',
|
||||
dsc = 'Рядом со мной стоит {лошадь}.',
|
||||
life = function(s)
|
||||
if not seen('horse') then
|
||||
move('horse', here(), s.__where);
|
||||
s.__where = pl.where;
|
||||
end
|
||||
end,
|
||||
};
|
||||
lifeon('horse');
|
||||
</code>
|
||||
|
||||
==== Таймер ====
|
||||
Начиная с версии 1.1.0 в instead появлилась возможность использовать таймер. (Только в графической версии интерпретатора.)
|
||||
|
||||
|
@ -1025,7 +1028,7 @@ main = room {
|
|||
force_dsc = true,
|
||||
nam = 'Таймер',
|
||||
dsc = function(s)
|
||||
return 'Демонстрация: '..tostring(s._time);
|
||||
return 'Демонстрация: '..tostring(s._time);
|
||||
end
|
||||
};
|
||||
</code>
|
||||
|
@ -1039,26 +1042,26 @@ input.key(s, pressed, key) -- обработчик клавиатуры; pressed
|
|||
Например:
|
||||
<code>
|
||||
input.key = function(s, pr, key)
|
||||
if not pr or key == "escape"then
|
||||
return
|
||||
elseif key == 'space' then
|
||||
key = ' '
|
||||
elseif key == 'return' then
|
||||
key = '^';
|
||||
end
|
||||
if key:len() > 1 then return end
|
||||
main._txt = main._txt:gsub('_$','');
|
||||
main._txt = main._txt..key..'_';
|
||||
return "look";
|
||||
if not pr or key == "escape"then
|
||||
return
|
||||
elseif key == 'space' then
|
||||
key = ' '
|
||||
elseif key == 'return' then
|
||||
key = '^';
|
||||
end
|
||||
if key:len() > 1 then return end
|
||||
main._txt = main._txt:gsub('_$','');
|
||||
main._txt = main._txt..key..'_';
|
||||
return "look";
|
||||
end
|
||||
|
||||
main = room {
|
||||
_txt = '_',
|
||||
force_dsc = true,
|
||||
nam = 'Клавиатура',
|
||||
dsc = function(s)
|
||||
return 'Демонстрация: '..tostring(s._txt);
|
||||
end
|
||||
_txt = '_',
|
||||
force_dsc = true,
|
||||
nam = 'Клавиатура',
|
||||
dsc = function(s)
|
||||
return 'Демонстрация: '..tostring(s._txt);
|
||||
end
|
||||
};
|
||||
</code>
|
||||
|
||||
|
@ -1067,7 +1070,7 @@ main = room {
|
|||
|
||||
input.click(s, pressed, mb, x, y, px, py) -- обработчик клика мыши; pressed -- нажатие или отжатие. mb -- номер кнопки (1 - левая), x и y -- координаты клика относительно левого верхнего угла. px и py присутствуют, если клик произошел в области картинки сцены и содержит координаты клика относительно левого верхнего угла картинки.
|
||||
|
||||
Обработчик может вернуть команду интерфейса stead, в этом случае клик не будет обработана интерпретатором.
|
||||
Обработчик может вернуть команду интерфейса stead, в этом случае клик не будет обработан интерпретатором.
|
||||
|
||||
Например:
|
||||
<code>
|
||||
|
@ -1135,10 +1138,10 @@ delete(n)
|
|||
new воспринимает строку-аргумент как конструктор объекта. Результатом выполнения конструктора должен быть объект. Таким образом в аргументе обычно задан вызов функции-конструктора. Например:
|
||||
<code>
|
||||
function myconstructor()
|
||||
local v = {}
|
||||
v.nam = 'тестовый объект',
|
||||
v.act = 'Тестовая реакция',
|
||||
return obj(v);
|
||||
local v = {}
|
||||
v.nam = 'тестовый объект',
|
||||
v.act = 'Тестовая реакция',
|
||||
return obj(v);
|
||||
end
|
||||
</code>
|
||||
Созданный объект будет попадать в файл сохранения. new() возвращает реальный объект; чтобы получить его имя, если это нужно, используйте функцию deref:
|
||||
|
@ -1150,24 +1153,26 @@ delete(o_name);
|
|||
Иногда вывод обработчика может формироваться сложным образом, в зависимости от условий. В таких случаях удобно пользоваться функциями p() и pn(). Эти функции добавляют текст в буфер, связанный с обработчиком, который будет возвращен из обработчика.
|
||||
<code>
|
||||
dsc = function(s)
|
||||
p "На полу стоит {бочка}."
|
||||
if s._opened then
|
||||
p "Крышка от бочки лежит рядом."
|
||||
end
|
||||
p "На полу стоит {бочка}."
|
||||
if s._opened then
|
||||
p "Крышка от бочки лежит рядом."
|
||||
end
|
||||
end
|
||||
</code>
|
||||
Функция pn() выполняет вывод текста в буфер, дополняя его переводом строки. Функция p() дополняет вывод пробелом.
|
||||
|
||||
Начиная с версии 1.1.6 существует функция pr(), которая не выполняет дополнение вывода.
|
||||
|
||||
Для очистки буфера, используйте pclr(). Если вам нужно вернуть статус действия, используйте pget().
|
||||
<code>
|
||||
use = function(s, w)
|
||||
if w == 'apple' then
|
||||
p 'Гм... Я почистил яблоко.';
|
||||
apple._peeled = true
|
||||
return
|
||||
end
|
||||
p 'Это нельзя использовать так!'
|
||||
return pget(), false
|
||||
if w == 'apple' then
|
||||
p 'Гм... Я почистил яблоко.';
|
||||
apple._peeled = true
|
||||
return
|
||||
end
|
||||
p 'Это нельзя использовать так!'
|
||||
return pget(), false
|
||||
end
|
||||
</code>
|
||||
|
||||
|
|
Loading…
Reference in a new issue