Перейти к содержанию

Сообщения от Скрипты

3 года назад

Большое спасибо за детальные комментарий ув. Долгий и ув. Jack of shadows. 

 

Проблема в том, что как я понимаю, если в хуке UnitMove я возвращаю not nil, то юнит не должен дальше перемещаться. У меня же получается ситуация, почему-то, что юнит и кастует заклинание, и делает ход, при чём ход он делает первым. Я перепроверил документацию Novik'a, там тоже написано, что UnitMove должен вызываться перед каждым ходом стека существа. 

 

То есть, ожидаемая последовательность действий:

1. Существо получает ход

2. Наступает хук UnitMove

3. В хуке я накладываю слепоту и возвращаю not nil

4. Существо остаётся на своём месте, проиграв анимацию заклинания. 

Реальная последовательность действий:

1. Существо получает ход

2. Наступакт хук UnitMove

3. Существо делает действие (бежит вперёд или атакует, если дотягивается)

4. Передаётся действие моему обработчику и существо накладывает заклинание

5. возвращается not nil

 

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

 

 

Аватар пользователя
3 года назад
А как выглядит ваш скрипт?
Аватар пользователя
3 года назад
Всё должно быть как вы ожидаете, особых хитростей там нет. Надо обложить код принтами и смотреть, может он валится где-то до выхода из UnitMove().
В ответ пользователю Jack_of_shadows
Аватар пользователя
3 года назад
Всем привет! Есть вопрос
Я написал скрипт по типу превращалки как в кампании РедХейвена, только оочень простую. Так вот, когда, например, кладу в превращалку 20 скелетов-лучников, то получаю 20 моих ncf скелетов, НО если я кладу туда два стека по 10 (то есть в общем 20), то результатом получаю 40(!)
----Превращалка: Хафад может преобразовывать обычную нежить в новых некроюнитов----
function CustomAbility(hero, id)
if (id == CUSTOM_ABILITY_3) then
Hero = hero
MakeHeroInteractWithObject(hero, "ritual")
sleep(10)
for i=0,6 do
local type, num = GetObjectArmySlotCreature("ritual", i)
if (type >= 30 and type <= 42 and mod(type, 2) == 0) or (type >= 152 and type <= 158) then
startThread(NecroRitual)
SetObjectOwner("ritual", PLAYER_2)
end
end
local x,y = GetObjectPosition("Hafad")
PlayVisualEffect("/Effects/_(Effect)/Spells/Curse.xdb#xpointer(/Effect)","","tag1", x+0.5,y+0.5,0,GROUND);
PlayVisualEffect("/Effects/_(Effect)/Spells/DisruptingRay.xdb#xpointer(/Effect)","","tag1", x+0.5,y+0.5,0,GROUND);
sleep(2)
PlayVisualEffect("/Effects/_(Effect)/Spells/AnimateDead.xdb#xpointer(/Effect)","","tag1", x+0.5,y+0.5,0,GROUND);
local Level = GetHeroLevel("Hafad")
local Spell = GetHeroStat("Hafad", STAT_SPELL_POWER)
local quantity = 0.35 * Level + Spell
AddHeroCreatures("Hafad", 40, quantity)
ShowFlyingSign("/Text/MasterOfDeath.txt", "Hafad", 1, 5.0)
sleep(1)
ControlHeroCustomAbility(hero, CUSTOM_ABILITY_3, CUSTOM_ABILITY_DISABLED)
end
end

function NecroRitual()
for i=0,6 do
local type, num = GetObjectArmySlotCreature("ritual", i)
if GetObjectArmySlotCreature("ritual", i) == 30 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 896, num)
elseif type == 32 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 897, num)
elseif type == 34 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 898, num)
elseif type == 36 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 899, num)
elseif type == 38 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 900, num)
elseif type == 90 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 901, num)
elseif type == 42 then
RemoveObjectCreatures('ritual', type, num, i)
AddHeroCreatures(Hero, 902, num)
end;
end;
end;
В ответ пользователю BlueHeavenHero
Аватар пользователя
3 года назад
У меня есть предположение, что функция GetObjectArmySlotCreature() делалась в основном для получения id со слота, а не кол-ва юнитов и возвращает общее кол-во данных существ

Добавлено через 19 минут
Ну или sleep() не хватает из-за чего кол-во существ успевает посчитаться дважды
В ответ пользователю Долгий
Аватар пользователя
3 года назад
Долгий
У меня есть предположение, что функция GetObjectArmySlotCreature() делалась в основном для получения id со слота, а не кол-ва юнитов и возвращает общее кол-во данных существ

Добавлено через 19 минут
Ну или sleep() не хватает из-за чего кол-во существ успевает посчитаться дважды
А в каком месте посоветуете поставить sleep()? Хочу сначала проверить второй вариант.
В ответ пользователю BlueHeavenHero
Аватар пользователя
3 года назад
BlueHeavenHero
А в каком месте посоветуете поставить sleep()? Хочу сначала проверить второй вариант.
Внутри цикла for, функции NecroRitual()
В ответ пользователю Долгий
Аватар пользователя
3 года назад
Долгий
Внутри цикла for, функции NecroRitual()
Так, у меня ничего не изменилось. походу надо переписывать весь скрипт ритуала(
В ответ пользователю BlueHeavenHero
Аватар пользователя
3 года назад
Я немного не понимаю эту часть - 

for i=0,6 do
     local type, num = GetObjectArmySlotCreature("ritual", i)
     if (type >= 30 and type <= 42 and mod(type, 2) == 0) or (type >= 152 and type <= 158) then
          startThread(NecroRitual)
          SetObjectOwner("ritual", PLAYER_2)
     end
end. 

и потом в функции ритуала - 

for i=0,6 do
    local type, num = GetObjectArmySlotCreature("ritual", i)
    if GetObjectArmySlotCreature("ritual", i) == 30 then
        RemoveObjectCreatures('ritual', type, num, i) ...

Зачем ты на каждый слот ставишь героя владельцем? По идее это можно сделать вне цикла. и почему ты на каждый слот начинаешь новый поток? Я скрипт не запускал, но выглядит так, будто ты на два слота стартуешь 2 потока работающих параллельно(типо) и когда обработка второго цикла по функции ритуала ПОВТОРНО проходит через все слоты, когда второй поток считывает первый слот он ещё не очищен(первым потоком). Вроде как, если убрать цикл в функции или убрать дублирование потоков, всё должно заработать. 


Типо-

        MakeHeroInteractWithObject(hero, "ritual")
        sleep(10)
        startThread(NecroRitual)
        SetObjectOwner("ritual", PLAYER_2)
        local x,y = GetObjectPosition(Hero) ...
А, и это чисто эстетически, но раз ты берёшь имя героя из функции, то почему пишешь в других местах "Hafad"? 
В ответ пользователю LetoX
Аватар пользователя
3 года назад
LetoX
Я немного не понимаю эту часть - 

for i=0,6 do
     local type, num = GetObjectArmySlotCreature("ritual", i)
     if (type >= 30 and type <= 42 and mod(type, 2) == 0) or (type >= 152 and type <= 158) then
          startThread(NecroRitual)
          SetObjectOwner("ritual", PLAYER_2)
     end
end. 

и потом в функции ритуала - 

for i=0,6 do
    local type, num = GetObjectArmySlotCreature("ritual", i)
    if GetObjectArmySlotCreature("ritual", i) == 30 then
        RemoveObjectCreatures('ritual', type, num, i) ...

Зачем ты на каждый слот ставишь героя владельцем? По идее это можно сделать вне цикла. и почему ты на каждый слот начинаешь новый поток? Я скрипт не запускал, но выглядит так, будто ты на два слота стартуешь 2 потока работающих параллельно(типо) и когда обработка второго цикла по функции ритуала ПОВТОРНО проходит через все слоты, когда второй поток считывает первый слот он ещё не очищен(первым потоком). Вроде как, если убрать цикл в функции или убрать дублирование потоков, всё должно заработать. 
Я сам плохо понимаю в таких скриптах( Поэтому, наверное, и сделал два раза.
LetoX

Типо-

        MakeHeroInteractWithObject(hero, "ritual")
        sleep(10)
        startThread(NecroRitual)
        SetObjectOwner("ritual", PLAYER_2)
        local x,y = GetObjectPosition(Hero) ...
А, и это чисто эстетически, но раз ты берёшь имя героя из функции, то почему пишешь в других местах "Hafad"? 
Ну, просто именно Хафад должен делать ритуал и получать войска, никому другому эта возможность недоступна, а в других местах так и оставил имя героя из функции


Добавлено через 44 секунды
Сейчас я шаманю над скриптом РедХевена по превращению обычных людей в зеленых. Вот это пляски с бубном...
Аватар пользователя
2 года назад
Можно ли в героях сделать такие скрипты:

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

2) Можно ли вообще любое здание сделать, как хижина пророка? Подходишь к башне лучников, а там тебе - принеси мол 100 дерева, а мы сделаем стрелы и пойдем с тобой в бой... Или подплываешь к объекту русалке, а она просит найти артефакт какой-то... Это перед объектом надо зону скрипта настроить или вообще в самих настройках объекта менять? 

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

4) Может ли наградой быть телепортация? Например выполняешь квест грифонов и герой оказывается за горами (типа птички перенесли)?

5) Могут ли на карте появляться объекты? Не монстры в какую-то неделю, а скажем шахты/повышалки/или там кактусы. Например, показать, что пришла засуха и хоп на карте какая-то кучка сухих деревьев возникла. И герой квестом/боем может убрать эти сухие деревья и вернуть снова прежний красивый вид. 

ЗЫ: Может еще какие мысли возникнут, но пока так.
В ответ пользователю Simsa
Аватар пользователя
2 года назад

Simsa,
1 и 2:  SetObjectEnabled("объект", true(работает как и должен) или false(становится как статика, с которой можно взаимодействовать)), после которого можешь поставить на объект триггер касания(OBJECT_TOUCH_TRIGGER) который будет вызывать функцию, в которой будут обрабатываться квесты и диалоги

3.
1) Если есть квест на сейв героя, то нужно переделать его в "болванку"(переключить на OBJECTIVE_KIND_MANUAL если был переключен), т.е. сделать фейл квеста только по скрипту по какому-то условию а не технически, иначе в любом случае будет проигрываться сценарий. Да, вот ещё что: чтобы фейлить квесты без завершения карты, нужно обязательно выставлять Ignore = true в скелетах квестов.
2) По телепорту героя в случае проигрыша: Кидаем главного героя в резерв игрока, удаляем его с карты ибо резервный герой изначально не должен на ней быть. Вначале сюжета ставим его на карту скриптом(DeployReserveHero("скриптовое имя героя", x, y, z куда ставить)) + можно развернуть функцией SetObjectRotation("скриптовое имя героя", градусы(против часовой стрелки)). Перед этим пропишем триггер на потерю героев у игрока и функцию которая будет запускаться, в которой отследим что если потеряли именно нужного героя то поставим его снова на карту в другой точке(так же через DeployReserveHero), выдадим нужную армию а дальше уже на своё усмотрение что делать. Рекомендую резервному герою задать хотя бы какую-то армию путём редактирования его параметров, иначе при спавне будет генерироваться случайная армия, основываясь на его специализации.

4. Да, можно через триггер изменения статуса заданий отследить у какого задания поменялся статус на "выполнено", и по случаю выполнения условия через функцию сделать нужному объекту SetObjectPosition()

5. Можно спавнить жилье юнитов, статику, ресурсы, артефакты, существ, караваны и героев(из резерва). С шахтами нельзя манипулировать, кроме как менять их владельцев и выключать/включать их стандартное посещение через SetObjectEnabled. С объектами, дающими бонусы, работает только выключение/включение. Насчёт удаления созданной статики я не знаю т.к. не работал с этим функционалом.

В ответ пользователю Азгалор
Аватар пользователя
2 года назад
Азгалор

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

5. Можно спавнить жилье юнитов, статику, ресурсы, артефакты, существ, караваны и героев(из резерва). 

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

Статика это что именно? Предметы окружения (кусты, камни и тд)? Тайлы я так понимаю нельзя перекрашивать? Типа траву заменить на лавовую землю или снег на траву? 

Вроде где-то читала, что можно работать со светом... можно же к примеру задать какое-то свечение объекту (тут я так понимаю возвращаемся к пункту 1 (false) - условно - куст светится красным  - герой натыкается на скрипт, где прописан бой (как с сундуком бывает) а после победы куст теряет красное свечение и становится обычным. Или не куст, а скажем фонтан. То есть в скрипте должно быть прописано условие типа после решения задачи скрипта (победить врагов) - объект снова должен стать true? 

Еще кстати:

6) Можно ли создавать слухи без таверны? Например я хочу чтобы у игрока не было возможности нанимать других героев, но при этом он может узнавать какие-то слухи. Для этого надо всякие нужные слухи просто добавить к юнитам/объектам на карте (например воин рассказывает историю, но это не квест. Как в таверне бывает - где-то в пустыне закопан артефакт - говорят). Или можно поставить таверны, но при этом без возможности нанять героев там. Но можно почитать слухи и посмотреть армию врага. Вообще эта функция смотреть армию врага (в таверне и логове воров) может быть создана с другими объектами? Например некий юнит играет роль шпиона - за определенную сумму или вещь (деньги/драгоценности/артефакт) он выдает информацию - по армии врага или секрет какой-то.

7) Туман войны можно включать заново? Например, я хочу, чтобы после очередной "смерти" герой оказывался в подземелье снова в темноте. Даже если он уже там бывал и облазил все. 

8) Чтобы случайные монстры не спавнились в подземелье - надо отключить недели спавна или указать, что спавн должен быть только на поверхности? Как бы совсем отключать недели спавна не хочется, но и оказаться с кучкой элементалей после недель спавна драконов/стрелков/энтов и просто застрять там без возможности выбраться не очень будет...
Аватар пользователя
2 года назад
Почитайте руководство Ogo-i для чайников и ЧаВо Jack of Shadows. Там ответы на многие ваши вопросы!

6) Только скриптами. Привязать к юнитам/объектам интерактив с выдачей случайных сообщений, сделать пул этих сообщений. Если нужна зависимость от событий на карте, то для этих событий нужно создать ивенты (например, в цикле проверять, изменился ли набор артефактов у героя и добавлять соответствующий слух).Так вам скажу: задача это нетривиальная, не для новичка. Рекомендую ограничиться просто фиксированными слухами, которые будете иметь в таблице:
custom_rumours={
"../Rumour1.txt",
"../ElseMoreRumours.txt",
"../ARumourToo.txt",
}

function NpcRumoursTalk(hero, obj)
if hero=="главный герой" then
local index = random(length(custom_rumours))
ShowFlyingSign(custom_rumours[index], obj, GetObjectOwner(hero), 10);
end
end

SetObjectEnabled("имя объекта", nil)
Trigger(OBJECT_TOUCH_TRIGGER, "имя объекта", "NpcRumoursTalk")

Приведённый простой скрипт будет выдавать указанным объектом всплывающее сообщение со случайнвм слухом из списка.

7) Нереализуемо.

8) Отключение недели спавна распространяется на все уровни.

В ответ пользователю Simsa
Аватар пользователя
2 года назад

Simsa

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

Статика это что именно? Предметы окружения (кусты, камни и тд)? Тайлы я так понимаю нельзя перекрашивать? Типа траву заменить на лавовую землю или снег на траву? 

Вроде где-то читала, что можно работать со светом... можно же к примеру задать какое-то свечение объекту (тут я так понимаю возвращаемся к пункту 1 (false) - условно - куст светится красным  - герой натыкается на скрипт, где прописан бой (как с сундуком бывает) а после победы куст теряет красное свечение и становится обычным. Или не куст, а скажем фонтан. То есть в скрипте должно быть прописано условие типа после решения задачи скрипта (победить врагов) - объект снова должен стать true? 

Для подобных телепортаций будет достаточно иметь одну таблицу координат и выбирать из них. Прописывать армию герою придётся так и так, т.к. из резерва он появляется либо со стандартной армией, либо с заранее прописанной в редакторе. Естественно так же придётся переносить прокачку, спеллы и артефакты от умершего героя на героя из резерва(офк, если это нужно по логике).
Статики - это в принципе любой объект, который имеет тип AdvMapStatic. Их можно создавать/удалять на карте в любое время. Здания, типа шахт имеют тип AdvMapBuilding, их создавать не получится.
Свечение на объектах можно настраивать заранее в редакторе, а так же с помощью функций SetObjectFlashlight/ResetObjectFlashlight, при этом источник света, который хочешь добавить на объект надо заранее вписать в ресурсы карты, в раздел point lights(мб немного другое название, точно не помню)

А так, как написал Хоттабыч, на большинство вопросов ответит стандартное руководство по скриптам в файлах игры, либо проверенные временем гайды от Новика или Jack of Shadows. Полного понимания они не дадут, но хотя бы позволят иметь представление, что в принципе можно сделать с помощью скриптов. Рекомендую также вступить в группу вк из подписи Хоттабыча, там оч много годной информации, в том числе и по очень специфичным фишкам скриптов. Можно написать мне в тг/дискорд(есть в профиле), могу подсказать по любым конкретным вопросам не только по скриптам, но и по редактору в целом.

Статистика

Приветствуем новейшего участника: recijeb