- Joined
- Apr 24, 2012
- Messages
- 5,113
Im new in vJASS but i have a problem with my script:
[jass=] //TESH.alwaysfold=0
scope LightningGrapple initializer OnInit
// requires TimerUtils, DummyCaster, GroupUtils, Knockback3D
// -----------------------------------------------------------------------------------------------------
// CALIBRATION SECTION
// -----------------------------------------------------------------------------------------------------
globals
private constant integer GrappleAbilityId = 'A000' // Rawcode for Lightning Grapple
private constant integer BuffAbilityId = 'A001' // Rawcode for AS/MS bonus ability
private constant real Timer = 0.025 // Period of timer for movement
private constant real AllyPickUpAoE= 128. // Area of effect allies within the caster can be dragged
// Effects
private constant string AoEEx = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdx" // Created at target point
private constant string TargetEx = "Abilities\\Weapons\\Bolt\\BoltImpact.mdx" // Created on damaged units.
private constant string TargetAttachment = "origin" // Attachment point of TARGET_EFFECT.
// Damage constants
private constant attacktype AttackType = ATTACK_TYPE_NORMAL
private constant damagetype DamageType = DAMAGE_TYPE_MAGIC
private constant weapontype WeaponType = null
private constant string LightningCode = "FORK"
private constant real LightningHeight = 45.
// Lightning ID's
// (thanks to PurgeandFire111):
//
// LIGHTNING_CHAIN_LIGHTNING_PRIMARY = "CLPB"
// LIGHTNING_CHAIN_LIGHTNING_SECONDARY = "CLSB"
// LIGHTNING_DRAIN = "DRAB"
// LIGHTNING_DRAIN_LIFE = "DRAL"
// LIGHTNING_DRAIN_MANA = "DRAM"
// LIGHTNING_FINGER_OF_DEATH = "AFOD"
// LIGHTNING_FORKED_LIGHTNING = "FORK"
// LIGHTNING_HEALING_WAVE_PRIMARY = "HWPB"
// LIGHTNING_HEALING_WAVE_SECONDARY = "HWSB"
// LIGHTNING_LIGHTNING_ATTACK = "CHIM"
// LIGHTNING_MAGIC_LEASH = "LEAS"
// LIGHTNING_MANA_BURN = "MBUR"
// LIGHTNING_MANA_FLARE = "MFPB"
// LIGHTNING_SPIRIT_LINK = "SPLK"
endglobals
private keyword grapple // ignore this
// What units are affected at the end of the charge?
// By default it is ALL units, in adherance to
// the request description:
// QUOTE:
// "After the Caster reaches the point,all units within 300 AoE will be knockbacked
// for 400 distance at 2 seconds and will take 300/400/500 damage."
//
private function IsTargetValid takes unit whichUnit returns boolean
return IsUnitEnemy(whichUnit, grapple.TempData.owningPlayer)
endfunction
// The maximum number of allies that can be affected in the Lightning Grapple
private constant function MaxAllies takes integer level returns integer
return 1 + level * 1
endfunction
// The duration of the knockback for units at the end of charge
private constant function KB_Duration takes integer level returns real
return 2.
endfunction
// The distance of the knockback for units at the end of charge
private constant function KB_Distance takes integer level returns real
return 400.
endfunction
// The area of effect to affect units at the end of charge
private constant function DamageAoE takes integer level returns real
return 300.
endfunction
// The damage dealt to units at the end of charge
private constant function DamageDealt takes integer level returns real
return level * 100. + 200.
endfunction
// The speed at which the caster grapples in Warcraft III units
private constant function GrappleSpeed takes integer level returns real
return 1250.
endfunction
//
// END OF CALIBRATION SECTION
// -----------------------------------------------------------------------------------------------------
private struct grapple
unit caster // caster of lightning grapple
player owningPlayer // owner of caster for lightning grapple
integer level // level at the time of cast
real damage // damage dealt to units at end of charge
real kbDist // knockback distance
real kbDur // knockback duration
real distance // distance from cast point to target point
real speed // distance moved per timer period
real cos
real sin
// Lightning variables
lightning lightning
// Lightning coordinates
real x1
real y1
real z1
real x2
real y2
real z2
// Allied picking up
integer unitCount
integer maxUnits
group alliedHeroes
// Timer for motion
timer timer
// Static variables
static thistype TempData // Used for group actions
private static location TempLoc = Location(0., 0.) // Location used to get a unit's Z
private static boolexpr AllyHeroFilter // Filter() stored into boolexpr for efficiency
private static boolexpr EnemyUnitFilter // Filter() stored into boolexpr for efficiency
private static method enemyUnitFilter takes nothing returns boolean
local unit u = GetFilterUnit()
if IsTargetValid(u) then
call UnitDamageTarget(.TempData.caster, u, .TempData.damage, true, false, AttackType, DamageType, WeaponType)
call DestroyEffect(AddSpecialEffectTarget(TargetEx, u, TargetAttachment))
call Knockback3D_add(u,kbDist,Atan2(GetUnitY(u) - .TempData.y2, GetUnitX(u) - .TempData.x2),0)
endif
set u = null
return false
endmethod
private static method allyHeroFilter takes nothing returns boolean
local unit u = GetFilterUnit()
if .TempData.unitCount < .TempData.maxUnits and not IsUnitInGroup(u, .TempData.alliedHeroes) and u != .TempData.caster and IsUnitAlly(u, .TempData.owningPlayer) and IsUnitType(u, UNIT_TYPE_HERO) and not IsUnitType(u, UNIT_TYPE_DEAD) then
call GroupAddUnit(.TempData.alliedHeroes, u)
set .TempData.unitCount = .TempData.unitCount + 1
call DestroyEffect(AddSpecialEffectTarget(TargetEx, u, TargetAttachment))
endif
set u = null
return false
endmethod
private static method bloodlustAllies takes nothing returns nothing
call IssueTargetOrder(DUMMY, "bloodlust", GetEnumUnit())
endmethod
private static method moveAlliedHeroes takes nothing returns nothing
local unit u = GetEnumUnit()
call SetUnitX(u, GetUnitX(u) + .TempData.cos)
call SetUnitY(u, GetUnitY(u) + .TempData.sin)
set u = null
endmethod
private static method timerCallback takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local real castx = GetUnitX(.caster) + .cos
local real casty = GetUnitY(.caster) + .sin
local real castz
call SetUnitX(.caster, castx)
call SetUnitY(.caster, casty)
call MoveLocation(.TempLoc, castx, casty)
set castz = GetLocationZ(.TempLoc) + GetUnitFlyHeight(.caster) + LightningHeight
call MoveLightningEx(.lightning, false, castx, casty, castz, .x2, .y2, .z2)
call DestroyEffect(AddSpecialEffect(AoEEx, .x2, .y2))
set .TempData = this
if .unitCount < .maxUnits then
call GroupEnumUnitsInArea(ENUM_GROUP, castx, casty, AllyPickUpAoE, thistype.AllyHeroFilter)
endif
call ForGroup(.alliedHeroes, function thistype.moveAlliedHeroes)
set .distance = .distance - .speed
if .distance <= 0. then // end of charge actions
call DestroyLightning(.lightning)
// Add bloodlust to dummy unit
call UnitAddAbility(DUMMY, BuffAbilityId)
call SetUnitAbilityLevel(DUMMY, BuffAbilityId, .level)
call IssueTargetOrder(DUMMY, "bloodlust", .caster)
call ForGroup(.alliedHeroes, function thistype.bloodlustAllies)
call UnitRemoveAbility(DUMMY, BuffAbilityId)
// Damage and knockback enemy units
set .TempData = this
call GroupEnumUnitsInArea(ENUM_GROUP, .x2, .y2, DamageAoE(.level), thistype.EnemyUnitFilter)
// Cleanup
call ReleaseGroup(.alliedHeroes)
call ReleaseTimer(.timer)
call .deallocate()
endif
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local real castx
local real casty
local real castz
local real angle
// Unit variables
set .caster = GetTriggerUnit()
set .owningPlayer = GetTriggerPlayer()
set .level = GetUnitAbilityLevel(.caster, GrappleAbilityId)
// Caster coordinates
set castx = GetUnitX(.caster)
set casty = GetUnitY(.caster)
call MoveLocation(.TempLoc, castx, casty)
set castz = GetLocationZ(.TempLoc) + GetUnitFlyHeight(.caster) + LightningHeight
// Target point coordinates
set .x2 = GetSpellTargetX()
set .y2 = GetSpellTargetY()
call MoveLocation(.TempLoc, .x2, .y2)
set .z2 = GetLocationZ(.TempLoc) + LightningHeight
set .distance = SquareRoot((.x2 - castx) * (.x2 - castx) + (.y2 - casty) * (.y2 - casty))
// Movement variables
set angle = Atan2(.y2 - casty, .x2 - castx)
set .speed = GrappleSpeed(.level) * Timer
set .cos = .speed * Cos(angle)
set .sin = .speed * Sin(angle)
// Stats
set .damage = DamageDealt(.level)
set .kbDist = KB_Distance(.level)
set .kbDur = KB_Duration(.level)
// Look for allies to drag along
set .unitCount = 0
set .maxUnits = MaxAllies(.level)
set .alliedHeroes = NewGroup()
set .TempData = this
call GroupEnumUnitsInArea(ENUM_GROUP, castx, casty, AllyPickUpAoE, thistype.AllyHeroFilter)
// Lightning itself
set .lightning = AddLightningEx(LightningCode, false, castx, casty, castz, .x2, .y2, .z2)
// Timer
set .timer = NewTimerEx(this)
call TimerStart(.timer, Timer, true, function thistype.timerCallback)
return this
endmethod
private static method onInit takes nothing returns nothing
set thistype.AllyHeroFilter = Filter(function thistype.allyHeroFilter)
set thistype.EnemyUnitFilter = Filter(function thistype.enemyUnitFilter)
endmethod
endstruct
private function OnSpellEffect takes nothing returns boolean
if GetSpellAbilityId() == GrappleAbilityId then
call grapple.create()
endif
return false
endfunction
private function OnInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function OnSpellEffect))
endfunction
endscope
[/code]
the problem is that i have not declared a variable this.
it always view this line
[jass=]call Knockback3D_add(u,kbDist,Atan2(GetUnitY(u) - .TempData.y2, GetUnitX(u) - .TempData.x2),0)[/code]
Testmap:
[jass=] //TESH.alwaysfold=0
scope LightningGrapple initializer OnInit
// requires TimerUtils, DummyCaster, GroupUtils, Knockback3D
// -----------------------------------------------------------------------------------------------------
// CALIBRATION SECTION
// -----------------------------------------------------------------------------------------------------
globals
private constant integer GrappleAbilityId = 'A000' // Rawcode for Lightning Grapple
private constant integer BuffAbilityId = 'A001' // Rawcode for AS/MS bonus ability
private constant real Timer = 0.025 // Period of timer for movement
private constant real AllyPickUpAoE= 128. // Area of effect allies within the caster can be dragged
// Effects
private constant string AoEEx = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdx" // Created at target point
private constant string TargetEx = "Abilities\\Weapons\\Bolt\\BoltImpact.mdx" // Created on damaged units.
private constant string TargetAttachment = "origin" // Attachment point of TARGET_EFFECT.
// Damage constants
private constant attacktype AttackType = ATTACK_TYPE_NORMAL
private constant damagetype DamageType = DAMAGE_TYPE_MAGIC
private constant weapontype WeaponType = null
private constant string LightningCode = "FORK"
private constant real LightningHeight = 45.
// Lightning ID's
// (thanks to PurgeandFire111):
//
// LIGHTNING_CHAIN_LIGHTNING_PRIMARY = "CLPB"
// LIGHTNING_CHAIN_LIGHTNING_SECONDARY = "CLSB"
// LIGHTNING_DRAIN = "DRAB"
// LIGHTNING_DRAIN_LIFE = "DRAL"
// LIGHTNING_DRAIN_MANA = "DRAM"
// LIGHTNING_FINGER_OF_DEATH = "AFOD"
// LIGHTNING_FORKED_LIGHTNING = "FORK"
// LIGHTNING_HEALING_WAVE_PRIMARY = "HWPB"
// LIGHTNING_HEALING_WAVE_SECONDARY = "HWSB"
// LIGHTNING_LIGHTNING_ATTACK = "CHIM"
// LIGHTNING_MAGIC_LEASH = "LEAS"
// LIGHTNING_MANA_BURN = "MBUR"
// LIGHTNING_MANA_FLARE = "MFPB"
// LIGHTNING_SPIRIT_LINK = "SPLK"
endglobals
private keyword grapple // ignore this
// What units are affected at the end of the charge?
// By default it is ALL units, in adherance to
// the request description:
// QUOTE:
// "After the Caster reaches the point,all units within 300 AoE will be knockbacked
// for 400 distance at 2 seconds and will take 300/400/500 damage."
//
private function IsTargetValid takes unit whichUnit returns boolean
return IsUnitEnemy(whichUnit, grapple.TempData.owningPlayer)
endfunction
// The maximum number of allies that can be affected in the Lightning Grapple
private constant function MaxAllies takes integer level returns integer
return 1 + level * 1
endfunction
// The duration of the knockback for units at the end of charge
private constant function KB_Duration takes integer level returns real
return 2.
endfunction
// The distance of the knockback for units at the end of charge
private constant function KB_Distance takes integer level returns real
return 400.
endfunction
// The area of effect to affect units at the end of charge
private constant function DamageAoE takes integer level returns real
return 300.
endfunction
// The damage dealt to units at the end of charge
private constant function DamageDealt takes integer level returns real
return level * 100. + 200.
endfunction
// The speed at which the caster grapples in Warcraft III units
private constant function GrappleSpeed takes integer level returns real
return 1250.
endfunction
//
// END OF CALIBRATION SECTION
// -----------------------------------------------------------------------------------------------------
private struct grapple
unit caster // caster of lightning grapple
player owningPlayer // owner of caster for lightning grapple
integer level // level at the time of cast
real damage // damage dealt to units at end of charge
real kbDist // knockback distance
real kbDur // knockback duration
real distance // distance from cast point to target point
real speed // distance moved per timer period
real cos
real sin
// Lightning variables
lightning lightning
// Lightning coordinates
real x1
real y1
real z1
real x2
real y2
real z2
// Allied picking up
integer unitCount
integer maxUnits
group alliedHeroes
// Timer for motion
timer timer
// Static variables
static thistype TempData // Used for group actions
private static location TempLoc = Location(0., 0.) // Location used to get a unit's Z
private static boolexpr AllyHeroFilter // Filter() stored into boolexpr for efficiency
private static boolexpr EnemyUnitFilter // Filter() stored into boolexpr for efficiency
private static method enemyUnitFilter takes nothing returns boolean
local unit u = GetFilterUnit()
if IsTargetValid(u) then
call UnitDamageTarget(.TempData.caster, u, .TempData.damage, true, false, AttackType, DamageType, WeaponType)
call DestroyEffect(AddSpecialEffectTarget(TargetEx, u, TargetAttachment))
call Knockback3D_add(u,kbDist,Atan2(GetUnitY(u) - .TempData.y2, GetUnitX(u) - .TempData.x2),0)
endif
set u = null
return false
endmethod
private static method allyHeroFilter takes nothing returns boolean
local unit u = GetFilterUnit()
if .TempData.unitCount < .TempData.maxUnits and not IsUnitInGroup(u, .TempData.alliedHeroes) and u != .TempData.caster and IsUnitAlly(u, .TempData.owningPlayer) and IsUnitType(u, UNIT_TYPE_HERO) and not IsUnitType(u, UNIT_TYPE_DEAD) then
call GroupAddUnit(.TempData.alliedHeroes, u)
set .TempData.unitCount = .TempData.unitCount + 1
call DestroyEffect(AddSpecialEffectTarget(TargetEx, u, TargetAttachment))
endif
set u = null
return false
endmethod
private static method bloodlustAllies takes nothing returns nothing
call IssueTargetOrder(DUMMY, "bloodlust", GetEnumUnit())
endmethod
private static method moveAlliedHeroes takes nothing returns nothing
local unit u = GetEnumUnit()
call SetUnitX(u, GetUnitX(u) + .TempData.cos)
call SetUnitY(u, GetUnitY(u) + .TempData.sin)
set u = null
endmethod
private static method timerCallback takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local real castx = GetUnitX(.caster) + .cos
local real casty = GetUnitY(.caster) + .sin
local real castz
call SetUnitX(.caster, castx)
call SetUnitY(.caster, casty)
call MoveLocation(.TempLoc, castx, casty)
set castz = GetLocationZ(.TempLoc) + GetUnitFlyHeight(.caster) + LightningHeight
call MoveLightningEx(.lightning, false, castx, casty, castz, .x2, .y2, .z2)
call DestroyEffect(AddSpecialEffect(AoEEx, .x2, .y2))
set .TempData = this
if .unitCount < .maxUnits then
call GroupEnumUnitsInArea(ENUM_GROUP, castx, casty, AllyPickUpAoE, thistype.AllyHeroFilter)
endif
call ForGroup(.alliedHeroes, function thistype.moveAlliedHeroes)
set .distance = .distance - .speed
if .distance <= 0. then // end of charge actions
call DestroyLightning(.lightning)
// Add bloodlust to dummy unit
call UnitAddAbility(DUMMY, BuffAbilityId)
call SetUnitAbilityLevel(DUMMY, BuffAbilityId, .level)
call IssueTargetOrder(DUMMY, "bloodlust", .caster)
call ForGroup(.alliedHeroes, function thistype.bloodlustAllies)
call UnitRemoveAbility(DUMMY, BuffAbilityId)
// Damage and knockback enemy units
set .TempData = this
call GroupEnumUnitsInArea(ENUM_GROUP, .x2, .y2, DamageAoE(.level), thistype.EnemyUnitFilter)
// Cleanup
call ReleaseGroup(.alliedHeroes)
call ReleaseTimer(.timer)
call .deallocate()
endif
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local real castx
local real casty
local real castz
local real angle
// Unit variables
set .caster = GetTriggerUnit()
set .owningPlayer = GetTriggerPlayer()
set .level = GetUnitAbilityLevel(.caster, GrappleAbilityId)
// Caster coordinates
set castx = GetUnitX(.caster)
set casty = GetUnitY(.caster)
call MoveLocation(.TempLoc, castx, casty)
set castz = GetLocationZ(.TempLoc) + GetUnitFlyHeight(.caster) + LightningHeight
// Target point coordinates
set .x2 = GetSpellTargetX()
set .y2 = GetSpellTargetY()
call MoveLocation(.TempLoc, .x2, .y2)
set .z2 = GetLocationZ(.TempLoc) + LightningHeight
set .distance = SquareRoot((.x2 - castx) * (.x2 - castx) + (.y2 - casty) * (.y2 - casty))
// Movement variables
set angle = Atan2(.y2 - casty, .x2 - castx)
set .speed = GrappleSpeed(.level) * Timer
set .cos = .speed * Cos(angle)
set .sin = .speed * Sin(angle)
// Stats
set .damage = DamageDealt(.level)
set .kbDist = KB_Distance(.level)
set .kbDur = KB_Duration(.level)
// Look for allies to drag along
set .unitCount = 0
set .maxUnits = MaxAllies(.level)
set .alliedHeroes = NewGroup()
set .TempData = this
call GroupEnumUnitsInArea(ENUM_GROUP, castx, casty, AllyPickUpAoE, thistype.AllyHeroFilter)
// Lightning itself
set .lightning = AddLightningEx(LightningCode, false, castx, casty, castz, .x2, .y2, .z2)
// Timer
set .timer = NewTimerEx(this)
call TimerStart(.timer, Timer, true, function thistype.timerCallback)
return this
endmethod
private static method onInit takes nothing returns nothing
set thistype.AllyHeroFilter = Filter(function thistype.allyHeroFilter)
set thistype.EnemyUnitFilter = Filter(function thistype.enemyUnitFilter)
endmethod
endstruct
private function OnSpellEffect takes nothing returns boolean
if GetSpellAbilityId() == GrappleAbilityId then
call grapple.create()
endif
return false
endfunction
private function OnInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function OnSpellEffect))
endfunction
endscope
[/code]
the problem is that i have not declared a variable this.
it always view this line
[jass=]call Knockback3D_add(u,kbDist,Atan2(GetUnitY(u) - .TempData.y2, GetUnitX(u) - .TempData.x2),0)[/code]
Testmap: