The New Future :: FOnline, Half-life 2 :: Roleplay It!  

Вернуться   The New Future :: FOnline, Half-life 2 :: Roleplay It! > Прочее > FOmod > TNF

TNF сервер и частично документация

Ответ
 
Опции темы Опции просмотра
Старый 13.01.2015, 17:34   #1
PowerMagic
Lost Overseer
 
Аватар для PowerMagic
 
Специализация: ест детей.
Регистрация: 29.01.2010
Сообщений: 1,000
Вес репутации: 571
PowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond reputePowerMagic has a reputation beyond repute
По умолчанию [doc] Система взлома

Система взлома:

При применении навыка взлома на дверь появляется меню:

1) постучать - появляется текст "тук-тук", видимый всем перед дверью и за дверью
2) применить силу - распахивает незапертые двери, в будующем будет чек на силовое открытие
3) начать взлом - открывает меню взлома.

меню взлома:
1) Осмотреть замок
2) Щуп дальше
3) Щуп назад
4) Щуп вверх
5) Щуп вниз
6) Повернуть
7) Вынуть отмычку

При взломе у двери набор язычков, 3 язычка у плохого замка, 4 у хорошего, 5 у лучшего.
У каждого 10 положений, для открытия двери нужно подобрать щупом правильные положения язычков и повернуть упор.

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

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

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

Иллюстрация


А теперь по порядку в скриптах:

Издалека:
Параметры используемые в скриптах взлома:
Сложность замка определяется при крафте, по формуле :
lock.LockerComplexity = crafter.SkillBase[SK_REPAIR] / 3 + crafter.SkillBase[SK_LOCKPICK] / 2
Тип замка определяется праметром предмета lock.Val0 , где lock - дверь, сундук и т.п.
lock.Val0 == 0 -не заперто
lock.Val0 == 1 -простой замок
lock.Val0 == 2 -хороший замок
lock.Val0 == 3 -лучший замок
lock.Val0 == 4 -электронный замок

lock.Val5 - код замка, от 2 до 4 порядков, генерируется при каждой попытке взлома
lock.Val4 - используется для хранения подбираемого кода
cr.StatBase[ST_VAR0] - используется для хранения ид замка
cr.StatBase[ST_VAR1] - используется для определения положения щупа (какую цифру подбираем в данный момент
cr.StatBase[ST_VAR2] - число попыток взлома, определяет шанс сломать ошибку при неверной комбинации

1) В скрипте взлома вызываем первое окно, в ST_VAR0 записываем ид замка, т.к. передать его напрямую в скрипт окна-ответа нельзя:
Код:
        cr.StatBase[ST_VAR0] = locker.Id;
        cr.ShowScreen(SCREEN_DIALOGBOX, 3, "answer_LOCKPICK");
        cr.Say(SAY_DIALOGBOX_TEXT, "Выберите действие");
        cr.Say(SAY_DIALOGBOX_BUTTON(0),"постучать");
        cr.Say(SAY_DIALOGBOX_BUTTON(1),"выбить");
        cr.Say(SAY_DIALOGBOX_BUTTON(2),"начать взлом");
т.о. вызывается меню с 3мя кнопками, скрипт-реакция на которое void answer_LOCKPICK, код этого меню целиком, далее подробнее:

объявляем замок по ST_VAR0 и отмычку в действующей руке.
Код:
    Item@ lock = GetItem(player.Stat[ST_VAR0]);
    if(lock is null) return;
    Item@lockpick = player.GetItem(0, SLOT_HAND1);
реакция на кнопку 1 - ставим текст на гекс
Код:
    if(answerI==0)
        {
        Map@ map = player.GetMap();
        map.SetText(lock.HexX, lock.HexY, COLOR_GRAY, "тук-тук");
        player.Say(SAY_NETMSG, "Вы постучали в дверь.");
        }
реакция на кнопку 2 - если дверь не заперта (lock.Val0==0) и не распахнута !FLAG(lock.LockerCondition,LOCKER_ISOPEN), то распахиваем ее и ставим красный текст на гекс - УДАР.
Код:
    if(answerI==1)
        {
        Map@ map = player.GetMap();
        map.SetText(lock.HexX, lock.HexY, COLOR_RED, "УДАР");
        if(!FLAG(lock.LockerCondition,LOCKER_ISOPEN) && lock.Val0==0)
            {
            lock.LockerOpen();
            return;
            }
        player.Say(SAY_NETMSG, "Вы сильно врезали по замку, но без какого либо эфекта.");
        Log_Lockpick(player, player.Stat[ST_VAR0], 1, 0, null, null);
        }
Начало реакции взлома - проверка на то, что дверь распахнута:
Код:
    if(answerI==2)
        {
        if(FLAG(lock.LockerCondition,LOCKER_ISOPEN))
            {
            player.Say(SAY_NETMSG, "Дверь и так открыта.");
            return;
            }
Если не заперта - нет замка
Код:
        if (lock.Val0==0)
            {
            player.Say(SAY_NETMSG, "Нет замка.");
            return;
            }
В зависимости от типа замка генерируется код замка lock.Val5 и текущий код отмычек lock.Val4, а также проверка на отмычки.
Код:
        if (lock.Val0==1)
            {
            lock.Val5=Random(100,999);
            lock.Val4=100;
            }
        if (lock.Val0==2)
            {
            if(!valid(lockpick) || lockpick.GetProtoId() != PID_EXP_LOCKPICK_SET && lockpick.GetProtoId() != PID_LOCKPICKS) {player.Say(SAY_NETMSG, "Нужны отмычки."); return;}
            lock.Val5=Random(1000,9999);
            lock.Val4=1000;
            }
        if (lock.Val0==3)
            {
            if(!valid(lockpick) || lockpick.GetProtoId() != PID_LOCKPICKS) {player.Say(SAY_NETMSG, "Нужен большой набор отмычек."); return;}
            lock.Val5=Random(10000,99999);
            lock.Val4=10000;
            }
Проверка на цельность отмычки, если lockpick.Val0 != 0 то значит отмычку не вытащили нормально из замка. Сразу после проверки в 50% случаев присваиваем значение 10, т.е. эта отмычка становится условно в замке и при прерывании взлома в следующий раз сломается.
Код:
        if (valid(lockpick) && lockpick.Val0 != 0)
            {
            DeleteItem(lockpick);
            player.Say(SAY_NETMSG, "Отмычка сломалась, видимо ее неудачно вытащили ее из замка в прошлый раз.");
            return;
        else if (valid(lockpick) && Random(0,1)==0) lockpick.Val0 = 10;
            }
Запускаем окно непосредственно взлома, делаем запись в лог о попытке взлома и запускаем таймаут на взлом.
Код:
        player.ShowScreen(SCREEN_DIALOGBOX, 7, "answer_LOCKPICK_lock");
        player.Say(SAY_DIALOGBOX_TEXT, "Состояние замка неизвестно");
        player.Say(SAY_DIALOGBOX_BUTTON(0),"Осмотреть замок");
        player.Say(SAY_DIALOGBOX_BUTTON(1),"Щуп дальше");
        player.Say(SAY_DIALOGBOX_BUTTON(2),"Щуп назад");
        player.Say(SAY_DIALOGBOX_BUTTON(3),"Щуп вверх");
        player.Say(SAY_DIALOGBOX_BUTTON(4),"Щуп вниз");
        player.Say(SAY_DIALOGBOX_BUTTON(5),"Повернуть");
        player.Say(SAY_DIALOGBOX_BUTTON(6),"Вынуть отмычку");
        Log_Lockpick(player, player.Stat[ST_VAR0], 0, 0, null, null);
        player.TimeoutBase[TO_SK_LOCKPICK]=LOCKPICK_TIMEOUT(player);
Далее идет скрипт-реакция на кнопки меню, где и происходит подбор кода замка, полный код, и далее расписываю по элементам:

Объявляем предмет lock - дверь или сундук, объявляем карту, объявляем разницу навыка взлома и сложность замка и ограничиваем диапазоном 5-95
state - вспомогательная строка для текстового вывода результата и событий.
curPos и curComb - буферные переменные для выделения выбранной цифры из подобранного кода и кода замка соответственно.
Код:
    Item@ lock = GetItem(player.Stat[ST_VAR0]);
    if(lock is null) return;
    Map@ map = player.GetMap();
    int base = player.Skill[SK_LOCKPICK]-lock.LockerComplexity;
    base=CLAMP(base,5,95);
    Item@lockpick = player.GetItem(0, SLOT_HAND1);

    string state="";
    int curPos=0, curComb=0;
реакция на кнопку 0 - осмотреть, пока без особого функционала, потом можно будет прикрутить проверку на ловушки
Код:
    if(answerI==0)
        {
        if (lock.Val0==1) state ="Замок так себе, ";
        if (lock.Val0==2) state ="Замок в хорошем состоянии, ";
        if (lock.Val0==3) state ="Очень хороший замок, ";
        }
реакция на кнопку 1 - двигать щуп дальше, если таймаут на взлом больше нуля, то ставим штрафные 10 сек и сообщение, что щуп застрял.
далее проверка положения щупа на количество цифр в шифре player.StatBase[ST_VAR1]<lock.Val0+2.
Если ничего не мешает, то прибавляем 1 к положению щупа - player.StatBase[ST_VAR1]++; и ставим 2 секунды таймаута, чтобы не дургали отмычку слишком быстро.
Код:
    if(answerI==1)
        {
        if (player.Timeout[TO_SK_LOCKPICK]>0)
            {
            state ="Щуп застрял, нужно чуть ослабить зажим и попробовать еще раз, ";
            player.TimeoutBase[TO_SK_LOCKPICK]=__FullSecond+REAL_SECOND(10);
            }
        else if (player.StatBase[ST_VAR1]<lock.Val0+2)
            {
            player.StatBase[ST_VAR1]++;
            state ="Вы продвинули щуп дальше, ";
            if (Random(0,2)==0) player.TimeoutBase[TO_SK_LOCKPICK]=__FullSecond+REAL_SECOND(2);
            }
        else state ="Щуп уперся и дальше в замок не продвигается, ";
        }
Реакция на кнопку 2 - почти полный аналог предыдущего скрипта, только проверка на положение щупа больше 1
Код:
    if(answerI==2)
Реакция на кнопку 3 - движение щупа вверх.
Код:
    if(answerI==3)
curPos - находим текущую цифру подбираемого шифра. Находим остаток от деления на 10 в степени=положению щупа, т.е. если скажем шифр 3489, а положение щупа=3, то 3489%1000= 489 ,затем отбрасываем цифры кроме первой, для этого делим остаток на 10 в степени = положение щупа минус один, т.е. 489/100=4.89 , но округляется до 4.
затем проверяем х<9 , т.е. если положение 9, то двигать щуп выше уже нельзя
Код:
        curPos=(lock.Val4%pow(10,player.StatBase[ST_VAR1]))/pow(10,player.StatBase[ST_VAR1]-1);
            if (curPos<9)
тем же способом находим curComb - текущую цифру кода замка
Код:
curComb=(lock.Val5%pow(10,player.StatBase[ST_VAR1]))/pow(10,player.StatBase[ST_VAR1]-1);
прибавляем 10 в степени = положение щупа минус один, т.е. если код был 3489, а положение 3, то 3489 + 100=3589,
также прибавляем 1 к curPos, т.к. дальше будем использовать его для сравнения.
Код:
            lock.Val4+=pow(10,player.StatBase[ST_VAR1]-1);
            curPos++;
определяем начало текстовой строки - результата, которую будем выводить в окне после совершнения действия.
Код:
            state ="Вы подвинули щупом язычек замка вверх, ";
идет проверка на торопливость - в 30% случаев, если щупом двигают раньше чем прошел таймаут на действие, то происходит реакция:
- ставится текст на гекс "click", как при стуке в дверь
- сбрасывается случайный язычек (случайная цифра) в коде замка
Код:
            if (player.Timeout[TO_SK_LOCKPICK]>0 && Random(0,2)==0)
                {
                map.SetText(lock.HexX, lock.HexY, COLOR_GRAY, "click");
                state +="вы поторопились и неловко дернули щупом, ";
                if (Random(0,1)==0)
                    {
                    int bar=Random(1,lock.Val0+2);
                    curComb=(lock.Val5%pow(10,bar))/pow(10,bar-1);
                    lock.Val5+=(Random(1,9)-curComb)*pow(10,bar-1);
                    }
                }
если подбираемая цифра совпала с цифрой кода - проверка на base (разница навыка и сложности замка), если больше случайного от 0 до 100, то слышим клик (к строке результата прибавляется "вы услышали щелчек,")
также идет проверка на чистый навык - если меньше случаного от 0 до 200, то видно текст на гекс "клик"
Код:
            else if (curComb==curPos && base>Random(0,100))
                {
                if (player.Skill[SK_LOCKPICK]<Random(0,200)) map.SetText(lock.HexX, lock.HexY, COLOR_GRAY, "click");
                state +="вы услышали щелчек, ";
                }
далее проверка если цифра на 1 отличается от кодовой, та же проверка, но доп ограничение - срабатывает только в 50% случаев, т.е. взломщик нащупав сначала область расположения верной цифры потом начинает перещелкивать значения, для того чтобы определить какая именно верная, причем чем больше навык, тем проще определить верную цифру
Код:
            else if (curComb>=(curPos-1) && curComb<=(curPos+1) && base>Random(0,100) && Random(0,1)==0)
                {
                if (player.Skill[SK_LOCKPICK]<Random(0,200)) map.SetText(lock.HexX, lock.HexY, COLOR_GRAY, "click");
                state +="вы услышали щелчек, ";
                }
далее по тому же принципу, но проверяются цифры отличающиеся на 2 и шанс срабатывания 25%
Код:
            else if (curComb>=(curPos-2) && curComb<=(curPos+2) && base>Random(0,100) && Random(0,3)==0)
                {
                if (player.Skill[SK_LOCKPICK]<Random(0,200)) map.SetText(lock.HexX, lock.HexY, COLOR_GRAY, "click");
                state +="вы услышали щелчек, ";
                }
далее проверка на совсем случайные щелчки, если base меньше случайного от 0 до 100 и только в 10% случаев:
Код:
            else if (base<Random(0,100) && Random(0,9)==0)
                {
                if (player.Skill[SK_LOCKPICK]<Random(0,200)) map.SetText(lock.HexX, lock.HexY, COLOR_GRAY, "click");
                state +="вы услышали щелчек, ";
                }
после этого ставим таймаут на взлом, 10 - навык деленый на 30, т.е. при навыке 0 - ожидание между действиями 10 сек, при 100 - 7 секунд, при 200 - 4сек, а при 300 - 0сек
Код:
    player.TimeoutBase[TO_SK_LOCKPICK]=__FullSecond+REAL_SECOND(10-player.Skill[SK_LOCKPICK]*0.03);
реакция на ответ 4 - щуп вниз, почти аналогично предыдущему
Код:
    if(answerI==4)
реакция на ответ 5 - повернуть упор, т.е. проверить правильно ли мы подобрали комбинацию.
если lock.Val4==lock.Val5 , т.е. комбинация подобрана верно, то
-распахиваем дверь/крышку lock.LockerOpen();
- открываем содержимое контейнера, если контейнер player.ShowContainer
- возвращаем отмычки в несломанное состояние lockpick.Val0 = 0;

если же не угадали идет проверка, если число попыток взлома меньше случайного от 1 до 5% от навыка взлома, т.е. шанс сломать отмычку даже первой попыткой есть всегда, но при высоких значения навыка этот шанс невелик.
ну и наконец если спасбросок на навык провалился, то идет провал взлома - окно взлома закрывается, код сбрасывается и в 50% случаев отмычка ломается
Код:
    if(answerI==5)
        {
        if (lock.Val4==lock.Val5)
            {
            lock.LockerOpen();
            if(lock.GetType()==ITEM_TYPE_CONTAINER)
                {
                player.ShowContainer(null,lock,lock.Proto.GroundLevel?TRANSFER_HEX_CONT_DOWN:TRANSFER_HEX_CONT_UP);
                }
            else player.Say(SAY_NETMSG, "Вы успешно вскрыли замок. Осторожно, дверь может захлонуться.");
            lock.Update();
            player.AddScore(SCORE_CRACKER,1);
            if (valid(lockpick)) lockpick.Val0 = 0;
            return;
            }
        else if (player.StatBase[ST_VAR2]<Random(0,base*0.05))
            {
            state ="Замок не поворачивается, ";
            player.StatBase[ST_VAR2]++;
            }
        else
            {
            player.SayMsg(SAY_NETMSG,TEXTMSG_GAME,STR_SKILL_LOCKPICK_FAIL);
            if (valid(lockpick) && Random(0,1)==0) lockpick.Val0 = 0;
            return;
            }
        }
Код:
    if(answerI==4)
реакция на ответ 6 - вынть отмычку, если положение отмычки не 1, то идет сообщение, что вынуть отмычку можно только из крайнего положения, а как вы помните есть ограничение в 2 секунды, на перемещение отмычки, так что моментально вытащить отмычку не всегда возможно,
если же положение крайнее, то возвращаем отмычку в несломанное состояние lockpick.Val0 = 0; и закрываем окно взлома return;
Код:
    if(answerI==6)
        {
        if (player.StatBase[ST_VAR1]>1) state ="Сначала выдвините щуп в первую позицию, ";
        else {lockpick.Val0 = 0; player.Say(SAY_NETMSG, "Вы аккуратно вытащили отмычку из замка."); return;}
        }
заключительная часть кода идет после реакций на ответы и если в процессе выполнения не было команды return; то эта часть выполняется всегда,
- над игроком пишется эмоут "возится с замком", так что любому окружающему видно чем занимается персонаж
- в строку добавляется позиция щупа
- вновь выводится меню взлома с кнопками-действиям
Код:
    player.Say(SAY_EMOTE_ON_HEAD, "возится с замком");
    state+="позиция щупа - "+player.StatBase[ST_VAR1];
    player.ShowScreen(SCREEN_DIALOGBOX, 7, "answer_LOCKPICK_lock");
    player.Say(SAY_DIALOGBOX_TEXT, state);
    player.Say(SAY_DIALOGBOX_BUTTON(0),"Осмотреть замок");
    player.Say(SAY_DIALOGBOX_BUTTON(1),"Щуп дальше");
    player.Say(SAY_DIALOGBOX_BUTTON(2),"Щуп назад");
    player.Say(SAY_DIALOGBOX_BUTTON(3),"Щуп вверх");
    player.Say(SAY_DIALOGBOX_BUTTON(4),"Щуп вниз");
    player.Say(SAY_DIALOGBOX_BUTTON(5),"Повернуть");
    player.Say(SAY_DIALOGBOX_BUTTON(6),"Вынуть отмычку");
__________________
Jet Rock's

Последний раз редактировалось PowerMagic; 13.01.2015 в 17:42.
PowerMagic вне форума   Ответить с цитированием
Данный человек сказал спасибо PowerMagic за этот пост:
Покемон (08.09.2015)
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 00:56.


Powered by vBulletin® Version 3.8.3
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot
Для внутреннего пользования