Добавлен , опубликован
Wurst Script - имеет множество плюшек в сравнении с другими языками, так как с его помощью можно уменьшить время пребывания в стандартном редакторе в разы! Практически всё можно делать в VSC. Весь редактор объектов уж точно. Об этом я напишу в этом ресурсе. Опишу только основы, но их вполне достаточно для понимания.

Редактор объектов

Абсолютно всё, что можно создать в редакторе объектов уже лежит в библиотеки Вурста. Точнее лежат стандартные юниты редактора, а нестандартные можно делать самому на их основе, как и в редакторе объектов.
Думаю стоит начать с самого важного - юнита.
Должен признать, что по началу это будет казаться жутко неудобным, но со временем вы будете с ненавистью смотреть на стандартный редактор. Проверил на собственном опыте.

Боевая единица

Если вы ещё не читали стати о Wurst Script, то я объясню.
Любой Wurst-код должен располагаться внутри пакета. Пакеты, в свою очередь, определяют организацию кода и пространства имен. Глобальное пространство имен, это пространство имен самого пакета, вне какого-либо блока кода (функции/класса/модуля и т.д.).
Подразумевается, что вы можете писать код в разных файлах, которые при инициализации карты сольются в полноценный. Поэтому все возможности библиотеки разбросаны по различным файлам и папкам для удобства и вам необходимо импортировать пакеты, чтобы они могли работать с вашим. Например чтобы создать юнита вам необходимо импортировать пакет UnitObjEditing. Для этого вы пишите import UnitObjEditing или же вызываете функцию, которая располагается внутри этого пакета и нажимаете CTRL + Ю и в появившемся списке выбираете нужный пакет.
Приведу небольшой пример.
@compiletime function flintShadowmore()
	new HeroDefinition(FLINT_SHADOWMORE_ID, UnitIds.arthas)
Первая строка создаёт функцию с названием flintShadowmore Не нужно волноваться об одинаковых названиях функций в разных пакетах, это не будет считаться ошибкой
Выражение new HeroDefinition обращается к публичносу классу в пакете UnitObjEditing и позволяет создать юнита.
FLINT_SHADOWMORE_ID - целочисленная переменная, в которой записан id юнита. вы можете придумать его сами, либо позволить сгенерировать. Далее вам нет нужды запоминать id, достаточно вставлять везде эту переменную.
public let FLINT_SHADOWMORE_ID = compiletime(HERO_ID_GEN.next())
UnitIds.arthas - обращение к пакету, в котором записаны id всех стандартных юнитов и им даны более читаемые названия чем 'hfoo'. Разумеется можно использовать и запись типа 'hfoo', но зачем, когда есть более удобная альтернатива.
Как мы теперь понимаем, мы создали нестандартного юнита на основе Артаса, как же нам изменить его параметры?
Для этого в Wurst Script используется запись типа .., после которой нам предлагаются на выбор все параметры юнита.
		..setAnimationRunSpeed(240.0)
		..setAnimationWalkSpeed(240.0)
		..setButtonPositionX(1)
		..setButtonPositionY(2)
		..setProjectileLaunchX(10.0)
		..setProjectileLaunchY(40.0)
		..setSelectionScale(1.3)
Весь Wurst Script написан на английском, но в целом он интуитивно понятен, так что проблем быть не должно.
Полный код юнита
package FlintShadowmore

import ObjectIds
import UnitObjEditing
import UnitIds
import Abilities
import public BountyHunter
import public RareVenom
import public StunGrenade
import public FlintEvasion
import ObjectIdGenerator

public let FLINT_SHADOWMORE_ID = compiletime(HERO_ID_GEN.next())

let NAME = "Bounty Hunter"
let FULLNAME = "Flint Shadowmore"
let ICON = "ReplaceableTextures\\CommandButtons\\BTNDarkSoldier2.blp"

let MODEL = "models\\FlintShadowmore\\FlintShadowmore.mdl"
let DESCRIPTION = "|cffffcc00Hero Unit (Melee)|r |nStrong Vs Heroes |nWeak Vs All Units, Buildings |n|n" +
									"|cffffcc00Role:|r |cff00ffffAssassin|r |n|n" +
									"|cffffcc00Can learn:|r |n" +
										"|cff00ffffBounty Hunter|r |cff6c7b8b(Passive Skill)|r |n  " +
											"|cffffdead125 + 275 extra gold for a kill|r |n  |cff6c7b8b(affects Heroes only)|r |n|n" +
										"|cff1c86eeRare Venom|r |cff6c7b8b(Orb Effect)|r |n  " +
											"|cffffdead20-50% to poison for 60s|r |n  |cff6c7b8b(affects organic Heroes only)|r |n  |cff6c7b8b(doesn't affect Special unit)|r |n|n" +
										"|cffff0000Stun Grenade|r |cff6c7b8b(Damage Spell)|r |n  " + 
											"|cffffdead125-250 damage, 5.5-7s stun|r |n  |cff6c7b8b(250-400 area of effect)|r |n|n" +
										"|cff00ffffEvasion|r |cff6c7b8b(Passive Skill)|r |n  " + 
											"|cffffdead13-25% to evade an attack|r"


@compiletime function flintShadowmore()
	new HeroDefinition(FLINT_SHADOWMORE_ID, UnitIds.arthas)
		..setHeroAbilities(commaList(BOUNTY_HUNTER_ID, RARE_VENOM_ID, STUN_GRENADE_ID, FLINT_EVASION_ID))
		..setNormalAbilities("AInv, A0ES")
		..setAnimationRunSpeed(240.0)
		..setAnimationWalkSpeed(240.0)
		..setButtonPositionX(1)
		..setButtonPositionY(2)
		..setProjectileLaunchX(10.0)
		..setProjectileLaunchY(40.0)
		..setSelectionScale(1.3)
		..setShadowImageCenterX(60.0)
		..setShadowImageCenterY(60.0)
		..setShadowImageHeight(140.0)
		..setShadowImageWidth(140.0)
		..setAcquisitionRange(700.0)
		..setAttack1AnimationBackswingPoint(0.84000003)
		..setAttack1AnimationDamagePoint(0.3)
		..setAttack1CooldownTime(1.8)
		..setAttack1DamageBase(214)
		..setAttack1DamageNumberofDice(1)
		..setAttack1DamageSidesperDie(21)
		..setAttack2AnimationBackswingPoint(0.84000003)
		..setAttack2AnimationDamagePoint(0.3)
		..setAttack2CooldownTime(1.8)
		..setAttack2DamageBase(214)
		..setAttack2DamageNumberofDice(1)
		..setAttack2DamageSidesperDie(21)
		..setAttack1WeaponSound(WeaponSound.MetalHeavySlice)
		..setAttack2ProjectileArt(Abilities.gargoyleMissile)
		..setAttack2ProjectileSpeed(2200)
		..setAttack2ProjectileHomingEnabled(true)
		..setAttack2Range(400)
		..setAttack2TargetsAllowed(TargetsAllowed.air)
		..setAttacksEnabled(3)
		..setDefenseBase(8)
		..setSpeedBase(220)
		..setTurnRate(3.0)
		..setCollisionSize(30.0)
		..setUnitSoundSet("")
		..setAgilityPerLevel(1.0)
		..setBuildTime(1)
		..setGoldBountyAwardedBase(0)
		..setGoldBountyAwardedNumberofDice(0)
		..setGoldBountyAwardedSidesperDie(0)
		..setGoldCost(1000)
		..setHitPointsMaximumBase(5000)
		..setHitPointsRegenerationRate(5.0)
		..setIntelligencePerLevel(1.0)
		..setLumberCost(0)
		..setManaInitialAmount(2000)
		..setManaMaximum(250)
		..setManaRegeneration(1.0)
		..setPointValue(360)
		..setPrimaryAttribute("AGI")
		..setPriority(3)
		..setSightRadiusDay(1000)
		..setStartingAgility(16)
		..setStartingIntelligence(2)
		..setStartingStrength(12)
		..setStockMaximum(1)
		..setStockReplenishInterval(600)
		..setStrengthPerLevel(1.0)
		..setHotkey("")
		..setName(NAME)
		..setTooltipBasic("Train " + NAME)
		..setProperNames(FULLNAME)
		..setCategorizationCampaign(false)
		..setIconGameInterface(ICON)
		..setIconScoreScreen(ICON)
		..setModelFile(MODEL)
		..setTooltipExtended(DESCRIPTION)
		..setScalingValue(0.9)
		..setAnimationCastBackswing(0.5)

Способность

Методика создания способности в целом не отличается.Самым большим отличием является то, что нам сперва нужно понять на основе какой способности мы хотим создать свою. Возьму способность того же самого Флинта - Bounty Hunter
Для начала нам нужно найти в библиотеке пакет AbilityObjEditing и поискать в нём нужную способность, допустим это аура архимага. на английском это Brilliance Aura, поэтому нажмём CTRL + F и впишем без пробела BrillianceAura, находим публичный класс с нужным названием, а это будет AbilityDefinitionArchMageBrillianceAura и копируем его, после чего пишем знакомый код, с небольшими изменениями.
@compiletime function bountyHunter()
	new AbilityDefinitionArchMageBrillianceAura(BOUNTY_HUNTER_ID)
Как и в случае с юнитом мы пишем new а затем вставляем название класса и импортируем пакет, вписываем наш id способности и вот способность готова. Точно так же мы можем при помощи двух точек вызвать все параметры способности и при желании изменить их. И тут выясняется, что есть ещё один плюс у Wurst Script, далеко не всегда нужно писать как в редакторе для каждого уровня способности отдельное описание.
..presetTooltipNormal(lvl -> NAME + " - [|cffffcc00Level " +  lvl.toString() + "|r]")
lvl -> - обозначает, что это описание используется для всех уровней способности. Переменная lvl находится внутри класса и принимает значение количества уровней способности. как видно из примера в Wurst Script можно в создании способностей использоавть переменные, к примеру lvl и NAME. Использовать их можно не только в описании, но и в числовых показателях.
..presetDamageAmount(lvl -> 100.0 + 25 * lvl)
Как видно из примера на каждом уровне способности её урон увеличивается на 25 единиц.
Полный код способности
package BountyHunter

import ObjectIdGenerator
import AbilityObjEditing
import BuffObjEditing
import Abilities
import ObjectIds
import Icons

public let BOUNTY_HUNTER_ID = compiletime(ABIL_ID_GEN.next())
public let BOUNTY_HUNTER_BUFF_ID = compiletime(BUFF_ID_GEN.next())

let NAME = "Bounty Hunter"

@compiletime function bountyHunter()
	new AbilityDefinitionArchMageBrillianceAura(BOUNTY_HUNTER_ID)
		..setName(NAME)
		..setLevels(7)
		..setLevelSkipRequirement(4)
		..presetHotkey("")
		..setTooltipLearnExtended("Gives extra gold")
		..presetManaRegenerationIncrease(lvl -> 0.0)
		..presetTooltipNormal(lvl -> NAME + " - [|cffffcc00Level " +  lvl.toString() + "|r]")
		..presetTooltipNormalExtended(lvl -> "")
		..presetTargetsAllowed(lvl -> TargetsAllowed.self)
		..setArtTarget(Abilities.drumsCasterHeal)
		..presetTooltipLearn(lvl -> "Learn " + NAME + " - [|cffffcc00Level " + lvl.toString() + "|r]")
		..presetAreaofEffect(lvl -> 0.1)
		..presetIcon(Icons.bTNMGExchange)
		..presetBuffs(lvl -> BOUNTY_HUNTER_BUFF_ID.toRawCode())
		..presetButtonPosNormal(0, 0)

@compiletime function bountyHunterBuff()
	new BuffDefinition(BOUNTY_HUNTER_BUFF_ID, 'BHab')
		..setRace(1, Race.Other.toObjectString())
		..setIcon(Icons.bTNMGExchange)
		..setArtTarget(1, "")
		..setTargetAttachmentPoint0(1, "")
		..setTooltipNormal(1, NAME)
		..setTooltipNormalExtended(1, "This unit gets extra gold for Hero kills.")

Послесловие

Я привел всего два примера, но механика создания предметов, баффов и прочего похожа с примерами и раздельно описывать кадый не вижу смысла. Я лишь показываю, что можно делать в Wurst Script, а не записываю подробные гайды.
Также должен отметить, что все не изменённые вами параметры той или иной боевой единицы, способности и прочего принимают значения того, что было взято за основу, как в стандартном редакторе объектов. В следующий раз я расскажу, как менять константы, экран загрузки и прочее через VSC.
`
ОЖИДАНИЕ РЕКЛАМЫ...