Суббота, 23.09.2017, 06:26
Under sky of Half-Life
Приветствую Вас Гость | RSS
Главная | Каталог статей | Регистрация | Вход
Меню сайта

Категории каталога
На движке Valve Source [29]
На движке Half-Life 1 [1]

Главная » Статьи » Статьи по мэппингу » На движке Valve Source

Работа с VScripts. Part 2

Ошибки в коде.

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

 

Скрытые ошибки- пока код не дойдёт до нее- все будет работать..

Одной из возможных и частых ошибок в коде это обращение (к примеру GetName() ) к объекту в переменной которого не существует или который не найден/не установлен до этого. По этому перед использованием функций касающихся объектов нужно проверять наличие в ней корректного объекта.

MyEntity<-null

MyEntity<- Entities.FindByName(null, "MyEnt")

if(MyEntity!=null)

{

}

 

Функции и примеры кода языка squirrel

 

http://www.squirrel-lang.org/doc/squirrel2.html

 

Точку с запятой в конце строки ставить не нужно, тип переменной указывать не нужно (хотя что вектор).

 

Создание переменной:

MyX <-null

MyX <-0

MyX <-true

 

Установка значение переменной знаком = либо <- описанным выше.

MyX =1

 

Локальные переменные

local a=0 //будет видна только в этом куске кода

 

Циклы.

 

for(local a=0;a<10;a+=1)
   print(a+"\n"); //10 раз вывести значение переменной а

 

 

Работа со string (строковым типом данных)

 

MyName<-"Stridemann”  //Берем в кавычки т. к. это текст

MyName=MyName.slice(0,5) //возвращает обрезанную строку от начала до 5-го символа

print(MyName+"\n") //На выходе: Strid

 

MyName=MyName+”er”

print(MyName+"\n") //На выходе: Strider

 

Векторы

 

Вариант 1:

 

local pos = Vector()

pos.x = myX

pos.y = myY

pos.z = myZ

        

Entities.FindByName(null, "MyEntity”).SetAbsOrigin(pos)

 

Вариант 2:

 

Entities.FindByName(null, "MyEntity”).SetAbsOrigin( Vector(myX,myY,myZ) )


 

Функции движка Source (Portal 2) и примеры кода

Это ваша библия на все время работы со скриптами в сорсе : https://developer.valvesoftware.com/wiki/List_of_Portal_2_Script_Functions:ru

 

Описываю примеры наиболее используемых функций на примере:

 

MyPlayerEntity <- Entities.FindByName(null, "!player")

 

MyPlayerEntity.GetName() - получить имя энтити. Получим string. В данном случае получим пустую строку, ибо у игрока имени нету..

 

EntFire( "MyPlayerEntity.GetName()", "SetHealth", "0" )

EntFire( "MyPlayerEntity.GetName()", "Kill" ) - выдать аутпут указанной энтите.

 

SendToConsole("developer 1") - написать команду в консоль.

 

MyPlayerEntity.GetAngles() - получить угол поворота энтити. Получим вектор (x,y,z)

MyPlayerEntity.GetOrigin() - получить координату энтити. Получим вектор (x,y,z)

 

MyPlayerEntity.GetClassname() - получить класс энтити. Получим string. В данном случае player.

MyPlayerEntity.GetForwardVector() - получить Forward вектор энтити. Если к координате энтити прибавлять этот вектор (умноженный на значение скорости), то энтитя будет двигатся куда смотрит. Пример:

MyPlayerEntity.SetAbsOrigin( MyPlayerEntity.GetOrigin() + (MyPlayerEntity.GetForwardVector()*10))

 

С игроком не удачный пример. Там точность получения значения поворота +-20 градусов. Правильно обрабатываются только при быстром и длительном повороте. Об этом в конце статьи.

 

MyPlayerEntity.GetModelName() - получить модель энтити. В нашем случае получим models/player/chell/player.mdl
 

MyPlayerEntity.SetAbsOrigin(10,10,10)

MyPlayerEntity.SetOrigin(10,10,10)

Телепортировать\переместить объект в указанную координату.

Разница между этими функциями что в SetAbsOrigin есть сглаживающая функция, и в связке с “ускорителем выполнения кода” объект будет двигатся очень плавно.

 

MyPlayerEntity.SetAngles() -повернуть энтитю в углах Эйлера (по координатам XYZ).

 

Это примеры наиболее часто используемых функций. В этом списке вы найдете все доступные функции.

 

Некоторые хитрости

Получить угол поворота игрока

Нельзя правильно получить угол поворота игрока через MyPlayerEntity.GetOrigin() . Точность +-20 градусов (примерно). Чтоб получить точный поворот нужно создать два info_target’а (view_target1 у глаз игрока и припарентить к игроку и view_target2) и постоянно телепортировать второй командой в консоль (желательно через ускоритель кода):

SendToConsole("ent_teleport view_target2")

 

Далее получаем Pitch и Yaw (Y, Z) поворота игрока через код:

 

x1<-Entities.FindByName(null, "view_target1").GetOrigin().x

y1<-Entities.FindByName(null, "view_target1").GetOrigin().y

z1<-Entities.FindByName(null, "view_target1").GetOrigin().z

 

x2<-Entities.FindByName(null, "view_target2").GetOrigin().x

y2<-Entities.FindByName(null, "view_target2").GetOrigin().y

z2<-Entities.FindByName(null, "view_target2").GetOrigin().z

 

x12<-x1-x2

y12<-y1-y2

z12<-z1-z2

tmp<-0

yaw<-0

pitch<-0

 

    if (y12 == 0 && x12 == 0)

    {

        yaw = 0

        if (z12 > 0)

            pitch = 270

        else

            pitch = 90

    }

    else

    {

        yaw = (atan2(y12, x12) * 180 / 3.14)

        if (yaw < 0)

            yaw += 360

 

        tmp = sqrt (x12*x12 + y12*y12)

        pitch = (atan2(-z12, tmp) * 180 / 3.14)

        if (pitch < 0)

            pitch += 360

    }

 

Этот код переводит вектор в углы Эйлера.

В переменных yaw и pitch будет хранится поворот игрока.

 

Фикс багов после релиза.

После релиза своего мода (Thinking with Time Machine) были ошибки в логике из за которых пришлось бы перекомпиливать карту, потом бы начались проблемы с сейвами (об этом попозже) и т. д.

В энтите math_counter был установлен максимальный предел счета 1, а нужно было 2. Достаточно было наступить на 1 кнопку (вместо 2-х нажатых кнопок) и дверь откроется. Такой баг.

Но у меня был скрипт, который запускался на каждой карте. При запуске карты одноразово выполнялась функция CheckMap(). В ней я написал:

function CheckMap()

{

if(GetMapName()=="tm_training_01")

EntFire( "button_counter", "SetHitMax", "2")

}

Таким способом при запуске карты фиксился мелкий баг логики. 

На основе этого можно почти любые ошибки логики исправлять без рекомпиляции карты.

 

"Безопасное" обновление карт

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

Я решил придумать систему безопасного обновления. 

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

Как это сделать. 

1) Новая карта именуется другим именем с приставкой -update2 .

2) По завершению карты запускается функция ( logic_script - CallScriptFunction NextMap ), которая меняет карту.

И нужно делать смену карты через скрипт:

MapCFG<- [

    { map = "tm_map_01b", next_map = "tm_scene_map-update2"},
    { map = "tm_scene_map", next_map = "tm_map_02b"},
    { map = "tm_scene_map-update2", next_map = "tm_map_02b"},
    { map = "tm_map_02b", next_map = "tm_map_03b"},
]

function NextMap()
{
    foreach (index, level in MapCFG)
    {    
        if (level.map == GetMapName())
        {
            SendToConsole("map " +level.next_map)
        }
    }
}

В этом случае если игрок прошел карту tm_map_01b - запускается функция NextMap, которая ищет в массиве название карты (tm_map_01b) и сравнивает с текущим названием карты (tm_map_01b). Если оно равно- сменить карту на tm_scene_map-update2, то есть на обновленную. В таком случае у игроков на карте tm_scene_map не будет сломан автосейв. Есть один минус, что игрок не увидит уже исправленной карты, но поверьте, это в 100 раз лучше чем получать сотни багрепортов о том, что видны триггеры, автосейв накрылся и т. д.

Категория: На движке Valve Source | Добавил: stridemann (05.08.2014)
Просмотров: 519
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Поиск

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

© 2017, MonoLife Сайт создан в системе uCoz