Десять уроков скриптинга (Урок 1)

Materials, references, tutorials

Moderators: Murderator+, Murderator

Edred
Expert!
Posts: 2544
Joined: 2004-04-03 17:36:29
Location: Saint-Petersburg

Десять уроков скриптинга (Урок 1)

Post by Edred »

ДЕСЯТЬ УРОКОВ СКРИПТИНГА В ИНЖЕКТЕ


Урок 1. Самая важная команда, синтаксис и "Hello, shard!"


Итак, вы стали счастливым обладателем инжекта, вам удалось его настроить (или для вас это сделал кто-то другой ;) ), вы прочитали справочник по инжекту (составленный мной), более-менее разобрались в его менюшках и настройках… Но самое главное - скрипты - для вас все еще тайна за семью печатями? Ну что ж, этот небольшой учебник поможет вам освоить азы программирования на инжекте. Я не буду пытаться охватить все команды инжекта, но я покажу вам как пользоваться основными командами, а дальше… дальше вы уже сами.

А начнем мы с самой важной команды скриптов. Команды, без которой не обходится, фактически, ни один скрипт. Команды, которую вы можете использовать только в скриптах - большинство команд инжекта имеют как форму для скриптов, так и "консольную" форму, то есть вы их можете писать прямо в клиенте и запускать. Многие мелкие скрипты, кстати, именно так и устроены. При бинде их на клавишу просто перечисляются команды инжекта и вуаля - скрипт готов. Но я отвлекся. Так вот, эту команду в консоли вы написать не можете. Как некоторые из вас уже наверно догадались, это команда Wait() - пауза.

Wait() - ждать заданное количество миллисекунд.

Внутри скобок этой команды надо указать ей параметр - сколько миллисекунд ждать. 1 секунда - это 1000 миллисекунд. Поэтому Wait(1000) - это ждать 1 секунду. В конце этого урока я приведу пример как не надо писать скрипты. А именно - скрипт который совершенно надежно подвешивает компьютер, на котором он запущен. И ошибка того скрипта в том, что в нем нету команды wait в нужном месте. Причем с самым маленьким параметром времени. Хотя бы wait(50) - и скрипт уже не подвесит вашу систему.

Паузы очень важны в ваших скриптах. Во-первых, нужно дожидаться, пока игра совершит какое-либо действие. Во-вторых, надо дожидаться появления какого-либо сообщения. В-третьих, надо дожидаться появления какого-либо чара или животного - в основном все скрипты состоят из пауз. Причем в начале, пока вы неопытны, вы будете использовать в основном фиксированные паузы, типа wait(4000) - ждать 4 секунды (именно столько вам надо ждать на Цитадели, чтобы сработал скил Хайдинг), в дальнейшем вы быстрее всего перейдете на использование динамических пауз - то есть пауз, длина которых заранее не определена, это просто паузы пока не совершится какое-либо событие. Но в основе этих динамических пауз все равно вы найдете команду wait.

Вот теперь пора познакомиться с синтаксисом скриптов инжекта.

Для начала, несколько слов о терминологии. Скрипт - это программа. Написанная на специальном языке. Основой для этого языка стал язык программирования Basic, причем в самой простой своей форме. Еще вам будут постоянно встречаться такие понятия, как функции и процедуры. По определению, функция получает какие-то параметры, обрабатывает их и возвращает какое-то значение. Процедура от функции отличается тем, что ничего не возвращает. На самом деле, разницы между процедурами и функциями никакой нету. Это те же самые скрипты. Или программы, как хотите. Зачастую функция, которая, по идее, что-то возвращает, будет вами использоваться как процедура - ну не нужен нам этот результат. А из процедуры можно вернуть результат "непрямым" способом. Да и параметры не обязательны. Головной скрипт (главный) - это тоже, фактически, процедура. Поэтому, если путаетесь - плюньте. Даже опытные программисты постоянно в этих терминах путаются и называют одно другим. Неважно. Главное - знать что все это отдельные программы.

Любой скрипт (программа) на языке скриптов инжекта всегда начинается с команды sub и заканчивается командой endsub. Скрипты пишутся в текстовые файлы, в одном файле может быть очень много скриптов (я даже затрудняюсь сказать сколько, у меня есть скрипта на 3000 строк кода, там этих функций и процедур под сотню, и ничего, все нормально живет в одном файле). Итак, любой скрипт должен выглядеть так:

Code: Select all

sub MyScript()
   ……….
endsub


Тут есть одна тонкость, запомните ее на будущее - если вы напишете команду sub вначале скрипта с заглавной буквы, то есть Sub - этот скрипт не будет отражаться в списке скриптов, доступных к запуску в инжекте, но при этом будет спокойно запускаться из других скриптов. Поэтому многие скриптеры "прячут" свои функции и процедуры именно таким образом, чтобы они "не мешали" в списке скриптов к запуску.

После команды sub через пробел пишется имя этого скрипта. После имени указываются круглые скобки, в которые могут быть помещены 1 или несколько имен переменных для параметров скрипта. Если это функция или процедура. :) (снова читаем тремя абзацами выше).

Но к параметрам мы еще вернемся. А пока давайте напишем самый первый скрипт, используя те знания, что уже получили:

Code: Select all

sub MyWait()
   wait(3000)
endsub


Этот скрипт делает всего одну вещь - он ждет 3 секунды. То есть ничего не делает. Но работает. :) Понятное дело, совершенно бесполезный скрипт. Пауза всегда нужна для чего-то, сама по себе она не нужна. Но ничего, счас изучим еще одну команду и сделаем первый рабочий скрипт. Эта команда – UO.Print(). Вывести сообщение.

UO.Print() – вывести информационное сообщение в игре

Внутри скобок этой команды надо указать сообщение в кавычках и вы получите в игре это сообщение. Его видите только вы и на сервер оно не направляется. Например UO.Print( 'Privet' ) – выведет сообщение 'Privet'. Кавычки вы можете использовать как одинарные (апостроф), так и двойные - главное чтобы они были одинаковые в начале и в конце выражения. Давайте вставим такую команду в наш скрипт.

Code: Select all

sub MyMessage()
   UO.Print( "Hello, shard!" )
   wait(3000)
endsub


Если вы сохраните и запустите этот скрипт он вам выдаст сообщение Hello, Shard!, потом подождет 3 сек (зачем-то) и закончит работу. Пауза здесь, как понятно, опять же не у дел. Но не будем ее трогать, а просто добавим еще одну команду UO.Print.

Code: Select all

sub MyMessage()
   UO.Print( "Hello, shard!" )
   wait(3000)
   UO.Print( "I go!" )
endsub


Вот теперь все встало на свои места. Скрипт говорит: "привет, шард", ждет три секунды и добавляет: "я иду"... :)

Все было бы хорошо, но вот только ваше приветствие кроме вас никто и не увидит... Лучше бы было, если бы эти фразы произносил ваш чар, тогда все кто рядом будут их "слышать". Нет проблем:

UO.Say() - произнести фразу чаром в игре

Так что если мы заменим в нашей программе UO.Print на UO.Say - получится то, что надо.

Code: Select all

sub MyMessage()
   UO.Say( "Hello, shard!" )
   wait(3000)
   UO.Say( "I go!" )
endsub


На самом деле язык скриптов инжекта содержит множество разных команд, которые позволяют выводить, говорить чаром, говорить минуя чара в игре и т. д. Потом, может быть, мы к этой теме еще вернемся, а пока этих двух команд нам вполне хватит.

Продолжим рассматривать синтаксис скриптов. Теперь поговорим о переменных. Переменная - это какое-то имя, заданное вами, которому в скрипте вы можете присваивать различные значения. Перед использованием переменную нужно создать. В более сложных языках программирования переменные обычно надо задавать указывая их тип: числовые, строковые и т. д. В инжекте вам это не требуется. Главное - ее создать. Создать ее можно перед самим использованием, но хорошей привычкой будет создавать все нужные вам переменные (пока не станете опытным скриптописателем) в начале скрипта. Для этого используется оператор VAR:

VAR myvar1, myvar2, myvar3 ...

Имена myvar1 и т.д. - это просто пример имен. Имя может быть любым, главное чтобы оно состояло из английских букв и цифр и не имело пробелов. Дефисы тоже допустимы. Цифру в начало имени не ставим.

Значение переменной присваивается знаком равно (=). Это можно сделать отдельной строкой, а можно сделать в операторе VAR:

VAR i = 1, mymessage1 = 'Hello, Shard!', mymessage2 = "I go!"

Вот тут переменная i числовая, мы ей присвоили единицу, остальные две переменные строковые - им мы присвоили свои сообщения. Естественно, в скрипте мы можем присвоить переменной новое значение в любой момент. Для этого ее создавать снова не надо, достаточно в отдельной строке скрипта написать:

i = 2

И все. Давайте перепишем наш скрипт на приветствие через переменные:

Code: Select all

sub MyMessage()
   VAR mymessage1 = 'Hello, Shard!', mymessage2 = "I go!"
   UO.Say( mymessage1 )
   wait(3000)
   UO.Say( mymessage2 )
endsub


Теперь мы передаем командам UO.Say не конкретный текст, а имена переменных, этот текст содержащих. По фигу. Одно и тоже.

Вот теперь стоит вернуться к функциям и процедурам. Давайте посмотрим как нам их писать (возращаемые значения пока рассматривать не будем, так что речь идет о процедурах).

Code: Select all

sub MyMessage()
   VAR mymessage1 = 'Hello, Shard!', mymessage2 = "I go!"
   MySay( mymessage1 )
   MySay( mymessage2 )
endsub

sub MySay( myparam )
   UO.Say( myparam )
   wait(1000)
endsub


У нас теперь два скрипта. Первый - основной, в нем мы создаем две переменных с приветствиями, и дважды вызываем процедуру MySay, передавая ей в качестве параметра имя переменной с сообщением. Потом у нас идет эта процедура, в имени которой в качестве параметра написано myparam - это мы определили новую переменную, в которую будет попадать параметр, переданный в эту процедуру. То есть текстовую строку. А дальше - процедура выводит ее на экран и ждет 1 сек.

Кстати, созданные вами переменные действуют только в пределах того скрипта (функции, процедуры), в которой вы их создали. В другом скрипте вы можете снова использовать эти же имена - это все равно будут другие переменные.

Вот с этим (все что выше) вам надо очень внимательно разорбраться. В дальнейшем я подобные вещи подробно расписывать не буду. Так что если хоть что-то осталось непонятно - перечитайте еще раз, попробуйте сами.

Теперь несколько слов о тех переменных, которые уже существуют в инжекте. Вы не можете использовать их имена, но вы можете использовать значения этих переменных просто указав в скрипте их имя. Перечислю основные:

UO.Life - текущее здоровье вашего чара
UO.Mana - текущее количество маны вашего чара
UO.Stamina - текущее количество стамины вашего чара
UO.STR - уровень силы вашего чара
UO.INT - уровень интеллекта вашего чара
UO.DEX - уровень ловкости вашего чара
UO.Weight - вес вашего чара
UO.Armor - текущий армор-класс вашего чара
UO.Gold - суммарное количество денег (бэкпак и банк) вашего чара
UO.BM - количество рега bloodmoss в паке у вашего чара
UO.BP - количество рега black pearl в паке у вашего чара
UO.GA - количество рега garlic в паке у вашего чара
UO.GS - количество рега ginseng в паке у вашего чара
UO.MR - количество рега mandrake root в паке у вашего чара
UO.NS - количество рега nightshade в паке у вашего чара
UO.SA - количество рега sulfurous ash в паке у вашего чара
UO.SS - количество рега spider's silk в паке у вашего чара
UO.VA - количество паган рега volcanic ash в паке у вашего чара
UO.EN - количество паган рега eyes of newt в паке у вашего чара
UO.WH - - количество паган рега wyrm's heart в паке у вашего чара
UO.FD - количество паган рега blackmoor в паке у вашего чара
UO.BR - количество паган рега fertile dirt в паке у вашего чара
UO.H - количество поушенов heal в паке у вашего чара
UO.C - количество поушенов cure в паке у вашего чара
UO.M - количество поушенов mana в паке у вашего чара
UO.L - количество поушенов refresh в паке у вашего чара
UO.B - количество бинтов в паке у вашего чара
UO.AR - количество стрел в паке у вашего чара
UO.BT - количество болтов в паке у вашего чара


Вы не можете изменять эти переменные, они автоматически изменяются в игре, но вы можете использовать их в своих скриптах. Не буду приводить примера, тут и так все ясно. Позже в примерах мы будем эти переменные активно использовать.

Теперь посмотрим как устроен скрипт. В скрипте каждая команда должна идти на отдельной строке, объединять несколько команд в одну строку нельзя. Если вам нужно просто выполнить несколько команд по очереди - это самый простейший вид скриптов, то вы пишете каждую команду в отдельную строку (именно так мы и делали в скрипте на приветствие) и все. Но такое требуется редко. Обычно в скриптах нужно проверять выполнение каких-нибудь условий, в зависимости от этого выполнять разные действия, повторять какой-то набор действий либо фиксированное количество раз, либо пока не выполнится определенное условие. Для этого нам потребуются условные операторы и циклы.

Простейший условный оператор - If. Выглядит он так:

Code: Select all

If условие Then
   .........
Endif


Если условие выполняется тогда делать то-то и то-то. Расширенный вариант этого условного оператора:

Code: Select all

If условие Then
   ...........
Else
   ...........
Endif


Если условие выполняется тогда делать то-то и то-то, иначе (если условие не выполняется) - делать другое что-то. Условный оператор If является простейшим способом проверки выполнения условия. И одним из основных. Давайте переделаем наш пример на приветствие с использованием проверки условия. При этом введем еще переменную i которой в начале присвоим 1.

Code: Select all

sub MyMessage()
   VAR i = 1
   VAR mymessage1 = 'Hello, Shard!', mymessage2 = "I go!"
   If i == 1 Then
      UO.Say( mymessage1 )
   Else
      UO.Say( mymessage2 )
   Endif
endsub


Внимательно посмотрите на пример. Во-первых, у нас появилось две строки с VAR. Их вообще может быть сколько угодно. Во-вторых, условие в If. Тут мы используем знак == - сравнение двух значений. Не путайте его с присваиванием (=). Если написать If i = 1 Then - вы получите ошибку. Что теперь делает наш скрипт? На самом деле он выводит только первое приветствие, второе не будет выводиться никогда. Разберитесь сами почему. Попробуйте в строке VAR i = 1 единицу заменить на 2. Посмотрите на результат. А я иду дальше.

Следующим оператором, важным для скриптинга в инжекте является while.

Code: Select all

While условие
   ...
Wend


Повторять действия до тех пор, пока выполняется условие. Проверка условия производится перед выполнением действий! То есть если условие не выполняется - никаких действий не будет. Скрипт сразу перейдет на следующую команду, расположенную сразу за словом wend. Вот теперь мы можем переделать наш скрипт на новый лад.

Code: Select all

sub MyMessage()
   VAR i = 1
   VAR mymessage1 = 'Hello, Shard!', mymessage2 = "I go!"
   While i < 3
      If i == 1 Then
         UO.Say( mymessage1 )
      Else
         UO.Say( mymessage2 )
      Endif
      i = i + 1
   Wend
endsub


Вот тут рассмотрим работу скрипта подробнее. Вначале у нас переменная i равна 1. Приходим к while. Проверяется i, меньше ли оно 3. 1 меньше чем 3, значит все что между while и wend будет выполняться. Здесь проверяется - равно ли i единице - равно. Поэтому сработает команда UO.Say( mymessage1 ). В результате чар скажет первое приветственное сообщение. Выход из if - следующий оператор i = i + 1. В нем переменная i будет увеличена на 1. Это стандартный способ увеличения счетчиков (такие переменные в скритптах обычно называют счетчиками) на какую-то величину. То есть к переменной i прибавляется 1 и результат сложения записывается в переменную i. В результате в переменная i будет равна 2. Дальше следует wend - значит переходим снова к строке While i < 3. Это условие опять выполняется (2 меньше 3). Теперь проверяется условие If. 2 не равно 1, поэтому условие не выполняется и будет выполнено действие после Else. То есть UO.Say( mymessage2 ) - получим на экране второе приветственное сообщение. Теперь опять счетчик увеличивается на 1 - i будет равно 3. Опять переходим на проверку условия в While - вот теперь оно не выполняется (3 не меньше 3) - соответсвенно сразу переходим на оператор после wend - а там у нас конец скрипта.

Разбирайтесь с этим примером столько раз, сколько потребуется чтобы все понять. Очень мало будет вам встречаться скриптов в которых нету операторов if, while и оператора repeat - аналогичного оператору while с некоторыми изменениями.

Code: Select all

repeat
   ....................
until условие


Выполнять действия пока условие НЕ выполняется. Проверка условия производится после действий! Этот оператор отличается от while - только этими двумя вещами, названными мной, но при этом это отличие принципиальное! Давайте рассмотрим маленький пример.

Code: Select all

while i < 3
   wait( 1000)
wend

Code: Select all

repeat
   wait(1000)
until i > 2


Вот два цикла. Условие в обоих одно и то же по действию - в первом случае цикл выполняется пока i меньше 3, во втором случае пока не выполняется i > 2. То есть пока i < 3. Проще всего это понять подставив вместо i разные числа. Если например i равняется 2: 2 меньше 3 - это верно, while выполняется. 2 не больше 2 - то есть условие в until не выполняется - значит действия в repeat выполняются. Понятно? Вот теперь насчет "после". Предположим, что i равно 3. Что у нас происходит? В цикле while проверка производится перед действиями - так как 3 не меньше 3, то никаких действий не производится, скрипт сразу переходит к командам после wend. В случае же repeat - проверка производится после действий, поэтому одна пауза в 1 секунду все равно будет выполнена! После этого проверка 3 > 2 выдаст истину и цикл repeat будет прерван. Итак, цикл repeat важен тем, что указанные в нем действия будут выполняться по крайней мере 1 раз!

Вот мы и подбираемся к концу первого урока. Это далеко не все операторы языка скриптов инжекта, но пока нам хватит и их. Другие операторы мы рассмотрим позже. А счас, как и обещал в начале, привожу пример (у вас достаточно знаний чтобы этот скрипт понять) скрипта, как не надо писать скрипты :)

Code: Select all

sub MyScript()
   While UO.Life > 0
      If UO.Life < 70 Then
         UO.Bandageself()
         wait(2000)
      Endif
   Wend
endsub


Этот скрипт - это попытка написать автополхилл чара. Цикл while "крутится" пока здоровья больше 0, то есть пока чар не умрет. Если здоровья становится меньше 70 - чар лечится с бинтов (именно это и делает команда UO.Bandageself() ). В чем же ошибка этого скрипта? Эта ошибка называется "пустой цикл". Давайте проверим, что происходит во время работы этого скрипта. А именно, если здоровья у чара больше 70 (или равно). В этом случае действия внутри if...endif не выполняются, и цикл while...wend становится пустым, то есть в нем не производится никаких действий. Скриптовый модуль инжекта устроен так, что в этом случае вы получите 100%-загрузку процессора вашего компьютера (зависнет) и, быстрее всего, креш игры или системы. Как избежать такого конца? Очень просто. Предусмотреть чтобы в скрипте всегда какие-нибудь действия производились. В данном случае вполне достаточно добавить Else:

Code: Select all

sub MyScript()
   While UO.Life > 0
      If UO.Life < 70 Then
         UO.Bandageself()
         wait(2000)
      Else
         wait(50)
      Endif
   Wend
endsub


Вот смотрите: мы добавили в скрипт паузу в 50 миллисекунд, то есть 0,005 секунды, а скрипт сразу заработал.

Ну и напоследок. Обратите внимание на то, как я привожу скрипты. А именно на отступы. Старайтесь сразу приучить себя использовать подобный стиль написания. Это облегчит понимание скриптов и вам, и тем другим, кто их будет смотреть. А чем легче читается скрипт, тем проще найти в нем ошибки.
666Man666
Junior Expert
Posts: 474
Joined: 2004-11-13 00:43:55
Location: Киберзадроцк
Contact:

Post by 666Man666 »

Хорошо поработал, а типерь для иностранцев переведи это, чтобы не обделять :P
Edred
Expert!
Posts: 2544
Joined: 2004-04-03 17:36:29
Location: Saint-Petersburg

Post by Edred »

666Man666 wrote:Хорошо поработал, а типерь для иностранцев переведи это, чтобы не обделять :P


Кто-нибудь другой пусть займется. Мне еще 9 уроков писать. От второго пока только половинка написана.

А вообще здесь это особо никому явно не надо. Параллельно этот текст публикуется на форуме шарда Цитадель, так там это вызвало обсуждение, а здесь никто даже не удосужился прочитать и обратить мое внимание на описки.
I'm
Expert!
Posts: 1396
Joined: 2004-10-15 22:38:04
Location: Moscow City.
Contact:

Post by I'm »

Да тебе памятник при жизни надо поставить за это!
Ugrum.
Posts: 69
Joined: 2004-04-05 11:59:21
Location: RunUO

Post by Ugrum. »

Ну почему же? Я прочитал,оценил общий стиль...обьем...Снимаю шляпу.Впечатляет.
666Man666
Junior Expert
Posts: 474
Joined: 2004-11-13 00:43:55
Location: Киберзадроцк
Contact:

Post by 666Man666 »

Для "новичка" в скриптинге - да.... а для "бывалого перца", это уже устарелая инфа :(
.GrAw
Posts: 7
Joined: 2004-10-16 12:09:59

Post by .GrAw »

Edred молодец. Уроки написаны грамотно .

RESPECT from GrAw
GimFlex
Expert!
Posts: 766
Joined: 2005-01-07 13:22:19
Contact:

Post by GimFlex »

раньше бы написал я бы научился прорамироать быстрее а не на своих ошибках респект ту ю
Edred
Expert!
Posts: 2544
Joined: 2004-04-03 17:36:29
Location: Saint-Petersburg

Post by Edred »

666Man666 wrote:Для "новичка" в скриптинге - да.... а для "бывалого перца", это уже устарелая инфа :(


Для того, кто понимает в программировании хоть что-то вполне достаточно моего старого учебника, который больше справочное руководство. А этот - он именно для чайников.
666Man666
Junior Expert
Posts: 474
Joined: 2004-11-13 00:43:55
Location: Киберзадроцк
Contact:

Post by 666Man666 »

Edred wrote:Для того, кто понимает в программировании хоть что-то вполне достаточно моего старого учебника, который больше справочное руководство. А этот - он именно для чайников.

Да нет.... всё нормально )
хорошо посторался....жаль его не было когда я инжу изучал :)
CErebrus
Posts: 44
Joined: 2004-12-09 03:29:14

Post by CErebrus »

статья для нубов ! Респект
Vija [ XAOC ]
Posts: 35
Joined: 2005-01-16 17:25:54
Contact:

Post by Vija [ XAOC ] »

ДА не плоха Разписал - Респект
A1ekc
Posts: 8
Joined: 2005-02-18 22:11:55
Contact:

Post by A1ekc »

Спасибо, я как раз хотел научитьс яазам скриптования , и не мог нигде найти пояснения , буду ждать 2 урока. :)

3.ы : правда немного недошло некоторые моменты :(
A1ekc
Posts: 8
Joined: 2005-02-18 22:11:55
Contact:

Post by A1ekc »

Извините уважаемые, можно поподробнее про воть это

Code: Select all

sub MyMessage() 
   VAR mymessage1 = 'Hello, Shard!', mymessage2 = "I go!"
   MySay( mymessage1 )
   MySay( mymessage2 )
endsub

sub MySay( myparam )
   UO.Say( myparam )
   wait(1000)
endsub


во первЫх , откуда взялось MySay что это такое ? не объяснили , вроде там должно быть Uo.Say и
во вторых что это за

Code: Select all

sub MySay( myparam ) 
   UO.Say( myparam )

разясните пожалуйста поподробнее!
Edred
Expert!
Posts: 2544
Joined: 2004-04-03 17:36:29
Location: Saint-Petersburg

Post by Edred »

A1ekc wrote:во первЫх , откуда взялось MySay что это такое ? не объяснили , вроде там должно быть Uo.Say и
во вторых что это за

Code: Select all

sub MySay( myparam ) 
   UO.Say( myparam )

разясните пожалуйста поподробнее!


Читаем внимательно и, если что-то непонятно, перечитываем столько раз сколько необходимо для понимания. Причем непросто читаем, а и выполняем. Ответ есть в тексте:

У нас теперь два скрипта. Первый - основной, в нем мы создаем две переменных с приветствиями, и дважды вызываем процедуру MySay, передавая ей в качестве параметра имя переменной с сообщением.


ЗЫ: Это учебник для новичков в инжекте, но это не учебник для полных чайников. Хоть какие-то минимальные знания надо иметь. Иначе мне бы пришлось первый урок назвать: "Распаковываем архив с инжектом".
Edred
Expert!
Posts: 2544
Joined: 2004-04-03 17:36:29
Location: Saint-Petersburg

Post by Edred »

Урок номер 2 будет, я думаю, в воскресенье к вечеру. Процентов 70 уже написано.
I'm
Expert!
Posts: 1396
Joined: 2004-10-15 22:38:04
Location: Moscow City.
Contact:

Post by I'm »

Ура! Эдред так держать!
TaraKaN
Posts: 6
Joined: 2005-03-19 16:01:55
Contact:

Post by TaraKaN »

Edred, жду 2ю серию как какой-нибудь любимый сериал %)))
Кстати, в заголовке темы таки надо было писать: " Пособие для Чайников"
TaraKaN
Posts: 6
Joined: 2005-03-19 16:01:55
Contact:

Post by TaraKaN »

Edred, жду 2й урок как какой-нибудь любимый сериал %)))
Кстати, в заголовке темы таки надо было писать: " Пособие для Чайников"
A1ekc
Posts: 8
Joined: 2005-02-18 22:11:55
Contact:

Post by A1ekc »

MySay = UO.SAY ? или как ? про это ничего не сказано !
а подскажи тогда где можно найти учебник для полных чайников ?
Post Reply