Naga'sShadow
Ultra Cool Member
- Reaction score
- 49
This is a half advice half help request thread. I recently made a simple charge spell. It works, but its not really the best. Omitting things that I know to fix, like the animation or lack of one, I don't think I've coded it the best. Could someone take a look at it and let me know what you think?
Here's the code.
One of my biggest questions is the filter function. Is there a way to check if a unit is an enemy of the caster without using a global to store the caster? I only need it there but it seems like it would make the spell non MUI.
Another question is that the way I'm damaging units right now doesn't seem to be working, as I only want the caster to hit a given unit once but in testing he just vaporizes anything he comes into contact with. Thanks for any input you can give.
Here's the code.
JASS:
scope Charge initializer Init
globals
private constant integer SPELLID = 039;A00L039;
private constant real INTERVAL = .03
private constant real STEP = 15
private constant real TRAMPLE_DIST = 200
private constant string EFFECT = "Abilities\\Weapons\\GlaiveMissile\\GlaiveMissileTarget.mdl"
private constant string SFX = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl"
private unit CASTER
endglobals
struct data
unit caster
group targets
real x
real y
real dx
real dy
real dist
real angle
group hit
real moved = 0
endstruct
private function Trample takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(CASTER)) == true and GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) >= .9 and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction
//Controls damage dealt
private function SetDamage takes integer level returns real
return I2R(100 * level)
endfunction
private function Effects takes nothing returns nothing
local timer t = GetExpiredTimer()
local data d = GetCSData(t)
local group targets = CreateGroup()
local real damage = SetDamage(GetUnitAbilityLevel(d.caster, SPELLID))
if GetUnitState(d.caster, UNIT_STATE_LIFE) <= .9 or d.moved >= d.dist then
call PauseTimer(t)
call DestroyTimer(t)
call PauseUnit(d.caster, false)
call SetUnitPathing(d.caster, true)
set CASTER = null
set d.caster = null
call DestroyGroup(d.hit)
call DestroyGroup(targets)
endif
set d.x = d.x + STEP * Cos(d.angle * bj_DEGTORAD)
set d.y = d.y + STEP * Sin(d.angle * bj_DEGTORAD)
call SetUnitX(d.caster, d.x)
call SetUnitY(d.caster, d.y)
call GroupEnumUnitsInRange(targets, d.x, d.y, TRAMPLE_DIST, Filter( function Trample))
loop
exitwhen FirstOfGroup(targets) == null
if IsUnitInGroup(FirstOfGroup(targets), d.hit) == false then
call UnitDamageTarget(d.caster, FirstOfGroup(targets), damage, false, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectLoc(SFX, GetUnitLoc(FirstOfGroup(targets))))
call GroupAddUnit(d.hit, FirstOfGroup(targets))
endif
call GroupRemoveUnit(targets, FirstOfGroup(targets))
endloop
call DestroyEffect(AddSpecialEffect(EFFECT,d.x,d.y))
call DestroyGroup(targets)
set d.moved = d.moved + STEP
endfunction
private function Go takes nothing returns nothing
local data d = data.create()
local unit caster = GetTriggerUnit()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real dx = GetLocationX(GetSpellTargetLoc())
local real dy = GetLocationY(GetSpellTargetLoc())
local real dist = SquareRoot((Pow(dx-x,2) + Pow(dy-y,2)))
local real angle = bj_RADTODEG * Atan2( dy-y, dx-x)
local timer t = CreateTimer()
set d.caster = caster
set d.x = x
set d.y = y
set d.dx = dx
set d.dy = dy
set d.dist = dist
set d.angle = angle
set CASTER = caster
call PauseUnit(caster, true)
call SetUnitPathing(caster, false)
call SetCSData(t, d)
call TimerStart(t, INTERVAL, true, function Effects)
endfunction
private function conditions takes nothing returns boolean
if GetSpellAbilityId()== SPELLID then
call Go()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition( function conditions))
endfunction
endscope
One of my biggest questions is the filter function. Is there a way to check if a unit is an enemy of the caster without using a global to store the caster? I only need it there but it seems like it would make the spell non MUI.
Another question is that the way I'm damaging units right now doesn't seem to be working, as I only want the caster to hit a given unit once but in testing he just vaporizes anything he comes into contact with. Thanks for any input you can give.