roXplosive
New Member
- Reaction score
- 15
I will start off by posting the extended tooltip of my hero :
The sole surviver from her batalion at the battle for the World Tree she recovered with the help of Furion and is now ready to assist the Sentinel against the defiling Scourge . She is adept of transmiting her pain to the enemies , attacking from afar and avenging her fallen comrades .
-----------------------HERE IS THE MAP --------------------------
Latest version here :
View attachment 32539
Changes :
- added special effects
- swapped to vJass
- limited number of Spellbinding arrow areas
- added a variable for blood hatred life regeneration
- removed a bug in programming
- added a GUI trigger (to have one of those too if you were wondering )
All right now I will gie some skill descriptions and what they should do . I think my tooltips are relevant enough but in any case :
1. Avenging Wrath (is highly customizable) - based off Channel .Sends out a number of spirits x spellLVL (chosen 8) on a N spikes star (chosen 7) that require 3 HP to summon each and each heals 6HP when it hits an enemy . Maximum heal is twice the life cost for casting the spell .
Initializer for variables used for faster computation
2. Spell Binding Arrow - based off Critical Strike Passive skill gives a chance on hitting to make a casred area in which Avenging Spirits spawn and patrol . All the statistics are based on her stats and the chance is based on skill level .
I wanted to make a trigger when a unit takes damage and how to attach the events to the actual trigger and +rep (when i learn how to do it ) goes to Deebee because I got insipred by this thread .
Here I have added the damage / healing part of my Blood Hatred skill because it makes it lighter on the code and uses almost al the conditions as Arrow Strike . I have discovered the crash bug that occured when I was trying to damage stuff with my hero so I disabled the Damage detection trigger before damaging . Changed yet again so if that my hero dies it won't damage ally and foe alike because the source of damage becomes null and null has no allies .
I have decided to add -as command to display the number of spirits summoned by ArrowStrike and their damage :
3. Blood Hatred - based off Evasion . You deal aditional damage of 1% * SpellLvl of your lost life as bonus damage and heal 1/2 of this bonus damage dealt and also if an enemy hero kills a nonhero,nonmechanical,nonbuilding unit you gain 0.01*SpellLvL Strength
Now If a player learns BloodHatred skill his hero will be memorized into an array and in similar arrays will be stored the Str bonuses to be gained and already gained due to this ability .
Upon further thinking I decided to make my hero playable by all the players but in 1 instance for every one of them . Here are the triggers for monitoring applying STR and displaying it with player command -bh
4. Pain of the Ancients - based off channel . It is mainly done but there are still issues
What it does :
- changes the hero into another one
- he keeps the BH strength bonus and BH still works normally thereafter
- he doesn't kill himself with SpellBindingArrow any more when changing forms
- He gains the multishot as he should
- he gsins the bonus damage and bonus damage for allied building lost normally
- he gains the armor and spell immunity
- autoactivates when HP < 30% ; now it autoactivates the second time and third time and so on too
- fixed so it has 45 seconds cooldown ; removed cooldown from the object editor spell
- can be activated
- uses up mana
- shows cripple but also plays the stupid cripple sound
- plays funny music but not as loud as I would like
What it doesn't do :
- doesn't display magic immunity buff (based off spell immunity unit ability)
- fills the hero skills tab with useless icons (and i would rather it doesn't do it)
- doesn't display cooldown in normal fashion ; I made some text messages to notify you but hope to improve it
Miscelaneous BUG (the passive abilities don't activate if I don't make this triggers executed at map init , and this last trigger does just that ) for which I found only this solution :
Now it is readable thanks' to SharkBait's efforts .
The sole surviver from her batalion at the battle for the World Tree she recovered with the help of Furion and is now ready to assist the Sentinel against the defiling Scourge . She is adept of transmiting her pain to the enemies , attacking from afar and avenging her fallen comrades .
-----------------------HERE IS THE MAP --------------------------
Latest version here :
View attachment 32539
Changes :
- added special effects
- swapped to vJass
- limited number of Spellbinding arrow areas
- added a variable for blood hatred life regeneration
- removed a bug in programming
- added a GUI trigger (to have one of those too if you were wondering )
All right now I will gie some skill descriptions and what they should do . I think my tooltips are relevant enough but in any case :
1. Avenging Wrath (is highly customizable) - based off Channel .Sends out a number of spirits x spellLVL (chosen 8) on a N spikes star (chosen 7) that require 3 HP to summon each and each heals 6HP when it hits an enemy . Maximum heal is twice the life cost for casting the spell .
Initializer for variables used for faster computation
JASS:
globals
trigger gg_trg_Startup
real Arc1Angle
real Arc2Angle
real Arc3Angle
real ArcRadius
real array Arcs1Start[100]
real array Arcs2Start[100]
real array Arcs3Start[100]
real array InnerCircleCentersX[100]
real array InnerCircleCentersY[100]
real array OuterCircleCentersX[100]
real array OuterCircleCentersY[100]
real ArcVariationOnTimer
real AvengingWrathAoE=600.00
integer AvengingWrathDuration=5
integer HealingFactor=2 //how much can AvengingWrath heal compared to it's life cost
integer Spirits = 8 //number of summoned spirits increases with skillevel
integer StarEdges = 7 //number of directions in which spirits will travel
real SummoningDamage = 3 //life cost for summoning an avenging spirit
integer Temporizator = 10 //determines how often do spirits move every second
string WispAnimation = "Abilities\\Spells\\Human\\Invisibility\\InvisibilityTarget.mdl"
//what special effect plays when spirits hit an enemy
//alternative effect "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl"
endglobals
scope Startup initializer InitTrig_Startup
function Trig_Startup_Actions takes nothing returns nothing
//local ariable for how much the arcs should be rotated;startup angle so that my image has an edge facing upwards
local real StarAngle
local real StartAngle
local integer A
//The dummy units will be displayed on the points delimited by global and local variables but will be relatie to current caster position
//call BJDebugMsg("Startup Initialising globalvars ")
set StarAngle=2*bj_PI/I2R(StarEdges)
//call BJDebugMsg("StarAngle="+R2S(StarAngle)+"rad")
set StartAngle=3*bj_PI/2.00
//call BJDebugMsg("StartAngle="+R2S(StartAngle)+"rad")
set ArcRadius=AvengingWrathAoE/SquareRoot(2*(1+Cos(StarAngle)))
//call BJDebugMsg("Trajectory radius="+R2S(ArcRadius)+"distance")
//Arc1Angle is the center angle of the first arc 2*STarAngle+2*(PI-StarAngle)/2
// Since Arc2Angle is the center angle it is twice the angle doing the same arc but with the edge on the circle
set Arc2Angle=Acos(1-2*Sin(StarAngle)*Sin(StarAngle))
set Arc1Angle=bj_PI+Arc2Angle/2
set Arc3Angle=Arc1Angle
set A=1
loop
//the points determining the centers of triangles inscribed in the AoE with 2 points on the edge and 1 in the center
//Using the definition of Cos in 1 triangle we can determine the length of the median line starting from the center point
// it is R*cos(alpha/2) where aplha is the angle of the triangle for the point which is the AoE center
// and the denter of the circumcised circle is a 2/3 median distance from a triangle's edges
set InnerCircleCentersX[A]=ArcRadius*Cos(StartAngle+StarAngle*A-StarAngle/2)
set InnerCircleCentersY[A]=ArcRadius*Sin(StartAngle+StarAngle*A-StarAngle/2)
//call BJDebugMsg("Center of Inner Circle "+I2S(A)+" X= "+R2S(InnerCircleCentersX[A])+" Y= "+R2S(InnerCircleCentersY[A]))
//The center points of the simmetrical triangles is well the double of the previous alues
set OuterCircleCentersX[A]=(2*AvengingWrathAoE*Cos(StarAngle/2)-ArcRadius)*Cos(StartAngle+StarAngle*A-StarAngle/2)
set OuterCircleCentersY[A]=(2*AvengingWrathAoE*Cos(StarAngle/2)-ArcRadius)*Sin(StartAngle+StarAngle*A-StarAngle/2)
//The acrs for the first drawing are the reverse of the arc between center and inner circles
set Arcs1Start[A]=StartAngle+StarAngle*A-StarAngle/2-bj_PI
//call BJDebugMsg("Starting angle for the first arc of position "+I2S(A)+" is "+R2S(Arcs1Start[A]*180/bj_PI))
//the arcs for the second drawing are similar but there is an extra -1/2 StarAngle
set Arcs2Start[A]=StartAngle+StarAngle*A-StarAngle/2-bj_PI+Arc2Angle/2
//the arcs for the third line start from the end position of the first drawn arc==StarAngle+PI
set Arcs3Start[A]=StartAngle+StarAngle*A-StarAngle/2+Arc2Angle/2
set A=A+1
exitwhen A>StarEdges
endloop
//I'm too lazy to use IF and I think this will make it easy on the code since if will be applied 1 time only
set InnerCircleCentersX[A]=InnerCircleCentersX[1]
set InnerCircleCentersY[A]=InnerCircleCentersY[1]
set OuterCircleCentersX[A]=OuterCircleCentersX[1]
set OuterCircleCentersY[A]=OuterCircleCentersY[1]
set Arcs1Start[A]=Arcs1Start[1]
set Arcs2Start[A]=Arcs2Start[1]
set Arcs3Start[A]=Arcs3Start[1]
set ArcVariationOnTimer=(Arc1Angle+Arc2Angle+Arc3Angle)/I2R(AvengingWrathDuration*Temporizator)
//call BJDebugMsg("Startup init ends")
endfunction
//===========================================================================
function InitTrig_Startup takes nothing returns nothing
set gg_trg_Startup = CreateTrigger( )
//call BJDebugMsg("Startup called")
call TriggerAddAction( gg_trg_Startup, function Trig_Startup_Actions )
endfunction
endscope //Startup
scope AvengingWrath initializer InitTrig_Avenging_Wrath
function Trig_Avenging_Wrath_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 039;A000039;
endfunction
function AvengingWrathDamage takes unit u , unit caster , real HealedMAX returns real Remaining_heal
local group g = CreateGroup()
local location l=GetUnitLoc(u)
local unit un
local real caster_life
local real life_bonus=0
//call BJDebugMsg("AvengingWrathDamage starts")
set g = GetUnitsInRangeOfLocAll(50,l)
loop
set un=FirstOfGroup(g)
if un!=null and (not IsUnitAlly(un,GetOwningPlayer(caster))) and GetUnitState(un,UNIT_STATE_LIFE)>0 then
call UnitDamageTarget(u,un,30,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect( AddSpecialEffectTargetUnitBJ( "overhead", un , WispAnimation ))
set life_bonus=life_bonus+SummoningDamage*HealingFactor
endif
call GroupRemoveUnit(g,un)
exitwhen un==null
endloop
call RemoveLocation(l)
call RemoveUnit(un)
call DestroyGroup(g)
set l=null
set un=null
//call BJDebugMsg("AengingWrathDmg ends")
//for each enemy struck the caster gains life
set caster_life=GetUnitState(caster,UNIT_STATE_LIFE)
//call BJDebugMsg("caster_life= " + R2S(caster_life))
if life_bonus<HealedMAX then
call SetUnitLifeBJ(caster,caster_life+life_bonus)
return HealedMAX-life_bonus
else
call SetUnitLifeBJ(caster,caster_life+HealedMAX)
return 0.00
endif
return 0.00
//return how much life can still be healed
endfunction
function Trig_Avenging_Wrath_Actions takes nothing returns nothing
local unit array spirits
local integer i
local integer j
local integer k
local integer d1
local integer d2
local unit u=GetTriggerUnit()
local integer lvl=GetUnitAbilityLevel(u,039;A000039;)
local integer SS=Spirits*lvl //SS stands for summonedspirits
local integer iterations=AvengingWrathDuration*Temporizator
local real X
local real Y
local real HealedMAX
//Temporizator is how many breaks should be in this thread during 1 second
//call BJDebugMsg("AvengingWrathActions Starts")
//call BJDebugMsg("Spirits for summoning : "+I2S(SS))
//debug action:
//set k=1
//set X=GetUnitX(u)
//set Y=GetUnitY(u)
//loop
//call CreateUnit(Player(11),'e000',X+InnerCircleCentersX[k],Y+InnerCircleCentersY[k],0)
//call CreateUnit(Player(11),'e000',X+OuterCircleCentersX[k],Y+OuterCircleCentersY[k],0)
//set k=k+1
//exitwhen k>StarEdges
//endloop
set i=1
// sets the maximum healing according to the damage taken when summoning and healing factor
set HealedMAX=lvl*SummoningDamage*StarEdges*Spirits
//this loop is used to create/move dummyunits and also make them damage enemies
//dummyunits are destroyed at the end of the iterations or when the caster is dead
loop
set X=GetUnitX(u)
set Y=GetUnitY(u)
if GetWidgetLife(u)>.405 and i<=SS then
//if there are left units to be summoned
set k=0
loop
if GetWidgetLife(u)>.405 then
set spirits[i+k*SS]=CreateUnit(GetOwningPlayer(u),039;e000039;,X,Y,0)
call UnitDamageTargetBJ(u,u,SummoningDamage,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_DIVINE)
endif
set k=k+1
exitwhen k>=StarEdges
endloop
endif
//Initially I wanted to move only the last created unit but it doesn't look right so it shall have some changes
//by moving all the available units except the last created one when possible
set j=1
if GetWidgetLife(u)>.405 then
loop
exitwhen j>i or j>SS
set k=0
loop
if (i-j+1)*ArcVariationOnTimer<=Arc1Angle then
call SetUnitPosition(spirits[j+k*SS],X+InnerCircleCentersX[k+1]+ArcRadius*Cos((i-j+1)*ArcVariationOnTimer+Arcs1Start[k+1]),Y+InnerCircleCentersY[k+1]+ArcRadius*Sin((i-j+1)*ArcVariationOnTimer+Arcs1Start[k+1]))
elseif (i-j+1)*ArcVariationOnTimer<=Arc1Angle+Arc2Angle then
call SetUnitPosition(spirits[j+k*SS],X+OuterCircleCentersX[k+2]+ArcRadius*Cos(Arc1Angle-(i-j+1)*ArcVariationOnTimer+Arcs2Start[k+2]),Y+OuterCircleCentersY[k+2]+ArcRadius*Sin(Arc1Angle-(i-j+1)*ArcVariationOnTimer+Arcs2Start[k+2]))
elseif (i-j+1)*ArcVariationOnTimer<=Arc1Angle+Arc2Angle+Arc3Angle then
call SetUnitPosition(spirits[j+k*SS],X+InnerCircleCentersX[k+2]+ArcRadius*Cos(Arc1Angle+Arc2Angle-(i-j+1)*ArcVariationOnTimer+Arcs3Start[k+2]),Y+InnerCircleCentersY[k+2]+ArcRadius*Sin(Arc1Angle+Arc2Angle-(i-j+1)*ArcVariationOnTimer+Arcs3Start[k+2]))
else
//I won't remove them here but move them to the caster's position
call SetUnitPosition(spirits[j+k*SS],X,Y)
endif
set k=k+1
exitwhen k>=StarEdges
endloop
set j=j+1
endloop
endif
// Well I have to do the damaging sequence too and I guess that soon after my damagefunc will be incorporated here
set k=1
loop
set j=0
loop
set HealedMAX=AvengingWrathDamage(spirits[k+j*SS],u,HealedMAX)
set j=j+1
exitwhen j>=StarEdges
endloop
set k=k+1
exitwhen k>=i or k>SS
endloop
//wait a while before moving/damaging again
call TriggerSleepAction(1/I2R(Temporizator))
set i=i+1
exitwhen i>iterations or GetWidgetLife(u)<.405 or u==null
endloop
//to do memory unalloc
set i=1
loop
set j=0
loop
call RemoveUnit(spirits[i+j*SS])
set spirits[i+j*SS]=null
set j=j+1
exitwhen j>=StarEdges
endloop
set i=i+1
exitwhen i>SS
endloop
//call RemoveUnit(u)
set u=null
//call BJDebugMsg("AvengingWrathActions ends")
endfunction
//===========================================================================
function InitTrig_Avenging_Wrath takes nothing returns nothing
set gg_trg_Avenging_Wrath = CreateTrigger( )
call TriggerExecute(gg_trg_Startup)
call TriggerRegisterAnyUnitEventBJ( gg_trg_Avenging_Wrath, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Avenging_Wrath, Condition( function Trig_Avenging_Wrath_Conditions ) )
call TriggerAddAction( gg_trg_Avenging_Wrath, function Trig_Avenging_Wrath_Actions )
endfunction
endscope
2. Spell Binding Arrow - based off Critical Strike Passive skill gives a chance on hitting to make a casred area in which Avenging Spirits spawn and patrol . All the statistics are based on her stats and the chance is based on skill level .
I wanted to make a trigger when a unit takes damage and how to attach the events to the actual trigger and +rep (when i learn how to do it ) goes to Deebee because I got insipred by this thread .
Here I have added the damage / healing part of my Blood Hatred skill because it makes it lighter on the code and uses almost al the conditions as Arrow Strike . I have discovered the crash bug that occured when I was trying to damage stuff with my hero so I disabled the Damage detection trigger before damaging . Changed yet again so if that my hero dies it won't damage ally and foe alike because the source of damage becomes null and null has no allies .
JASS:
globals
trigger gg_trg_InitSpellBindingArrowAddEvent
trigger gg_trg_SpellBindingArrowAddEvent
trigger gg_trg_SpellBindingArrowStrikeDisplay
constant integer MaxSpiritFields=10 //set up a maximum number of spirit fields to prevent lag
integer CurrentSpiritFields = 1
integer FieldsInGame = 1
integer FieldsToKill = 0
real increment=bj_PI/100 //speed of summoned spirits in radians
real BH_regeneration = 0.5 // factor of bloodhatred damage restored as HP
endglobals
//TRIGGER FOR REGISTERING UNIT_DAMAGE FOR STARTUP UNITS
scope InitSpellBindingArrowEvent initializer InitTrig_InitSpellBindingArrowAddEvent
function Trig_InitSpellBindingArrowAddEvent_Actions takes nothing returns nothing
local group G
local unit u
set G = GetUnitsInRectAll(GetPlayableMapRect())
loop
set u=FirstOfGroup(G)
call TriggerRegisterUnitEvent( gg_trg_SpellBindingArrowStrike, u , EVENT_UNIT_DAMAGED )
call TriggerRegisterUnitEvent( gg_trg_PotADismountLifeCheck , u , EVENT_UNIT_DAMAGED )
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
call RemoveUnit(u)
set u=null
call DestroyGroup(G)
set G=null
endfunction
//===========================================================================
function InitTrig_InitSpellBindingArrowAddEvent takes nothing returns nothing
set gg_trg_InitSpellBindingArrowAddEvent = CreateTrigger( )
call TriggerAddAction( gg_trg_InitSpellBindingArrowAddEvent, function Trig_InitSpellBindingArrowAddEvent_Actions )
endfunction
endscope
//TRIGGER FOR REGISTERING EVENT_UNIT_DAMAGE FOR NEWLY CREATED UNITS
scope SpellBindingArrowEvent initializer InitTrig_SpellBindingArrowAddEvent
function Trig_SpellBindingArrowAddEvent_Actions takes nothing returns nothing
call TriggerRegisterUnitEvent( gg_trg_SpellBindingArrowStrike, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
call TriggerRegisterUnitEvent( gg_trg_PotADismountLifeCheck , GetTriggerUnit(), EVENT_UNIT_DAMAGED )
endfunction
//===========================================================================
function InitTrig_SpellBindingArrowAddEvent takes nothing returns nothing
set gg_trg_SpellBindingArrowAddEvent = CreateTrigger( )
call TriggerRegisterEnterRectSimple( gg_trg_SpellBindingArrowAddEvent, GetPlayableMapRect() )
call TriggerAddAction( gg_trg_SpellBindingArrowAddEvent, function Trig_SpellBindingArrowAddEvent_Actions )
endfunction
endscope
//TRIGGER FOR SHOWING NUMBER OF SPIRITS AND DAMAGE WITH -AS COMMAND
scope SpellBingingArrowCommand initializer InitTrig_SpellBindingArrowStrikeDisplay
function Trig_SpellBindingArrowStrikeDisplay_Actions takes nothing returns nothing
local player p=GetTriggerPlayer()
local group g=GetUnitsInRectAll(GetPlayableMapRect())
local unit u
set bj_wantDestroyGroup=true
loop
set u=FirstOfGroup(g)
if IsUnitType(u,UNIT_TYPE_HERO) and GetUnitAbilityLevel(u,039;A002039;)>0 and (GetOwningPlayer(u)==p)then
//call BJDebugMsg("Spellbinding Arrow summons "+R2S(30*GetHeroInt(u,true)/100)+" spirits that damage for "+R2S((GetHeroStr(u,true)+GetHeroAgi(u,true))/5)+" damage")
call DisplayTimedTextToPlayer(p,0,0,3,"Spellbinding Arrow summons "+R2S(30*GetHeroInt(u,true)/100)+" spirits that damage for "+R2S((GetHeroStr(u,true)+GetHeroAgi(u,true))/5)+" damage")
endif
call GroupRemoveUnit(g,u)
exitwhen u==null
endloop
call DestroyGroup(g)
call RemoveUnit(u)
set g=null
set u=null
set p=null
endfunction
//===========================================================================
function InitTrig_SpellBindingArrowStrikeDisplay takes nothing returns nothing
set gg_trg_SpellBindingArrowStrikeDisplay = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(0), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(1), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(2), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(3), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(4), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(5), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(6), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(7), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(8), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(9), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(10), "-as", true )
call TriggerRegisterPlayerChatEvent( gg_trg_SpellBindingArrowStrikeDisplay, Player(11), "-as", true )
call TriggerAddAction( gg_trg_SpellBindingArrowStrikeDisplay, function Trig_SpellBindingArrowStrikeDisplay_Actions )
endfunction
endscope
//TRIGGER DOING THE ACTUAL SUMMONING ON STRIKING AND DOES BH BONUS DAMAGE TOO
scope SpellbindingArrow initializer InitTrig_SpellBindingArrowStrike
function Trig_SpellBindingArrowStrike_Conditions takes nothing returns boolean
//activate arrow effects if target is not a structure , the attacker is hero
//and the attacked is not ally of attacker
return (not IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE)) and IsUnitType(GetEventDamageSource(),UNIT_TYPE_HERO) and (not IsUnitAlly(GetTriggerUnit(),GetOwningPlayer(GetEventDamageSource())))
endfunction
function SpellBindDamage takes unit u , player owner , integer damage returns nothing
local group g = CreateGroup()
local location l=GetUnitLoc(u)
local unit un
set g = GetUnitsInRangeOfLocAll(50,l)
loop
set un=FirstOfGroup(g)
if un!=null and not IsUnitAlly(un,owner) and GetWidgetLife(un)>.405 and not IsUnitType(un,UNIT_TYPE_MAGIC_IMMUNE) then
call UnitDamageTargetBJ(u,un,damage,ATTACK_TYPE_HERO,DAMAGE_TYPE_MAGIC)
call DestroyEffect( AddSpecialEffectTargetUnitBJ( "overhead", un , WispAnimation ))
endif
call GroupRemoveUnit(g,un)
exitwhen un==null
endloop
call RemoveLocation(l)
call RemoveUnit(un)
call DestroyGroup(g)
set l=null
set un=null
endfunction
function Trig_SpellBindingArrowStrike_Actions takes nothing returns nothing
local unit att=GetEventDamageSource()
local player owner=GetOwningPlayer(att)
local unit target=GetTriggerUnit()
local integer lvl=GetUnitAbilityLevel(att,039;A002039;)
local boolean undead=IsUnitType(GetTriggerUnit(),UNIT_TYPE_UNDEAD)
local real X=GetLocationX(GetUnitLoc(target))
local real Y=GetLocationY(GetUnitLoc(target))
local integer STR=GetHeroStr(att,TRUE)
local integer AGI=GetHeroAgi(att,TRUE)
local integer INT=GetHeroInt(att,TRUE)
local integer AoEX=R2I(STR+INT+100)
local integer AoEY=R2I(AGI+INT+100)
local integer HorizL=IMinBJ(R2I(20*STR/100),5)
local integer VertiL=IMinBJ(R2I(10*AGI/100),9)
local integer SpiritsNo=(30*INT/100)
local integer SpiritDMG=R2I((AGI+STR)/5)
local integer chance
local unit array spirits
local integer i
local integer j
local real angle
local integer fieldcode=-1
//Parameters for BH
local integer lvl2=GetUnitAbilityLevel(att,039;A003039;)
local real lifelost
local real BHdamage
local real Texttag_Vlcty = 60
local real Texttag_Size = 10
local real Texttag_Red = 250
local real Texttag_Green = 86
local real Texttag_Blue = 245
local real Texttag_Trsprcy = 8
local real Texttag_Angle = 90
local real Texttag_Durtn = 1.25
local real Cut_Off_Durtn = 2.5
local texttag t
//call BJDebugMsg("ArrowStrike Actions")
//call BJDebugMsg("ArrowStrike lvl "+I2S(lvl))
//if undead then
//call BJDebugMsg("Undead target")
//endif
//call BJDebugMsg("Target Position X "+R2S(X)+" Y "+R2S(Y))
//call BJDebugMsg("Attacker stats S="+I2S(STR)+" A="+I2S(AGI)+" I="+I2S(INT))
//call BJDebugMsg("AoE X="+I2S(AoEX)+" Y="+I2S(AoEY))
//call BJDebugMsg("Loops X="+I2S(HorizL)+" Y="+I2S(VertiL))
//call BJDebugMsg("Spirits No="+I2S(SpiritsNo)+" Dmg="+I2S(SpiritDMG))
//creating a random value to see if the ability triggers
//Doing BH damage here
if lvl2>0 then
set lifelost=GetUnitState(att,UNIT_STATE_MAX_LIFE)-GetUnitState(att,UNIT_STATE_LIFE)
set BHdamage=0.01*lvl2*lifelost
//Amazingly I cannot use the hero to damage stuff while the trigger is activated FFS
call DisableTrigger(gg_trg_SpellBindingArrowStrike)
call UnitDamageTarget(att,target,BHdamage, false , false ,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_DIVINE,WEAPON_TYPE_WHOKNOWS)
call EnableTrigger(gg_trg_SpellBindingArrowStrike)
call SetUnitLifeBJ(att,GetUnitState(att,UNIT_STATE_LIFE)+BHdamage*BH_regeneration)
//display damage in black
if R2I(BHdamage)>0 then
set t = CreateTextTagUnitBJ("+" + I2S(R2I(BHdamage)), target , Texttag_Vlcty, Texttag_Size, Texttag_Red, Texttag_Green, Texttag_Blue, Texttag_Trsprcy)
call SetTextTagVelocityBJ(t, Texttag_Vlcty, Texttag_Angle)
call SetTextTagPermanent(t, false)
call SetTextTagLifespan(t, Texttag_Durtn)
endif
endif
//ArrowStrike here
if lvl>0 then
if undead then
set chance = GetRandomInt(1,50)
else
set chance = GetRandomInt(1,100)
endif
//checking and doing actions if it does
if chance<=5*lvl then
//call BJDebugMsg("Spirits have been summoned")
if (fieldcode==-1) then
if (CurrentSpiritFields==MaxSpiritFields) then
set fieldcode=MaxSpiritFields
set FieldsInGame=FieldsInGame+1
set CurrentSpiritFields=1
if FieldsInGame>MaxSpiritFields then
set FieldsToKill=fieldcode
endif
else
set fieldcode=CurrentSpiritFields
set FieldsInGame=FieldsInGame+1
set CurrentSpiritFields=CurrentSpiritFields+1
if FieldsInGame>MaxSpiritFields then
set FieldsToKill=fieldcode
endif
endif
endif
set angle=2*bj_PI/SpiritsNo
set i=0
loop
set spirits<i>=CreateUnit(GetOwningPlayer(att),039;e000039;,X+AoEX*Cos(HorizL*i*angle),Y+AoEY*Sin(VertiL*i*angle),0)
set i=i+1
exitwhen i==SpiritsNo
endloop
set i=0
loop
set j=0
loop
call SetUnitPosition(spirits[j],X+AoEX*Cos(HorizL*(j*angle+i*increment)),Y+AoEY*Sin(VertiL*(j*angle+i*increment)))
//for this damage function I used the owner because inlike Avenging Wrath if the hero dies it will still go on
//the hero may die if he morphs and we don't want the morphed hero to take damage from his own skill
//so he has the same owner as the previous unit spawning this effect so the player and his allies are
//safe from selfdamage
call SpellBindDamage(spirits[j],owner,SpiritDMG)
set j=j+1
exitwhen j==SpiritsNo
endloop
call TriggerSleepAction(0.04)
set i=i+1
exitwhen i*increment>bj_PI or fieldcode==FieldsToKill
endloop
set j=0
loop
call RemoveUnit(spirits[j])
set spirits[j]=null
set j = j + 1
exitwhen j==SpiritsNo
endloop
set FieldsInGame=FieldsInGame-1
if FieldsToKill==fieldcode then
set FieldsToKill=0
endif
endif
endif// lvl of arrowstrike >0
endfunction
//===========================================================================
function InitTrig_SpellBindingArrowStrike takes nothing returns nothing
set gg_trg_SpellBindingArrowStrike = CreateTrigger( )
call TriggerAddCondition(gg_trg_SpellBindingArrowStrike , Condition(function Trig_SpellBindingArrowStrike_Conditions))
call TriggerAddAction( gg_trg_SpellBindingArrowStrike, function Trig_SpellBindingArrowStrike_Actions )
endfunction
endscope
</i>
I have decided to add -as command to display the number of spirits summoned by ArrowStrike and their damage :
3. Blood Hatred - based off Evasion . You deal aditional damage of 1% * SpellLvl of your lost life as bonus damage and heal 1/2 of this bonus damage dealt and also if an enemy hero kills a nonhero,nonmechanical,nonbuilding unit you gain 0.01*SpellLvL Strength
Now If a player learns BloodHatred skill his hero will be memorized into an array and in similar arrays will be stored the Str bonuses to be gained and already gained due to this ability .
Upon further thinking I decided to make my hero playable by all the players but in 1 instance for every one of them . Here are the triggers for monitoring applying STR and displaying it with player command -bh
JASS:
globals
trigger gg_trg_BHDisplay
integer array BH_StrengthAdded
real array BH_StrengthTotal
endglobals
//TRIGGER FOR INCREASING HERO STRENGTH FOR ALLIED CREEP KILLED BY ENEMY HERO
scope BHStrengthBonus initializer InitTrig_BHStrengthBonus
function Trig_BHStrengthBonus_Actions takes nothing returns nothing
local integer i=0
local integer Strength
local group g
local unit un
loop
exitwhen i==12
//the players will gain strength if :
// the killed enemy isn't building, hero or mechanical
//the killing unit is an enemy hero
//my array contains only the units that have already learned BH so testing if the unit shall have STR++ is unnecesary
if (not IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE)) and (not IsUnitType(GetTriggerUnit(),UNIT_TYPE_HERO)) and (not IsUnitType(GetTriggerUnit(),UNIT_TYPE_MECHANICAL)) and IsUnitEnemy(GetKillingUnit(),Player(i)) and IsUnitType(GetKillingUnit(),UNIT_TYPE_HERO) then
set g=GetUnitsOfPlayerAll(Player(i))
loop
set un = FirstOfGroup(g)
call GroupRemoveUnit(g,un)
exitwhen un==null or GetUnitAbilityLevel(un,039;A003039;)>0
endloop
//we consider the hero is unique and cannot be purchased more than once by a player
//we also consider that all players can have the same hero
set BH_StrengthTotal<i>=BH_StrengthTotal<i> + 0.01*GetUnitAbilityLevel(un,039;A003039;)
if R2I(BH_StrengthTotal<i>)>BH_StrengthAdded<i> then
set Strength=GetHeroStr(un,false)
call SetHeroStr(un,Strength+R2I(BH_StrengthTotal<i>)-BH_StrengthAdded<i>,true)
set BH_StrengthAdded<i>=R2I(BH_StrengthTotal<i>)
endif
endif
set i=i+1
endloop
endfunction
//===========================================================================
function InitTrig_BHStrengthBonus takes nothing returns nothing
set gg_trg_BHStrengthBonus = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(gg_trg_BHStrengthBonus,EVENT_PLAYER_UNIT_DEATH)
call TriggerAddAction( gg_trg_BHStrengthBonus, function Trig_BHStrengthBonus_Actions )
endfunction
endscope
//TRIGGER FOR DISPLAYING THE STRENGTH GAINED
scope display initializer InitTrig_BHDisplay
function Trig_BHDisplay_Actions takes nothing returns nothing
//call BJDebugMsg("Your BloodHatred strength is "+R2S(BH_StrengthTotal<i>))
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,3,"Your BloodHatred strength is "+R2S(BH_StrengthTotal[GetPlayerId(GetTriggerPlayer())]))
endfunction
//===========================================================================
function InitTrig_BHDisplay takes nothing returns nothing
set gg_trg_BHDisplay = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(0), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(1), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(2), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(3), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(4), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(5), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(6), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(7), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(8), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(9), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(10), "-bh", true )
call TriggerRegisterPlayerChatEvent( gg_trg_BHDisplay, Player(11), "-bh", true )
call TriggerAddAction( gg_trg_BHDisplay, function Trig_BHDisplay_Actions )
endfunction
endscope
</i></i></i></i></i></i></i></i></i>
4. Pain of the Ancients - based off channel . It is mainly done but there are still issues
What it does :
- changes the hero into another one
- he keeps the BH strength bonus and BH still works normally thereafter
- he doesn't kill himself with SpellBindingArrow any more when changing forms
- He gains the multishot as he should
- he gsins the bonus damage and bonus damage for allied building lost normally
- he gains the armor and spell immunity
- autoactivates when HP < 30% ; now it autoactivates the second time and third time and so on too
- fixed so it has 45 seconds cooldown ; removed cooldown from the object editor spell
- can be activated
- uses up mana
- shows cripple but also plays the stupid cripple sound
- plays funny music but not as loud as I would like
What it doesn't do :
- doesn't display magic immunity buff (based off spell immunity unit ability)
- fills the hero skills tab with useless icons (and i would rather it doesn't do it)
- doesn't display cooldown in normal fashion ; I made some text messages to notify you but hope to improve it
JASS:
globals
trigger gg_trg_PotADismountLifeCheck
trigger gg_trg_PotABuildingLost
trigger gg_trg_PotAHeroReived
trigger gg_trg_PotARevive
integer array PotA_FallenAllies[12]
integer array PotALostBuildings[12]
boolean array PotAOnCooldown[12]
real ActivationLifePercent=30.00
endglobals
//TRIGGER FOR COUNTING BUILDINGS AND ALLIED HEROES DEAD
scope LostAllies initializer InitTrig_PotABuildingLost
function Trig_PotABuildingLost_Actions takes nothing returns nothing
local integer i=0
local integer owner=GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
//hero death
if IsUnitType(GetTriggerUnit(),UNIT_TYPE_HERO) then
loop
if IsPlayerAlly(Player(i),Player(owner)) then
//call BJDebugMsg("An allied hero of player "+I2S(i)+"has been slain !!!")
set PotA_FallenAllies<i>=PotA_FallenAllies<i>+1
endif
exitwhen i>11
set i=i+1
endloop
//unit death
elseif IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE) then
loop
if IsPlayerAlly(Player(i),Player(owner)) then
//call BJDebugMsg("Our base??? is under attack !!! - ally of player " + I2S(i))
set PotALostBuildings<i>=PotALostBuildings<i> + 1
endif
exitwhen i>11
set i = i + 1
endloop
endif
endfunction
//===========================================================================
function InitTrig_PotABuildingLost takes nothing returns nothing
set gg_trg_PotABuildingLost = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(gg_trg_PotABuildingLost,EVENT_PLAYER_UNIT_DEATH)
call TriggerAddAction( gg_trg_PotABuildingLost, function Trig_PotABuildingLost_Actions )
endfunction
endscope
//TRIGGER ALLIED HERO REVIED DURING ULTIMATE TO REDUCE MULTISHOT TARGETS
scope AllyRevived initializer InitTrig_PotAHeroReived
function Trig_PotAHeroReived_Actions takes nothing returns nothing
local integer i
local integer owner = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
loop
if IsPlayerAlly(Player(i),Player(owner)) then
set PotA_FallenAllies<i> = PotA_FallenAllies<i> - 1
endif
exitwhen i>11
set i=i+1
endloop
endfunction
//===========================================================================
function InitTrig_PotAHeroReived takes nothing returns nothing
set gg_trg_PotAHeroReived = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(gg_trg_PotAHeroReived,EVENT_PLAYER_HERO_REVIVE_FINISH)
call TriggerAddAction( gg_trg_PotAHeroReived, function Trig_PotAHeroReived_Actions )
endfunction
endscope
//TRIGGER FOR REVIVING A HERO DEAD DURING THE ULTIMATE
scope revive initializer InitTrig_PotARevive
function Trig_PotARevive_Conditions takes nothing returns boolean
return GetUnitTypeId(GetTriggerUnit()) == 039;E001039;
endfunction
function Trig_PotARevive_Actions takes nothing returns nothing
local unit caster=GetTriggerUnit()
local integer AWlevels = GetUnitAbilityLevel(caster,039;A000039;)
local integer SbAlevels = GetUnitAbilityLevel(caster,039;A002039;)
local integer BHlevels = GetUnitAbilityLevel(caster,039;A003039;)
local integer PotAlevels = GetUnitAbilityLevel(caster,039;A005039;)
local integer StatsLevels = GetUnitAbilityLevel(caster,039;A001039;)
local real lifelevel = GetUnitState(caster,UNIT_STATE_LIFE)
local integer i
set caster=ReplaceUnitBJ(caster,039;E002039;,bj_UNIT_STATE_METHOD_RELATIVE)
call SetUnitState(caster,UNIT_STATE_LIFE,lifelevel)
call SetHeroStr(caster,GetHeroStr(caster,false)+BH_StrengthAdded[GetPlayerId(GetOwningPlayer(caster))],true)
//it's left to learn the abilities of the hero
set i=0
loop
exitwhen i==AWlevels
call SelectHeroSkill(caster,039;A000039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==SbAlevels
call SelectHeroSkill(caster,039;A002039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==BHlevels
call SelectHeroSkill(caster,039;A003039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==PotAlevels
call SelectHeroSkill(caster,039;A004039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==StatsLevels
call SelectHeroSkill(caster,039;A001039;)
set i=i+1
endloop
set caster = null
endfunction
//===========================================================================
function InitTrig_PotARevive takes nothing returns nothing
set gg_trg_PotARevive = CreateTrigger( )
call DisableTrigger( gg_trg_PotARevive )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(0), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(1), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(2), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(3), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(4), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(5), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(6), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(7), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(8), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(9), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(10), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_PotARevive, Player(11), EVENT_PLAYER_HERO_REVIVE_FINISH )
call TriggerAddCondition( gg_trg_PotARevive, Condition( function Trig_PotARevive_Conditions ) )
call TriggerAddAction( gg_trg_PotARevive, function Trig_PotARevive_Actions )
endfunction
endscope
//TRIGGER FOR AUTOACTIATION OF POTA
scope AutoActivation initializer InitTrig_PotADismountLifeCheck
function Trig_PoTADismountCheck_Conditions takes nothing returns boolean
return GetUnitStatePercent(GetTriggerUnit(),UNIT_STATE_LIFE,UNIT_STATE_MAX_LIFE)<ActivationLifePercent and GetUnitAbilityLevel(GetTriggerUnit(),039;A004039;)>0
endfunction
function Trig_PotADismountLifeCheck_Actions takes nothing returns nothing
//call BJDebugMsg("life <30%")
if not PotAOnCooldown[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] then
call TriggerExecute(gg_trg_PotADismount)
endif
endfunction
//===========================================================================
function InitTrig_PotADismountLifeCheck takes nothing returns nothing
set gg_trg_PotADismountLifeCheck = CreateTrigger( )
call TriggerAddCondition(gg_trg_PotADismountLifeCheck , Condition(function Trig_PoTADismountCheck_Conditions))
call TriggerAddAction( gg_trg_PotADismountLifeCheck, function Trig_PotADismountLifeCheck_Actions )
endfunction
endscope
//TRIGGER FOR DOING ACTIONS FOR PAIN OF THE ANCIENTS
scope PotAActions initializer InitTrig_PotADismount
function Trig_PotADismount_Conditions takes nothing returns boolean
return GetSpellAbilityId()==039;A004039;
endfunction
function Trig_PotADismount_Actions takes nothing returns nothing
local unit caster=GetTriggerUnit()
local integer AWlevels = GetUnitAbilityLevel(caster,039;A000039;)
local integer SbAlevels = GetUnitAbilityLevel(caster,039;A002039;)
local integer BHlevels = GetUnitAbilityLevel(caster,039;A003039;)
local integer PotAlevels = GetUnitAbilityLevel(caster,039;A004039;)
local integer StatsLevels = GetUnitAbilityLevel(caster,039;A001039;)
local real lifelevel = GetUnitState(caster,UNIT_STATE_LIFE)
local real manalevel = GetUnitState(caster,UNIT_STATE_MANA)
//this one is because it's annoying to reselect the hero time and again
local boolean isselected = IsUnitSelected(caster,GetOwningPlayer(caster))
local integer i
local integer j=0
local integer loops = 5+5*PotAlevels
local integer allies_dead = PotA_FallenAllies[GetPlayerId(GetOwningPlayer(caster))]
local integer allies_dead_new
local integer buildings_lost = PotALostBuildings[GetPlayerId(GetOwningPlayer(caster))]
local integer buildings_lost_new
//local unit holder = CreateUnit(GetOwningPlayer(caster),'h000',0,0,0)
if not PotAOnCooldown[GetPlayerId(GetOwningPlayer(caster))] then
//adjusting mana consumed and putting skill on cooldown
set manalevel=manalevel - 50*(PotAlevels+1)
set PotAOnCooldown[GetPlayerId(GetOwningPlayer(caster))]=true
set caster=ReplaceUnitBJ(caster,039;E001039;,bj_UNIT_STATE_METHOD_RELATIVE)
call SetHeroStr(caster,GetHeroStr(caster,false)+BH_StrengthAdded[GetPlayerId(GetOwningPlayer(caster))],true)
call AddSpecialEffectTargetUnitBJ( "origin", caster, "Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl" )
call PlaySoundOnUnitBJ( gg_snd_ArcherPissed2, 100, caster )
//it's left to learn the abilities of the hero
//here go the usual abilities
set i=0
loop
exitwhen i==AWlevels
call SelectHeroSkill(caster,039;A000039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==StatsLevels
call SelectHeroSkill(caster,039;A001039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==SbAlevels
call SelectHeroSkill(caster,039;A002039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==BHlevels
call SelectHeroSkill(caster,039;A003039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==PotAlevels
call SelectHeroSkill(caster,039;A005039;)
set i = i + 1
endloop
//after setting all the abilities we set the life/mana values so that leveling stats won't give hero HP;MP heal
call SetUnitState(caster,UNIT_STATE_LIFE,lifelevel)
call SetUnitState(caster,UNIT_STATE_MANA,manalevel)
//Add spell Immunity
call UnitAddAbility(caster,039;A008039;)
//adding the hero only multishot
//the level of multishot is basically the number of allied heroes fallen but I capped it to
//a number between 1 and 5 because that is how many levels I gave the multishot ability
if allies_dead>0 then
call UnitAddAbility(caster,039;A006039;)
call SetUnitAbilityLevel(caster,039;A006039;,IMinBJ(IMaxBJ(allies_dead,1),5))
endif
//selecting new hero
call SelectUnit(caster,isselected)
//Adding auras with damage and armor on the dummy unit created
call UnitAddAbility(caster,039;A007039;)
call SetUnitAbilityLevel(caster,039;A007039;,20*(PotAlevels-1)+IMinBJ(buildings_lost,19))
//In the loop I will add also the skill for bonus damage and modify stuff as necessary :
//remove spell imunity , increase damage dealt , reduce or increase multishot level
loop
call TriggerSleepAction(1)
set allies_dead_new = PotA_FallenAllies[GetPlayerId(GetOwningPlayer(caster))]
set buildings_lost_new = PotALostBuildings[GetPlayerId(GetOwningPlayer(caster))]
if allies_dead_new>allies_dead then
set allies_dead = allies_dead_new
call SetUnitAbilityLevel(caster,039;A006039;,IMinBJ(IMaxBJ(allies_dead,1),5))
endif
//get the damage bonus from the buildings lost or the base ;
//bonus from buildings lost is capped at 19 instances
if buildings_lost_new>buildings_lost then
set buildings_lost=buildings_lost_new
call UnitAddAbility(caster,039;A007039;)
call SetUnitAbilityLevel(caster,039;A007039;,20*(PotAlevels-1)+IMinBJ(buildings_lost,19))
endif
if j==3*PotAlevels then
//remove spell imunity and add an icon holder
call UnitRemoveAbility(caster,039;A008039;)
endif
exitwhen j==loops or GetWidgetLife(caster)<.405
set j = j+1
endloop
//call BJDebugMsg("Should return hero to normal " )
//the archer now remounts
if GetWidgetLife(caster)>.405 then
set AWlevels = GetUnitAbilityLevel(caster,039;A000039;)
set SbAlevels = GetUnitAbilityLevel(caster,039;A002039;)
set BHlevels = GetUnitAbilityLevel(caster,039;A003039;)
set PotAlevels = GetUnitAbilityLevel(caster,039;A005039;)
set StatsLevels = GetUnitAbilityLevel(caster,039;A001039;)
set lifelevel = GetUnitState(caster,UNIT_STATE_LIFE)
set manalevel = GetUnitState(caster,UNIT_STATE_MANA)
set isselected = IsUnitSelected(caster,GetOwningPlayer(caster))
set caster=ReplaceUnitBJ(caster,039;E002039;,bj_UNIT_STATE_METHOD_RELATIVE)
call SetHeroStr(caster,GetHeroStr(caster,false)+BH_StrengthAdded[GetPlayerId(GetOwningPlayer(caster))],true)
//it's left to learn the abilities of the hero
set i=0
loop
exitwhen i==AWlevels
call SelectHeroSkill(caster,039;A000039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==SbAlevels
call SelectHeroSkill(caster,039;A002039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==BHlevels
call SelectHeroSkill(caster,039;A003039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==PotAlevels
call SelectHeroSkill(caster,039;A004039;)
set i=i+1
endloop
set i=0
loop
exitwhen i==StatsLevels
call SelectHeroSkill(caster,039;A001039;)
set i=i+1
endloop
//after setting all the abilities we set the life/mana values so that leveling stats won't give hero HP;MP heal
call SetUnitState(caster,UNIT_STATE_LIFE,lifelevel)
call SetUnitState(caster,UNIT_STATE_MANA,manalevel)
call SelectUnit(caster,isselected)
else
//enable reviving trigger
call EnableTrigger(gg_trg_PotARevive)
endif // unit is alive when the skill finishes
call DestroyEffect(GetLastCreatedEffectBJ())
//waiting the remaining time till cooldown is over
call TriggerSleepAction(45-loops)
set PotAOnCooldown[GetPlayerId(GetOwningPlayer(caster))]=false
call DisplayTimedTextToPlayer(GetOwningPlayer(caster),0,0,3," Pain of the Ancients cooldown has finished")
else
call DisplayTimedTextToPlayer(GetOwningPlayer(caster),0,0,3," Pain of the Ancients is on cooldown ")
endif // if not on cooldown
endfunction
//===========================================================================
function InitTrig_PotADismount takes nothing returns nothing
set gg_trg_PotADismount = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_PotADismount , EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_PotADismount, Condition( function Trig_PotADismount_Conditions ) )
call TriggerAddAction( gg_trg_PotADismount, function Trig_PotADismount_Actions )
endfunction
endscope
</i></i></i></i></i></i>
Miscelaneous BUG (the passive abilities don't activate if I don't make this triggers executed at map init , and this last trigger does just that ) for which I found only this solution :
Trigger:
- Init
- Events
- Map initialization
- Conditions
- Actions
- Custom script: call TriggerExecute(gg_trg_SpellBindingArrowStrike)
- Custom script: call TriggerExecute(gg_trg_InitSpellBindingArrowAddEvent)
- Events
Now it is readable thanks' to SharkBait's efforts .