Name | Type | is_array | initial_value |
TempLoc | location | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
-=Ex Hydratia=-
by (c)Paladon
The spell "Ex Hydratia" is coded in vJass.
It needs the JassNewGenPack in order to be modified/used properly.
You can get the JNGP here: "http://www.wc3c.net/showthread.php?t=90999"
Of course, this spell is MUI and such stuff.
'Description:'
Dehydrates a target. For each interval of the dehydration,
the target takes 30 damage. The hero uses the gained
water to form a shield, increasing the armour by 1 for
each interval absorbed. As soon as the hero absorbed
6 intervals, he completely absorbs the shield of water
and regenerates 15 hitpoints and mana per absorbed
interval actively used to form the shield.
Level 1 - Dehydrates the target for 3 intervals.
Level 2 - Dehydrates the target for 4 intervals.
Level 3 - Dehydrates the target for 5 intervals.
'Import'
To import this spell into your very own map, you need to work with the JNGP named above.
For this spell, you need the "Ey Hydratia" trigger (below the Readme)
as well as the DUMMY.mdx out of the Import Editor, the WaterEssence.mdx and the Dummy unit out of the Object Editor.
Furthermore, you need the spells "Ex Hydratia [Spell]" and "Ex Hydratia [Armour]" which are located in the Object Editor as well.
Import and copy all these things into your map and adjust the settings in the header of the
"Ex Hydratia" trigger to your own needs.
'Imported Resources'
DUMMY.mdx
WaterEssence.mdx
~a modified "WaterElementalMissile" (without the long light blue beam)
'Other stuff'
The usual ownership conditions apply.
~Paladon
*****Changelog*****
- various improvements concerning code and visuals
//TESH.scrollpos=0
//TESH.alwaysfold=0
//!*********************************EX HYDRATIA [Paladon]******************************!\\
//**************************************************************************************\\
scope ExHydratia initializer SetEvent
native UnitAlive takes unit id returns boolean
globals
//!**********************************THE SETTINGS*****************************!\\
//*****************************************************************************\\
// General Settings
private constant integer SPELL_ID = 'A000' // Spell's rawcode
private constant integer EFFECT_ID = 'A001' // Armour effect's rawcode
private constant integer DUMMY_ID = 'n000' // Dummy's rawcode
private constant real TIMER = 0.01 // Interval of the timer
private constant real INTERVAL_TIMER = 0.5 // Time between the intervals of dehydration
private constant integer INIT_DEHYDRATION_COUNT = 3 // Intervals (Level 1)
private constant integer INCR_DEHYDRATION_COUNT = 1 // Intervals added per each level (Level 2 and higher)
private constant string SFX_WATER_MISSILE = "war3mapImported\\WaterEssence.mdl" // Model of the missiles
private constant string SFX_DEHYDRATION_EFFECT = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl" // Model of the "death" animation displayed upon creation of the missiles
private constant string SFX_HEAL_EFFECT = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl" // Model of the "death" animation displayed upon impact on enemied units
private constant string DUMMY_ATTACH = "chest" // Attachment point of the effects on the "Dummy" model (Missile)
private constant string ENEMY_ATTACH = "origin" // Attachment point of the effects on the enemy (Dehydration)
private constant string HEAL_ATTACH = "origin" // Attachment point of the effects on your hero (Heal)
// Orbital Settings
private constant real ORBITAL_SPEED_MIN = 5.55 // Defines the minimal orbital speed
private constant real ORBITAL_SPEED_MAX = 7.55 // Defines the maximal orbital speed
private constant real ORBITAL_ANGLE_SPIN_MAX = -0.65 // Defines the minimal speed of the spin of the orbital movement
private constant real ORBITAL_ANGLE_SPIN_MIN = 0.65 // Defines the maximal speed of the spin of the orbital movement
private constant real ORBITAL_SIZE_MIN = 110. // Defines the minimal size of the orbital movement of a single orb
private constant real ORBITAL_SIZE_MAX = 150. // Defines the maximal size of the orbital movement of a single orb
private constant real ORBITAL_HEIGHT_MIN = 0. // Defines partially the height of the orbital (minimal).
private constant real ORBITAL_HEIGHT_MAX = 60. // Defines partially the height of the orbital (maximal).
//! I recommend playing around with these values for ground units to find something fitting. For air units, i recommend for the height simply "0".
// Damage / Heal Settings
private constant real INIT_DAMAGE_DEHYDRATION = 30. // Defines the damage dealt per dehydration interval (lvl 1)
private constant real INCR_DAMAGE_DEHYDRATION = 0. // Defines the damage added per level (lvl 2 and up) for each dehydration interval
private constant real INIT_HEAL_HITPOINTS = 15. // Defines the amount of hitpoints healed per hydration counter (see below) by reaching the limit (lvl 1)
private constant real INCR_HEAL_HITPOINTS = 0. // Defines the amount of hitpoints healed added for level 2 and higher
private constant real INIT_HEAL_MANA = 15. // Defines the amount of mana healed per hydration counter (see below) by reaching the limit (lvl 1)
private constant real INCR_HEAL_MANA = 0. // Defines the amount of mana healed added for level 2 and higher
// Misc Settings
private constant integer TRIGGER_HYDRATION_COUNTER = 6 // Defines the "amount" of water needed to trigger the hydration
private constant real MISSILE_SPEED = 5.5 // The speed of a released missile outside the orbital
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL // The attacktype of the damage dealt
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL // The damagetype of the damage dealt
private constant weapontype WEAPON_TYPE = null // The weapontype of the damage dealt
//!*******************************END OF THE SETTINGS*************************!\\
//**Do not modify anything below this line unless you know what you are doing**\\
//!***************************************************************************!\\
private real array R
endglobals
private struct S
private unit hero
private unit missile
private unit target
private integer state
private integer level
private real d1 // Distance reference
private real angle // Not always used as angle but in cases of reference as the corresponding rad/deg
private real t1 // The first time counter
private real t2 // The second time counter
private real x // coordinate for the orbital
private real y // coordinate for the orbital
private real z // coordinate for the orbital
private real OSp // Orbital Speed
private real OAS // Orbital Angle Spin
private real OSi // Orbital Size
private real OHe // Orbital Height
private real OEx // Orbital Value Reference (also used for directional purposes)
private effect sfx
private static S array indx
private static integer counter = 0
private static timer time = CreateTimer()
static method Execution takes nothing returns nothing
local S d
local integer i = 0
local integer l = 0
local integer a = 0
local integer b = 0
local unit u
loop
exitwhen i >= S.counter
set d = S.indx[i]
if d.state == 0 then
// Remove & Recycle
call DestroyEffect(d.sfx)
call RemoveUnit(d.missile)
set d.hero = null
set d.missile = null
set d.target = null
set d.sfx = null
call d.destroy()
set S.counter = S.counter - 1
set S.indx[i] = d.indx[S.counter]
set i = i - 1
elseif d.state == 2 or d.state == 4 then
// Launch and move the missile
// X/Y Movement
if d.state == 4 then
set R[0] = GetUnitX(d.target)
set R[1] = GetUnitY(d.target)
else
set R[0] = d.x
set R[1] = d.y
endif
set R[2] = GetUnitX(d.missile)
set R[3] = GetUnitY(d.missile)
set R[4] = Atan2(R[1]-R[3],R[0]-R[2])
call SetUnitX(d.missile,R[2] + MISSILE_SPEED * Cos(R[4]))
call SetUnitY(d.missile,R[3] + MISSILE_SPEED * Sin(R[4]))
call SetUnitFacing(d.missile,R[4]*bj_RADTODEG)
// Z Movement
set R[0] = R[2] - R[0]
set R[1] = R[3] - R[1]
set R[2] = SquareRoot(R[0]*R[0]+R[1]*R[1])
if d.state == 4 then
set R[0] = GetUnitFlyHeight(d.target)
else
set R[0] = d.z
endif
set R[1] = GetUnitFlyHeight(d.missile)
set R[0] = R[0]-R[1]
set R[0] = R[0]/(R[2]/MISSILE_SPEED)
call SetUnitFlyHeight(d.missile,R[1]+R[0],0)
if R[2] <= MISSILE_SPEED then // Missile reached target
if d.state == 2 then
set d.state = 3
set l = GetUnitAbilityLevel(d.hero,EFFECT_ID)
if l == 0 then
call UnitAddAbility(d.hero,EFFECT_ID)
elseif l+1 >= TRIGGER_HYDRATION_COUNTER then // Trigger Heal
call UnitRemoveAbility(d.hero,EFFECT_ID)
call DestroyEffect(AddSpecialEffectTarget(SFX_HEAL_EFFECT,d.hero,HEAL_ATTACH))
set u = d.hero
set a = d
set b = 0
loop
exitwhen b >= S.counter
set d = S.indx[b]
if d.hero == u and d.state == 3 then
set d.state = 4
set d.target = u
endif
set b = b + 1
endloop
set d = a
else // Simple increase
call SetUnitAbilityLevel(d.hero,EFFECT_ID,l+1)
endif
else // Heal effect, state = 4
call SetWidgetLife(d.hero,INIT_HEAL_HITPOINTS + (INCR_HEAL_HITPOINTS * d.level) + GetWidgetLife(d.hero))
call SetUnitState(d.hero, UNIT_STATE_MANA,INIT_HEAL_MANA + (INCR_HEAL_MANA * d.level) + GetUnitState(d.hero,UNIT_STATE_MANA))
set d.state = 0
endif
elseif not UnitAlive(d.hero) then
set d.state = 0
endif
elseif d.state == 1 then // Creates a missile and triggers dehydration on the enemy
set d.t1 = d.t1 + TIMER
if not UnitAlive(d.target) or not UnitAlive(d.hero) then
set d.state = 0
elseif d.t1 >= d.t2 then
set d.t1 = 0
// init single dehydration
set R[0] = GetUnitX(d.target)
set R[1] = GetUnitY(d.target)
set d.missile = CreateUnit(GetOwningPlayer(d.hero),DUMMY_ID,R[0],R[1],0)
call UnitAddAbility(d.missile,'Arav')
call UnitRemoveAbility(d.missile,'Arav')
// The following 4 lines are necessary since an initial setting cannot work
call SetUnitPathing(d.missile,false)
call SetUnitX(d.missile,R[0])
call SetUnitY(d.missile,R[1])
call SetUnitFlyHeight(d.missile,GetUnitFlyHeight(d.target),0)
call DestroyEffect(AddSpecialEffectTarget(SFX_DEHYDRATION_EFFECT,d.target,ENEMY_ATTACH))
call UnitDamageTarget(d.hero,d.target,INIT_DAMAGE_DEHYDRATION + (INCR_DAMAGE_DEHYDRATION * d.level), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
// Prepares the data for the movement and orbital shape
set d.sfx = AddSpecialEffectTarget(SFX_WATER_MISSILE,d.missile,DUMMY_ATTACH)
set d.OAS = GetRandomReal(ORBITAL_ANGLE_SPIN_MIN,ORBITAL_ANGLE_SPIN_MAX)*bj_DEGTORAD
set d.state = 2
endif
endif
if d.state == 1 or d.state == 2 or d.state == 3 then
set d.angle = d.angle + d.OAS
set d.d1 = d.d1 + d.OSp
set R[0] = (d.d1/d.OEx)*bj_DEGTORAD
set R[1] = d.OSi*Sin(R[0])
set R[2] = d.angle*bj_DEGTORAD
set d.x = GetUnitX(d.hero)+R[1]*Cos(R[2])
set d.y = GetUnitY(d.hero)+R[1]*Sin(R[2])
set d.z = (d.OSi-d.OHe)*Cos(R[0])+d.OHe+GetUnitFlyHeight(d.hero)
if d.state == 3 then
call SetUnitX(d.missile,d.x)
call SetUnitY(d.missile,d.y)
call SetUnitFlyHeight(d.missile,d.z,0)
call SetUnitFacing(d.missile,d.angle)
endif
// Since the orbs move with a circular movement, we can reset the angle.
if d.angle >= 360. then
set d.angle = d.angle - 360.
endif
if not UnitAlive(d.hero) then
set d.state = 0
endif
endif
set i = i + 1
endloop
set u = null
set i = 0
if S.counter == 0 then
call PauseTimer(S.time)
endif
endmethod
static method SetStruct takes unit hero, unit target, real amount, real specific, real time, integer level returns nothing
// This method mainly inits the orbital movement data and determines the movement shape
local S d = S.allocate()
set d.hero = hero
set d.target = target
set d.level = level
set d.state = 1
set d.d1 = 0
set d.angle = (360/amount) * specific
set d.t1 = 0
set d.t2 = time
set d.OSp = GetRandomReal(ORBITAL_SPEED_MIN,ORBITAL_SPEED_MAX)
set d.OSi = GetRandomReal(ORBITAL_SIZE_MIN,ORBITAL_SIZE_MAX)
set d.OAS = 5. // constant to create the "waterwave" effect when the missile is moving
set d.OHe = GetRandomReal(ORBITAL_HEIGHT_MIN,ORBITAL_HEIGHT_MAX)
set d.OEx = d.OSi/90
if S.counter == 0 then
call TimerStart(S.time,TIMER,true,function S.Execution)
endif
set S.indx[S.counter] = d
set S.counter = S.counter + 1
endmethod
static method Dehydrate takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer l = GetUnitAbilityLevel(u,SPELL_ID)-1
set R[0] = 0
set R[1] = INIT_DEHYDRATION_COUNT + (INCR_DEHYDRATION_COUNT * l)
loop
exitwhen R[0] == R[1]
call S.SetStruct(u,GetSpellTargetUnit(),R[1],R[0],INTERVAL_TIMER*R[0],l)
set R[0] = R[0] + 1
endloop
set u = null
endmethod
endstruct
private function Trigger takes nothing returns boolean
if GetSpellAbilityId() == SPELL_ID then
call S.Dehydrate()
endif
return true
endfunction
private function SetEvent takes nothing returns nothing
local trigger t = CreateTrigger()
// Preloading the armour effect
local unit u = CreateUnit(Player(15),DUMMY_ID,0,0,0)
call UnitAddAbility(u,EFFECT_ID)
call UnitRemoveAbility(u,EFFECT_ID)
call RemoveUnit(u)
// Trigger settings
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Trigger))
// Preloading effects
call Preload(SFX_WATER_MISSILE)
call Preload(SFX_DEHYDRATION_EFFECT)
call Preload(SFX_HEAL_EFFECT)
call PreloadStart()
set u = null
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//*****************************************************
//! The following triggers are test related stuff only!
//*****************************************************