Как сделать ловушку через триггеры

Добавлен , опубликован
Геймплей:
Механика
Эта статья содержит поэтапные указания, в результате которых должна получится некая ловушка, основанная на триггерах в workshop tools. Также она является примером того, как работают триггеры и как ими пользоваться. Это переведенная статья и картинки и видео взяты с оригинала, ссылка на который находится внизу.

Что у вас должно получится, следуя этой статье:

Создание юнита

Такой результат получен с помощью невидимого блока trigger_dota, который запускает функцию npc_dota_base, выпускающую стрелу в его сторону. Звучит немного сложно, но на самом деле все проще, чем кажется. Первым делом нам нужен юнит-пустышка. Мы создадим его в текстовом файле cripts\npcs\npc_units_custom.txt , который находится в папке с нашей картой.
Код
// Юниты
"DOTAUnits"
{
  "Version"  "1"
  "npc_dota_arrow_trap"
  {
    "Model"      "models/development/invisiblebox.mdl"
    "BaseClass"  "npc_dota_creature"
    
    // Способности
    //----------------------------------------------------------------
    "Ability1"   "dota_ability_trap_arrow"
    "Ability2"   "unselectable"
    "Ability3"   ""
    "Ability4"   ""
 
    // Атака
    //----------------------------------------------------------------
    "AttackCapabilities"  "DOTA_UNIT_CAP_NO_ATTACK"
 
    // Передвижение
    //----------------------------------------------------------------
    "MovementCapabilities"  "DOTA_UNIT_CAP_MOVE_NONE"
 
    "UnitRelationshipClass" "DOTA_NPC_UNIT_RELATIONSHIP_TYPE_WARD"
  }
}
Самая важная часть в создании ловушки это добавить ей способность dota_ability_trap_arrow. Вторая способность unseletable делает юнита невидимым и некликабельным, но можно обойтись без нее.
Еще, что важно, этот юнит не может передвигаться или атаковать. Это сделано для того, чтобы ваша невидимая ловушка не бегала по карте и атаковала всех из инвиза.

Способности для ловушки

Следующим нашим шагом будет создать способности dota_ability_trap_arrow и unseletable в текстовом файле scripts\npcs\npc_abilities_custom.txt:
Код
// Герои Доты
"DOTAAbilities"
{
  "Version"    "1"
  //=========================================================================================
  // Скрываем юнита
  //=========================================================================================
  "unselectable"
  {
    // Общее
    //-------------------------------------------------------------------------------------------------------------
    "AbilityBehavior"        "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_HIDDEN"
    
    "BaseClass"             "ability_datadriven"
    
    "Modifiers"
    {
      "modifier_unselectable"
      {
        "Passive" "1"
        "States"
        {
          "MODIFIER_STATE_UNSELECTABLE"         "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_NO_UNIT_COLLISION"    "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_NOT_ON_MINIMAP"       "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_PROVIDES_VISION"      "MODIFIER_STATE_VALUE_DISABLED"
          "MODIFIER_STATE_ROOTED"               "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_SOFT_DISARMED"        "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_INVULNERABLE"         "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_LOW_ATTACK_PRIORITY"  "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_FLYING"               "MODIFIER_STATE_VALUE_ENABLED"
          "MODIFIER_STATE_BLOCK_DISABLED"       "MODIFIER_STATE_VALUE_ENABLED"
        }
      }
    }
  }
  "dota_ability_trap_arrow"
  {
    "BaseClass"           "mirana_arrow"
    // Общее
    //-------------------------------------------------------------------------------------------------------------
    "AbilityBehavior"        "DOTA_ABILITY_BEHAVIOR_DIRECTIONAL | DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING"
    
    // Каст
    //-------------------------------------------------------------------------------------------------------------
    "AbilityCastRange"        "3000"
    "AbilityCastPoint"        "0"
 
    // Перезарядка
    //-------------------------------------------------------------------------------------------------------------
    "AbilityCooldown"        "4"
 
    // Затрачиваемая мана
    //-------------------------------------------------------------------------------------------------------------
    "AbilityManaCost"        "0"
 
    // Особое
    //-------------------------------------------------------------------------------------------------------------
    "AbilitySpecial"
    {
      "01"
      {
        "var_type"      "FIELD_FLOAT"
        "arrow_speed"    "857.0"
      }
      "02"
      {
        "var_type"      "FIELD_INTEGER"
        "arrow_width"    "115"
      }
      "03"
      {
        "var_type"      "FIELD_INTEGER"
        "arrow_range"    "3000"
      }
      "04"
      {
        "var_type"      "FIELD_INTEGER"
        "arrow_max_stunrange"  "1500"
      }
      "05"
      {
        "var_type"      "FIELD_FLOAT"
        "arrow_min_stun"  "2"
      }
      "06"
      {
        "var_type"      "FIELD_FLOAT"
        "arrow_max_stun"  "2"
      }
      "07"
      {
        "var_type"      "FIELD_FLOAT"
        "arrow_bonus_damage"  "140"
      }
      "08"
      {
        "var_type"      "FIELD_INTEGER"
        "arrow_vision"  "650"
      }
    }
  }
}
Из кода, написанного выше, вы можете увидеть, что наша ловушка dota_ability_trap_arrow основана на способности мираны. Она как раз подходит для ловушки, которую мы собираемся сделать, но любая другая способность похожего типа подойдет.
Рассмотрим некоторые модификации, которые мы сделали. Заметьте, что наша стреляющая ловушка не имеет маны, поэтому на каст стрелы мы установили 0 AbilityManaCost (Затрачиваемая мана), чтобы не делать способность бесполезной. Также стоит обратить на AbilityCastPoint (Задержка каста), которой мы тоже присвоили значение 0. Даже наша ловушка может иметь задержку перед кастом, а это значит, что она будет стрелять немного позже того момента, когда герой вступит на область. Поэтому, если хотите, чтобы стрела выпускалась мгновенно, то в этом поле стоит оставить 0. Хотя вы можете поэкспериментировать и выставить любое другое значение, подходящее вам.
Также мы изменили перезарядку стандартной стрелы мираны на 4 секунды, чтобы сделать ловушку более быстрой, но вы можете указать свое значение. Помимо этого мы поменяли и время стана, но это тоже можно отрегулировать на ваш вкус.
Теперь, когда мы добавили нашей ловушке способность выпускать стрелы, нам нужно заставить ее стрелять по команде с помощью триггеров.

Триггеры

После следующих действий, так будет выглядеть наша ловушка в редакторе:
Первым делом поставим npc_dota_base в то место, откуда вы хотите, чтобы вылетали стрелы:
И затем мы изменяем его Object Properties (Свойства объекта) так, чтобы у него было особое имя и наш trigger_dota работал вместе с npc_dota_base и присваиваем ему Entity Script arrow_trap_ai.lua, который мы доделаем позже. Наконец, можно поставить Unit Name (Имя юнита) npc_dota_arrow_trap , чтобы ловушка работала корректно.
Наш NPC готов метать стрелы, но нужно, чтобы ему что-то приказывало это делать. Это что-то будет trigger_dota . Для этого мы выбираем toolsstrigger.vmat материал для нашего блока и ставим его на карту:
Дальше мы жмем “Tie Selected Meshes To Entity” и меняем сущность объекта на trigger_dota . (У меня этот пункт стоит по дефолту, т.к. я настроил свой редактор, у вас, возможно, стоит trigger_multiply)
Жмем Alt+Enter, и открывается окно свойств объекта trigger_dota. Теперь мы выбираем вкладку Outputs и жмем Add, чтобы создать новый output. Нам нужно, чтобы ловушка реагировала на героя и запускала триггер, поэтому в поле My output named выбираем OnTrigger. В следующем поле Target entities named выбираем то имя, которым мы назвали свойство, в данном случае это npc_arrow_trap1. В окне Via this input выбираем пункт CallScriptFunction, который будет вызывать функцию из Entity Scripts, которая относится к нему. И в последнем пункте (который мы заполним) With a parameter override of назовем функцию Fire.
Можно добавить немного декораций, чтобы смотрелось лучше, но это уже на ваш выбор.

Функция Fire

Ловушка почти готова! Осталось только создать функцию Fire в scripts\vscripts\arrow_trap_ai.lua.
Код
function Fire(data)
  local target = data.caller
  if target ~= nil then
    local arrow = thisEntity:FindAbilityByName("dota_ability_trap_arrow")
    thisEntity:CastAbilityOnPosition(target:GetOrigin(), arrow, -1 )
  end
end
Скрипт получает доступ к определению объекта, связанному с ним через переменную thisEntity. Кроме того, если Output запускает функцию через CallScriptFunction, то запускаемое определение передается в параметры как вызов. Благодаря этим двум вещам, мы можем использовать функцию CastAbilityOnPosition, которая выстреливает стрелой по направлению к Origin (Точка начала координат) области trigger_dota, когда игрок входит в нее.
Замечание: хочу заметить, что способность кастуется по направлению к началу координат trigger_dota. Чтобы узнать, где это находится нужно выбрать Translate tool (Перемещение), и вы увидите три оси, выходящих из одной точки. Это и будет Origin области trigger_dota. В данном примере эта точка находится ровно по центру, но это не принципиально, и вы можете поставить ее где хотите.

Precache

Наконец, как и все другие пункты в д2 модмейкинге, предварительное кэширование играет очень важную роль.
Так как мы используем стрелу мираны, то мы должны создать видимость и звук этой стрелы. Если вы не сделаете этого, то не увидите и не услышите ее. Это делается достаточно легко, путем редактирования Precache функции в scripts\vscripts\addon_game_mode.lua
Код
if CArrowTrapDemo == nil then
  CArrowTrapDemo = class({})
end
 
function Precache( context )
  PrecacheResource( "soundfile", "soundevents/game_sounds_heroes/game_sounds_mirana.vsndevts", context )
  PrecacheResource( "particle_folder", "particles/units/heroes/hero_mirana", context )
end
 
-- Create the game mode when we activate
function Activate()
  GameRules.AddonTemplate = CArrowTrapDemo()
  GameRules.AddonTemplate:InitGameMode()
end
 
function CArrowTrapDemo:InitGameMode()
end
Если вы все сделали согласно этому уроку, то ваша ловушка должна работать как на первом видео.

`
ОЖИДАНИЕ РЕКЛАМЫ...
4
20
10 лет назад
4
У меня все получилось как в инструкции, так что, если у вас что-то не работает, задавайте вопросы.
3
15
10 лет назад
3
ЖУТЬ КАК СЛОЖНО! Запилите триггеры ( ааааааааа пощади меня !
0
20
10 лет назад
0
Но триггеры уже есть.
0
15
10 лет назад
0
Praytic:
Но триггеры уже есть.
ого! А как давно их сделали ?
Этот комментарий удален
1
20
10 лет назад
1
Mark Mocherad:
Praytic:
Но триггеры уже есть.
ого! А как давно их сделали ?
Триггер в д2 - это по сути совокупность области действия и связанного с ней объекта действия, а не то, что ты подумал типо варкрафта.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.