- Joined
- Jun 5, 2008
- Messages
- 2,572
Im making skills for my hero, the Artisan of War.
After that, we will see.
After that, we will see.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
//==========================================================================================
//Soul Harvest (Xerex) v1.02 by watermelon_1234
//__________________________________________________________________________________________
//Description:
// Corpses within 500 range of Dark Lord will bolster his offensive power.
//******************************************************************************************
//Libraries required:
// - BonusMod
// - GroupUtils
// - TimedLoop
//##########################################################################################
//Importing:
// 1. Copy the ability, Soul Harvest, and its buff.
// 2. Copy this trigger.
// 3. Implement required libraries.
// 4. Configure the spell.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Notes:
// The level check may be inefficient as it always update to that manually. The nice thing
// is that this spell supports Tome of Retraining.
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//Changelog:
// v1.02: Made it reduce the time it would check, adds a special effect if the hero has a
// bonus.
// v1.01: Made it use TimedLoop
//==========================================================================================
scope SoulHarvest
native UnitAlive takes unit id returns boolean //A better way to check if a unit is alive.
globals
private constant integer SPELL_ID = 'A005' //Raw id of the Soul Harvest ability.
private constant real TIMER_LOOP = 0.5 //How often the timer would check the corpses
private constant string BONUS_SFX = "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl" //The SFX that would be attached to the hero if it has a damage bonus
private constant string BONUS_SFX_ATTACH = "hand,left" //The attachment point for the BONUS_SFX
endglobals
//The range of the ability which enumerates corpses.
private constant function Range takes integer lvl returns real
return 500. + 0*lvl
endfunction
//The damage bonus gained for each corpse.
private constant function DamageBonus takes integer lvl returns integer
return 2 + 2*lvl
endfunction
//The max damage bonus that one can get from this ability.
private constant function MaxDamageBonus takes integer lvl returns integer
return 70 + 0*lvl
endfunction
//-------------END OF CONFIGURATION-------------------
globals
private boolexpr e //Used for counting corpses
endglobals
private struct Data
unit hero //The hero that learned the ability.
integer lvl = 1 //The level of the ability for the hero. Is updated at the end of every loop as it stores the past level.
integer count //Counts how many corpses there are near the hero.
integer oldCount = 0 //Stores the count from the previous time the loop was run. Used to update the attack damage bonus correctly.
integer totalBonus = 0 //The total attack damage bonus the hero has from this ability.
real timeCounter = 0 //Counts how often the struct should be looped.
effect sfx = null //The effect for the bonus.
private static thistype temp //Used for the group filter so that we can set count of a struct instance correctly.
static method create takes unit h returns thistype
local thistype this = thistype.allocate()
set .hero = h
call .startTimedLoop()
return this
endmethod
//Note that this is a filter. Used only to count dead units for the bonus.
static method countCorpses takes nothing returns boolean
if not UnitAlive(GetFilterUnit()) then //Corpses count as units that are dead.
set temp.count = temp.count + 1
endif
return false
endmethod
//Used so many times that I just made a method for this. Basically removes any bonus the hero gained from this spell.
method resetBonus takes nothing returns nothing
call AddUnitBonus(.hero,BONUS_DAMAGE,-.totalBonus)
endmethod
method removeEffect takes nothing returns nothing
call DestroyEffect(.sfx)
set .sfx = null
endmethod
method onTimedLoop takes nothing returns boolean
local integer add //Considers what attack damage bonus the spell needs to add
local integer curLvl = GetUnitAbilityLevel(.hero,SPELL_ID)
//If the level is 0 that means the hero no longer has the ability. That means the spell should stop.
if curLvl == 0 then
//Only reset the bonus if .totalBonus is greater than 0.
if .totalBonus > 0 then
call .resetBonus()
call .removeEffect()
endif
return false
endif
if .timeCounter == 0 then
if UnitAlive(.hero) then
set .count = 0 //Set to 0 first or else counting the corpses will be messed up.
set temp = this
call GroupEnumUnitsInArea(ENUM_GROUP,GetUnitX(.hero),GetUnitY(.hero),Range(.lvl),e)
//No corpses but oldCount has a different number. Remove any bonus given to the hero and correctly set oldCount to 0.
if .count == 0 and .oldCount != 0 then
call .resetBonus()
call .removeEffect()
set .totalBonus = 0
set .oldCount = 0
//Previous level is not updated with the current level.
//In this case, ignore any bonus the hero has received from last loop by resetting it and manually give the correct bonus.
elseif .lvl != curLvl then
call .resetBonus()
//Make sure the bonus will not exceed MaxDamageBonus.
//Remember: The bonus given to the hero is the # of corpses times the damage bonus each corpse gives but the bonus is capped.
if .count*DamageBonus(curLvl) > MaxDamageBonus(curLvl) then
set .totalBonus = MaxDamageBonus(curLvl)
else
set .totalBonus = .count*DamageBonus(curLvl)
endif
call AddUnitBonus(.hero,BONUS_DAMAGE,.totalBonus)
set .lvl = curLvl
elseif .count != .oldCount then //The counts of the corpses aren't the same so change the bonus. Otherwise, don't do anything after this as all is well.
//If the supposed bonus is bigger than MaxDamageBonus, limit it.
//add is the difference between the bonus the hero should have from the spell and the current bonus it has.
if .count*DamageBonus(.lvl) > MaxDamageBonus(.lvl) then
set add = MaxDamageBonus(.lvl) - .totalBonus
else
set add = .count*DamageBonus(.lvl) - .totalBonus
endif
call AddUnitBonus(.hero,BONUS_DAMAGE,add)
//Update some variables to work for the next loop
set .oldCount = .count
set .totalBonus = .totalBonus + add
endif
if .totalBonus > 0 and .sfx == null then
set .sfx = AddSpecialEffectTarget(BONUS_SFX,.hero,BONUS_SFX_ATTACH)
endif
endif
endif
set .timeCounter = .timeCounter + TimedLoop_PERIOD
if .timeCounter >= TIMER_LOOP then
set .timeCounter = 0
endif
return true
endmethod
implement TimedLoop
static method learnSkill takes nothing returns boolean
if GetLearnedSkill() == SPELL_ID and GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID) == 1 then
call thistype.create(GetTriggerUnit())
endif
return false
endmethod
static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
call TriggerAddCondition(t,Condition(function thistype.learnSkill))
set e = Filter(function thistype.countCorpses)
endmethod
endstruct
endscope
I'm pretty sure only vJass is accepted, sorry. However, things may change if there's a serious lack of coders which appears to be happening right now...I want to create the spells for Dentothor, is that OK?
I use GUI if that is alright.
