moyack
Cool Member
- Reaction score
- 9
Runes
(vJASSified)
By moyack. 2009.
Thanks Kam for the screenshot
(vJASSified)
By moyack. 2009.
Thanks Kam for the screenshot
A long time ago, I did by request a spell for the project Tides of Darkness. Now I decided to vJASSify it and this is the result.
This spell resembles the one in WC2, used by the ogre magi units.
Requirements:
Spell Description:
Warcraft II Strategy: Units said:The exact nature of the Runes used by Ogre-Magi is unknown to the Humans, but their effect is obvious: anyone straying into the area warded by the Runes is struck by a fiery explosion capable of killing or injuring the hardiest unit. Each "Rune" consists of 5 distinct points, each of which will explode only once. The Runes are also indiscriminate-any unit, friend or foe, that runs over them will be affected. Only flying units are immune to the effects. Since the Runes "float" on top of water, they are pretty good against enemy ships, especially transports.
How to install:
- Open the test map.
- Copy the trigger and the ability used in this spell into you map. If you have a dummy unit on it, set the unit rawcode in the spell description and in the ability.
- Voila!! spell installed.
JASS:
//***************************************************************************************************************
//* *
//* Runes Spell (vJASSified). *
//* By Moyack. *
//* V.2.2. *
//* *
//***************************************************************************************************************
//*
library Runes initializer init
//***************************************************************************************************************
//* The constant data where you can modify the ability properties
//*
globals
private constant integer SpellID = 039;A000039; // Returns the spell ID. Spell based on Serpent Ward
private constant integer RuneID = 039;o000039; // Returns the dummy summoned unit ID.
private constant real dt = 0.2 // the rate which the runes will detect an unit
endglobals
private constant function Range takes integer lvl returns real
return 120. + 50. * (lvl - 1) // Returns the range where the runes will detect units
endfunction
private constant function Radius takes integer lvl returns real
return 2 * Range(lvl) // Returns the radius where the runes will be placed
endfunction
private constant function Amount takes integer lvl returns integer
return 4 + 1 * (lvl - 1) // Returns the number of runes in the at the perimeter
endfunction
private constant function Damage takes integer lvl returns real
return 350. + 50. * (lvl - 1) // Returns the damage dealt to units near to the runes
endfunction
private constant function Duration takes integer lvl returns real
return 40. + 5. * (lvl - 1) // Returns the runes timed life
endfunction
//***************************************************************************************************************
//* end constant data...
//*
globals
private group G = CreateGroup()
endglobals
private function GetFX takes integer id returns string
return GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, id)
endfunction
private struct rune
unit c
player p
effect f
real x
real y
real d = 0.
integer l
integer i
private static integer counter = 0
private static rune array runes
private static integer do = 0
private static integer id = 0
static unit dummy = null
private static method GetUnits takes nothing returns boolean
local unit u = GetFilterUnit()
if GetWidgetLife( u ) > 0.405 and IsUnitType(u, UNIT_TYPE_FLYING) == false then
call SetUnitOwner(rune.dummy, rune.runes[rune.id].p, false)
if GetWidgetLife(rune.runes[rune.id].c) > 0.405 then
call UnitDamageTarget(rune.runes[rune.id].c, u, Damage(rune.runes[rune.id].l), false, false, ATTACK_TYPE_SIEGE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_ROCK_HEAVY_BASH)
else
call UnitDamageTarget(rune.dummy, u, Damage(rune.runes[rune.id].l), false, false, ATTACK_TYPE_SIEGE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_ROCK_HEAVY_BASH)
endif
set rune.do = rune.do + 1
endif
set u = null
return false
endmethod
private method onDestroy takes nothing returns nothing
call DestroyEffect(.f)
if .d < Duration(.l) then
call DestroyEffect(AddSpecialEffect(GetFX(1), .x, .y))
call DestroyEffect(AddSpecialEffect(GetFX(2), .x, .y))
endif
set rune.counter = rune.counter - 1
set rune.runes[rune.counter].i = .i
set rune.runes[.i] = rune.runes[rune.counter]
endmethod
static method Start takes unit c, real x, real y returns nothing
local rune R = rune.allocate()
if IsPlayerAlly(GetLocalPlayer(), GetOwningPlayer(c)) then
set R.f = AddSpecialEffect(GetFX(0), x, y)
else
set R.f = AddSpecialEffect("Abilities\\Spells\\NightElf\\TreeofLifeUpgrade\\TreeofLifeUpgradeTargetArt.mdl", x, y)
endif
set R.c = c
set R.p = GetOwningPlayer(c)
set R.x = x
set R.y = y
set R.l = GetUnitAbilityLevel(c, SpellID)
set R.i = rune.counter
set rune.runes[rune.counter] = integer(R)
set rune.counter = rune.counter + 1
endmethod
static method Update takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= rune.counter
set rune.id = i
set rune.do = 0
set rune.runes<i>.d = rune.runes<i>.d + dt
call GroupEnumUnitsInRange(G, rune.runes<i>.x, rune.runes<i>.y, Range(rune.runes<i>.l), Condition(function rune.GetUnits))
if rune.do > 0 or rune.runes<i>.d >= Duration(rune.runes<i>.l) then
call rune.runes<i>.destroy()
endif
set i = i + 1
endloop
endmethod
endstruct
//***************************************************************************************************************
//* *
//* Runes Casting Functions *
//* *
//***************************************************************************************************************
private function Conditions takes nothing returns boolean
return GetUnitTypeId(GetSummonedUnit()) == RuneID
endfunction
private function Actions takes nothing returns nothing
local unit c = GetSummoningUnit()
local unit r = GetSummonedUnit()
local real lx = GetUnitX(r)
local real ly = GetUnitY(r)
local real fc = GetUnitFacing(c) * bj_DEGTORAD
local real a = Amount(GetUnitAbilityLevel(c, SpellID))
local real R = Radius(GetUnitAbilityLevel(c, SpellID))
local real angle = 2 * bj_PI / a
local integer count = 0
local real x
local real y
call RemoveUnit(r)
call rune.Start(c, lx, ly)
loop
exitwhen count == a
set x = lx + R * Cos(fc + count * angle)
set y = ly + R * Sin(fc + count * angle)
call rune.Start(c, x, y)
set count = count + 1
endloop
set c = null
set r = null
endfunction
//===========================================================================
private function init takes nothing returns nothing
local trigger t= CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SUMMON )
call TriggerAddCondition( t, Condition( function Conditions ) )
call TriggerAddAction( t, function Actions )
call Preload(GetFX(0))
call Preload(GetFX(1))
call Preload(GetFX(2))
set rune.dummy = CreateUnit(Player(15), RuneID, 0,0,0)
call ShowUnit(rune.dummy, false)
call TimerStart(CreateTimer(), dt, true, function rune.Update)
set t = null
endfunction
endlibrary</i></i></i></i></i></i></i></i>
Changelog:
- 2.0: Initial Release
- 2.1: Improved the killing credits and performance a little bit more.
- 2.2: Simplified the code a little bit in the Grouping units, and if the caster is alive in that moment, the killing credit goes to him. Added to the resurrection some eyecandy