27

» WarCraft 3 / Смена текстуры медведя в игре

Ev3nt, только эффект способности также может влиять и на портреты. там белые портретики. знаю, что приведен как пример этот случай. Но в основном больше и нигде использовать этот эффект нельзя (кроме мем хака), почему нельзя изменить скины? почему я должен тысячу копии моделей импортировать для таких случаев.
27

» WarCraft 3 / Бета версия Warcraft III Reforged 1.32

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

» WarCraft 3 / Бета версия Warcraft III Reforged 1.32

vasya1:
yellyex:
отличное видео
старая озвучка намного колоритнее, в новой все актёры слишком спокойные
из новой озвучки лучше только таурен (и то в большой степени из-за неудачного эффекта окружения, но по напряжению голоса всё равно проигрывает, спокойный слишком. как будто не на войне, а у камина чай с плюшками пьёт).
но в целом сойдёт, комьюнити всегда придирается
в любом случае теперь у нас будет две озвучки, а мы всегда сможем выбрать ту, что по душе
они мало чем отличаются, на чуть чуть. где то хуже где то лучше. мне немного понрав рефорджа, просто старая либо слишком эмоциональна, или просто поднадоела: повторяют одни и те же фразы, их стоит увеличить
ну и бывает и хуже, у рефордж тоже не идеал. где то старые получше: по звучанию, тембру голоса, и пр
Есть и такие изменения: вот Рохан, к рефорджа спокойный какой то старческий голос, а в старой озвучке: молодой крикливый голос, кричащий вечно спешит куда то
27

» WarCraft 3 / Событие для способности типа вкл/выкл(жар преисподней)

Начало этой способности ловится событиями "юнит применяет способность", "юнит завершает способность", "юнит прекращает способность". А отмена ловится приказом. Приказом хорошо ловится (начало, отмена).
27

» WarCraft 3 / Удалить сообщение DisplayTimedTextToForce

DopaMine, ну пишешь, по идее триггер сработал у GetTriggerPlayer()
GetTriggerPlayer - игрок триггера
if GetLocalPlayer() == GetTriggerPlayer() then
	call ClearTextMessages()
endif
прочитай про статью GetLocalPlayer() на нашем сайте
константа GetLocalPlayer() возвращает локального игрока, у которого запущена игра. Допустим есть 2 игрока, играющие между собой. на машине первого игрока GetLocalPlayer() вернет первого, на машине второго игрока GetLocalPlayer() вернет второго игрока. Вообще между ними должна сихронизация. иначе при неправильном коде при сработке вылетает и все.
Главное просто условие записать. "локал игрок == твой игрок"
И ещё: как на основе канала сделать способность, которая не прервёт текущего приказа? Не нашёл чё-то. P.S. Рёв не подходит, ибо мне нужно одновременно иметь 11 таких абилок(с разным ID приказа)
Поменяй приказ. У канала это возможно. см. ссылка
27

» WarCraft 3 / Загрузка по хэндлу в функцию

очень сложно понять, что вы хотите сделать. зачем такая сложная конструкция, что у вас не работает не понятна.
Если я вызову функцию из таймера, то в ней опять нельзя будет использовать GetTriggerUnit(), а у меня в этой функции объявлен старт ещё одного таймера...
константы варика вроде GetTriggerUnit вызывают и передают аргументы через события
см. в теме 7 сообщение тебе уж объясняли в этой теме
см в теме 16 сообщение и скачай текстовый файл
ты же сам хранишь этот параметр "True/False" в хэше. И изменяешь в зависимости от срабатывания события вроде юза абилити, таймера истек GetExpiredTimer().
При том, что я в нём каждые 0.05 секунд загружаю булин. А в основной функции написано, что если этот булин тру, то делать дальше.
Зачем тебе создавать лишний таймер, и периодически проверять => лишняя работа. Можно напрямую узнать в хэше. Если значение изменится, ты сам узнаешь через сработки события юза абилити или завершения таймера
27

» WarCraft 3 / CreateTimer

вот код
function CheckTimer takes nothing returns nothing

local timer t = GetExpiredTimer()
local integer h1 = GetHandleId(t)

local unit caster = LoadUnitHandle(udg_hash,h1,StringHash("caster")) //вызывается функция CheckTimer таймером, то вар константы вроде GetSpellAbilityUnit() не работают. тк завяны на потоки. Поэтому загружаем кастера из хэша, который сохраняю по ключу хэндла таймера t

local integer h2 = GetHandleId(caster) //далее достаем ключ хэндла кастера

local location point = LoadLocationHandle(udg_hash,h2,StringHash("point"))
local boolean check = LoadBoolean(udg_hash,h2,StringHash("check"))
//call SaveInteger(udg_hash,h2,StringHash("h"), h2 ) //не понятное действие
далее 3 варианта:
1)пересохраняем call SaveBoolean(udg_hash,h2,StringHash("check"), false)
2) очищаете ячейку call RemoveSavedHandle(udg_hash,h2,StringHash("check"))
3) по привычке удалить таймер и очистить таблицу по h1 и h2
берем 3 вариант, тк очистим ячейки хэша и удалим таймер.
call DestroyTimer(t)
call FlushChildHashtable(udg_hash,h1)
call FlushChildHashtable(udg_hash,h2)

set caster = null
set point = null
set t = null

endfunction
function Attack takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location point = GetSpellTargetLoc() //для чего точка используется?
local timer t = CreateTimer() //Создаём таймер

local integer h1 = GetHandleId(t)
local integer h2 = GetHandleId(caster)
local boolean check = true

call SaveUnitHandle(udg_hash,h1,StringHash("caster"),caster)
call SaveLocationHandle(udg_hash,h1,StringHash("point"),point) //зачем точку создавать?
call SaveBoolean(udg_hash,h2,StringHash("check"),check)
call TimerStart(t, 1, false, function CheckTimer)
set caster = null
set point = null
set t = null

endfunction
27

» WarCraft 3 / Движение по 3 ося XYZ

Принятый ответ
есть статья готовая = xgm.guru/p/wc3/mathmov
вот статья из вики
векторы
library vectors
    
    struct vector
        real x
        real y
        real z
        //Статичный метод создающий вектор, принимает координаты возвращает вектор. 
        //Вектор - отрезок AB, соединяющий из точки A в точку B. Вектор кроме того имеет направление. 
        //V = (x, y, z)  => казалось храним координаты точки, не совсем точно. Храним отрезок с направлением.
        //правильнее V = (Bx-Ax, By-Ay, Bz-Az)  => из конца вычитаем начало
        //эта функция создаем вектор. создается структура, короче выделяется место под массивы. максимум доступно 8190
        //прописываем: local vector v = vector.create(0,0,0) <= координаты
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate() // <= что-то вроде перебора индекса массива
            set v.x=x
            set v.y=y
            set v.z=z
            return v //<= возвращает на самом деле индекс, номер структуры
        endmethod

        //Умножает вектор на какое либо число.
        //V = V * r
        //если раскрыть: 
        //set v_x[this]=v_x[this] * r
        //set v_y[this]=v_y[this] * r
        //set v_z[this]=v_z[this] * r
        //пишем: local vector v = vector.create(1,1,1)
        //пишем: call v.realmul(2)  // <= результат вектор с координатами 2 2 2
        method realmul takes real r returns nothing
            set .x=.x*r
            set .y=.y*r
            set .z=.z*r
        endmethod
        
        //Модуль вектора - метод возвращающий длину вектора (число всегда >0)
        //|V| = sqrt(x*x + y*y + z*z)
        //пишем: local vector v = vector.create(0,0,1)
        //пишем: local real r = v.getlength() <= результат равен 1
        method getlength takes nothing returns real
            return SquareRoot(.x*.x+.y*.y+.z*.z)
        endmethod
        
        //Устанавливет длину вектора равным 1
        //Нормализация — приведение к единичному размеру; 
        //нормализация в трехмерном пространстве - по сути является масштабированием в куб единичного размера 
        //Для нормализации вектора нужно каждую компоненту поделить на длину вектора, или умножить инверсию длины на данный вектор.
        //V/|V| = (x/|V|, y/|V|, z/|V|) <= короче складываем кажду координату, больше вычислении нужно
        //set InvLength = 1/legth  <=инверсия, здесь меньше вычислении
        method normalize takes nothing returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(1/l)
            endif
        endmethod   
        
        //Принимает число. Устанавливает длину вектора равной этому числу.
        //похожий метод у функции normalize
        //пишем: local vector v = vector.create(54,0,0)
        //пишем: call v.setlength(30) <= результат: вектор а равен 30 0 0
        method setlength takes real r returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(r/l)
            endif
        endmethod
        
        //Принимает вектор. Возвращает число равное скалярному произведению этих векторов.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // A*B = Ax*Bx + Ay*By + Az*Bz
        //используется часто для вычисления углов между векторами
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.scalarmul(w)
        //результат равен 10
        method scalarmul takes vector v returns real
            return .x*v.x+.y*v.y+.z*v.z
        endmethod
        
        //Принимает вектор. Устанавливает вызывающий вектор равным сумме самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // Bx= Ax+Bx, By= Ay+By, Bz = Az+Bz   <= изменяются параметры вектора B
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.vectoradd(w)
        //результат: вектор v равен 2 2 6, вектор w не изменился
        method vectoradd takes vector v returns nothing
            set .x=.x+v.x
            set .y=.y+v.y
            set .z=.z+v.z
        endmethod
        //аналогично как и метод vectoradd, только вычитывает
        method vectorsub takes vector v returns nothing
            set .x=.x-v.x
            set .y=.y-v.y
            set .z=.z-v.z
        endmethod
        
        //Принимает вектор. Устанавливает вызывающий вектор равным векторному произведению самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Bx= (Ay*Bz - By*Az), By= (Az*Bx - Bz*Ax), Bz = (Ax*By - Bx*Ay)
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: local real r = v.vectormul(w)
        //результат: вектор v равен 0 0 1, вектор w не изменился
        method vectormul takes vector v returns nothing
            local real x = .y*v.z-v.y*.z
            local real y = .z*v.x-v.z*.x
            local real z = .x*v.y-v.x*.y
            set .x = x
            set .y = y
            set .z = z
        endmethod
        
        //Принимает вектор. Возвращает вектор равный вызывающему.
        //Смысл: эта функция создает копию-вектор, который принимает те же значения что у оригинала
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.clone()
        //результат: вектор v равен 1 0 0, вектор w равен 1 0 0
        method clone takes nothing returns vector
            local vector v=vector.allocate()
            set v.x=.x
            set v.y=.y
            set v.z=.z
            return v
        endmethod      
        
        //Принимает вектор. Устанавливает значение вызывающего вектора равным принятому вектору.
        //В отличии от метода clone здесь не создается двойник, у нас уже имеется вектор. Не всегда имеет смысл создавать двойников
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: call v.copy(w)
        //результат: вектор v равен 0 1 0, вектор w равен 0 1 0
        method copy takes vector p returns nothing
            set .x=p.x
            set .y=p.y
            set .z=p.z            
        endmethod
        
        //Принимает координаты x, y и z. Форсированное изменение координат вектора.
        //Изменяет текущий вектор.
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: call v.change(1,1,1)
        //результат: вектор v равен 1 1 1
        method change takes real x, real y, real z returns nothing
            set .x=x
            set .y=y
            set .z=z
        endmethod
        
        
        //Принимает вектор. Вычисляет угол между двумя векторами.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Вытекает из скалярного произведения AB*Cos(A)
        //CosA = AB/|A|*|B|, где AB = ax*bx + ay*by + az*bz и |A| = sqrt(ax*ax + ay*ay + az*az), |B| = sqrt(bx*bx + by*by + bz*bz)
        method AngleBetweenVectors takes vector b returns real //в радинах
            local real ab =.scalarmul(b)/(.getlength()*b.getlength())
            return ab
        endmethod
        method AngleBetweenVectors2 takes vector b returns real //в градусах
            local real ab =.scalarmul(b)/(.getlength()*b.getlength())
            return Acos(ab)
        endmethod
        
    endstruct    
    
endlibrary
пример движения (для новичка), то же самое что и в статье.
хотя я и сам новичок, тк не каждый день приходиться кодить и писать движения. Мне приходится вспоминать свои шпаргалки, или браться за учебники матана.
ниже представлен пример движения снаряда u от u1 (кастера) до u2 (цели)
local unit u1 = GetTriggerUnit()
local unit u2 = GetSpellTargetUnit()

local real x1 = GetUnitX(u1)
local real y1 = GetUnitY(u1)
local real z1 = GetUnitZ(u1)

local real x2 = GetUnitX(u2)
local real y2 = GetUnitY(u2)
local real z2 = GetUnitZ(u2)

local real x
local real y
local real z

local real facing = GetUnitFacing(u1)
local real apha //угол между точками кастера и цели 
local real theta //угол между вектором dz и точкой движения (точнее текущей длиной между точками кастера и цели)

local real dx
local real dy
local real dz
local real dist

local real move_cord = 1000. //move_cord - смещение от начала точки, по-другому можно назвать скоростью speed, если представить окружность то это значение будет радиус-вектором R 

if u2 == null then
	set x2 = GetSpellTargetX()
	set y2 = GetSpellTargetY()
	set z2 = GetLocZ(x2,y2)
endif

set dx = (x2-x1)
set dy = (y2-y1)
set dz = (z2-z1)
set dist = SquareRoot( dx*dx + dy*dy )
set alpha = Atan2(dy, dx)
set theta = Atan2(dz, dist)

x = x1 + move_cord * Cos( alpha ) * Sin( theta )
y = y1 + move_cord * Sin( alpha ) * Sin( theta )
z = z1 + move_cord * Cos( theta )

Движение по Z организовывается чуть сложнее, чем в плоскости, из-за особенностей вара:

//инициализация движения

real speed = 1000.0 //скорость движения
    
//теперь надо преобразовать скорость в вектор движения
    
real speed_x = speed * Cos(apha) * Sin(theta)
real speed_y = speed * Sin(apha) * Sin(theta)
real speed_z = speed * Cos(theta)

//сохраняем в хеш проекции скорости, и двигаем юнит таймером
//по Z чуть труднее
//не забываем умножать скорость на период таймера

real X = GetUnitX(u) + speed_x * timerPeriod
real Y = GetUnitY(u) + speed_y * timerPeriod
real Z = GetUnitFlyHeight(u) + speed_z * timerPeriod
real land_z = GetLocZ(X,Y) - GetLocZ(GetUnitX(u), GetUnitY(u)) //изменение высот ландшафта между текущей точкой юнита и будущей точкой (X,Y)

SetUnitX(u, X)
SetUnitY(u, Y)
SetUnitFlyHeight(u, Z+land_z, 0)
xgm.guru/p/wc3/183641?postid=343279 я собирал кучу наработку движения снарядов. там есть прямые движение по xyz. так вроде недавно видел много наработок и статье по lua
Загруженные файлы
27

» WarCraft 3 / Как на Jass'е вернуть уникальное ID юнита и записать в локалку?

Я только не понимаю: 0 - это значение, с которым мы сохраняем кастера? А если кастеров много, они все будут записываться в значение 0?
parentKey - родительский ключ
childKey - младший ключ
ты похоже не понимаешь как работает. хэндл у объектов разный, это просто счетчик объектов. например, создается первый футман ему перечисляют номер 1000 (1000-это условно, просто handle берет большие значения), спавнится второй футман он имеет номер 1001, создается третий футман 1002, создается стрелок 1003, декор 1004 итд. короче у разных кастеров не мб конфликта тк хэндлы разные
конфликты могут быть в коде, если старший и младший ключи совпадают. например 2 разных триггера, короче 2 абилки. Но имеют одинаковые ключи (первый: handle,0 второй: handle,0. Может произойти так что в одном триггере сохранишь, а в каком-нибудь втором из них перезапишешь данные. надо во втором триггере изменить младший ключ. изменить во втором во так: handle,1 - будет совсем другая ячейка)
А как это именно внутри функции с условием написать?
На гуи есть готовое решение. В разделе Boolean => HaveSavedHandle
И что такое число A?
Ну можно числа загружать из хэша
LoadInteger(Hash,id,0)>0 //в разделе integer
LoadReal(Hash,id,0)>0 //в разделе real

Кстати есть вот такая готовая функция BJ, в разделе boolean. не знал что есть
функция
function HaveSavedValue takes integer key, integer valueType, integer missionKey, hashtable table returns boolean
    if (valueType == bj_HASHTABLE_BOOLEAN) then
        return HaveSavedBoolean(table, missionKey, key)
    elseif (valueType == bj_HASHTABLE_INTEGER) then
        return HaveSavedInteger(table, missionKey, key)
    elseif (valueType == bj_HASHTABLE_REAL) then
        return HaveSavedReal(table, missionKey, key)
    elseif (valueType == bj_HASHTABLE_STRING) then
        return HaveSavedString(table, missionKey, key)
    elseif (valueType == bj_HASHTABLE_HANDLE) then
        return HaveSavedHandle(table, missionKey, key)
    else
        // Unrecognized value type - ignore the request.
        return false
    endif
endfunction
27

» WarCraft 3 / Как на Jass'е вернуть уникальное ID юнита и записать в локалку?

вот проверка тема
проверка хэндла
native HaveSavedHandle takes hashtable table, integer parentKey, integer childKey returns boolean
проверка числа integer или real проверяем условием A>0
обычно изначально в ячейках если ничего не записано, то вернет 0 или null
27

» WarCraft 3 / Как на Jass'е вернуть уникальное ID юнита и записать в локалку?

DopaMine, что вы хотите сделать? просто зачем вам хэш?
есть статья
просто для начала нужна ссылка на объект хэндл, чтобы получить GetHandleId(<object>). Или как-то записать или как-то по логике вызывается. Я просто напишу примеры для понимания как это работает. Хэндл этот просто помогает хранить/доставать данные, короче работать с ячейками
пример магазина, также можно сделать склад
как пример на jass
триггер 1 - продаем в магазин
событие - юнит закладывает в лавку (у нас 3 вар переменные: продавец и покупатель, предмет item, который продают в магазин. Эти 3 переменные-константы вызываемые при событии)
допустим мы можем сохранить item в хэш-таблицу по ключам. Это нужно для того, чтобы знать что есть в магазине. Какие предметы хранятся в магазине, в каком слоте, сколько зарядов. Просто нет никаких доп нативок для узнавания, поэтому мы импровизируем, создаем свою базу данных. Этот хэндл сыграл существенную роль
GetHandleId(<покупатель>)
также в хэш можно записать разные данные вроде тип, заряды, номер слота и пр
триггер 2 - выкупаем из магазина (аналогично 3 вар переменные, только роли продавца и покупателя меняются местами)
событие - юнит закладывает из лавки
допустим предмет удаляется из магазина, нам нужно из таблицы в данных магазина удалить этот предмет. с помощью хэндла магазина GetHandleId(продавец). С помощью вар переменной item можно достать тип и др данные хранящие в хэндле GetHandleId(продавец)
ваш случай
А триггера два, так как когда юнит жмёт способность, она сработает только если этот юнит атакован, в противном случае - просто идёт кулдаун. Как это сделать в одном триггере - хз.
Не знаю что хотите сделать. Но примерно догадываюсь, но это можно подкорректировать. Можно в атакующем юните хранить boolean b (да/нет), по хэндлу атакующего сохранять. Этот флаг будет говорить находится ли в кулдауне или нет.
Триггер 1 - при атаке загружаем boolean b по хэндлу атакующего и проверяем. Если boolean b вернет истину, то ваши действия.
Триггер 2 - при активации абилки запускаем таймер. Сохраняем в хэше boolean b = true (истина). Таймер длится столько сколько в кулдауне указано. По истечению таймера boolean b = false (ложь). Можно просто очистить хэш.
27

» WarCraft 3 / Как на Jass'е вернуть уникальное ID юнита и записать в локалку?

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

Если вы хотите знать кто зашел, то можно строкой выводить на экран. Выводите имя юнита. GetUnitName(<unit>) точнее вам будет название типа юнита, как в редакторе назвали юнита так и будет. Например, пехотинец, лучник итд
ID этого юнита(не ID типа юнита, а ID юнита!)
Если вам нужен не ID типа юнит, то что это за ID юнит? мб handle юнита? handle - номер объекта, у разных объектов разные номера. Но счетчики там большие. Есть нативка определения хэндла
GetHandleId(<unit>), которое возвращает целое число integer. короче номер объекта. не только юнита, можно любой наследник-объект хэндла (итем, декор, юниты, группа, олния и пр)
чтобы вывести строку на экран, нужно конвентировать число в строку I2S(<integer>)
на jass функция GetUnitTypeId(<unit>) возвращает id-тип, короче число. К примеру 'hfoo' - равкод футмана. мне лень просто объяснять вот
еще одна функция
GetObjectName(<id-object>) - в эту функцию вписываешь номер, целочисленное число. Короче тип объекта id-object. Это мб ид-юнит, ид-предмет, ид-декор, ид-абилы и др
27

» WarCraft 3 / Порча не работает на картах с размером больше 256х256

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

создай проверку, и искусственно чекай точки при отдаче приказа в точку "строить" и создавай порчу. это самое легкое
27

» WarCraft 3 / Проводник по способностям

keksCsGo777, никак. там у несколько игрушечных абил приказ общий. изменить это никак.
можно через канал+dummy-cast, но визуально вы не увидите как ставите, за вас сделает даймик
27

» WarCraft 3 / Нестандартные фундаменты

Принятый ответ
создать нестанд картинку, обведя альфа-слой без прозрачного слоя вокруг картинка получится смазанной, поэтому обязательно нужно края альфа-каналом обработать
еще в slk-файле редактировать
смотри в Splats\UberSplatData.slk информацию (извлеки эту таблицу из архива игры), там и код и анимация создания и появления, короче настройки указаны в slk. А вот в РО указано в "графика - текстура почвы (ubersplat)"
Либо берешь и заменяешь стандартные уберсплаты, заменяя станд путь. Или берешь slk-таблицу, в ней создаешь новую нестанд уберсплат, новый код и новую импортную картинку. пример
нажми Shift+Enter и пропиши новый код. Например, башня Альянса имеет код HSMA. Можешь сначала в slk-таблице создать QWER, а потом попробовать в башне прописать QWER
мб ошибаюсь, не знаю будет ли работать не стандартный код
27

» WarCraft 3 / Удаление дамми после каста спелла

юзаем поиск: dummy-cast (есть статья для начинающих)
смотря какие задачи перед вами стоят:
таймер смерти добавляешь на юнита. по истечении которого ваш юнит сам умрет. все так делали. вешали таймер, и юнит умирал после каста.

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

» WarCraft 3 / Вылетает редактор при изменении тригера.

событие какое? мб это вылетает из-за того что пытаешься удалить исследуемого юнита? "исследуемый юнит" - так понимаю, это юнит который завершает исследование, но ты пытаешься удалить его?
еще проверь не приводят ли замена бнитов к фаталу, особенно здания. больше пока не вижу на скрине ничего такого
27

» Crazy Dwarf Race / Crazy Dwarf Race

koloff, ну если хотите что то уникальное придумать =) и не "никакие" это не сложности
27

» Crazy Dwarf Race / Crazy Dwarf Race

Bergi_Bear,
я хочу упереться в борт, потерять 30% скорости и продолжить движение, но тут я даже не вижу этих бортов
можно навигационную стрелочку над головой сделать, пусть показывает что едешь правильно/не правильно. участки дороги можно поделить на мелкие прямые трассы (если будет крутой поворот, тогда нужно сразу делить тк навигатор сразу в обход к финишу поведет, а надо по дороге ехать. короче дугу на несколько кривых делим), на каждом участке дороги будет места куда надо доехать
стрелочку сделать не трудно и пусть меняет цвет красный: зеленый .