на jazz'e globals
// Чёрная магия: Темница spell raw code
// Default: A004
private constant integer BMAGIC_RAWCODE = 'A004'
// меч raw code
// Default: u001
private constant integer SWORD_RAWCODE = 'u001'
// Dummy Темница raw code
// Default: A005
private constant integer BROOTS_RAWCODE = 'A005'
// Dummy Темница buff raw code
// Default: B001
private constant integer BROOTS_BUFF_RAWCODE = 'B001'
// Lightning type ***
// Default: DRAM
private constant string LIGHTNING_TYPE = "DRAM"
// Model file of sword
// Default: war3mapImported\\Frostmourne.mdx
private constant string SWORD_MODEL_FILE = "war3mapImported\\Frostmourne.mdx"
// Blood effect
// Default: Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl
private constant string BLOOD_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
// Blood effects attach point to target
// Default: origin
private constant string ATTACH_POINT = "origin"
// Dummy ability order id
// Default: entanglingroots
private constant string DUMMY_ORDER = "entanglingroots"
// Extra swords distance from target
// Default: 300.
private constant real EXTRA_SWORDS_OFFSET = 300.
// Pitch angle of extra swords
// Default: 45
private constant integer EXTRA_SWORDS_PITCH = 45
// Extra swords appear / disappear time in seconds
// Default: 0.9
private constant real EXTRA_SWORDS_APPEAR_TIME = 0.9
// Spells interval
// Default: 0.025
private constant real INTERVAL = 0.025
// Swords speed
// Default: 1000.
private constant real SWORD_SPEED = 1000.
// Every n intervals load blades old motion
// Default: 8
private constant integer BLADE_MOTION_FACTOR = 8
// Units stab z offset
// Default: 70.
private constant real STAB_Z_OFFSET = 70.
// Main swords height
// Default: 65.
private constant real SWORD_Z = 65.
// Level data should be edited below in function setup, not here
// {
private dd_color LightningColor = Null
private integer array NumberOfSwords
private real array SwordDamage
private real array SwordDamageExtra
private real array RootDuration
// }
endglobals
// --------------------------------------------------------------
private function Setup takes nothing returns nothing
// Max Spell Level
// Default: 3
//! set MaxLevel = 3
// Main swords damage on hit (percentage of targets max_life)
// Default: 20% / 25% / 30%
set SwordDamage[1] = 20.
set SwordDamage[2] = 25.
set SwordDamage[3] = 30.
// Extra swords damage
// Default: 50 / 60 / 65
set SwordDamageExtra[1] = 50.
set SwordDamageExtra[2] = 60.
set SwordDamageExtra[3] = 65.
// Duration of blood root
// Default: 2. / 2.75 / 4.
set RootDuration[1] = 2.00
set RootDuration[2] = 2.75
set RootDuration[3] = 4.00
// Number of smaller swords created per level
// Number of swords must be less or equal to 16
// Default: 3 / 3 / 4
set NumberOfSwords[1] = 3
set NumberOfSwords[2] = 3
set NumberOfSwords[3] = 4
// This is the color of the lightning.
// Default: Red 255, Green 255, Blue 255, Alpha 192
set LightningColor = CreateColor(255, 255, 255, 192)
endfunction
// =======================================================================
// DO NOT EDIT BELOW IF YOU DONT KNOW JASS
// =======================================================================
// *** Custom spells globals ***
globals
private integer array NRoots[8191]
endglobals
// ===================================================================
// *** Custom Spell Types / Structs ***
// ===================================================================
// ----------------------------------------------------------------
// *** Type: Sword ***
// - Description:
//
// *** Its an main sword traveling from start to end ***
//
// - Members:
// u -> Main sword unit
// v -> Units current position
// tr -> Target to which sword is traveling
// exec -> Current timed execution
// lig -> Travel path lightning
// pow -> Power of sword (ability level)
// ----------------------------------------------------------------
private struct sword
// *** Members ***
private unit u
private dd_vector v
private unit tr
private integer exec
private lightningex lig
private integer pow
// *** Static vars ***
private static constant real START_OFFSET = 115.
private static constant real FADE_TIME = 1.5
private static constant real MOTION_FADE_TIME = 1.25
private static constant real FADE_VELOCITY = 150.
// *** Constructor ***
//! runtextmacro constr("create", "unit caster")
// *** Assign members ***
set this.tr = GetSpellTargetUnit()
set this.v = CreateVectorDD(GetUnitX(caster), GetUnitY(caster), SWORD_Z, E_AngWidget(caster, this.tr)*DEGTORAD, 0.)
set this.u = CreateUnit(GetOwningPlayer(caster), SWORD_RAWCODE, 0., 0., this.v.alpha*RADTODEG)
set this.lig = CreateLightningAngle(LIGHTNING_TYPE, this.v.x, this.v.y, this.v.z, 0., 0., 0.)
set this.pow = GetUnitAbilityLevel(caster, BMAGIC_RAWCODE)
set this.exec = 0
// *** Offset move vector ***
call this.v.OffsetMove(sword.START_OFFSET)
// *** Lightning paint ***
call ChangeLightningColor(this.lig, LightningColor.r, LightningColor.g, LightningColor.b, LightningColor.a)
// *** Move Sword ***
call MakeUnitUnselectable(this.u)
call MakeUnitFlyable(this.u)
call SetUnitVPos(this.u, this.v)
//! runtextmacro endconstr()
// *** Destructor ***
//! runtextmacro destr()
// *** Sword fade and push timed ***
call E_FadeUnit(this.u, sword.FADE_TIME, 0., 100.)
call PushUnit(this.u, sword.FADE_VELOCITY, 0., sword.FADE_VELOCITY, sword.FADE_VELOCITY*sword.FADE_TIME, this.v.alpha, 0., LineData())
call RemoveUnitTimed(this.u, sword.FADE_TIME)
// *** Clear leaks ***
call FadeLightning(this.lig, LightningColor.a, 0, sword.FADE_TIME)
call DestroyLightningTimedEx(this.lig, sword.FADE_TIME+0.1)
call this.v.delete()
set this.u = null
set this.tr = null
//! runtextmacro enddestr()
// ---------------------------------------------------------------------
// *** Sword Methods ***
// ---------------------------------------------------------------------
// *** Moves sword offset and returns true if it reached target ***
public method OffsetMove takes real offset returns boolean
// *** Do main movement ***
call this.v.Direction(E_AngWidget(this.u, this.tr)*DEGTORAD, 0.)
call this.v.OffsetMove(offset)
call SetUnitVPos(this.u, this.v)
// *** Lightning move ***
call SetLightningPartPos(this.lig, this.v.x, this.v.y, this.v.z, 2)
// *** Every n execs load sword's illusion ***
if (QMod(this.exec, BLADE_MOTION_FACTOR) == 0) then
set bj_lastCreatedUnit = CreateUnit(DD_p[15], SWORD_RAWCODE, 0., 0., this.v.alpha*RADTODEG)
call MakeUnitFlyable(bj_lastCreatedUnit)
call MakeUnitUnselectable(bj_lastCreatedUnit)
call SetUnitVPos(bj_lastCreatedUnit, this.v)
call E_FadeUnit(bj_lastCreatedUnit, sword.MOTION_FADE_TIME, 35., 100.)
call RemoveUnitTimed(bj_lastCreatedUnit, sword.MOTION_FADE_TIME+0.1)
endif
// *** Next exec ***
set this.exec = this.exec + 1
// *** Is done? ***
return hypot(GetUnitX(this.tr)-this.v.x, GetUnitY(this.tr)-this.v.y) <= 2500.
endmethod
// ---------------------------------
// *** Operators ***
// ---------------------------------
// *** Returns owner of sword / casting unit
public method operator owner takes nothing returns player
return GetOwningPlayer(this.u)
endmethod
// *** Returns strength of sword ***
public method operator power takes nothing returns integer
return this.pow
endmethod
// *** Returns target unit ***
public method operator target takes nothing returns unit
return this.tr
endmethod
endstruct
// -------------------------------------------------------------------------
// *** Type: Extra Swords Data
//
// - eswords contains data which is requied for extra swords actions
// -------------------------------------------------------------------------
private struct eswords
// *** Members ***
public graphic array grp[16]
public player pl
public unit target
public integer lvl
public integer n
//! runtextmacro destr()
local real apptime = EXTRA_SWORDS_APPEAR_TIME*0.66667
local real time = ((EXTRA_SWORDS_OFFSET - (EXTRA_SWORDS_OFFSET/Pow(apptime*SQRT_2, 2.)))*(apptime/EXTRA_SWORDS_OFFSET)) + (1./apptime)
local integer alpha = GetGraphicAlpha(this.grp[0])
set this.target = null
debug call RMsg(time)
// *** Graphic free ***
loop
set this.n = this.n - 1
if (alpha >= 0xFA) then
call PushGraphic(this.grp[this.n], 0., EXTRA_SWORDS_OFFSET, EXTRA_SWORDS_OFFSET/apptime, EXTRA_SWORDS_OFFSET, this.grp[this.n].GetFacing()*DEGTORAD, EXTRA_SWORDS_PITCH*DEGTORAD, LineData())
endif
call FadeGraphic(this.grp[this.n], alpha, 0, time)
set GRAPHIC_DURATION = 0.1
call DestroyGraphicTimed(this.grp[this.n], time+0.1)
set this.grp[this.n] = Null
exitwhen (this.n == 0)
endloop
//! runtextmacro enddestr()
endstruct
// ------------------------------------------
// *** Other spell neccessary functions ***
// ------------------------------------------
// ------------------------------------------------------------
// *** Plays sword start sound if possible ***
private function TryPlaySwordStartSound takes nothing returns nothing
local unit u = GetTriggerUnit()
if (E_DistWidget(u, GetSpellTargetUnit()) > 300.) then
call GenericSoundDD(SOUND_ON_START, 100., 0., 0., 1.)
call SetSoundVolumeAs3D(bj_lastPlayedSound, GetUnitX(u), GetUnitY(u), 100., 3500.)
endif
set u = null
endfunction
// ------------------------------------------------------------
// *** Plays given sword sound at given position ***
private function PlaySwordSound takes integer sndType, real x, real y returns nothing
if (sndType == 'stab') then
call GenericSoundDD(SOUND_ON_STAB, 100., 0., 0., 1.)
elseif (sndType == 'disp') then
call GenericSoundDD(SOUND_ON_DISAPPEAR, 100., 0., 0., 1.)
endif
call SetSoundVolumeAs3D(bj_lastPlayedSound, x, y, 100., 3500.)
endfunction
// ------------------------------------------------------------
// *** Causes extra swords to deal damage ***
private function ExtraSwordsDamage takes nothing returns nothing
// *** Locals list ***
local eswords es = GetSleepData()
// *** Deal damage ***
call UnitDamageTarget(DDCreateDummy(es.pl, 0.1), es.target, es.n*SwordDamageExtra[es.lvl], true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_HEAVY_SLICE)
// *** Play swords stab sound ***
call PlaySwordSound('stab', GetUnitX(es.target), GetUnitY(es.target))
// *** Load blood effects ***
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT, es.target, ATTACH_POINT))
// *** Unpause target ***
call PauseUnit(es.target, false)
endfunction
// ------------------------------------------------------------
// *** Loads extra swords on hit ***
private function LoadSwords takes player pl, location pos, integer lvl, unit target returns eswords
// *** Locals ***
local real s_rad = GetRandomReal(0., TWO_PI)
local real cz = Cos(EXTRA_SWORDS_PITCH*DEGTORAD)
local real sz = SquareRoot(1.-(cz*cz))
local real rad
local real apptime = EXTRA_SWORDS_APPEAR_TIME*0.66667
local eswords es = eswords.create()
// *** Add swords ***
//! runtextmacro FOR("es.n", "0", "NumberOfSwords[lvl]")
set rad = s_rad + (es.n * TWO_PI / NumberOfSwords[lvl])
set es.grp[es.n] = AddGraphicPitch(SWORD_MODEL_FILE, GetLocationX(pos) + EXTRA_SWORDS_OFFSET * Cos(rad)*cz, GetLocationY(pos) + EXTRA_SWORDS_OFFSET * Sin(rad)*cz, STAB_Z_OFFSET + EXTRA_SWORDS_OFFSET * sz, rad*RADTODEG, 1., Real(-EXTRA_SWORDS_PITCH))
call PushGraphic(es.grp[es.n], EXTRA_SWORDS_OFFSET/EXTRA_SWORDS_APPEAR_TIME, 0., EXTRA_SWORDS_OFFSET/EXTRA_SWORDS_APPEAR_TIME, EXTRA_SWORDS_OFFSET, rad-PI, -EXTRA_SWORDS_PITCH*DEGTORAD, LineData())
call FadeGraphic(es.grp[es.n], 64, 255, apptime)
//! runtextmacro ENDFOR()
// Set eswords members
set es.target = target
set es.lvl = lvl
set es.pl = pl
// *** Pause target now ***
call PauseUnit(target, true)
// *** Deal extra swords damage ***
call SleepEx(apptime, function ExtraSwordsDamage, integer(es))
// *** End func ***
return (es)
endfunction
// ------------------------------------------------------------
// *** Summon blood roots on target ***
private function UnsummonRoots takes nothing returns nothing
// *** Locals ***
local eswords es = GetSleepData()
local integer id = HtoI(es.target)
// *** Remove one root ***
set NRoots[id] = NRoots[id] - 1
// *** If unit is alive ***
if (not IsUnitDead(es.target)) then
// *** No roots? ***
if (NRoots[id] == 0) then
call UnitRemoveAbility(es.target, BROOTS_BUFF_RAWCODE)
endif
// *** Blood effect ending ***
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT, es.target, ATTACH_POINT))
endif
// *** Disappear sword sound ***
call PlaySwordSound('disp', GetUnitX(es.target), GetUnitY(es.target))
// *** Clear memory ***
call es.delete()
endfunction
private function SummonRoots takes eswords es returns nothing
// *** Locals ***
local integer id = HtoI(es.target)
// *** Dummy load ***
call UnitDamageTarget(DDCreateDummy(es.pl, 0.5), es.target, GetUnitState(es.target, UNIT_STATE_MAX_LIFE)*SwordDamage[es.lvl]*0.01, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_METAL_HEAVY_SLICE)
call PlaySwordSound('stab', GetUnitX(es.target), GetUnitY(es.target))
if (IsUnitDead(es.target)) then
call es.delete()
return
endif
call UnitAddAbility(bj_lastCreatedUnit, BROOTS_RAWCODE)
call IssueTargetOrder(bj_lastCreatedUnit, DUMMY_ORDER, es.target)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT, es.target, ATTACH_POINT))
// *** Store Target ***
set NRoots[id] = NRoots[id] + 1
// *** Do free unit ***
call SleepEx(RootDuration[es.lvl], function UnsummonRoots, integer(es))
endfunction
// ------------------------------------------------------------
// *** Main periodic movement of sword ***
private function MovementPeriodic takes nothing returns nothing
// *** Locals ***
local timer t = GetExpiredTimer()
local sword sw = DDGetValue(t)
local eswords es = Null
local location loc
// *** Check are we done movement ***
if (sw.OffsetMove(SWORD_SPEED*INTERVAL)) then
// *** Free timer ***
call PauseTimer(t)
call DestroyTimer(t)
// *** Load swords and get eswords ***
set loc = GetUnitLoc(sw.target)
set es = LoadSwords(sw.owner, loc, sw.power, sw.target)
// *** Summon roots and deal damage now ***
call SummonRoots(es)
// *** Disappear sound play ***
call PlaySwordSound('disp', GetUnitX(es.target), GetUnitY(es.target))
// *** Clear leaks ***
call RemoveLocation(loc)
call sw.delete()
set loc = null
endif
// *** Clear leaks ***
set t = null
endfunction
// ------------------------------------------------------------
// *** Main Trigger Condition ***
private constant function Conditions takes nothing returns boolean
return GetSpellAbilityId() == BMAGIC_RAWCODE
endfunction
// ------------------------------------------------------------
// *** Main Trigger Actions ***
private function Actions takes nothing returns nothing
// *** Locals ***
local timer t = CreateTimer()
local sword sw = sword.create(GetTriggerUnit())
// *** Play start sound ***
call TryPlaySwordStartSound()
// *** Start movement ***
call DDStoreValue(t, integer(sw))
call TimerStart(t, INTERVAL, true, function MovementPeriodic)
// *** Clear leaks ***
set t = null
endfunction
// =============================================================
// *** Init function ***
private function Init takes nothing returns nothing
// *** Events / Conditions / Actions ***
call onSpellEffectRegister(function Conditions, function Actions)
// *** Define user setup here ***
call Setup()
// *** Preloads ***
call Preload(SWORD_MODEL_FILE)
call Preload(BLOOD_EFFECT)
call Preload(SOUND_ON_START)
call Preload(SOUND_ON_STAB)
call Preload(SOUND_ON_DISAPPEAR)
call Preload("Textures\\DemonRune2.blp")
call Preload("Textures\\DemonRune3.blp")
call Preload("UI\\Glues\\SinglePlayer\\Undead3D_Exp\\FrostMorne.blp")
endfunction
endlibrary
<b>Alice</b>, из за тебя пропадает смысл в паролях, а так же постоянно будет требоваться пинать админа...(Enforcer)