Moderator
M
Moderator
21:19, 11th Aug 2014
BPower:
The code looks good to me. Approved and recommended.
BPower:
The code looks good to me. Approved and recommended.
// **************************************************************************** //
// //
// Bone Blade //
// v1.6 //
// by: Dalvengyr //
// //
// Description //
// Launches a bone blade at targeted enemy unit. The bone blade will //
// attack the target several times. Each successful landed attack deals //
// pure damage. //
// //
// Requirements //
// - //
// //
// How to import //
// 1. Import all models and icons at Import Manager to your map //
// 2. Copy both dummy unit and spell to your map //
// 3. Copy this folder to your map //
// 4. Delete the variable creator trigger //
// //
// Credits //
// 1. BTNBonespear by Peekay //
// 2. BoneSpear.mdx by Peekay //
// 3. dummy.mdx by Vexorian //
// //
// Link //
// hiveworkshop.com/forums/spells-569/bone-blade-v1-0-a-255874/ //
// //
// **************************************************************************** //
// **************************************************************************** //
// //
// CONFIGURATION //
// //
// 1. Dummy unit's raw code at Object Editor //
constant function BB__DummyID takes nothing returns integer
return 'h000'
endfunction
// 2. Main spell raw code at Object Editor //
constant function BB__SpellID takes nothing returns integer
return 'A000'
endfunction
// 3. Accuracy of the spell. Just leave it //
constant function BB__Accuracy takes nothing returns real
return 0.0312500
endfunction
// 4. File path of the missile //
constant function BB__MissileSfx takes nothing returns string
return "war3mapImported\\PeeKay's BoneSpear.mdx"
endfunction
// 5. Attached sfx upon hit //
constant function BB__HitSfx takes nothing returns string
return "Abilities\\Weapons\\HydraliskImpact\\HydraliskImpact.mdl"
endfunction
// 6. Attachment point for hit sfx //
constant function BB__HitSfxPt takes nothing returns string
return "origin"
endfunction
// 7. Normal height Z for missiles //
constant function BB__MissileZ takes nothing returns real
return 40.0
endfunction
// 8. Higher toleration makes the missile become less precise //
// Toleration is additional angle to tolerate the missiles when they are aiming //
// for their target. So they can start dashing earlier even before they are //
// successfully facing at the target //
constant function BB__Toleration takes nothing returns real
return 0.0
endfunction
// 9. Hit radius of each missile. Maximum radius for missiles to hit/attack //
// their targets //
constant function BB__HitRadius takes nothing returns real
return 100.0
endfunction
// 10. Turn rate of missiles when they are dashing at target (at high speed) //
constant function BB__MissileTurnRateMin takes integer level returns real
return 1.0
endfunction
// 11. Turn rate of missiles when they are turning around (at low speed) //
// Logically, this one should have higher value than the other one (minimum) //
constant function BB__MissileTurnRateMax takes integer level returns real
return 4.0
endfunction
// 12. Speed of missiles when they are turning (aiming) for the target //
constant function BB__MissileSpeedMin takes integer level returns real
return 10.0
endfunction
// 13. Max speed of missiles when they are dashing at their targets //
constant function BB__MissileSpeedMax takes integer level returns real
return 50.0
endfunction
// 14. Acceleration rate after missiles are turning (aiming) //
constant function BB__MissileAcceleration takes integer level returns real
return 2.5
endfunction
// 15. Deacceleration (braking) rate after missiles hit/miss their target //
constant function BB__MissileDeacceleration takes integer level returns real
return 1.5
endfunction
// 16. Distance extension when missile starts to brake //
constant function BB__MissileBrakePoint takes integer level returns real
return 200.0
endfunction
// 17. Dealt damage on hit //
constant function BB__DealtDamage takes integer level returns real
return 75.0
endfunction
// 18. Lifespan duration for each missile //
constant function BB__Duration takes integer level returns real
return 18.0
endfunction
// 19. Maximum number of attacks before missiles are expired //
constant function BB__AttackCount takes integer level returns integer
return 1 + level
endfunction
// 20. Damage type of dealt damage //
constant function BB__DamageType takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
// 21. Attack type of dealt damage //
constant function BB__AttackType takes nothing returns attacktype
return ATTACK_TYPE_CHAOS
endfunction
// 22. Weapon type of dealt damage //
constant function BB__WeaponType takes nothing returns weapontype
return WEAPON_TYPE_WHOKNOWS
endfunction
// 23. Decay time for missiles when death //
constant function BB__DecayTime takes nothing returns real
return 5.0
endfunction
// 24. Additional effect attached to the target on hit //
function BB__AdditionalEffect takes unit target returns nothing
// Put here //
endfunction
// //
// END OF CONFIGURATION //
// //
// **************************************************************************** //
// Furthermore, edit them by your own risk!
// Function to get distance between given coordinates
function BB__GetDistance takes real x, real y, real xt, real yt returns real
return SquareRoot((xt - x) * (xt - x) + (yt - y) * (yt - y))
endfunction
// Function to return facing angle between coordinates (in radian)
function BB__GetAngle takes real x, real y, real xt, real yt returns real
return Atan2(yt - y, xt - x)
endfunction
// Function to check whether a unit is alive or not
function IsUnitAlive takes unit id returns boolean
return not IsUnitType(id, UNIT_TYPE_DEAD) and GetUnitTypeId(id) != 0
endfunction
function BB__Deindex takes integer i returns nothing
set udg_BB__Caster[i] = udg_BB__Caster[udg_BB__Total]
set udg_BB__Player[i] = udg_BB__Player[udg_BB__Total]
set udg_BB__Target[i] = udg_BB__Target[udg_BB__Total]
set udg_BB__Angle[i] = udg_BB__Angle[udg_BB__Total]
set udg_BB__Missile[i] = udg_BB__Missile[udg_BB__Total]
set udg_BB__Sfx[i] = udg_BB__Sfx[udg_BB__Total]
set udg_BB__Dx[i] = udg_BB__Dx[udg_BB__Total]
set udg_BB__Dc[i] = udg_BB__Dc[udg_BB__Total]
set udg_BB__State[i] = udg_BB__State[udg_BB__Total]
set udg_BB__SpeedMin[i] = udg_BB__SpeedMin[udg_BB__Total]
set udg_BB__SpeedMax[i] = udg_BB__SpeedMax[udg_BB__Total]
set udg_BB__Acceleration[i] = udg_BB__Acceleration[udg_BB__Total]
set udg_BB__Deacceleration[i] = udg_BB__Deacceleration[udg_BB__Total]
set udg_BB__BrakePoint[i] = udg_BB__BrakePoint[udg_BB__Total]
set udg_BB__TurnRateMax[i] = udg_BB__TurnRateMax[udg_BB__Total]
set udg_BB__TurnRateMin[i] = udg_BB__TurnRateMin[udg_BB__Total]
set udg_BB__Speed[i] = udg_BB__Speed[udg_BB__Total]
set udg_BB__Damage[i] = udg_BB__Damage[udg_BB__Total]
set udg_BB__Count[i] = udg_BB__Count[udg_BB__Total]
set udg_BB__Duration[i] = udg_BB__Duration[udg_BB__Total]
endfunction
function BB__onPeriodic takes nothing returns nothing
local integer i = 1
local real a
local real x
local real y
local real x2
local real y2
local unit f
loop
exitwhen i > udg_BB__Total
set x = GetUnitX(udg_BB__Missile[i])
set y = GetUnitY(udg_BB__Missile[i])
set x2 = GetUnitX(udg_BB__Target[i])
set y2 = GetUnitY(udg_BB__Target[i])
set a = BB__GetAngle(x, y, x2, y2)
set udg_BB__Duration[i] = udg_BB__Duration[i] - BB__Accuracy()
if udg_BB__State[i] then
if udg_BB__Count[i] > 0 then
// Detect the target as long as missile is still in dashing state
call GroupEnumUnitsInRange(udg_BB__Group, x, y, BB__HitRadius(), null)
loop
set f = FirstOfGroup(udg_BB__Group)
exitwhen f == null
if f == udg_BB__Target[i] and IsUnitAlive(udg_BB__Target[i]) then
set udg_BB__Count[i] = udg_BB__Count[i] - 1
call UnitDamageTarget(udg_BB__Caster[i], udg_BB__Target[i], udg_BB__Damage[i], false, false, BB__AttackType(), BB__DamageType(), BB__WeaponType())
call DestroyEffect(AddSpecialEffectTarget(BB__HitSfx(), udg_BB__Target[i], BB__HitSfxPt()))
call BB__AdditionalEffect(udg_BB__Target[i])
if udg_BB__Count[i] > 0 then
set udg_BB__State[i] = false
endif
endif
call GroupRemoveUnit(udg_BB__Group, f)
endloop
else
set udg_BB__Duration[i] = 0.0
endif
if udg_BB__Dc[i] < udg_BB__Dx[i] then
set udg_BB__Speed[i] = udg_BB__Speed[i] + udg_BB__Acceleration[i]
set udg_BB__Dc[i] = udg_BB__Dc[i] + udg_BB__Speed[i]
if udg_BB__Speed[i] > udg_BB__SpeedMax[i] then
set udg_BB__Speed[i] = udg_BB__SpeedMax[i]
endif
// Adjust missile's facing
if udg_BB__TurnRateMin[i] > 0 and Cos(udg_BB__Angle[i]-a) < Cos(udg_BB__TurnRateMin[i]) then
if Sin(a-udg_BB__Angle[i]) >= 0 then
set udg_BB__Angle[i] = udg_BB__Angle[i] + udg_BB__TurnRateMin[i]
else
set udg_BB__Angle[i] = udg_BB__Angle[i] - udg_BB__TurnRateMin[i]
endif
else
set udg_BB__Angle[i] = a
endif
else
set udg_BB__State[i] = false
endif
else
if udg_BB__Speed[i] > udg_BB__SpeedMin[i] then
set udg_BB__Speed[i] = udg_BB__Speed[i] - udg_BB__Deacceleration[i]
if udg_BB__Speed[i] < udg_BB__SpeedMin[i] then
set udg_BB__Speed[i] = udg_BB__SpeedMin[i]
endif
else
if udg_BB__TurnRateMax[i] > 0 and Cos(udg_BB__Angle[i]-a) < Cos(udg_BB__TurnRateMax[i]) then
if Sin(a-udg_BB__Angle[i]) >= 0 then
set udg_BB__Angle[i] = udg_BB__Angle[i] + udg_BB__TurnRateMax[i]
else
set udg_BB__Angle[i] = udg_BB__Angle[i] - udg_BB__TurnRateMax[i]
endif
else
set udg_BB__Angle[i] = a
set udg_BB__Dc[i] = 0.0
set udg_BB__Dx[i] = BB__GetDistance(x, y, x2, y2) + udg_BB__BrakePoint[i]
set udg_BB__State[i] = true
endif
endif
endif
set x = x + udg_BB__Speed[i] * Cos(udg_BB__Angle[i])
set y = y + udg_BB__Speed[i] * Sin(udg_BB__Angle[i])
call SetUnitFacing(udg_BB__Missile[i], udg_BB__Angle[i] * bj_RADTODEG)
if x < udg_BB__BoundMaxX and x > udg_BB__BoundMinX and y < udg_BB__BoundMaxY and y > udg_BB__BoundMinY then
call SetUnitX(udg_BB__Missile[i], x)
call SetUnitY(udg_BB__Missile[i], y)
else
// Kill the missile if not in map boudaries
set udg_BB__Duration[i] = 0.0
endif
if udg_BB__Duration[i] <= 0.0 then
call DestroyEffect(udg_BB__Sfx[i])
call UnitApplyTimedLife(udg_BB__Missile[i], 'BTLF', BB__DecayTime())
if i != udg_BB__Total then
call BB__Deindex(i)
endif
set udg_BB__Total = udg_BB__Total - 1
if udg_BB__Total == 0 then
call PauseTimer(udg_BB__Timer)
else
set i = i - 1
endif
endif
set i = i + 1
endloop
endfunction
function BB__onCast takes nothing returns boolean
local real x
local real y
local integer l
if GetSpellAbilityId() == BB__SpellID() then
set udg_BB__Total = udg_BB__Total + 1
set udg_BB__Caster[udg_BB__Total] = GetTriggerUnit()
set udg_BB__Player[udg_BB__Total] = GetTriggerPlayer()
set x = GetUnitX(udg_BB__Caster[udg_BB__Total])
set y = GetUnitY(udg_BB__Caster[udg_BB__Total])
set l = GetUnitAbilityLevel(udg_BB__Caster[udg_BB__Total], BB__SpellID())
set udg_BB__Target[udg_BB__Total] = GetSpellTargetUnit()
set udg_BB__Angle[udg_BB__Total] = GetUnitFacing(udg_BB__Caster[udg_BB__Total]) * bj_DEGTORAD
set udg_BB__Missile[udg_BB__Total] = CreateUnit(udg_BB__Player[udg_BB__Total], BB__DummyID(), x, y, udg_BB__Angle[udg_BB__Total] * bj_RADTODEG)
set udg_BB__Sfx[udg_BB__Total] = AddSpecialEffectTarget(BB__MissileSfx(), udg_BB__Missile[udg_BB__Total], "origin")
set udg_BB__Dx[udg_BB__Total] = 0.0
set udg_BB__Dc[udg_BB__Total] = 0.0
set udg_BB__State[udg_BB__Total] = false
set udg_BB__SpeedMin[udg_BB__Total] = BB__MissileSpeedMin(l)
set udg_BB__SpeedMax[udg_BB__Total] = BB__MissileSpeedMax(l)
set udg_BB__Acceleration[udg_BB__Total] = BB__MissileAcceleration(l)
set udg_BB__Deacceleration[udg_BB__Total] = BB__MissileDeacceleration(l)
set udg_BB__BrakePoint[udg_BB__Total] = BB__MissileBrakePoint(l)
set udg_BB__TurnRateMax[udg_BB__Total] = BB__MissileTurnRateMax(l) * bj_DEGTORAD
set udg_BB__TurnRateMin[udg_BB__Total] = BB__MissileTurnRateMin(l) * bj_DEGTORAD
set udg_BB__Speed[udg_BB__Total] = udg_BB__SpeedMin[udg_BB__Total]
set udg_BB__Damage[udg_BB__Total] = BB__DealtDamage(l)
set udg_BB__Count[udg_BB__Total] = BB__AttackCount(l)
set udg_BB__Duration[udg_BB__Total] = BB__Duration(l)
if UnitAddAbility(udg_BB__Missile[udg_BB__Total], 'Amrf') and UnitRemoveAbility(udg_BB__Missile[udg_BB__Total], 'Amrf') then
endif
call SetUnitFlyHeight(udg_BB__Missile[udg_BB__Total], BB__MissileZ(), 0.0)
if udg_BB__Total == 1 then
call TimerStart(udg_BB__Timer, BB__Accuracy(), true, function BB__onPeriodic)
endif
endif
return false
endfunction
function InitTrig_BoneBlade takes nothing returns nothing
set gg_trg_BoneBlade = CreateTrigger()
set udg_BB__Timer = CreateTimer()
set udg_BB__Group = CreateGroup()
set udg_BB__TAU = 2.0 * bj_PI
// Set the map bound for later use
set udg_BB__BoundMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
set udg_BB__BoundMinX = GetRectMinX(bj_mapInitialPlayableArea)
set udg_BB__BoundMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
set udg_BB__BoundMinY = GetRectMinY(bj_mapInitialPlayableArea)
call TriggerRegisterAnyUnitEventBJ(gg_trg_BoneBlade, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_BoneBlade, Condition(function BB__onCast))
endfunction