[jass=Breath of Fire]scope BreathOfFire//version 1.4 by kawas11
/******************************************************************************************************
*
* Requires: Missle, DelFX, TimerUtils, and IsUnitChanneling
* Optional: SpellEffectEvent, IsDestructableTree (if you want to check if destructables are trees)
*
*
*
* How to import:
* - Copy BoF trigger
* - Copy Libraries folder
* - Copy Universal Dummy
* - Copy Breath of Fire Ability
*
* Changelog:
* v1.0
* - First Release
* v1.1
* - Tooltip correction
* - Removed unused globals
* - Shorter code
* - Tree filter (IsDestructableTree)
* - onCast now returns boolean
* v1.2
* - Now using KillTree function from IsDestructableTree
* - Improved documentation
* - Structured trigger folders
* 1.3
* - Now based on channel ability
* - Removed unused tree_rect
* - Updated missle library
* - No longer requires CTL, now using TimerUtils
* - Fixed tooltip
* 1.4
* - method Destroy -> method destroy
* - Caster's animation speed correction
* - Fireballs will be now always removed in onRemove method independant of the user setting
*
*
*********************************************************************************************************/
/**************************************************************************************
* *
* CONFIGURATION *
* *
**************************************************************************************/
native UnitAlive takes unit id returns boolean
globals
//Breath of Fire ability rawcode
private constant integer SPELL_ID = 'A000'
//Cast time - time needed for animation
private constant real CAST_TIME = 1.00
//Caster animation speed in percent
private constant real CASTER_ANIMATION_SPEED = 60
//Total spell channel time (exclude CAST_TIME)
private constant real CHANNEL_TIME = 5.00
//Every X timer ticks (0.031250) spawn new fireball
private constant integer FIRE_CD = 3
//Attachment point for damage effect
private constant string DAMAGE_EFFECT_ATTACH = "chest"
//Damage effect
private constant string DAMAGE_EFFECT = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
//Fireballs remove effect
private constant string REMOVE_EFFECT = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
//Fireballs spawn effect
private constant string SPAWN_EFFECT = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
//Fireballs model
private constant string DUMMY_MODEL = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
//Fireballs Scale in percent
private constant real DUMMY_SCALE = 120
//Fireballs height
private constant real DUMMY_HEIGHT = 70
//Fireballs move speed every 0.031250
private constant real DUMMY_SPEED = 25
//Fireballs collision size - used for units and destructables
private constant real DUMMY_COLISION = 75
//Distance between caster and fireballs spawn location
private constant real DUMMY_CREATE_DIST = 85
//Set minimum angle difference of caster's facing
private constant real MIN_ANGLE = 15
//Set maximum angle difference of caster's facing
private constant real MAX_ANGLE = 15
//Remove fireballs when collide with units and trees?
private constant boolean REMOVE = true
//Remove fireballs when collide with other destructables (not trees)?
private constant boolean REMOVE2 = true
//Destroy trees?
private constant boolean TREE = true
//Damage and attack type
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
private constant real INTERVAL = 0.031250
endglobals
//Max distance traveled by fireballs
private constant function GetDistance takes integer level returns real
return 800.00 + 100.00 * level
endfunction
//Damage per fireball
private constant function GetDamage takes integer level returns real
return 5.00 + 5.00 * level
endfunction
//Which units should/shouldn't be damaged?
private function DamageFilter takes unit target, player owner returns boolean
return (not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE)) and (not IsUnitType(target, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(target, UNIT_TYPE_FLYING)) and (UnitAlive(target)) and (IsUnitEnemy(target, owner))
endfunction
/**************************************************************************************
* *
* CONFIGURATION END *
* *
**************************************************************************************/
private struct BoF
unit caster
player owner
integer cast
integer fireCD
real castTime
real distance
real targetX
real targetY
real channelTime
real damage
timer t
method destroy takes nothing returns nothing
call ReleaseTimer(t)
call SetUnitTimeScale(caster, 1)
set t = null
set caster = null
set owner = null
call deallocate()
endmethod
static method onLoop takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local real casterX
local real casterY
local real createX
local real createY
local real angle
local Missile m
//Cast time
if castTime > 0 then
set castTime = castTime - INTERVAL
else
//No reason to set caster's animation sped multiple times
if cast == 1 then
call SetUnitTimeScale(caster, 0)
set cast = 0
endif
//Cooldown between creating new fireballs
if FIRE_CD == fireCD then
set casterX = GetUnitX(caster)
set casterY = GetUnitY(caster)
set angle = Atan2(targetY - casterY, targetX - casterX) + (GetRandomReal(-MIN_ANGLE, MAX_ANGLE) * bj_DEGTORAD)
set createX = casterX + DUMMY_CREATE_DIST * Cos(angle)
set createY = casterY + DUMMY_CREATE_DIST * Sin(angle)
//Spawn effect
call CreateDelayedEffectZ(SPAWN_EFFECT, createX, createY, DUMMY_HEIGHT, 0, 0)
//Fireball create and launch it
set m = Missile.create(createX, createY, DUMMY_HEIGHT, angle, distance, DUMMY_HEIGHT)
set m.source = caster
set m.owner = owner
set m.speed = DUMMY_SPEED
set m.damage = damage
set m.collision = DUMMY_COLISION
set m.scale = DUMMY_SCALE * 0.01
set m.model = DUMMY_MODEL
call thistype.launch(m)
//Reseting fireballs create cooldown
set fireCD = 0
endif
set fireCD = fireCD + 1
set channelTime = channelTime - INTERVAL
endif
if channelTime <= 0 or not IsUnitChanneling(caster) then
call destroy()
endif
endmethod
static method onCollide takes Missile missile, unit hit returns boolean
if DamageFilter(hit, missile.owner) then
call UnitDamageTarget(missile.source, hit, missile.damage, false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
call DestroyEffect(AddSpecialEffectTarget(DAMAGE_EFFECT, hit, DAMAGE_EFFECT_ATTACH))
endif
return REMOVE
endmethod
static method onRemove takes Missile missile returns boolean
call DestroyEffect(AddSpecialEffectTarget(REMOVE_EFFECT, missile.dummy, "origin"))
return true
endmethod
static method onDestructable takes Missile missile, destructable hit returns boolean
static if LIBRARY_IsDestructableTree and TREE then
call KillTree(hit)
endif
return REMOVE2
endmethod
implement MissileStruct
static method onCast takes nothing returns boolean
local BoF data = BoF.create()
local integer level
set data.t = NewTimerEx(data)
set data.caster = GetTriggerUnit()
set data.owner = GetTriggerPlayer()
set level = GetUnitAbilityLevel(data.caster, SPELL_ID)
set data.targetX = GetSpellTargetX()
set data.targetY = GetSpellTargetY()
set data.channelTime = CHANNEL_TIME
set data.castTime = CAST_TIME
set data.distance = GetDistance(level)
set data.damage = GetDamage(level)
set data.cast = 1
set data.fireCD = FIRE_CD
call SetUnitTimeScale(data.caster, CASTER_ANIMATION_SPEED * 0.01)
call TimerStart(data.t, INTERVAL, true, function BoF.onLoop)
return false
endmethod
static if not LIBRARY_SpellEffectEvent then
private static method condition takes nothing returns boolean
return (GetSpellAbilityId() == SPELL_ID) and thistype.onCast()
endmethod
endif
private static method onInit takes nothing returns nothing
static if LIBRARY_SpellEffectEvent then
call RegisterSpellEffectEvent(SPELL_ID, function thistype.onCast)
else
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.condition))
set t = null
endif
//Preloading effects to prevent first use lag
call Preload(DUMMY_MODEL)
call Preload(SPAWN_EFFECT)
call Preload(REMOVE_EFFECT)
call Preload(DAMAGE_EFFECT)
endmethod
endstruct
endscope[/code] | Chen takes deep breath and release fireballs upon target area.
Level 1 - Each Fireball deals 10 Damage.
Level 2 - Each Fireball deals 15 Damage.
Level 3 - Each Fireball deals 20 Damage.
Cast time: 1 second
Channel time: 5 seconds |