Footmen Cannon
Jass: Yes.
MUI: Yes.
Laggless: Yes.
Leakless: Yes, I think so.
Requires: NewGen Editor, TT Credits to Cohadar, HSAS Credits to Pandamine
Description:
The Footman lord summons a random amount of Footmans around him and fires them at a target with some kind of mystical psychic power.
Lvl 1: Deals 10 damage per unit and summons 3-4 Footmans.
Lvl 2: Deals 20 damage per unit and summons 6-8 Footmans.
Lvl 3: Deals 30 damage per unit and summons 9-12 Footmans.
Code:
Screenshot: (It looks better ingame!
)
Changelog:
Footman Cannon
Jass: Yes.
MUI: Yes.
Laggless: Yes.
Leakless: Yes, I think so.
Requires: NewGen Editor, TT Credits to Cohadar, HSAS Credits to Pandamine
Description:
The Footman lord summons a random amount of Footmans around him and fires them at a target with some kind of mystical psychic power.
Lvl 1: Deals 10 damage per unit and summons 3-4 Footmans.
Lvl 2: Deals 20 damage per unit and summons 6-8 Footmans.
Lvl 3: Deals 30 damage per unit and summons 9-12 Footmans.
Code:
JASS:
// ==================================================================================================================================================================
//
// Footman cannon created by: Gwypaas
//
// ==================================================================================================================================================================
// ==================================================================================================================================================================
// How to import:
//
// 1. Create a spell named what you want this spell to be named and add the ID to the constants further down.
// 2. Create the dummy units for this spell and add the ID at the constants further down
// 3. Import the librarys TT made by Cohadar and HSAS made by Pandamine to your map
// 4. Change the rest of the values at the spell constants further down so the spell acts the way you want it to do.
//
// Not: if you really want to you can change the HSAS calls to ABC calls or another library that uses handle attaching.
//
// ==================================================================================================================================================================
scope UnitCannon // Uses HSAS and TT
globals
// The ID of the main ability.
private constant integer ABILID = 'A000'
// The ID of the dummy unit used in this spell.
private constant integer DUMMYID = 'h000'
// The ID of the eye candy dummy used when summoning
private constant integer EYECANDYDUMMY = 'h001'
// How fast they travels.
private constant real SPEED = 40
// How long time it takes to summon all units.
private constant real TOTALTIMESUMMONING = 1.25
// The radius of the circle the units are summoned in.
private constant real CIRCLERADIUS = 400
// The radius of the circle it damages in.
private constant real DAMAGERADIUS = 200
// The ID of the ability called Crow Form, used in this spell to cause the units flying.
private constant integer CROWFORMID = 'Amrf'
// The max height the units are able to be on.
private constant real MAXHEIGHT = 2 // This value is used like this: Total Distance / This.
// The damage is calculated by this formula lvl*YourValue so change YourValue here to the value you want.
private constant real DAMAGE = 10
// The unit amount is calculated like this: A random integer between lvl*MINAMOUNT and lvl*MAXAMOUNT
private constant integer MINAMOUNT = 3
private constant integer MAXAMOUNT = 4
endglobals
// =========== DO NOT EDIT ANYTHING AFTER THIS LINE! ===========
// =========== DO NOT EDIT ANYTHING AFTER THIS LINE! ===========
// =========== DO NOT EDIT ANYTHING AFTER THIS LINE! ===========
private function H2I takes handle h returns integer
return h
return 0
endfunction
//! runtextmacro HSAS_Static("Cannon")
//! runtextmacro HSAS_Static("Fire")
private struct Data
unit caster
unit array dummies[11]
integer dummyAmount
integer currentdummies = 0
integer unitsFired = 0
integer level
real targetX
real targetY
endstruct
private struct SlideData
unit damager // The hero that casts the spell
unit whichUnit
real totalDist
real distDone = 0
real startX
real startY
real targetX
real targetY
real cX
real cY
real angle
real speed
real maxHeight
endstruct
private function RandomPointCircle takes real x, real y, real d returns location // Credits to Vexorian!
local real cx = GetRandomReal(-d,d)
local real ty = SquareRoot(d*d-cx*cx)
return Location(x+cx, y+ GetRandomReal(-ty,ty) )
endfunction
private function ParabolicMovement takes real h, real d, real x returns real // h Height, d total distance, x dist to add.
// thanks to moyack for this function!
return (-4*h/(3*d*d))*x*x + (4*h/(3*d))*x
endfunction
private function DamageAmount takes integer lvl returns real
return lvl*DAMAGE
endfunction
private function UnitAmount takes integer lvl returns integer
return GetRandomInt(lvl*MINAMOUNT, lvl*MAXAMOUNT)
endfunction
private function DamageFilter takes unit caster, unit target returns boolean
return (IsUnitEnemy(target, GetOwningPlayer(caster))) and (IsUnitType(target, UNIT_TYPE_GROUND)) and (GetUnitState(target, UNIT_STATE_LIFE) > 0.405)
endfunction
private function SlideCallback takes nothing returns boolean
local SlideData SD = TT_GetData()
local group g = CreateGroup()
local unit u
local real z = ParabolicMovement(SD.maxHeight, SD.totalDist, SD.distDone)
if SD.distDone >= SD.totalDist then
call GroupEnumUnitsInRange(g, GetUnitX(SD.whichUnit), GetUnitY(SD.whichUnit), DAMAGERADIUS, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if DamageFilter(SD.damager, u) == true then
call UnitDamageTarget(SD.damager, u, DamageAmount(GetUnitAbilityLevel(SD.damager, ABILID)) , FALSE, FALSE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
endif
call GroupRemoveUnit(g, u)
set u = null
endloop
set SD.damager = null
call SetUnitExploded(SD.whichUnit, true)
call KillUnit(SD.whichUnit)
set SD.whichUnit = null
call SD.destroy()
return true
else
set SD.cX = SD.cX + SD.speed * Cos(SD.angle)
set SD.cY = SD.cY + SD.speed * Sin(SD.angle)
call SetUnitX(SD.whichUnit, SD.cX)
call SetUnitY(SD.whichUnit, SD.cY)
call SetUnitFlyHeight(SD.whichUnit, z, 0)
set SD.distDone = SD.distDone + SD.speed
endif
set u = null
call DestroyGroup(g)
set g = null
return false
endfunction
private function Slide takes unit whichUnit, real startX, real startY, real targetX, real targetY, real speed, unit damager returns nothing
local SlideData SD = SlideData.create()
set SD.damager = damager
set SD.startX = startX
set SD.startY = startY
set SD.targetX = targetX
set SD.targetY = targetY
set SD.cX = startX
set SD.cY = startY
set SD.whichUnit = whichUnit
set SD.angle = Atan2((SD.targetY-SD.startY),(SD.targetX-SD.startX))
set SD.speed = speed
set SD.totalDist = SquareRoot(Pow((SD.targetX-SD.startX), 2) + Pow((SD.targetY-SD.startY), 2))
set SD.maxHeight = SD.totalDist/MAXHEIGHT
call TT_Start(function SlideCallback, SD)
endfunction
private function FireUnitsCallback takes nothing returns nothing
local timer t2 = GetExpiredTimer()
local Data data = GetAttachedStructFire(t2)
local integer i = 0
if data.unitsFired >= data.dummyAmount then
call PauseTimer(t2)
call DestroyTimer(t2)
set data.caster = null
loop
exitwhen i == 11
set data.dummies<i> = null
set i = i+1
endloop
call data.destroy()
else
call Slide(data.dummies[data.unitsFired], GetUnitX(data.dummies[data.unitsFired]), GetUnitY(data.dummies[data.unitsFired]), data.targetX, data.targetY, SPEED, data.caster)
set data.unitsFired = data.unitsFired + 1
endif
set t2 = null
endfunction
private function CreateUnitAndRemoveAfter takes integer ID, real X, real Y, real time, boolean kill, player whichPlayer returns nothing
local unit u = CreateUnit(whichPlayer, ID, X, Y, GetRandomReal(0, 360))
if kill == true then
call TriggerSleepAction(time)
call KillUnit(u)
else
call TriggerSleepAction(time)
call RemoveUnit(u)
endif
set u = null
endfunction
private function CreateUnitCallback takes nothing returns nothing
local timer t = GetExpiredTimer()
local Data data = GetAttachedStructCannon(t)
local integer i = 0
local real casterX = GetUnitX(data.caster)
local real casterY = GetUnitY(data.caster)
local location l = Location(0,0)
if data.currentdummies == data.dummyAmount then
call PauseTimer(t)
call DestroyTimer(t)
else
set l = RandomPointCircle(casterX, casterY, CIRCLERADIUS)
set data.dummies[data.currentdummies] = CreateUnit(GetOwningPlayer(data.caster), DUMMYID, GetLocationX(l), GetLocationY(l), GetRandomReal(0, 360))
call UnitApplyTimedLife( data.dummies[data.currentdummies], 'BTLF', TOTALTIMESUMMONING*5 )
call UnitAddAbility(data.dummies[data.currentdummies], CROWFORMID)
call UnitRemoveAbility(data.dummies[data.currentdummies], CROWFORMID)
call CreateUnitAndRemoveAfter.execute(EYECANDYDUMMY, GetLocationX(l), GetLocationY(l), TOTALTIMESUMMONING*2, false, GetOwningPlayer(data.caster))
set data.currentdummies = data.currentdummies+1
endif
set t = null
call RemoveLocation(l)
set l = null
endfunction
private function Actions takes nothing returns nothing
local Data data = Data.create()
local integer i = 0
local real waitBetween
local timer t = CreateTimer()
local timer t2 = CreateTimer()
local location targ = GetSpellTargetLoc()
set data.caster = GetSpellAbilityUnit()
set data.dummyAmount = UnitAmount(GetUnitAbilityLevel(data.caster, ABILID))
set waitBetween = TOTALTIMESUMMONING/data.dummyAmount
set data.level = GetUnitAbilityLevel(data.caster, ABILID)
set data.targetX = GetLocationX(targ)
set data.targetY = GetLocationY(targ)
call AttachStructCannon(t, data)
call TimerStart(t, waitBetween, true, function CreateUnitCallback)
call TriggerSleepAction(TOTALTIMESUMMONING+TOTALTIMESUMMONING/3)
call AttachStructFire(t2, data)
call TimerStart(t2, waitBetween, true, function FireUnitsCallback)
set t = null
set t2 = null
call RemoveLocation(targ)
set targ = null
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABILID
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
local trigger Trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( Trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition(Trig, Condition(function Conditions))
call TriggerAddAction( Trig, function Actions )
set Trig = null
endfunction
endscope</i>
Screenshot: (It looks better ingame!
Added a special effect when summoning, speeded up a bit.
Attachments
-
195.6 KB Views: 2,203
-
38.9 KB Views: 409