//TESH.scrollpos=0
//TESH.alwaysfold=0
native UnitAlive takes unit u returns boolean
globals
constant boolean ENABLE_TEST = false //should be false
constant boolean ENABLE_BOSS_TEST = false
constant boolean SETUP_DIALOG = true //this should be true
constant boolean ENABLE_FOG_OF_WAR = true //this should be false
constant boolean ENABLE_MP = false //this should be true to enable Multi Player
constant integer MAX_UNIT = 6 //for AI attacking (AISetup)
constant integer MAX_UNIT_FULL = 10 //for AI attacking (AISetup)
constant integer BOSS_LEVEL = 50
constant real START_GAME = 60 //60 seconds
constant string MAP_VERSION = "Field of Conflict v1.2"
endglobals
Name | Type | is_array | initial_value |
Base | location | Yes | |
Boss | unit | No | |
BossMode | integer | No | |
BossModeCheck | boolean | No | false |
Caravan | unit | No | |
CheckMode | boolean | No | |
CONFIG_NP_Dur | real | No | |
DA_Base_Damage | real | No | |
DA_Casting_Unit | unit | No | |
DA_Damage_Group | group | No | |
DA_Dummy_Ability_Fire | abilcode | No | |
DA_Dummy_Ability_Slow | abilcode | No | |
DA_Dummy_Ability_Stunn | abilcode | No | |
DA_Dummy_Ability_Water | abilcode | No | |
DA_Hero_Ability_Level | integer | No | |
DA_Loop_Distance | real | No | |
DA_Loop_Location | location | No | |
DA_Number_of_Charges | integer | No | |
DA_Owner_of_Caster | player | No | |
DA_Radius_AoE | real | No | |
DA_Radius_Level_AoE | real | No | |
DA_Targeted_Location | location | No | |
Death_Loc | location | No | |
DPL_Counter | integer | No | |
DPL_Group | group | No | |
DPL_Portal | unit | No | |
DPL_Timer | timer | No | |
DW_Caster | unit | No | |
DW_UGrp | group | No | |
FN_Effect_Loc | location | No | |
FN_Int | integervar | No | |
HASH | hashtable | No | |
Hash_01 | hashtable | No | |
Hash_02 | hashtable | No | |
HeroIndexDummy | unit | No | |
Hints | string | Yes | |
IB_ang | real | No | |
IB_ang_add | real | No | |
IB_tmpeff | effect | No | |
IB_tmppoint | location | No | |
IB_tmppoint2 | location | No | |
IB_tmppoint3 | location | No | |
MainHeroGroup | group | No | |
ObeliskP101112 | unit | No | |
ObeliskP123 | unit | No | |
ObeliskP456 | unit | No | |
ObeliskP789 | unit | No | |
RANGER_Group | group | No | |
RANGER_Loc | location | No | |
RANGER_Real_1 | real | No | |
SND_Warning | sound | No | |
TargetLoc | location | No | |
TempLoc | location | No |
//TESH.scrollpos=13
//TESH.alwaysfold=0
HERO TOOLTIP TEMPLATE:
/*
The Templar is a Holy Warrior, exceptional at defense and decreasing the capability of enemy troops.
Can learn Impede Vortex, Refresh, Holy Seal and Vindication.
|cffffcc00Attacks land units.|r
|cffffcc00Race.|r: Human
|cff19DE6BMain Attribute|r: Strength
|cffFFDE19Starting Stats|r:
|cffFF5A73Agility|r: 13
|cff083A84Intelligence|r: 17
|cff8C0810Strength|r: 22
======================
BUTTON POSITIONS:
00, 10, 20, 30
01, 11, 21, 31
02, 12, 22, 32
*/
TO BE DONE:
/*
DONE: Score Mode - Escort the caravan to your base to gather points. Highest score wins.
DONE: Level Mode - Level up your hero. Highest level of hero wins.
DONE: Kills Mode - Kill enemy units. Highest kills wins.
DONE: Boss Mode - Team up to kill the boss and guard your obelisk.
- Hero Arena Mode - No creeps just heroes and neutral hostile.
Shops with items
Rewards
- Every Caravan score, gets a reward (DONE)
- Every kill has a reward (DONE)
- Item rewards
- Aura rewards = mana, speed, damage, life
- Unit rewards
*/
//TESH.scrollpos=299
//TESH.alwaysfold=0
[center][otable][tr][titletd]
[img]http://www.hiveworkshop.com/forums/attachment.php?attachmentid=114736&stc=1&d=1339166933[/img]
Field of Conflict (formerly named: Smells like DotA)
[/titletd][/tr]
[tdalt]
This is an AoS type game but with 4 teams instead of 2.
[COLOR="Yellow"]Game Modes are:[/COLOR]
- Score Mode - Escort the caravan to your base to gather points. Highest score wins.
- Level Mode - Level up your hero. Highest level of hero wins.
- Kills Mode - Kill enemy units. Highest kills wins.
- Boss Mode - Team up to kill the boss and guard your obelisk.
- Hero Arena Mode - No creeps just heroes and neutral hostile.
[/tdalt][/otable]
[B][COLOR="Orange"][SIZE="4"]===Features===[/SIZE][/COLOR][/B]
- 24 classic Heroes made by Blizzard with one extra ultimate ability
- 24 Custom Heroes
- 72 Custom Spells & 24 Ultimate Spells for Custom Heroes
- Train more than 1 heroes at a time
- Playable againts up to 11 AI's
- Playable for 8 players
- Kill a hero then gain a level
[B][SIZE="4"][COLOR="Orange"]===Playable Heroes===[/COLOR][/SIZE][/B]
[tabs]
[tab=Conjurer]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126385d1370360444-field-conflict-v1-1-conjurer.jpg[/img]
Race: Dwarf
Created by: Mckill2009 & Defskull
Abilties:
Fire Erruption
Necrogenesis
Molten Rocks
Wrath of Fire (ultimate)
[/tab]
[tab=Dark Knight]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126386d1370360444-field-conflict-v1-1-dark-knight.jpg[/img]
Race: Human
Created by: Mckill2009 & Defskull
Abilities:
Plunk Down
Confinement
Sudden Blow
Charged Bolt (ultimate)
[/tab]
[tab=Fallen Corpse]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126387d1370360444-field-conflict-v1-1-fallen-corpse.jpg[/img]
Race: Undead
Created by: WillofKhrone
Abilties:
Fallen Corpse Bombardment
Wind of Decay
Necrotic Poisoning
Wings of Life (ultimate)
[/tab]
[tab=Golum]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126388d1370360444-field-conflict-v1-1-golum.jpg[/img]
Race:Golem
Created by: Chizume
Abilties:
Boulder Roll
Shatter
Dead Material
Decoy (ultimate)
[/tab]
[tab=Griefer]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126389d1370360474-field-conflict-v1-1-griefer.jpg[/img]
Race: Ice Troll
Created by: Mckill2009
Abilties:
Ice Shot (ATC)
Freeze
Frost Shield
Summon Blue Dragon (ultimate)
[/tab]
[tab=Lilith]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126390d1370360474-field-conflict-v1-1-lilith.jpg[/img]
Race: Demon
Created by: Mckill2009
Abilties:
Fire Vortex
Ignition
Burn
Devil's Decree (ultimate)
[/tab]
[tab=Medical Sparkbot]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126391d1370360474-field-conflict-v1-1-medical-sparkbot.jpg[/img]
Race: Robot
Created by: WillofKhrone
Abilties:
Field Medic
Medical Powa!
Overload
Mechanical Reboot (ultimate)
[/tab]
[tab=Ranger]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126393d1370360474-field-conflict-v1-1-ranger.jpg[/img]
Race: Elf
Created by: Animoi666
Abilities:
Focus
Power Shot
Hit and Run
Suppressing Fire (ultimate)
[/tab]
[tab=Toxin]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126398d1370360506-field-conflict-v1-1-toxin.jpg[/img]
Race: Scorpion
Created by: mckill2009
Abilties:
Sting
Dig
Slow Poison
Outbreak (ultimate)
[/tab]
[tab=Templar]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126395d1370360506-field-conflict-v1-1-templar.jpg[/img]
Race: Human
Created by: mckill2009
Abilties:
Refresh
Impede Vortices
Holy Seal
Vindication (ultimate)
[/tab]
[/tabs]
[tabs]
[tab=Space Orc]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126394d1370360506-field-conflict-v1-1-space-orc.jpg[/img]
Race: Orc
Created by: mckill2009
Abilties:
Air Raid
Grenade
Boost
Bombardment (ultimate)
[/tab]
[tab=Poltergeist]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126392d1370360474-field-conflict-v1-1-poltergeist.jpg[/img]
Race: Ghost
Created by: mckill2009
Abilties:
Mind Control
Mist
Seize
Doppelganger (ultimate)
[/tab]
[tab=Tombcaster]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126396d1370360506-field-conflict-v1-1-tombcaster.jpg[/img]
Race: Undead
Created by: mckill2009
Abilties:
Blood Shed
Death Waves
Rise, Decay (ultimate)
[/tab]
[tab=Gnome]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126399d1370360554-field-conflict-v1-1-gnome.jpg[/img]
Race: Goblin
Created by: mckill2009
Abilties:
Garlamesh
Invoke
Shamanic Fury
Sacrifice (ultimate)
[/tab]
[tab=Tormentor]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126397d1370360506-field-conflict-v1-1-tormentor.jpg[/img]
Race: Demon
Created by: mckill2009
Abilties:
Howling Wail
Suffucate
Curse of Silence
Dreamscape (ultimate)
[/tab]
[/tabs]
[COLOR="orange"][SIZE="4"][B]===NPC - Non Playable Characters (AI's)===[/B][/SIZE][/COLOR]
[tabs]
[tab=Ghost Keeper of the Groove]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126420d1370389174-field-conflict-v1-1-chost-keeper-groove-ai-npc.jpg[/img]
Race: Night Elf
Created by: rysnt11 & mckill2009
Abilties: Soul Drain
Whirlwind
Mass Root
Faeriefire
[/tab]
[tab=Ghost Archmage]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126421d1370389174-field-conflict-v1-1-ghost-archmage-ai-npc.jpg[/img]
Race: Human
Created by: mckill2009
Abilties:
Flame Blast
Crushing Wave
Life Mana
Lightning Shield
[/tab]
[tab=Ghost Necromancer]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126422d1370389174-field-conflict-v1-1-ghost-necromancer-ai-npc.jpg[/img]
Race: Undead
Created by: rysnt11 & mckill2009
Abilties:
Cripple
Death Trap
Soul Release
Blood Curse
[/tab]
[tab=Chaos Blademaster]
[img]http://www.hiveworkshop.com/forums/attachments/maps-564/126423d1370389174-field-conflict-v1-1-chaos-blademaster-ai-npc.jpg[/img]
Race: Orc
Race: Orc
Created by: mckill2009
Abilties:
Sweeping Strike
Leap Blow
Trample
Critical Strike
[/tab]
[/tabs]
[/center]
[hidden=Credits]
[B][COLOR="Orange"]Project Leader/Lead Coder[/COLOR][/B]
mckill2009
[B][COLOR="Orange"]Spell Makers and Ideas:[/COLOR][/B]
Defskull, Animoi666, rysnt11
[COLOR="orange"][B]Terrainer:[/B][/COLOR]
Naro and mrstormyz
[COLOR="orange"][B]Systems:[/B][/COLOR]
- Vexorian
- Bribe
- Magtheridon96
- Nesthaurus
- Anitarf
- looking_for_help aka eey
- Jesus4Lyf
- PitzerMike
[COLOR="orange"][B]Imported Spells:[/B][/COLOR]
Dual Adaptation by -BerzekeR-
Diabolic Edict by Siraraz/BlackRose
Fire Nova by MortAr
Sun Ray by Flame_Phoenix
Runes by Moyack
Lightning Ward by Septimus
[COLOR="orange"][B]Imported Models:[/B][/COLOR]
Goblin Mage by Kuhneghetz
[COLOR="orange"][B]Imported Icons:[/B][/COLOR]
BTNGoblinMage01 by Kuhneghetz
BTNAdvancedMageStaff By LiOneSS
BTNRelentlessness by 67chrome
BTNcrWarp10 Created by CRAZYRUSSIAN
BTNHowlOfTerrorV2 by The_Silent
BTNMindsooth Created by Anachron
BTNTorment Created by PeeKay
[COLOR="orange"][B]Plese tell me if you're not included in the credits lists so that I may add your name. Thank you![/B][/COLOR]
[/hidden]
[hidden=FOC v1.2 Screenshots, with the new hero Tormentor]
[IMG]http://www.hiveworkshop.com/forums/attachments/maps-564/126424d1370389652-field-conflict-v1-1-ss-01.jpg[/IMG]
[IMG]http://www.hiveworkshop.com/forums/attachments/maps-564/126425d1370389652-field-conflict-v1-1-ss-02.jpg[/IMG]
[/hidden]
[hidden=Changelog]
version 1.2
- Added 1 boss hero for boss event: Ice Boss (Melta)
- Added 2 heroes, Gnome (Goblin) and Tormentor (Demon)
- Fixed rune stats powerup bug
- Can be played as single player
- Player gold/lumber reward notification removed
version 1.1
- Moderator's comment applied
- Fire Boss more advanced in attacking
version 1.0
- Boss Mode added
- Items and Rewards created
version 0.8
- Kills mode done
- Added shops to each base, still need more items
- Added market to the north and south
- Improved coding
[/hidden]
[B][SIZE="3"]NOTE:
- This map is NOT protected, and no one is authorized to edit this!
- Player 1 must be a user to pick game modes.
[/SIZE][/B]
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Cam
private struct Cam
static real INT = 0.03
static real DIST = 3000
private static method onCam takes nothing returns boolean
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, DIST, INT)
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t, INT, true)
call TriggerAddCondition(t, function thistype.onCam)
set t = null
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BossTest initializer init
globals
private integer BOSS = 1
endglobals
private function RunTest takes nothing returns nothing
if ENABLE_BOSS_TEST then
call BossBattle.bossbattleOn(BOSS)
endif
endfunction
private function init takes nothing returns nothing
call TimerStart(CreateTimer(), 2.0, false, function RunTest)
endfunction
endscope
//TESH.scrollpos=38
//TESH.alwaysfold=0
scope TimerTemplate
//uses SpellEffectEvent
globals
private constant integer SPELL_ID = 'A01N'
private constant integer DUMMY_ID = 'n00B'
private constant integer BUFF_ID = 'BNic'
private constant string SFX = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_FIRE
endglobals
struct TT
unit u
real dur
//timer setup
static timer t
static integer index = 0
static integer array indexAR
static real interval = 1.0
static method looper takes nothing returns nothing
local thistype this
local integer i = 0
loop
set i = i+1
set this = indexAR[i]
if .dur > 0 then
set .dur = .dur - interval
//do all here
else
set .u = null
call .destroy()
set indexAR[i] = indexAR[index]
set indexAR[index] = this
set index = index - 1
set i = i-1
if index==0 then
call PauseTimer(t)
call DestroyTimer(t)
endif
endif
exitwhen i==index
endloop
endmethod
static method create takes unit u returns thistype
local thistype this = allocate()
set .u = u
set .dur = 10.
if index==0 then
set t = CreateTimer()
call TimerStart(t, interval, true, function thistype.looper)
endif
set index = index + 1
set indexAR[index] = this
return this
endmethod
static method cast takes nothing returns nothing
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope TimerTemplateCTL
//uses SpellEffectEvent
globals
private constant integer SPELL_ID = 'A01N'
private constant integer DUMMY_ID = 'n00B'
private constant integer BUFF_ID = 'BNic'
private constant string SFX = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_FIRE
endglobals
struct TTctl
unit u
real dur
implement CTL
implement CTLExpire
implement CTLNull
implement CTLEnd
static method cast takes nothing returns nothing
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
endmethod
endstruct
endscope
//TESH.scrollpos=12
//TESH.alwaysfold=0
scope Template
//uses TimerLooper v2.0
globals
private constant integer SPELL_ID = 'A01N'
private constant integer DUMMY_ID = 'n00B'
private constant integer BUFF_ID = 'BNic'
private constant string SFX = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_FIRE
private constant real INTERVAL = 0.5
endglobals
struct WalkingBomb
unit caster
unit target
real damage
real duration
method getDamage takes integer i returns real
return 150 + i * 100.
endmethod
method getDuration takes integer i returns real
return 10.
endmethod
static method looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer this = LoadData(t)
if .duration > 0 then
set .duration = .duration - INTERVAL
else
if not IsUnitType(.target, UNIT_TYPE_DEAD) and GetUnitAbilityLevel(.target, BUFF_ID) > 0 then
endif
call StopTimer(t)
call .deallocate()
endif
set t = null
endmethod
static method cast takes nothing returns nothing
local thistype this = create()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)
set .caster = GetTriggerUnit()
set .target = GetSpellTargetUnit()
set .damage = getDamage(level)
set .duration = getDuration(level)
call SaveData(t, this)
call TimerStart(t, INTERVAL, true, function thistype.looper)
set t = null
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BurningPath
globals
private constant integer SPELL_ID = 'A03O'
endglobals
struct BurningPath
static method cond takes nothing returns nothing
local unit attacked
local unit attacker = GetAttacker()
local unit dummy
if SpellLevel(attacker, SPELL_ID) and IsUnitEnemy(attacker, GetTriggerPlayer()) then
if GetRandomInt(0,100) < 10 then
call BJDebugMsg("OK")
endif
endif
set attacker = null
endmethod
static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function thistype.cond)
endmethod
endstruct
endscope
//TESH.scrollpos=4
//TESH.alwaysfold=0
scope QC initializer init
//call QCreate(1, "MyTestQuest", "Description", "ReplaceableTextures\\CommandButtons\\BTNDivineIntervention.blp", true)
globals
//How to win
private constant string INTRO = "These are the options in order to win the game:"
private constant string OBE = "|n- |cffD4A017Skirmish|r - Kill the enemie's |cff8E35EObelisk.|r"
private constant string SM = "|n- |cffD4A017Score Mode|r - the team that has the |cff8E35EFrequired score|r wins."
private constant string LM = "|n- |cffD4A017Level Mode|r - the Main Hero that reaches the |cff8E35EFrequired level|r wins."
private constant string KM = "|n- |cffD4A017Kills Mode|r - team with the highest kills wins."
private constant string BM = "|n- |cffD4A017Boss Mode|r - all players should team up to kill the Boss."
//Shops
private constant string MER = "There are 3 merchants on every team which sells:"
private constant string SP = "|n- Powerups, healings, weapons and other things to upgrade your hero"
private constant string MAR = "|n|nThere are also 2 markets in this map located to the center North and South which trades lumber for gold and vice-versa."
//FAQ
private constant string FAQ_ICON = "ReplaceableTextures\\WorldEditUI\\Editor-Random-Building.blp"
private constant string Q1 = "|cff083A84Why are the default heroes available to pick from?|r"
private constant string A1 = "|n- Because it's included in the theme of the map."
private constant string Q2 = "|n|n|cff083A84The classic hero spells are weak compared to custom heroes, will you add more spells to the default hero?|r"
private constant string A2 = "|n- Only Attribute Bonus is added to the default hero but it can level up to 10, so the hero is strong enough to compete to custom heroes."
endglobals
private function QC takes nothing returns boolean
call QCreate(1, "How to win?", INTRO+OBE+SM+LM+KM+BM, "ReplaceableTextures\\WorldEditUI\\Editor-Random-Unit.blp", true)
call QCreate(2, "Shops", MER+SP+MAR, "ReplaceableTextures\\CommandButtons\\BTNBlackMarket.blp", true)
call QCreate(3, "FAQ", Q1+A1+Q2+A2, FAQ_ICON, false)
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t, 0.1, false)
call TriggerAddCondition(t, function QC)
set t = null
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope HeroEvents initializer init
globals
private constant real herorevivetimer = 40 //40 seconds
private boolean array TrainCheck
private Table herotim
endglobals
//First Time Use Only
private function HeroSold takes nothing returns nothing
local unit hero
local unit indicator
local integer pNum
if IsUnitType(GetSoldUnit(), UNIT_TYPE_HERO) then
set hero = GetSoldUnit()
set pNum = GetPlayerId(GetOwningPlayer(hero))
if not TrainCheck[pNum] then
//call BJDebugMsg("check OK")
//so that only in this group has the main hero
if udg_BossModeCheck then
call SetHeroLevel(hero,10,true)
endif
call GroupAddUnit(udg_MainHeroGroup, hero)
call SetUnitPosition(hero, GetPlayerStartLocationX(Player(pNum)), GetPlayerStartLocationY(Player(pNum)))
call MbSetTextValue(pNum+1,1,FixedColor(pNum, GetHeroProperName(hero)))
call MbSetTextValue(pNum+1,2,FixedColor(pNum, I2S(GetHeroLevel(hero))))
call MbSetTextValue(pNum+1,7,FixedColor(pNum, "Alive"))
set TrainCheck[pNum] = true
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup,Player(pNum),null)
loop
set indicator = FirstOfGroup(bj_lastCreatedGroup)
exitwhen indicator==null
if GetUnitTypeId(indicator)=='h00U' then
call KillUnit(indicator)
call RemoveUnit(indicator)
endif
call GroupRemoveUnit(bj_lastCreatedGroup,indicator)
endloop
endif
set hero = null
endif
endfunction
//=======================================
//=====HERO DIES TIMER:
private function ReviveHeroTimer2 takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetTimerData(t)
local unit hero = herotim.unit[tID]
local real xLoc = GetPlayerStartLocationX(GetOwningPlayer(hero))
local real yLoc = GetPlayerStartLocationY(GetOwningPlayer(hero))
local integer pID = GetPlayerId(GetOwningPlayer(hero))
call ReviveHero(hero, xLoc, yLoc, true)
call DestroyTimerDialog(herotim.timerdialog[GetHandleId(hero)])
call MbSetTextValue(pID+1,1,FixedColor(pID, GetHeroProperName(hero)))
call MbSetTextValue(pID+1,2,FixedColor(pID, I2S(GetHeroLevel(hero))))
call MbSetTextValue(pID+1,7,FixedColor(pID, "Alive"))
if udg_BossModeCheck and GetPlayerController(GetOwningPlayer(hero))==MAP_CONTROL_COMPUTER then
//call SetEngageUnit(hero,false,30.)
//call SetUnitRetreat(hero)
//call SetUnitPickItem(hero)
endif
call ReleaseTimer(t)
call herotim.remove(tID)
call herotim.remove(GetHandleId(hero))
set t = null
set hero = null
endfunction
private function ReviveHeroTimer takes unit hero, integer pID returns nothing
local timer t = NewTimer()
local timerdialog td = CreateTimerDialog(t)
local integer tID = GetHandleId(t)
if GetLocalPlayer()==GetOwningPlayer(hero) then
call TimerDialogDisplay(td, true)
endif
set herotim.unit[tID] = hero
set herotim.timerdialog[GetHandleId(hero)] = td
call TimerDialogSetTitle(td, GetHeroProperName(hero))
//call MbSetTextValue(pID+1,1,FixedColor(pID, GetHeroProperName(hero)))
call MbSetTextValue(pID+1,7,FixedColor(pID, "Dead"))
call SetTimerData(t, tID)
call TimerStart(t, herorevivetimer, false, function ReviveHeroTimer2)
set t = null
endfunction
//=======================================
private function RemovedNonMainHero takes nothing returns nothing
call RemoveUnit(GetUnitHandle(GetTimerData(GetExpiredTimer()), 1))
call ReleaseTimer(GetExpiredTimer())
endfunction
private function HeroRevive takes nothing returns nothing
local unit hero
if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
set hero = GetTriggerUnit()
if IsUnitInGroup(hero, udg_MainHeroGroup) then
//Revives Main Hero
call ReviveHeroTimer(hero, GetPlayerId(GetTriggerPlayer()))
else
//Removes the non-MAIN Hero from the game
set bj_cineFadeFinishTimer = NewTimer()
call SetUnitHandle(GetHandleId(bj_cineFadeFinishTimer), 1, hero)
call SetTimerData(bj_cineFadeFinishTimer, GetHandleId(bj_cineFadeFinishTimer))
call TimerStart(bj_cineFadeFinishTimer, 3, false, function RemovedNonMainHero)
set bj_cineFadeFinishTimer = null
endif
set hero = null
endif
endfunction
private function init takes nothing returns nothing
local integer i = 0
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function HeroRevive)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SELL, function HeroSold)
set herotim = Table.create()
loop
set TrainCheck[i] = false
exitwhen i==12
set i = i + 1
endloop
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Pre initializer init
private function init takes nothing returns nothing
call PreloadSpell('A007') //Ice Burst
call PreloadSpell('A03S') //Shattering Frost
call PreloadSpell('A03T') //Shattering Frost (dummy)
call PreloadSpell('A03E') //Diabolic Edict
call PreloadSpell('A03J') //Dual Adaptation
call PreloadSpell('A03M') //Fire Nova
call PreloadSpell('A03N') //Spread Shot
call PreloadSpell('A02U') //Spread Shot (dummy)
//call PreloadSpell('A03E') //
//call PreloadSpell('A03E') //
//call PreloadSpell('A03E') //
//call PreloadSpell('A03E') //
//call PreloadSpell('A03E') //
//call PreloadUnit(unitID)
//call PreloadUnit(unitID)
//call PreloadUnit(unitID)
//call PreloadUnit(unitID)
//call PreloadUnit(unitID)
endfunction
endscope
//TESH.scrollpos=21
//TESH.alwaysfold=0
library GameModesSetup initializer DialogInit uses MbUpdates, MultiboardSystem, IntroCreation
//This system runs after the timer
globals
private dialog Dia
private integer ind = 0 //used to display MSG only once
private button Back
//Modes, Main menu
private button ScoreMode
private button LevelMode
private button KillsMode
private button BossMode
//Mode arrays, Sub menu
private button array SMode
private button array LevMode
private button array KillMode
private button array BosMode
//Mode Titles
private constant string ScoreModeTitle = " - Score Mode"
private constant string LevelModeTitle = " - Level Mode"
private constant string KillsModeTitle = " - Kills Mode"
//private constant string BossModeTitle = " - Boss Mode"
//Mode starters
private integer RequiredScore = 0
private integer RequiredLevel = 0
public integer RequiredKills = 0
//public variables
public boolean ScMode = false //used by MbUpdates
private boolean LvMode = false
public boolean KlMode = false
endglobals
private function IntroMsg takes nothing returns nothing
local integer i = 0
call ClearTextMessages()
loop
call DisplayTimedTextToPlayer(Player(i),0,0,30,"|cffffcc00Field of Conflict:|r Made by mckill2009")
call DisplayTimedTextToPlayer(Player(i),0,0,30,"- You have " +R2S(START_GAME)+ " seconds to pick your hero.")
call DisplayTimedTextToPlayer(Player(i),0,0,30,"- Heroes are located inside taverns at the center of the map.")
call DisplayTimedTextToPlayer(Player(i),0,0,30,"- Pick your hero wisely because that is your 'Main' hero.")
call DisplayTimedTextToPlayer(Player(i),0,0,30,"- Other heroes cannot be revived except your Main hero.")
call DisplayTimedTextToPlayer(Player(i),0,0,30,"- You may play up to 3 hero.")
set i = i+1
exitwhen i==12
endloop
endfunction
//===Score Mode Code:
private function ScoreModeP takes nothing returns boolean
local integer index
local unit first
//used if ScoreMode is true
//use MbUpdates_ScoreP[?] also
if ScMode then
set index = 11
call ClearTextMessages()
loop
exitwhen index==0
set index = index - 1
if MbUpdates_ScoreP[index] >= RequiredScore or MbUpdates_ScoreP2[index] >= RequiredScore then
call GroupEnumUnitsInRect(bj_lastCreatedGroup, GetWorldBounds(), null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
if IsUnitEnemy(first, Player(index)) then
call CustomDefeatBJ(GetOwningPlayer(first), "Defeat!")
call KillUnit(first)
else
call CustomVictoryBJ(Player(index), true, true)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
endloop
set MbUpdates_VarScoreMode = 0
endif
return false
endfunction
//===Level Mode Code:
private function HeroLvlNow takes unit hero returns boolean
if IsUnitType(hero, UNIT_TYPE_HERO) and IsUnitInGroup(hero, udg_MainHeroGroup) and GetHeroLevel(hero) >= RequiredLevel then
return true
endif
return false
endfunction
private function LevelModeP takes nothing returns boolean
local integer i
if HeroLvlNow(GetTriggerUnit()) and LvMode then
set i = 11
loop
exitwhen i==0
set i = i - 1
if IsUnitEnemy(GetTriggerUnit(), Player(i)) then
call CustomDefeatBJ(Player(i), "Defeat!")
else
call CustomVictoryBJ(Player(i), true, true)
endif
endloop
endif
return false
endfunction
//===Kills Mode Code:
private function KillsModeP takes nothing returns boolean
local unit killing = MbUpdates_VarKillingUnit
local integer i = 12
loop
exitwhen i==0
set i = i - 1
if IsUnitEnemy(killing, Player(i)) then
call CustomDefeatBJ(Player(i), "Defeat!")
else
call CustomVictoryBJ(Player(i), true, true)
endif
endloop
set MbUpdates_VarKillMode = 0
return false
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
private function ScoreModeValue takes integer score returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "MbUpdates_VarScoreMode", EQUAL, 1)
call TriggerAddCondition(t, function ScoreModeP)
call MbSetTitle(FixedColor(29, MAP_VERSION+ScoreModeTitle) + " (" + I2S(score)+" Points required)")
set RequiredScore = score
set ScMode = true
set udg_CheckMode = true
set t = null
call IntroCreation()
endfunction
private function LevelModeValue takes integer level returns nothing
call MbSetTitle(FixedColor(29, MAP_VERSION+LevelModeTitle) + " (" + I2S(level)+" Hero level required)")
set RequiredLevel = level
set LvMode = true
set udg_CheckMode = true
call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_LEVEL, function LevelModeP)
call IntroCreation()
endfunction
private function KillModeValue takes integer kills returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "MbUpdates_VarKillMode", EQUAL, 1)
call TriggerAddCondition(t, function KillsModeP)
call MbSetTitle(FixedColor(29, MAP_VERSION+KillsModeTitle) + " (" + I2S(kills)+" Kills required)")
set RequiredKills = kills
set KlMode = true
set udg_CheckMode = true
set t = null
call IntroCreation()
endfunction
private function BossModeValue takes integer boss returns nothing
call ClearTextMessages()
call MbShow(false)
set udg_BossMode = boss
set udg_BossModeCheck = true
set udg_CheckMode = false //caravans and engaging units will not be created
call MakeAllAlly() //this calls also "IntroCreation" but in boss mode
set udg_BossMode = boss //this should be greater than 0
endfunction
private function HeroArenaModeValue takes nothing returns nothing
//NOT YET DONE!!!!!
call ClearTextMessages()
call MbShow(false)
set udg_BossMode = 0 //greater than 0 is the BossMode
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
private function DialogButClicked takes nothing returns boolean
local button but = GetClickedButton()
local integer index1
local integer index2
call DialogClear(Dia)
//udg_CheckMode
if but==ScoreMode then
call DialogSetMessage(Dia, "Highest Score")
set Back = DialogAddButton(Dia, "Go Back", 1)
set SMode[0] = DialogAddButton(Dia, "10", 2)
set SMode[1] = DialogAddButton(Dia, "20", 3)
set SMode[2] = DialogAddButton(Dia, "30", 4)
set SMode[3] = DialogAddButton(Dia, "40", 5)
set SMode[4] = DialogAddButton(Dia, "50", 6)
call DialogDisplay(Player(0), Dia, true)
elseif but==LevelMode then
call DialogSetMessage(Dia, "Highest Hero Level")
set Back = DialogAddButton(Dia, "Go Back", 1)
set LevMode[0] = DialogAddButton(Dia, "20", 2)
set LevMode[1] = DialogAddButton(Dia, "35", 3)
set LevMode[2] = DialogAddButton(Dia, "50", 4)
set LevMode[3] = DialogAddButton(Dia, "65", 5)
set LevMode[4] = DialogAddButton(Dia, "80", 6)
call DialogDisplay(Player(0), Dia, true)
elseif but==KillsMode then
call DialogSetMessage(Dia, "Highest Kills Goal")
set Back = DialogAddButton(Dia, "Go Back", 1)
set KillMode[0] = DialogAddButton(Dia, "100", 2)
set KillMode[1] = DialogAddButton(Dia, "200", 3)
set KillMode[2] = DialogAddButton(Dia, "300", 4)
set KillMode[3] = DialogAddButton(Dia, "400", 5)
set KillMode[4] = DialogAddButton(Dia, "500", 6)
call DialogDisplay(Player(0), Dia, true)
elseif but==BossMode then
call DialogSetMessage(Dia, "Kill The Boss In The Map")
set Back = DialogAddButton(Dia, "Go Back", 1)
set BosMode[1] = DialogAddButton(Dia, "Fire Boss", 2) //should start by 1
set BosMode[2] = DialogAddButton(Dia, "Ice Boss", 3) //
call DialogDisplay(Player(0), Dia, true)
elseif but==Back then
set ScoreMode = DialogAddButton(Dia, "Score Mode", 1)
set LevelMode = DialogAddButton(Dia, "Level Mode", 2)
set KillsMode = DialogAddButton(Dia, "Kills Mode", 3)
set BossMode = DialogAddButton(Dia, "Boss Mode", 4)
//set HeroArenaMode = DialogAddButton(Dia, "Hero Arena Mode", 5)
call DialogSetMessage(Dia, "Pick Game Mode")
call DialogDisplay(Player(0), Dia, true)
else
//Enables All: user already picks game mode
call IntroMsg()
call EnableUserControl(true)
call DialogDestroy(Dia)
call DestroyTrigger(GetTriggeringTrigger())
//=====SCORE MODE:
set index1 = 0
set index2 = 0
loop
set index2 = index2 + 10
if but==SMode[index1] then
call ScoreModeValue(index2)
endif
set index1 = index1 + 1
exitwhen index1==5
endloop
//=====LEVEL MODE:
set index1 = 0
set index2 = 20
loop
if but==LevMode[index1] then
call LevelModeValue(index2)
endif
set index2 = index2 + 15
set index1 = index1 + 1
exitwhen index1==5
endloop
//=====KILLS MODE:
set index1 = 0
set index2 = 100
loop
if but==KillMode[index1] then
call KillModeValue(index2)
endif
set index2 = index2 + 100
set index1 = index1 + 1
exitwhen index1==5
endloop
//=====BOSS MODE: Uses BossBattle library
set index1 = 1
loop
if but==BosMode[index1] then
call BossModeValue(index1)
endif
set index1 = index1 + 1
exitwhen index1==5
endloop
endif
return false
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
private function Defeat takes nothing returns nothing
local integer p = 0
loop
call CustomDefeatBJ(Player(p), "Defeat!")
set p = p + 1
exitwhen p==12
endloop
endfunction
private function DialogRun takes nothing returns nothing
local integer i = 0
call DialogClear(Dia)
set ScoreMode = DialogAddButton(Dia, "Score Mode", 1)
set LevelMode = DialogAddButton(Dia, "Level Mode", 2)
set KillsMode = DialogAddButton(Dia, "Kills Mode", 3)
set BossMode = DialogAddButton(Dia, "Boss Mode", 4)
//set HeroArenaMode = DialogAddButton(Dia, "Hero Arena Mode", 5)
call DialogSetMessage(Dia, "Pick Game Mode")
call DialogDisplay(Player(0), Dia, true)
if ind==0 then
set ind = ind+1
call BJDebugMsg("Important Notice: Player 1 must play as user")
call BJDebugMsg("- A dialog button has been displayed to Player 1")
call BJDebugMsg("- Other players must wait for Player 1")
endif
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
endfunction
private function diainit takes nothing returns nothing
local trigger t
//0,1==3,4==6,7==9,10
if GetPlayerSlotState(Player(0))==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(0))==MAP_CONTROL_USER then
static if SETUP_DIALOG then
set t = CreateTrigger()
set Dia = DialogCreate()
call EnableUserControl(false)
call TimerStart(CreateTimer(), 0.0, false, function DialogRun)
call TriggerRegisterDialogEvent(t, Dia)
call TriggerAddCondition(t, function DialogButClicked)
set t = null
endif
if GetLocalPlayer()==Player(0) then
call EnableUserControl(true)
endif
static if ENABLE_FOG_OF_WAR then
call FogEnable(false)
call FogMaskEnable(false)
endif
else
call BJDebugMsg("Player 1 MUST be a User slot for picking game modes.")
call EnableUserControl(false)
call TimerStart(CreateTimer(), 3.0, false, function Defeat)
endif
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
endfunction
private function DialogInit takes nothing returns nothing
local integer i = 0
local integer index = 0
if not ENABLE_TEST then
//0,1==3,4==6,7==9,10
loop
if GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING then
if Player(i)!=Player(2) and Player(i)!=Player(5) and Player(i)!=Player(8) and Player(i)!=Player(11) then
set index = index + 1
endif
endif
set i = i + 1
exitwhen i==12
endloop
static if ENABLE_MP then
if index > 2 then
call TimerStart(CreateTimer(), 0.03, false, function diainit)
else
call EnableUserControl(false)
call BJDebugMsg("- You need at least 3 players to start this game.")
call BJDebugMsg("- Fight againts Users or AIs.")
call BJDebugMsg("- Player 1 MUST be a User slot for picking game modes.")
call TimerStart(CreateTimer(), 3.0, false, function Defeat)
endif
else
call TimerStart(CreateTimer(), 0.03, false, function diainit)
endif
endif
endfunction
endlibrary
//TESH.scrollpos=147
//TESH.alwaysfold=0
library MbUpdates initializer init uses MultiboardSystem, RegisterPlayerUnitEvent, ColorUtils, Rewards, SimpleFunctions
globals
private constant hashtable HT = InitHashtable()
private constant integer CHILD_ID = 0x75396
private constant integer MAX = 13
private integer array KILLS
private integer array DEATHS
private integer array SCORE
private string SFX = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
endglobals
globals
//All of these are used by GameModesSetup library
public integer array ScoreP
public integer array ScoreP2
public real VarScoreMode = 0
public real VarKillMode = 0
public unit VarKillingUnit = null
endglobals
//2,5,8,11
private function EngagingPlayers takes integer i returns boolean
return (Player(i)==Player(2) or Player(i)==Player(5) or Player(i)==Player(8) or Player(i)==Player(11))
endfunction
private function MBSetup takes nothing returns nothing
local integer i = 0
call MbSetTitle(RandomColor(MAP_VERSION))
call MbSetupFirst(MAX, 8, true, false)
call MbSetTextValue(0,0,RandomColor("User"))
call MbSetTextValue(0,1,RandomColor("Hero Name"))
call MbSetTextValue(0,2,RandomColor("[L]"))
call MbSetTextValue(0,3,RandomColor("[HK]")) //Hero Kills
call MbSetTextValue(0,4,RandomColor("[K]")) //Total Kills
call MbSetTextValue(0,5,RandomColor("[D]")) //Deaths
call MbSetTextValue(0,6,RandomColor("Score"))
call MbSetTextValue(0,7,RandomColor("Status"))
call MbSetAllWidth(0.04)
loop
call MbSetIndividualWidths(i,0,0.03) //Slot
set i = i+1
exitwhen i==MAX
endloop
set i=0
loop
call MbSetIndividualWidths(i,1,0.1) //Hero Name
set i = i+1
exitwhen i==MAX
endloop
set i=0
loop
call MbSetIndividualWidths(i,6,0.05) //Score
set i = i+1
exitwhen i==MAX
endloop
set i=0
loop
set i = i+1
if GetPlayerSlotState(Player(i-1))==PLAYER_SLOT_STATE_PLAYING and not EngagingPlayers(i-1) then
call MbSetTextValue(i,1,FixedColor(i-1,"null"))
call MbSetTextValue(i,2,FixedColor(i-1,"0"))
call MbSetTextValue(i,3,FixedColor(i-1,"0"))
call MbSetTextValue(i,4,FixedColor(i-1,"0"))
call MbSetTextValue(i,5,FixedColor(i-1,"0"))
call MbSetTextValue(i,6,FixedColor(i-1,"0"))
call MbSetTextValue(i,7,FixedColor(i-1,"null"))
if GetPlayerController(Player(i-1))==MAP_CONTROL_COMPUTER then
call MbSetTextValue(i,0,FixedColor(i-1,"AI"))
else
call MbSetTextValue(i,0,FixedColor(i-1,"PL"))
endif
elseif not EngagingPlayers(i-1) then
call MbSetTextValue(i,0,"xxx")
call MbSetTextValue(i,1,"=====N/A=====")
call MbSetTextValue(i,2,"xxx")
call MbSetTextValue(i,3,"xxx")
call MbSetTextValue(i,4,"xxx")
call MbSetTextValue(i,5,"xxx")
call MbSetTextValue(i,6,"xxx")
call MbSetTextValue(i,7,"xxx")
endif
if EngagingPlayers(i-1) then
call MbSetTextValue(i,0, FixedColor(i-1,"==="))
call MbSetTextValue(i,1, FixedColor(i-1,"Ai-Engaging"))
call MbSetTextValue(i,2, FixedColor(i-1,"==="))
call MbSetTextValue(i,3, FixedColor(i-1,"==="))
call MbSetTextValue(i,4, FixedColor(i-1,"==="))
call MbSetTextValue(i,5, FixedColor(i-1,"==="))
call MbSetTextValue(i,6, FixedColor(i-1,"==="))
call MbSetTextValue(i,7, FixedColor(i-1,"==="))
endif
exitwhen i==MAX
endloop
//Setup Arrays:
loop
set KILLS[i] = 0
set DEATHS[i] = 0
set SCORE[i] = 0
set i = i+1
exitwhen i==MAX
endloop
//destroying the timer
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
endfunction
//=================================================================================================
//==========KILLS & DEATHS UPDATE:==========
//! textmacro FUNC takes func, u, update, n, bo
private function $func$Update takes nothing returns nothing
local unit u = Get$u$Unit()
local integer i = 0
if not udg_BossModeCheck then
loop
if GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING then
if GetOwningPlayer(Get$u$Unit())==Player(i) and FilterKilledUnit(u) then
if IsUnitEnemy(u, GetTriggerPlayer())==$bo$ then
//2,5,8,11 cant score!
if not EngagingPlayers(i) then
set $update$[i] = $update$[i] + 1
call MbSetTextValue(i+1,$n$, FixedColor(i, I2S($update$[i])))
//used only if Lk is true
if GameModesSetup_KlMode then
if GameModesSetup_RequiredKills==$update$[i] then
set VarKillingUnit = GetKillingUnit()
set VarKillMode = 1
endif
endif
endif
set u = null
endif
endif
endif
set i = i+1
exitwhen i==12
endloop
endif
set u = null
endfunction
//! endtextmacro
//! runtextmacro FUNC("Kills", "Killing", "KILLS", "4", "true")
//! runtextmacro FUNC("Deaths", "Trigger", "DEATHS", "5", "false")
private function HeroKillsUpdate takes nothing returns nothing
local unit u = GetKillingUnit()
local integer load
local integer pID
if not udg_BossModeCheck then
if IsUnitType(u, UNIT_TYPE_HERO) and FilterKilledUnit(GetTriggerUnit()) and IsUnitEnemy(u,GetTriggerPlayer()) then
set pID = GetPlayerId(GetOwningPlayer(u))
call SaveInteger(HT, GetHandleId(u), CHILD_ID, LoadInteger(HT, GetHandleId(u), CHILD_ID)+1)
set load = LoadInteger(HT, GetHandleId(u), CHILD_ID)
call MbSetTextValue(pID+1,3, FixedColor(pID, I2S(load)))
endif
endif
set u = null
endfunction
//=================================================================================================
//==========HERO CLICKED, CHANGE NAME IN MULTIBOARD:==========
private function HeroPicked takes nothing returns nothing
local unit u
local integer id
local integer pID
local integer load
if not udg_BossModeCheck then
if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
set u = GetTriggerUnit()
if GetOwningPlayer(u)==GetTriggerPlayer() then
set pID = GetPlayerId(GetOwningPlayer(u))
set load = LoadInteger(HT, GetHandleId(u), CHILD_ID)
call MbSetTextValue(pID+1,1,FixedColor(pID, GetHeroProperName(u)))
call MbSetTextValue(pID+1,2,FixedColor(pID, I2S(GetHeroLevel(u))))
call MbSetTextValue(pID+1,3,FixedColor(pID, I2S(load))) //Hero Kills
call MbSetTextValue(pID+1,7,FixedColor(pID, "Alive"))
endif
endif
endif
set u = null
endfunction
//=================================================================================================
//==========SCORE UPDATES: Caravan Enters Player Base==========
//Base 2,5,8,11
//! textmacro Func takes F,pID,pID2
private function FilterBase$F$ takes nothing returns boolean
if not udg_BossModeCheck then
if GetTriggerUnit()==udg_Caravan then
call ClearTextMessages()
//Updates Score for Players 0,3,6,9
if GetPlayerSlotState(Player($pID$))==PLAYER_SLOT_STATE_PLAYING then
set SCORE[$pID$] = SCORE[$pID$] + 1
call MbSetTextValue($pID$+1, 6, FixedColor($pID$, I2S(SCORE[$pID$])))
//this will be used for ScoreMode
set ScoreP[$pID$] = SCORE[$pID$]
call RewScore($pID$, ScoreP[$pID$])
endif
//Updates Score for Players 1,4,7,10
if GetPlayerSlotState(Player($pID2$))==PLAYER_SLOT_STATE_PLAYING then
set SCORE[$pID2$] = SCORE[$pID2$] + 1
call MbSetTextValue($pID2$+1, 6, FixedColor($pID2$, I2S(SCORE[$pID2$])))
set ScoreP2[$pID2$] = SCORE[$pID2$]
call RewScore($pID2$, ScoreP[$pID2$])
endif
call IssueImmediateOrder(udg_Caravan, "stop")
call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(udg_Caravan), GetUnitY(udg_Caravan)))
call SetUnitPosition(udg_Caravan, 0, -700)
call StartSound(udg_SND_Warning)
//used only if ScoreMode is true
if GameModesSetup_ScMode then
set VarScoreMode = 1
endif
endif
endif
return false
endfunction
//! endtextmacro
//! runtextmacro Func("Team1","0","1")
//! runtextmacro Func("Team2","3","4")
//! runtextmacro Func("Team3","6","7")
//! runtextmacro Func("Team4","9","10")
//=================================================================================================
//==========HERO LEVEL UPDATE:==========
private function HeroLevelUpdate takes nothing returns nothing
local unit hero = GetTriggerUnit()
local integer pID
if not udg_BossModeCheck then
if IsUnitInGroup(hero, udg_MainHeroGroup) then
set pID = GetPlayerId(GetTriggerPlayer())
call MbSetTextValue(pID+1,2,FixedColor(pID, I2S(GetHeroLevel(hero))))
endif
endif
set hero = null
endfunction
private function InitRegions takes nothing returns nothing
local trigger t
local region array r
//===
//! textmacro R takes F, R
set t = CreateTrigger()
set r[$R$] = CreateRegion()
call RegionAddRect(r[$R$], gg_rct_CaravanEnters$F$)
call TriggerRegisterEnterRegion(t, r[$R$], null)
call TriggerAddCondition(t, function FilterBase$F$)
set r[$R$] = null
//! endtextmacro
//! runtextmacro R("Team1","1")
//! runtextmacro R("Team2","2")
//! runtextmacro R("Team3","3")
//! runtextmacro R("Team4","4")
//===
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function KillsUpdate)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function DeathsUpdate)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function HeroKillsUpdate)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SELECTED, function HeroPicked)
call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_LEVEL, function HeroLevelUpdate)
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
set t = null
endfunction
private function init takes nothing returns nothing
if not ENABLE_TEST then
call TimerStart(CreateTimer(), 0., false, function MBSetup)
call TimerStart(CreateTimer(), 0., false, function InitRegions)
endif
endfunction
endlibrary
//TESH.scrollpos=3
//TESH.alwaysfold=0
library IntroCreation uses AISetup, PreloadUtils, BossBattle, RemoveComputer
globals
private timerdialog temptimerdialog
private integer array AiFirst
private group AI_GRP //hero AI only
private Table aitimer
endglobals
private function UnitOrderNotChannel takes integer order returns boolean
//starfall, tranquility, blizzard, rain of fire, earthquake, channel, tornado, drain
return not (order==852183 or order==854184 or order==852089 or order==852238 or order==852121 /*
*/ or order==852600 or order==852597 or order==852593 or order==852487)
endfunction
private function AIHeroAppear takes nothing returns nothing
local integer ID = GetHandleId(GetExpiredTimer())
local integer pID = aitimer[ID]
local real xLoc = GetPlayerStartLocationX(Player(pID))
local real yLoc = GetPlayerStartLocationY(Player(pID))
local unit ai = CreateUnit(Player(pID), AiFirst[GetRandomInt(0,3)], xLoc, yLoc, 0) //creating AI's
//AI heroes is added to the MainHeroGroup, this will be recalled in other libraries
call GroupAddUnit(udg_MainHeroGroup, ai)
call GroupAddUnit(AI_GRP, ai)
call MbSetTextValue(pID+1,1,FixedColor(pID, GetHeroProperName(ai)))
call MbSetTextValue(pID+1,2,FixedColor(pID, I2S(GetHeroLevel(ai))))
call MbSetTextValue(pID+1,7,FixedColor(pID, "Alive"))
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
call aitimer.remove(pID)
if udg_BossModeCheck then
call SetHeroLevel(ai,10,true)
call SuspendHeroXP(ai, true)
call GroupAddUnit(BossBattle.aiGroup, ai)
call TimerStart(CreateTimer(), 2.5, true, function BossBattle.onLoopEngage)
endif
set ai = null
endfunction
private function AIHeroEngaging takes nothing returns nothing
if UnitOrderNotChannel(GetUnitCurrentOrder(GetEnumUnit())) then
call IssuePointOrder(GetEnumUnit(), "attack", GetUnitX(udg_Caravan), GetUnitY(udg_Caravan))
endif
endfunction
private function PingCaravan takes nothing returns nothing
call ForGroup(AI_GRP, function AIHeroEngaging)
call PingMinimap(GetUnitX(udg_Caravan), GetUnitY(udg_Caravan), 1)
endfunction
//2,5,8,11
private function NearCaravanFilter takes integer i returns integer
local integer ret
if i==0 or i==1 then
set ret = 2
elseif i==3 or i==4 then
set ret = 5
elseif i==6 or i==7 then
set ret = 8
elseif i==9 or i==10 then
set ret = 11
endif
return ret
endfunction
private function NearCaravanNow takes nothing returns boolean
local unit u = GetTriggerUnit()
if IsUnitType(u, UNIT_TYPE_HERO) then
call IssuePointOrderLoc(udg_Caravan, "move", udg_Base[NearCaravanFilter(GetPlayerId(GetOwningPlayer(u)))])
endif
set u = null
return false
endfunction
//starts after timer (START), 60 seconds
private function SetupAll takes nothing returns nothing
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
call DestroyTimerDialog(temptimerdialog)
//Score, Level, Kills Modes
if udg_CheckMode then
call EngageAI() //runs engaging AI's
set udg_Caravan = CreateUnit(Player(15), 'h000', 0, -700, 0)
set udg_HeroIndexDummy = CreateUnit(Player(15), 'h004', 0, -700, 0)
call TimerStart(CreateTimer(), 3, true, function PingCaravan)
call TriggerRegisterUnitInRange(CreateTrigger(), udg_Caravan, 250, function NearCaravanNow)
else
//Boss and HeroArena Modes - remove the caravan here
if udg_BossMode==0 then
//HERO ARENA MODE HERE !!! NOT YET DONE !!!
else
//udg_BossMode is integer determines what boss is created
call BossBattle.bossbattleOn(udg_BossMode)
endif
endif
endfunction
//THIS SHOULD BE CALLED AFTER THE TIMER:
private function SetupFirst takes nothing returns nothing
local timer tm1 = CreateTimer()
local timer tm2
local integer i = 0
local real xLoc
local real yLoc
local unit u
local unit farm
set AI_GRP = CreateGroup()
set aitimer = Table.create()
call TimerStart(tm1, START_GAME, false, function SetupAll)
set temptimerdialog = CreateTimerDialog(tm1)
call TimerDialogSetTitle(temptimerdialog, "Starting In")
call TimerDialogDisplay(temptimerdialog, true)
//call DialogInit() //runs setup dialog
loop
if GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING and Player(i)!=Player(2) and Player(i)!=Player(5) and Player(i)!=Player(8) and Player(i)!=Player(11) then
set xLoc = GetPlayerStartLocationX(Player(i))
set yLoc = GetPlayerStartLocationY(Player(i))
if GetPlayerController(Player(i))==MAP_CONTROL_USER then
set farm = CreateUnit(Player(i), 'hhou', xLoc, yLoc, 0)
call UnitAddAbility(farm, 'Aloc')
call ShowUnit(farm, false)
set farm = null
else
//creates AI hero here
//MainHeroGroup
set tm2 = CreateTimer()
set aitimer[GetHandleId(tm2)] = i
call TimerStart(tm2, START_GAME+2, false, function AIHeroAppear)
set tm2 = null
endif
set u = null
endif
set i = i+1
exitwhen i==12
endloop
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
set tm1 = null
endfunction
function IntroCreation takes nothing returns nothing
call TimerStart(CreateTimer(), 0.1, false, function SetupFirst)
//setup AI heroes
set AiFirst[0] = 'Hgam' //Ghost Arhmage
set AiFirst[1] = 'Opgh' //Chaos Blademaster
set AiFirst[2] = 'Uktl' //Ghost Necromancer
set AiFirst[3] = 'Ekgg' //Ghost Keeper of the Grove
//Preloading things
call PreloadUnit('h000')
call PreloadUnit('Hgam')
call PreloadUnit('Opgh')
call PreloadUnit('Uktl')
call PreloadUnit('Ekgg')
endfunction
//This is only at BossMode
function MakeAllAlly takes nothing returns nothing
local integer i = 0
local unit first
loop
call SetPlayerAlliance(Player(0),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(1),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(2),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(3),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(4),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(5),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(6),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(7),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(8),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(9),Player(i),ALLIANCE_PASSIVE,true)
call SetPlayerAlliance(Player(10),Player(i),ALLIANCE_PASSIVE,true)
set i = i + 1
exitwhen i==11
endloop
set i = 9
loop
call SetPlayerAlliance(Player(9),Player(i),ALLIANCE_PASSIVE,false)
call SetPlayerAlliance(Player(10),Player(i),ALLIANCE_PASSIVE,false)
call SetPlayerAlliance(Player(11),Player(i),ALLIANCE_PASSIVE,false)
set i = i + 1
exitwhen i==11
endloop
//===last to be called
call IntroCreation()
call RemoveComputer.playerSetup()
endfunction
endlibrary
//TESH.scrollpos=62
//TESH.alwaysfold=0
library AISetup uses RegisterPlayerUnitEvent
globals
private group array WaveGroup
private integer array UnitCount
private integer array WaveUnit
endglobals
//! textmacro CR takes U, X, Y, PLAYER
set i = 0
loop
set u = CreateUnit(Player($U$), WaveUnit[i], $X$, $Y$, 0)
call IssuePointOrder(u, "attack", GetUnitX(udg_Caravan), GetUnitY(udg_Caravan))
call GroupAddUnit(WaveGroup[$PLAYER$], u)
set UnitCount[$PLAYER$] = UnitCount[$PLAYER$] + 1
set i = i+1
exitwhen i==MAX_UNIT
endloop
//! endtextmacro
//! textmacro WAVE takes PLAYER
private function UnitCount$PLAYER$ takes nothing returns nothing
if IsUnitInGroup(GetTriggerUnit(), WaveGroup[$PLAYER$]) then
set UnitCount[$PLAYER$] = UnitCount[$PLAYER$] - 1
call GroupRemoveUnit(WaveGroup[$PLAYER$], GetTriggerUnit())
endif
endfunction
//! endtextmacro
//=================================================================================
//=====Ai Engages to the Caravan:
private function WaveGuardCaravan takes nothing returns nothing
if GetUnitCurrentOrder(GetEnumUnit())==0 or GetUnitCurrentOrder(GetEnumUnit())==null then
call IssuePointOrder(GetEnumUnit(), "attack", GetUnitX(udg_Caravan), GetUnitY(udg_Caravan))
endif
endfunction
private function WaveAttackLoop takes nothing returns nothing
call ForGroup(WaveGroup[0], function WaveGuardCaravan)
call ForGroup(WaveGroup[1], function WaveGuardCaravan)
call ForGroup(WaveGroup[2], function WaveGuardCaravan)
call ForGroup(WaveGroup[3], function WaveGuardCaravan)
endfunction
//=====Wave creation for Ai:
private function WaveCreationLoop takes nothing returns nothing
local integer i
local unit u
if UnitCount[0] <= MAX_UNIT_FULL then
//! runtextmacro CR("2", "-8242", "8374", "0")
endif
if UnitCount[1] <= MAX_UNIT_FULL then
//! runtextmacro CR("5", "8900", "7200", "1")
endif
if UnitCount[2] <= MAX_UNIT_FULL then
//! runtextmacro CR("8", "-9573", "-8727", "2")
endif
if UnitCount[3] <= MAX_UNIT_FULL then
//! runtextmacro CR("11", "7813", "-10000", "3")
endif
endfunction
//=====UPODATES THE WAVE MAX_UNITS AND REMOVES FROM GROUP
//! runtextmacro WAVE("0")
//! runtextmacro WAVE("1")
//! runtextmacro WAVE("2")
//! runtextmacro WAVE("3")
function EngageAI takes nothing returns nothing
local integer i = 0
local unit u
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function UnitCount0)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function UnitCount1)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function UnitCount2)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function UnitCount3)
call TimerStart(CreateTimer(), 3, true, function WaveAttackLoop)
call TimerStart(CreateTimer(), 15, true, function WaveCreationLoop)
set WaveUnit[0] = 'nwlg'
set WaveUnit[1] = 'nwlg'
set WaveUnit[2] = 'nfsp'
set WaveUnit[3] = 'nban'
set WaveUnit[4] = 'nbrg'
set WaveUnit[5] = 'nhrr'
set WaveGroup[0] = CreateGroup()
set WaveGroup[1] = CreateGroup()
set WaveGroup[2] = CreateGroup()
set WaveGroup[3] = CreateGroup()
set UnitCount[0] = 0
set UnitCount[1] = 0
set UnitCount[2] = 0
set UnitCount[3] = 0
call WaveCreationLoop()
//Preloading
loop
set u = CreateUnit(Player(15), WaveUnit[i], 0, 0, 0)
call KillUnit(u)
call ShowUnit(u, false)
set u = null
set i = i+1
exitwhen i==MAX_UNIT
endloop
endfunction
endlibrary
//TESH.scrollpos=1
//TESH.alwaysfold=0
//This is called after BossMode and HeroArenaMode
library RemoveComputer
struct RemoveComputer
//removes player 2,5,8,11
static method filterUnits takes unit u, player p returns boolean
return UnitAlive(u) and (p==Player(2) or p==Player(5) or p==Player(8) or p==Player(11))
endmethod
//sets player ally and transfer of control
static method playerSetup takes nothing returns nothing
local unit first
call GroupEnumUnitsInRect(bj_lastCreatedGroup, GetWorldBounds(), null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if filterUnits(first, GetOwningPlayer(first)) then
call RemoveUnit(first)
endif
call GroupRemoveUnit(bj_lastCreatedGroup,first)
endloop
endmethod
endstruct
endlibrary
//TESH.scrollpos=33
//TESH.alwaysfold=0
library BossBattle uses GuardAoe, Table, ColorUtils, IsUnitChanneling
struct BossDies
static method dies takes nothing returns boolean
local integer pID = 11
loop
exitwhen pID==0
set pID = pID - 1
call CustomVictoryBJ(Player(pID), true, true)
endloop
return false
endmethod
static method bossDies takes unit boss returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterUnitEvent(t,boss,EVENT_UNIT_DEATH)
call TriggerAddCondition(t,function thistype.dies)
set t = null
endmethod
endstruct
struct BossBattle
static unit Boss = null
static group aiGroup = CreateGroup()
static constant integer fireBoss = 'Orex' //based on Rexxar
static constant integer iceBoss = 'Orkn' //based on Shadow Hunter
static method periodic takes nothing returns nothing
if not IsUnitChanneling(GetEnumUnit()) then
call IssuePointOrder(GetEnumUnit(), "attack", GetUnitX(Boss), GetUnitY(Boss))
endif
endmethod
static method onLoopEngage takes nothing returns nothing
call ForGroup(aiGroup, function thistype.periodic)
endmethod
static method bossbattleOn takes integer boss returns nothing
local integer pID = 0
local string n = ""
call ClearTextMessages()
//0=none, 1=point, 2=unit
if boss==1 then
set n = "Fire Boss"
set Boss = CreateUnit(Player(11),fireBoss,0,-700,0)
call CastSpellSystem.castEnemy(Boss,852588,852218,852119)
//'A03M' - Fire Nova (howl of terror) 852588, none
//'A03J' - Dual Adaptation (carrion swarm) 852218, point
//'A03N' - Spread Shot (chain lightning) 852119, unit
elseif boss==2 then
set n = "Ice Boss"
set Boss = CreateUnit(Player(11),iceBoss,0,-700,0)
call CastSpellSystem.castEnemy(Boss,852588,852218,852226)
//'A007' - Cold Vortex (holw of terror) 852588, none
//'A03Q' - Back Shot (crushing wave) 852218, point
//'A03S' - Shattering Frost (frost nova) 852226, unit
endif
//================
call BJDebugMsg(FixedColor(36, GetHeroProperName(Boss)+" ("+n+") "+"created."))
call BJDebugMsg("- Team with all players to kill the Boss.")
call FogEnable(false)
call FogMaskEnable(false)
call SetHeroLevel(Boss,BOSS_LEVEL,true)
call GuardAoe.guardAoe(Boss,2000.)
call BossDies.bossDies(Boss)
endmethod
endstruct
endlibrary
//TESH.scrollpos=24
//TESH.alwaysfold=0
library Rewards initializer init uses ColorUtils, MuiDummyCasters, PreloadUtils, SimpleFunctions
//used byMbUpdates
globals
//dummies
private constant real DUR = 60.
private constant integer DUMMY_ID = 'h004'
private constant integer REVEAL_ID = 'A02C' //Far sight, 852122
private constant integer DAM_ID = 'A02D' //Command Aura, increases damage
private constant integer MOV_ID = 'S004' //Move Speed Aura, increase movement
private constant integer ATK_ID = 'S003' //Attack Speed Aura
private constant integer MAN_ID = 'A02G' //Mana Regen
private constant integer LYF_ID = 'A02F' //Life Regen
endglobals
globals
private constant integer MAX_GOLD = 100
private constant integer MAX_LUMBER = 50
private constant integer REWARD_INTERVAL = 5 //should be 5
private integer array Rew_Score
private integer array Rew_ScoreInterval
endglobals
private function CUnit takes integer pID, integer abilityID, real duration returns nothing
local unit dummy = CreateUnit(Player(pID),DUMMY_ID,0,0,0)
call UnitAddAbility(dummy, abilityID)
call UnitApplyTimedLife(dummy, 'BTLF', duration)
set dummy = null
endfunction
private function CMsg takes integer pID, string abil returns nothing
local integer i = 11
local string msg = FixedColor(pID, "Player "+I2S(pID+1)) + " and it's allies got an " + FixedColor(pID, abil) + " aura, lasts 60 seconds."
call ClearTextMessages()
loop
call DisplayTextToPlayer(Player(i), 0, 0, msg)
exitwhen i==0
set i = i - 1
endloop
endfunction
//=====REWARD SCORE:=====
//used by MbUpdates
function RewScore takes integer pID, integer score returns nothing
local integer ran1 = GetRandomInt(0,1) //should be 0,1
local integer random
local integer gold
local integer lumber
local integer rewardAmt
local string msg
local string msgrew
local integer i
set Rew_Score[pID] = Rew_Score[pID] + 1
//call BJDebugMsg(I2S(Rew_ScoreInterval[pID]))
if Rew_Score[pID]==Rew_ScoreInterval[pID] then
set Rew_ScoreInterval[pID] = Rew_ScoreInterval[pID] + REWARD_INTERVAL
if ran1==0 then
//Resource setup
set random = GetRandomInt(0,3)
if random==0 or random==1 then
set gold = GetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_GOLD)
set rewardAmt = GetRandomInt(10, MAX_GOLD)
call SetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_GOLD, gold + rewardAmt)
set msgrew = " gold"
elseif random==2 or random==3 then
set lumber = GetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_LUMBER)
set rewardAmt = GetRandomInt(10, MAX_LUMBER)
call SetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_LUMBER, lumber + rewardAmt)
set msgrew = " lumber"
endif
//FixedColor takes integer colorindex, string s returns string
call ClearTextMessages()
set msg = FixedColor(pID, "Player "+I2S(pID+1)) + " got " + FixedColor(pID, I2S(rewardAmt)+msgrew)
set i = 11
loop
call DisplayTextToPlayer(Player(i), 0, 0, msg)
exitwhen i==0
set i = i - 1
endloop
else
//Ability setup
set random = GetRandomInt(0,6) //should be 0,6
if random==0 then
call MuiDummyCasters.hitPoint(Player(pID),0,0,0,0,REVEAL_ID,852122,1)
//call MuiDummyCasters.hitPoint(Player(pID),0,0,0,0,REVEAL_ID,852122,1)
call BJDebugMsg(FixedColor(pID, "Player "+I2S(pID+1)) + " and it's allies can see all locations, lasts 60 seconds.")
elseif random==2 then
call CUnit(pID, DAM_ID, DUR)
call CMsg(pID, "increased damage!")
elseif random==3 then
call CUnit(pID, MOV_ID, DUR)
call CMsg(pID, "increased movement speed!")
elseif random==4 then
call CUnit(pID, ATK_ID, DUR)
call CMsg(pID, "increased attack rate!")
elseif random==5 then
call CUnit(pID, MAN_ID, DUR)
call CMsg(pID, "increased mana regeneration rate!")
elseif random==6 then
call CUnit(pID, LYF_ID, DUR)
call CMsg(pID, "increased life regeneration rate!")
endif
endif
endif
endfunction
//=====REWARD KILLS:=====
//=====Every kills got a reward either gold or lumber
private function RewKills takes nothing returns nothing
local unit kU = GetKillingUnit()
local unit killed = GetTriggerUnit()
local integer pID
local integer random
local integer rewardAmt
local integer resource
if IsUnitEnemy(kU, GetTriggerPlayer()) and FilterKilledUnit(killed) then
set random = GetRandomInt(0,3)
set pID = GetPlayerId(GetOwningPlayer(kU))
if IsUnitType(killed, UNIT_TYPE_HERO) then
set rewardAmt = GetRandomInt(15, 35)
else
set rewardAmt = GetRandomInt(2, 9)
endif
if random==0 or random==1 then
//call DisplayTextToPlayer(Player(pID),0,0,"You earned "+I2S(rewardAmt)+" gold!")
set resource = GetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_GOLD)
call SetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_GOLD, resource + rewardAmt)
else
//call DisplayTextToPlayer(Player(pID),0,0,"You earned "+I2S(rewardAmt)+" lumber!")
set resource = GetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_LUMBER)
call SetPlayerState(Player(pID), PLAYER_STATE_RESOURCE_LUMBER, resource + rewardAmt)
endif
endif
set kU = null
set killed = null
endfunction
private function init takes nothing returns nothing
local integer i = 11
loop
set Rew_Score[i] = 0
set Rew_ScoreInterval[i] = REWARD_INTERVAL
exitwhen i==0
set i = i - 1
endloop
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function RewKills)
endfunction
endlibrary
//TESH.scrollpos=81
//TESH.alwaysfold=0
/*
===Dynamic Timer v1.3
===Created by Mckill2009
INPIRED BY:
- CTL by Nesthaurus
- Dynamic GUI Indexing by Hanky
API: Module
implement DTloop
- Not optional, this needs to be on TOP of implementations
- You may declare your locals here
- This is where your condition is generated/running, this by default is TRUE
- If it encounters FALSE on the first "if", statement, it will automatically deindexed
- Take note that you dont need to put an "endif" to your condition
Sample:
implement DTloop
local unit x = GetUnitX(.hero)
local unit y = GetUnitY(.hero)
if UnitAlive(.hero) then
YOUR ACTIONS HERE!
implement DTend
implement DTnulls
- Optional, used to null your local variables created via DTloop
implement DTend
- Not optional, this needs to be BELOW of DTloop or implementations
- This calls the "create(real variable)", this is where a timer interval is dynamic
API: Methods
static method create takes real interval returns thistype
- By default, timer runs at INTERVAL (0.03125)
- The "interval" simply delays the 0.03125
CREDITS:
- Deaod for suggesting standard methods
*/
library DynamicTimer
globals
//These should NOT be modified
private constant integer MAX_INDEX = 8190
private constant real INTERVAL = 0.03125
endglobals
module DTloop //not optional
readonly boolean bol
readonly real gap
readonly real in
static boolean chkindex = true
static integer index1 = 0 //
static integer array indexAr
static timer t
method chk takes nothing returns boolean
endmodule
module DTnulls //optional
return true
endif
endmodule
module DTend //not optional
implement DT_DO_NOT_IMPLEMENT_THIS
endif
endif
exitwhen looper==index1
endloop
endmethod
private static method create takes real interval returns thistype
local thistype this
if (index1 < MAX_INDEX) then
set this = allocate()
set .gap = 0
set .in = interval
set .bol = true
if index1==0 then
set t = CreateTimer()
call TimerStart(t,INTERVAL,true,function thistype.looper)
endif
set index1 = index1 + 1
set indexAr[index1] = this
elseif chkindex then
set chkindex = false
debug call BJDebugMsg("ERROR: Struct has "+ I2S(MAX_INDEX)+ " index, unable to allocate!: TIMER DESTROYED.")
call PauseTimer(t)
call DestroyTimer(t)
endif
return this
endmethod
endmodule
//NEVER IMPLEMENT THIS
module DT_DO_NOT_IMPLEMENT_THIS //XD
implement DTnulls
set .bol = false
return .bol
endmethod
static method looper takes nothing returns nothing
local thistype this
local integer looper = 0
loop
set looper = looper + 1
set this = indexAr[looper]
set .gap = .gap + INTERVAL
if .gap >= .in then
set .gap = 0
call chk()
if not .bol then
call .destroy()
set indexAr[looper] = indexAr[index1]
set indexAr[index1] = this
set looper = looper - 1
set index1 = index1 - 1
if index1==0 then
call PauseTimer(t)
call DestroyTimer(t)
endif
endmodule
endlibrary
//TESH.scrollpos=3
//TESH.alwaysfold=0
//TimerLooper v2.0
//Created by Mckill2009
//for hashtable usage
library TimerLooper
globals
private hashtable H = InitHashtable()
private integer index = 0
private timer array Timers
//private integer ind = 0 //for testing only, not needed
endglobals
function LoadData takes timer t returns integer
return LoadInteger(H, GetHandleId(t), 0)
endfunction
function SaveData takes timer t, integer value returns nothing
call SaveInteger(H, GetHandleId(t), 0, value)
endfunction
function StopTimer takes timer t returns nothing
call PauseTimer(t)
set Timers[index] = t
set index = index - 1
call FlushChildHashtable(H, GetHandleId(t))
endfunction
function GetTimer takes nothing returns timer
set index = index + 1
if Timers[index]==null then
//for testing only, not needed
//set ind = ind+1
//call BJDebugMsg("Timers Created "+I2S(ind))
//======================
return CreateTimer()
endif
return Timers[index]
endfunction
endlibrary
//TESH.scrollpos=12
//TESH.alwaysfold=0
library SimpleFunctions
//! textmacro FOG_ADD takes X, Y, A
call GroupEnumUnitsInRange(bj_lastCreatedGroup, $X$, $Y$, $A$, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
//! endtextmacro
//! textmacro FOG_REMOVE
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
//! endtextmacro
function FilterEnemyAndSpellLevel takes player p, unit u, integer spellID returns boolean
return IsUnitEnemy(u, p) and GetUnitAbilityLevel(u, spellID) > 0
endfunction
function ManaNeeded takes unit u, real m returns boolean
return (GetUnitState(u, UNIT_STATE_MANA) > m)
endfunction
function SpellLevel takes unit u, integer spellID returns boolean
return GetUnitAbilityLevel(u, spellID) > 0
endfunction
private function G takes integer i returns real
return 5 + i * 5.
endfunction
function GetChance takes unit u, integer spellid returns boolean
if GetUnitAbilityLevel(u, spellid) > 0 and GetRandomInt(1, 100) <= G(GetUnitAbilityLevel(u, spellid)) then
return true
endif
return false
endfunction
function GetChance2 takes integer i returns boolean
return GetRandomInt(1, 100) <= G(i)
endfunction
function FilterKilledUnit takes unit u returns boolean
return not IsUnitIllusion(u) and (GetUnitAbilityLevel(u, 'Aloc')==0) /*
*/ and GetOwningPlayer(u)!=Player(12) and GetOwningPlayer(u)!=Player(15) /*
*/ and not (GetUnitTypeId(u)=='h00U') and not (GetUnitTypeId(u)=='n00A') /*
*/ and not (GetUnitTypeId(u)=='n007')
endfunction
endlibrary
//TESH.scrollpos=10
//TESH.alwaysfold=0
/*
===IsUnitEngageable v1.1
===Created by: Mckill2009
HOW TO INSTALL:
- Copy this script to your trigger editor via custom text
- Copy the custom abilty from the object editor named 'IsUnitEngageable' to your map
- Make sure you change also the rawID below (SPELL_ID) if you change the rawID of your imported ability
- Done!
API:
function IsUnitEngageable takes unit u returns boolean
Undetects units that is:
- Invulnerable
- Burrowed
- Invisible
- Ethereal
- Have locust
*/
library IsUnitEngageable
globals
//Custom ability based on Unholy Frenzy
private constant integer SPELL_ID = 'A03O' //rawID
//Unit ID based on priest, never change this!
private constant integer DUMMY_ID = 'hmpr'
private unit DUMMY
endglobals
function IsUnitEngageable takes unit u returns boolean
call SetUnitPosition(DUMMY, GetUnitX(u), GetUnitY(u))
return IssueTargetOrderById(DUMMY, 852209, u) and not IsUnitType(u,UNIT_TYPE_ETHEREAL)
endfunction
struct onInit
static method onInit takes nothing returns nothing
set DUMMY = CreateUnit(Player(15), DUMMY_ID, 0,0,0)
call UnitAddAbility(DUMMY, SPELL_ID)
call UnitAddAbility(DUMMY, 'Aloc')
call ShowUnit(DUMMY, false)
endmethod
endstruct
endlibrary
//TESH.scrollpos=7
//TESH.alwaysfold=0
//System: Fundamentals
//Made by Mckill2009
//These are my simple functions/conversions, very easy to use
library Fundamentals
globals
private location LOC = Location(0,0)
endglobals
function FUN_UnitAlive takes unit u returns boolean
return not (IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId(u)==0)
endfunction
function FUN_GetParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)//Standard parabola
endfunction
function FUN_GetUnitZ takes unit u, real height returns real
call MoveLocation(LOC, GetUnitX(u), GetUnitY(u))
return GetLocationZ(LOC) + height
endfunction
function FUN_GetAngle takes real x1, real y1, real x2, real y2 returns real
return Atan2(y2-y1, x2-x1)
endfunction
function FUN_GetDistance takes real x1, real y1, real x2, real y2 returns real
return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)
endfunction
function FUN_MoveDummyXY takes unit u, real xPoint, real yPoint, real speed, real angle returns nothing
call SetUnitX(u, xPoint + speed * Cos(angle))
call SetUnitY(u, yPoint + speed * Sin(angle))
endfunction
function FUN_GetAngleUnitFacing takes unit u returns real
return GetUnitFacing(u) * bj_DEGTORAD
endfunction
function FUN_MakeUnitFly takes unit u returns nothing
if UnitAddAbility(u, 'Arav') then
call UnitRemoveAbility(u, 'Arav')
endif
endfunction
function FUN_UnitAddLocust takes unit u returns nothing
call UnitAddAbility(u, 'Aloc')
endfunction
function FUN_UnitRemoveLocust takes unit u returns nothing
call ShowUnit(u, false)
call UnitRemoveAbility(u, 'Aloc')
call ShowUnit(u, true)
endfunction
function FUN_SpecialEffectXY takes string sfx, real x, real y returns nothing
call DestroyEffect(AddSpecialEffect(sfx, x, y))
endfunction
function FUN_SpecialEffectTarget takes unit u, string sfx, string attachment returns nothing
call DestroyEffect(AddSpecialEffectTarget(sfx, u, attachment))
endfunction
function FUN_OrganicUnits takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and FUN_UnitAlive(u)
endfunction
function FUN_LifeTaken takes unit u returns boolean
return (GetWidgetLife(u) < (GetUnitState(u, UNIT_STATE_MAX_LIFE)-50))
endfunction
function FUN_DamageGroundUnits takes unit source, unit target, real d, attacktype atk, damagetype dmg returns nothing
if IsUnitEnemy(source, GetOwningPlayer(target)) and IsUnitType(target, UNIT_TYPE_GROUND) and FUN_UnitAlive(target) then
call UnitDamageTarget(source, target, d, false, false, atk, dmg, null)
endif
endfunction
function FUN_DamageTarget takes unit source, unit target, real d, attacktype atk, damagetype dmg returns nothing
call UnitDamageTarget(source, target, d, false, false, atk, dmg, null)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
===Aura Level Detection by Mckill2009
WHAT IS THIS:
- Intead of making many buff ID's in the object editor, you could use this
PARAMETER EXPLANATION and API:
- forUnit (unit) = the unit who has the buff
- auraID (integer) = the BASE unit who gives the buff or has the spell
- buffID (integer) = the buff that will be detected
- aoe (real) = if your aura has 900 aoe, this should be 900 as well
local integer level = GetAuraLevel(forUnit, auraID, buffID, aoe)
CREDITS:
- Bribe (for the IMaxBJ info, which reduced the code a lot)
*/
library AuraLevel
function GetAuraLevel takes unit forUnit, integer auraID, integer buffID, real aoe returns integer
local unit first
local integer level = 0
if GetUnitAbilityLevel(forUnit, buffID) > 0 then
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(forUnit), GetUnitY(forUnit), aoe, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if not IsUnitType(first, UNIT_TYPE_DEAD) then
set level = IMaxBJ(level, GetUnitAbilityLevel(first, auraID))
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
return level
endfunction
endlibrary
//TESH.scrollpos=47
//TESH.alwaysfold=0
library GuardAoe uses Table, IsUnitEngageable, IsUnitChanneling
globals
private Table g
endglobals
struct GuardAoe
unit guard
unit target
real aoe
real aoef
real xbase
real ybase
real dur
static constant real in = 3
method filterU takes unit g, unit t returns boolean
return UnitAlive(t) and IsUnitEnemy(g,GetOwningPlayer(t)) and IsUnitEngageable(t)
endmethod
static method seekAoe takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = g[GetHandleId(t)]
local real x = GetUnitX(.guard)
local real y = GetUnitY(.guard)
local real distx
local unit first
if UnitAlive(.guard) then
if not IsUnitChanneling(.guard) then
set distx = (.xbase-x)*(.xbase-x)+(.ybase-y)*(.ybase-y)
if UnitAlive(.target) then
if distx < .aoe then
call IssuePointOrder(.guard,"attack",GetUnitX(.target),GetUnitY(.target))
else
set .target = null
call IssuePointOrder(.guard,"attack",.xbase,.ybase)
endif
else
call IssuePointOrder(.guard,"attack",.xbase,.ybase)
call GroupEnumUnitsInRange(bj_lastCreatedGroup,x,y,.aoef,null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if filterU(.guard,first) and first!=g.unit[GetHandleId(guard)] then
set .target = first
endif
call GroupRemoveUnit(bj_lastCreatedGroup,first)
endloop
endif
endif
else
call PauseTimer(t)
call DestroyTimer(t)
set .target = null
call .deallocate()
endif
set t = null
endmethod
static method guardAoe takes unit guard, real aoe returns nothing
local thistype this = allocate()
local timer t = CreateTimer()
set .guard = guard
set .target = null
set .aoe = (aoe-150)*(aoe-150)
set .aoef = aoe-150
set .xbase = GetUnitX(guard)
set .ybase = GetUnitY(guard)
set .dur = 5.0
set g.unit[GetHandleId(guard)] = guard
set g[GetHandleId(t)] = this
call TimerStart(t,in,true,function thistype.seekAoe)
set t = null
endmethod
private static method onInit takes nothing returns nothing
set g = Table.create()
endmethod
endstruct
endlibrary
//TESH.scrollpos=49
//TESH.alwaysfold=0
/*
MuiDummyCasters v4.4
Created by: Mckill2009
REQUIRES:
- Table by Bribe
- RegisterPlayerUnitEvent by Magtheridon96
INTRODUCTION:
- This System uses the FirstOfGroup native to take the caster from a group, then orders it to cast
a certain spell, instead of indexing the dummy.
- Very simple to use.
INSTRUCTIONS:
- Copy ALL that is in the "MuiDummyCasters" folder into your map.
- Enable the "MuiDummyCastersSetup", save the map and exit.
- Open your map again. Disable OR delete the "MuiDummyCastersSetup".
- Copy the required libraries Table and RegisterPlayerUnitEvent to your map
- In the object editor, the "DummyCaster(LUA)" should be there.
- DONE!
- Note: The raw code "dumy" can be used as a dummy unit for your entire map.
WARNING: Bugs may occur
- Please DO NOT name ANY of your custom unit's raw code as 'xcvb', coz it will screw everything.
The LUA SCRIPT will overwrite unit objects in your map if you do that.
- Since the dummy cannot move, it's best that the hitPoint and hitTarget is reachable, else
this will bug.
- The ability casted MUST have 0 cooldown.
API:
call MuiDummyCasters.hitTarget(owningplayer, target, xSource, ySource, abilityID, orderID, level)
call MuiDummyCasters.hitPoint(owningplayer, xSource, ySource, xDist, yDist, abilityID, orderID, level)
call MuiDummyCasters.hitNone(owningplayer, xSource, ySource, abilityID, orderID, level)
PARAMETEER EXPLANATION:
- owningplayer (player) - the owner of the casting unit
- target (unit) - the spelltarget
- xSource and ySource (real) - the coordinate where the dummy will be located
- xDist and yDist (real) - the coordinate where the dummy will cast the spell
- abilityID (integer) - the raw code of of the ability being cast
- orderID (integer) - the orderID of the abilityID
- level (integer) - the level of the abilityID
CREDITS:
- Bribe (for info about the 'Amov' ability remove)
*/
library MuiDummyCasters uses Table, RegisterPlayerUnitEvent
globals
//The DUMMY_CASTER raw ID is the only one you may adjust, NEVER touch the rest!
private TableArray mdc
private constant player OWNER = Player(15)
private constant integer DUMMY_CASTER = 'h004'
private group DummyTake = CreateGroup()
private unit dummy = null
//===FOR TESTING ONLY ON HOW MANY DUMMIES ARE CREATED:
private constant boolean DEBUG_MODE = false
private integer index = 0
endglobals
//! textmacro ISSUE takes order
local unit dum = thistype.takeDummyUnit()
call SetUnitPosition(dum, xSource, ySource)
call UnitAddAbility(dum, abilityID)
call SetUnitAbilityLevel(dum, abilityID, level)
call SetUnitOwner(dum, owningplayer, false)
call Issue$order$
set mdc[0][GetHandleId(dum)] = abilityID
//This is just a fail safe, in case the target is invulnerable, invisible or cannot be casted
if GetUnitCurrentOrder(dummy)==0 then
call thistype.refreshDummyUnit(dum)
endif
set dum = null
//! endtextmacro
struct MuiDummyCasters extends array
private static method refreshDummyUnit takes unit d returns nothing
local integer ID = GetHandleId(d)
call SetUnitOwner(d, OWNER, false)
call UnitRemoveAbility(d, mdc[0][ID])
call GroupAddUnit(DummyTake, d)
endmethod
private static method takeDummyUnit takes nothing returns unit
if FirstOfGroup(DummyTake)== null then
debug static if DEBUG_MODE then
debug set index = index + 1
debug call BJDebugMsg("only "+I2S(index) + " dummies created")
debug endif
set dummy = CreateUnit(OWNER, DUMMY_CASTER, 0, 0, 0)
call UnitRemoveAbility(dummy,'Amov')
else
//if group is not empty then it will pick the first dummy in the group
set dummy = FirstOfGroup(DummyTake)
call GroupRemoveUnit(DummyTake, dummy)
endif
return dummy
endmethod
private static method instantCastEnd takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit())==DUMMY_CASTER then
call thistype.refreshDummyUnit(GetTriggerUnit())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_ENDCAST, function thistype.instantCastEnd)
set mdc = TableArray[0x2000]
endmethod
//==================================
// 3 API functions you can use.
//==================================
static method hitTarget takes player owningplayer, unit target, real xSource, real ySource, integer abilityID, integer orderID, integer level returns nothing
//! runtextmacro ISSUE("TargetOrderById(dum, orderID, target)")
endmethod
static method hitPoint takes player owningplayer, real xSource, real ySource, real xDist, real yDist,integer abilityID, integer orderID, integer level returns nothing
//! runtextmacro ISSUE("PointOrderById(dum, orderID, xDist, yDist)")
endmethod
static method hitNone takes player owningplayer, real xSource, real ySource, integer abilityID, integer orderID, integer level returns nothing
//! runtextmacro ISSUE("ImmediateOrderById(dum, orderID)")
endmethod
endstruct
endlibrary
//TESH.scrollpos=85
//TESH.alwaysfold=0
//System Name: HashT v1.0 (One Hashtable for vJASS codes)
//Made By: Mckill2009
//Inspired by Bribe's New Table
//How do you like to create ONE hashtable for your entire vJASS codes or map?
//well, this system is just right and enough for you
//this is also GUI friendly
//As long as it has a unique childID and not flushed, it should'nt conflict things even if it has the same parentID,
//much more if it has different parentID
library HashT
globals
private constant hashtable HT = InitHashtable()
endglobals
//! textmacro ONE_HASH takes FuncName, Native, Prefix
function Set$FuncName$ takes integer parent, integer child, $Prefix$ value returns nothing
call Save$Native$(HT, parent, child, value)
endfunction
function Get$FuncName$ takes integer parent, integer child returns $Prefix$
return Load$Native$(HT, parent, child)
endfunction
//! endtextmacro
//! runtextmacro ONE_HASH("Integer", "Integer", "integer")
//! runtextmacro ONE_HASH("Real", "Real", "real")
//! runtextmacro ONE_HASH("Str", "Str", "string")
//! runtextmacro ONE_HASH("UnitHandle", "UnitHandle", "unit")
//! runtextmacro ONE_HASH("Boolean", "Boolean", "boolean")
//! runtextmacro ONE_HASH("AbilityHandle", "AbilityHandle", "ability")
//! runtextmacro ONE_HASH("ButtonHandle", "ButtonHandle", "button")
//! runtextmacro ONE_HASH("GroupHandle", "GroupHandle", "group")
//! runtextmacro ONE_HASH("ImageHandle", "ImageHandle", "image")
//! runtextmacro ONE_HASH("ItemHandle", "ItemHandle", "item")
//! runtextmacro ONE_HASH("ItemPoolHandle", "ItemPoolHandle", "itempool")
//! runtextmacro ONE_HASH("LeaderboardHandle", "LeaderboardHandle", "leaderboard")
//! runtextmacro ONE_HASH("LightningHandle", "LightningHandle", "lightning")
//! runtextmacro ONE_HASH("LocationHandle", "LocationHandle", "location")
//! runtextmacro ONE_HASH("MultiboardHandle", "MultiboardHandle", "multiboard")
//! runtextmacro ONE_HASH("PlayerHandle", "PlayerHandle", "player")
//! runtextmacro ONE_HASH("QuestHandle", "QuestHandle", "quest")
//! runtextmacro ONE_HASH("RectHandle", "RectHandle", "rect")
//! runtextmacro ONE_HASH("SoundHandle", "SoundHandle", "sound")
//! runtextmacro ONE_HASH("RegionHandle", "RegionHandle", "region")
//! runtextmacro ONE_HASH("TextTagHandle", "TextTagHandle", "texttag")
//! runtextmacro ONE_HASH("TimerDialogHandle", "TimerDialogHandle", "timerdialog")
//! runtextmacro ONE_HASH("TimerHandle", "TimerHandle", "timer")
//! runtextmacro ONE_HASH("TrackableHandle", "TrackableHandle", "trackable")
//! runtextmacro ONE_HASH("WidgetHandle", "WidgetHandle", "widget")
//! runtextmacro ONE_HASH("EffectHandle", "EffectHandle", "effect")
//=====RemoveSaved and HaveSaved:
//! textmacro SR_HASH takes TypeName
function Has$TypeName$ takes integer parent, integer child returns boolean
return HaveSaved$TypeName$(HT, parent, child)
endfunction
function Remove$TypeName$ takes integer parent, integer child returns nothing
call RemoveSaved$TypeName$(HT, parent, child)
endfunction
//! endtextmacro
//! runtextmacro SR_HASH("Integer")
//! runtextmacro SR_HASH("Real")
//! runtextmacro SR_HASH("String")
//! runtextmacro SR_HASH("Boolean")
//! runtextmacro SR_HASH("Handle")
function Flush takes integer parent returns nothing
call FlushChildHashtable(HT, parent)
endfunction
function RemoveTimer takes timer t, integer ID returns nothing
call Flush(ID)
call PauseTimer(t)
call DestroyTimer(t)
endfunction
function RemoveFromGroupAndEnd takes integer index, group g, unit u, timer t returns integer
set index = index - 1
call GroupRemoveUnit(g, u)
if index==0 then
call PauseTimer(t)
endif
return index
endfunction
function AddToGroupAndStart takes integer index, group g, unit u, timer t, real interval, boolean b, code func returns integer
if not IsUnitInGroup(u, g) then
call GroupAddUnit(g, u)
if index==0 then
call TimerStart(t, interval, b, func)
endif
set index = index + 1
endif
return index
endfunction
endlibrary
//TESH.scrollpos=41
//TESH.alwaysfold=0
/*
================QuestUtils===============
==========Created by Mckill2009==========
This is an alternative to GUI Quest creation, very easy to use, the quest variable is indexed
and can be retrieved by integers...
*/
library QuestUtils
globals
private constant integer MAX_INDEX = 500 //Max quest to be destroyed
private quest array Qst
private questitem array QstItem
endglobals
//! textmacro Q takes Func, Snd
function Q$Func$ takes integer qindex returns nothing
call QuestSet$Func$(Qst[qindex], true)
call StartSound(bj_quest$Snd$Sound)
call FlashQuestDialogButton()
endfunction
//! endtextmacro
//! runtextmacro Q("Completed","Completed")
//! runtextmacro Q("Discovered","Discovered")
//! runtextmacro Q("Failed","Failed")
//! runtextmacro Q("Enabled","Hint")
function QMessageHint takes player p, string messagetitle, string message returns nothing
call DisplayTimedTextToPlayer(p, 0, 0, 5, "|cffffff00"+messagetitle+": |r"+message)
call StartSound(bj_questHintSound)
endfunction
//===This should be used if you want to destroy all quests created
function QResetAll takes nothing returns nothing
local integer i = 0
loop
set i = i+1
exitwhen i==MAX_INDEX
call DestroyQuest(Qst[i])
endloop
endfunction
function QUpdateTexts takes integer qindex, string title, string description returns nothing
call QuestSetTitle(Qst[qindex], title)
if description != "" then
call QuestSetDescription(Qst[qindex], description)
endif
call StartSound(bj_questUpdatedSound)
call FlashQuestDialogButton()
endfunction
//call QCreate(1, "MyTestQuest", "Description", "ReplaceableTextures\\CommandButtons\\BTNDivineIntervention.blp", true)
function QCreate takes integer qindex, string title, string description, string iconpath, boolean required returns nothing
set Qst[qindex] = CreateQuest()
call QuestSetTitle(Qst[qindex], title)
call QuestSetDescription(Qst[qindex], description)
call QuestSetIconPath(Qst[qindex], iconpath)
call QuestSetRequired(Qst[qindex], required)
call StartSound(bj_questDiscoveredSound)
call FlashQuestDialogButton()
endfunction
//=========================================================
//===Creation of Quest Items, qindex is the index of the QUEST
function QItemQuestCreate takes integer qindex, integer qindexitem, string description returns nothing
set QstItem[qindexitem] = QuestCreateItem(Qst[qindex])
call QuestItemSetDescription(QstItem[qindexitem], description)
call StartSound(bj_questDiscoveredSound)
call FlashQuestDialogButton()
endfunction
function QItemUpdateTexts takes integer qindexitem, string description returns nothing
call QuestItemSetDescription(QstItem[qindexitem], description)
call StartSound(bj_questUpdatedSound)
call FlashQuestDialogButton()
endfunction
function QItemCompleted takes integer qindexitem returns nothing
call QuestItemSetCompleted(QstItem[qindexitem], true)
call StartSound(bj_questCompletedSound)
call FlashQuestDialogButton()
endfunction
endlibrary
//TESH.scrollpos=196
//TESH.alwaysfold=0
//System Name: Multiboard System (with time Elapsed & Timer)
//Made by: Mckill2009
//Requires:
//- Jass New Gen Pack
library MultiboardSystem
globals
private hashtable H = InitHashtable()
private multiboard MB
private integer CHILD = 0
//===Time Elapsed code
private integer M_Seconds = 0
private integer Seconds = 0
private integer M_Minutes = 0
private integer Minutes = 0
private integer Hour = 0
private timer TIMER
private integer ROW
private integer COLUMN
//===Timer code
private integer T_M_Seconds = 0
private integer T_Seconds = 0
private integer T_M_Minutes = 0
private integer T_Minutes = 0
private integer T_Hour = 0
private timer T_TIMER
private integer T_ROW
private integer T_COLUMN
endglobals
//===This is the first thing you want to do, setting up the multiboard
function MbSetupFirst takes integer rowQty, integer columnQty, boolean values, boolean icons returns nothing
call MultiboardDisplay(MB, true)
call MultiboardSetColumnCount(MB, columnQty)
call MultiboardSetRowCount(MB, rowQty)
call MultiboardSetItemsStyle(MB, values, icons)
call MultiboardMinimize(MB, true)
endfunction
//===The second thing you do, set the title and width
function MbSetTitle takes string s returns nothing
call MultiboardSetTitleText(MB, s)
endfunction
//===real value should be 0.1 or less
function MbSetAllWidth takes real r returns nothing
call MultiboardSetItemsWidth(MB, r)
endfunction
//Sets individual widths
function MbSetIndividualWidths takes integer row, integer column, real r returns nothing
local multiboarditem mbi = MultiboardGetItem(MB, row, column)
call MultiboardSetItemWidth(mbi, r)
call MultiboardReleaseItem(mbi)
set mbi = null
endfunction
//Show/Hide individual values
function MbSetIndividualValues takes integer row, integer column, boolean text, boolean icon returns nothing
local multiboarditem mbi = MultiboardGetItem(MB, row, column)
call MultiboardSetItemStyle(mbi, text, icon)
call MultiboardReleaseItem(mbi)
set mbi = null
endfunction
//===Maximize/Minimize multiboard
function MbMaximize takes boolean bol returns nothing
if bol then
call MultiboardMinimize(MB, false)
else
call MultiboardMinimize(MB, true)
endif
endfunction
//===This is used just to hide/unhide your multiboard
function MbShow takes boolean b returns nothing
call MultiboardDisplay(MB, b)
endfunction
//===Change the icon
function MbSetIcon takes integer row, integer column, string iconpath returns nothing
local multiboarditem mbi = MultiboardGetItem(MB, row, column)
call MultiboardSetItemIcon(mbi, iconpath)
call MultiboardReleaseItem(mbi)
set mbi = null
endfunction
//===This is the MAIN multiboard value and text change
function MbSetTextValue takes integer row, integer column, string s returns nothing
local multiboarditem mbi = MultiboardGetItem(MB, row, column)
call MultiboardSetItemValue(mbi, s)
call MultiboardReleaseItem(mbi)
set mbi = null
endfunction
private struct MBGo
private static method onInit takes nothing returns nothing
//set T_TIMER = CreateTimer()
set MB = CreateMultiboard()
endmethod
endstruct
//===========================================================
//====================TIME ELAPSED===========================
//===========================================================
//===Setting up Time Elapsed is optional
//===Supports 5-6 digits, "00:00:00"
private function MbTimerElapsed takes integer row, integer column returns nothing
local multiboarditem mbi = MultiboardGetItem(MB, row, column)
set M_Seconds = M_Seconds + 1
call MultiboardSetItemValue(mbi, I2S(Hour)+":"+I2S(Minutes)+I2S(M_Minutes)+":"+I2S(Seconds)+I2S(M_Seconds))
if Minutes==5 and M_Minutes==10 then
set Minutes = -1
set Hour = Hour + 1
endif
if M_Minutes==10 then
set M_Minutes = 0
set Minutes = Minutes + 1
endif
if Seconds==5 and M_Seconds==9 then
set Seconds = -1
set M_Minutes = M_Minutes + 1
endif
if M_Seconds==9 then
set M_Seconds = -1
set Seconds = Seconds + 1
endif
call MultiboardReleaseItem(mbi)
set mbi = null
endfunction
private function MbTimeElapsedLooper takes nothing returns nothing
call MbTimerElapsed(ROW, COLUMN)
endfunction
//===========================================================
//====================ELAPSED TIMER==========================
//===========================================================
//===Setting up Time Elapsed is optional
//===Supports 5-6 digits, "00:00:00"
function MbTimerPause takes boolean pause returns nothing
if pause then
call PauseTimer(TIMER)
else
call ResumeTimer(TIMER)
endif
endfunction
function MbResetTimerElapsed takes integer row, integer column, integer value returns nothing
local multiboarditem mbi = MultiboardGetItem(MB, row, column)
set M_Seconds = value
set Seconds = value
set M_Minutes = value
set Minutes = value
set Hour = value
call MultiboardSetItemValue(mbi, I2S(Hour)+":"+I2S(Minutes)+I2S(M_Minutes)+":"+I2S(Seconds)+I2S(M_Seconds))
call MultiboardReleaseItem(mbi)
set mbi = null
endfunction
function MbSetupTimeElapsed takes real timerspeed, integer row, integer column returns nothing
set TIMER = CreateTimer()
set ROW = row
set COLUMN = column
call TimerStart(TIMER, timerspeed, true, function MbTimeElapsedLooper)
endfunction
//===========================================================
//========================TIMER==============================
//===========================================================
private function MbTimer takes nothing returns nothing
local integer ID = GetHandleId(GetExpiredTimer())
local integer row = LoadInteger(H, ID, CHILD)
local integer column = LoadInteger(H, ID, CHILD+1)
local integer hour = LoadInteger(H, ID, CHILD+2)
local integer minutes = LoadInteger(H, ID, CHILD+3)
local integer Mminutes = LoadInteger(H, ID, CHILD+4)
local integer seconds = LoadInteger(H, ID, CHILD+5)
local integer Mseconds = LoadInteger(H, ID, CHILD+6)
if (hour==0 and minutes==0 and Mminutes==0 and seconds==0 and Mseconds==0) then
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
call MbSetTextValue(row, column, "")
else
call MbSetTextValue(row, column, I2S(hour)+":"+I2S(minutes)+I2S(Mminutes)+":"+I2S(seconds)+I2S(Mseconds))
call SaveInteger(H, ID, CHILD+6, Mseconds - 1)
if Mseconds==0 then
call SaveInteger(H, ID, CHILD+6, 9)
call SaveInteger(H, ID, CHILD+5, seconds - 1)
if seconds==0 and Mseconds==0 then
call SaveInteger(H, ID, CHILD+5, 5)
call SaveInteger(H, ID, CHILD+4, Mminutes - 1)
if Mminutes==0 then
call SaveInteger(H, ID, CHILD+4, 9)
call SaveInteger(H, ID, CHILD+3, minutes - 1)
if minutes==0 and Mminutes==0 then
call SaveInteger(H, ID, CHILD+3, 5)
call SaveInteger(H, ID, CHILD+2, hour - 1)
endif
endif
endif
endif
endif
endfunction
//call MbSetupTimer(0.01, 1, 1, 1, 1, 1, 2,9)
function MbSetupTimer takes real timerspeed, integer row, integer column, integer hour, integer minutes, integer Mminutes, integer seconds, integer Mseconds returns nothing
local timer t = CreateTimer()
local integer ID = GetHandleId(t)
call SaveInteger(H, ID, CHILD, row)
call SaveInteger(H, ID, CHILD+1, column)
call SaveInteger(H, ID, CHILD+2, hour)
call SaveInteger(H, ID, CHILD+3, minutes)
call SaveInteger(H, ID, CHILD+4, Mminutes)
call SaveInteger(H, ID, CHILD+5, seconds)
call SaveInteger(H, ID, CHILD+6, Mseconds)
call MbSetTextValue(row, column, I2S(hour)+":"+I2S(minutes)+I2S(Mminutes)+":"+I2S(seconds)+I2S(Mseconds))
call TimerStart(t, timerspeed, true, function MbTimer)
set t = null
endfunction
endlibrary
//TESH.scrollpos=1
//TESH.alwaysfold=0
//PreloadUtils
//Created by Mckill2009
library PreloadUtils
globals
private unit DUM
endglobals
function PreloadSpell takes integer abilityid returns nothing
call UnitAddAbility(DUM, abilityid)
call UnitRemoveAbility(DUM, abilityid)
endfunction
function PreloadUnit takes integer unitID returns nothing
local unit u = CreateUnit(Player(15), unitID,0,0,0)
call UnitApplyTimedLife(u, 'BTLF', 1.0)
call ShowUnit(u, false)
set u = null
endfunction
private module SetPreload
static method onInit takes nothing returns nothing
set DUM = CreateUnit(Player(15),'hpea',0,0,0)
call ShowUnit(DUM, false)
call UnitAddAbility(DUM, 'Aloc')
endmethod
endmodule
private struct onInit extends array
implement SetPreload
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitRemover initializer init uses Table
globals
private Table rem
private integer index = 0
private timer array Timers
endglobals
private function StopTimer takes timer t returns nothing
call PauseTimer(t)
set Timers[index] = t
set index = index - 1
endfunction
private function GetTimer takes nothing returns timer
set index = index + 1
if Timers[index]==null then
return CreateTimer()
endif
return Timers[index]
endfunction
private function RemoveUnitNow takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
call RemoveUnit(rem.unit[tID])
call StopTimer(GetExpiredTimer())
call rem.remove(tID)
endfunction
private function Actions takes nothing returns nothing
local timer t = GetTimer()
set rem.unit[GetHandleId(t)] = GetTriggerUnit()
call TimerStart(t, 3.0, false, function RemoveUnitNow)
endfunction
private function Cond takes nothing returns boolean
return not (IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO))
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t, function Cond)
call TriggerAddAction(t, function Actions)
set rem = Table.create()
set t = null
endfunction
endlibrary
//TESH.scrollpos=159
//TESH.alwaysfold=0
/*
=====Simple Missile System
=====Created by: Mckill2009
REQUIRES:
- Jass New Gen Pack By Vexorian
- Timer32 By Jesus4Lyf (http://www.thehelper.net/forums/showthread.php/132538-Timer32)
HOW TO INSTALL:
- Create 2 triggers named MS and T32, convert it to custom text >>> EDIT >>> CONVERT TO CUSTOM TEXT
- Create 1 dummy unit as the caster of the stun
- Create 1 unit modeled as shochwave
- Copy the Timer32 library from http://www.thehelper.net/forums/showthread.php/132538-Timer32 and paste it to your T32x trigger
- Copy the code I made and paste it to the MS trigger
- Take note that you MUST overwrite all text from MS and T32x when pasting
- Change the raw code of DUMMY_ID if needed, raw codes can be viewed by pressing CTRL + D from object editor
API:
- function SetMissileSingleTargetById takes unit caster, unit target, integer missileid, real damage, real speed, real height, string sfx returns nothing
- function SetMissileSingleTargetByUnit takes unit caster, unit target, unit missile, real damage, real speed, real height, string sfx returns nothing
- function SetMissileAoeByUnit takes unit missile, real xDist, real yDist, real aoe, real damage, real speed, real height, integer abilId, integer orderId, integer level, boolean firsttarget
*/
library SimpleMissileSystem uses T32
globals
private constant integer DUMMY_ID = 'h004' //raw code of the UNIT dummy, change this if needed, but it MUST have mana
//private constant integer MISSILE_SPEED = 30 //speed in which the missile travels
private constant attacktype ATK = ATTACK_TYPE_NORMAL
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
private constant real IMPACT = 3000 //don't edit
private constant real FIRST_IMPACT = 500
endglobals
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function UnitFly takes unit u returns nothing
if GetUnitAbilityLevel(u, 'Arav')==0 then
call UnitAddAbility(u, 'Arav')
endif
endfunction
//===AoE Target
private struct MS
unit missile
real angle
real distance
real xdist
real speed
real aoe
real damage
integer abilId
integer orderId
integer level
boolean firsttarget
method periodic takes nothing returns nothing
local unit first
local unit dummy
local real x
local real y
if .distance > .xdist then
set x = GetUnitX(.missile)
set y = GetUnitY(.missile)
set .xdist = .xdist + .speed
call SetUnitX(.missile, x + .speed * Cos(.angle))
call SetUnitY(.missile, y + .speed * Sin(.angle))
//Damages all units, recommended aoe is 80
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, .aoe, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(first, GetOwningPlayer(.missile)) and UnitAlive(first) then
call UnitDamageTarget(.missile, first, .damage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
//Targets first unit
if .firsttarget then
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, FIRST_IMPACT, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(first, GetOwningPlayer(.missile)) and UnitAlive(first) then
set .firsttarget = false
set dummy = CreateUnit(GetOwningPlayer(.missile), DUMMY_ID, x, y, 0)
call UnitApplyTimedLife(dummy, 'BTLF', 2.0)
call UnitAddAbility(dummy, .abilId)
call SetUnitAbilityLevel(dummy, .abilId, .level)
call IssueTargetOrderById(dummy, .orderId, first)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
else
call KillUnit(.missile)
call .stopPeriodic()
call .destroy()
endif
set first = null
set dummy = null
endmethod
implement T32x
static method setMissileAoE takes unit m, real a, real d, real ao, real dam, real spd, integer ab, integer o, integer l, boolean firsttarget returns nothing
local thistype this = create()
set .missile = m
set .angle = a
set .distance = d
set .aoe = ao
set .abilId = ab
set .orderId = o
set .level = l
set .damage = dam * T32_PERIOD
set .firsttarget = firsttarget
set .xdist = 0
set .speed = spd
call .startPeriodic()
endmethod
endstruct
//===Single Target
private struct MSS
unit target
unit missile
real damage
real speed
string sfx
method periodic takes nothing returns nothing
local real x0 = GetUnitX(.missile)
local real y0 = GetUnitY(.missile)
local real x1 = GetUnitX(.target)
local real y1 = GetUnitY(.target)
local real angle
local real impact = (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)
if UnitAlive(.target) and impact > IMPACT then
set angle = Atan2(y1-y0, x1-x0)
call SetUnitX(.missile, x0 + .speed * Cos(angle))
call SetUnitY(.missile, y0 + .speed * Sin(angle))
else
call UnitDamageTarget(.missile, .target, .damage, false, false, ATK, DMG, null)
call DestroyEffect(AddSpecialEffectTarget(.sfx, .target, "origin"))
call KillUnit(.missile)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method setMissileSingle takes unit t, unit m, real d, real s, string sfx returns nothing
local thistype this = create()
set .target = t
set .missile = m
set .damage = d
set .speed = s
set .sfx = sfx
call .startPeriodic()
endmethod
endstruct
function SetMissileSingleTargetById takes unit caster, unit target, integer missileid, real damage, real speed, real height, string sfx returns nothing
local real x = GetUnitX(caster) + 100 * Cos(GetUnitFacing(caster)*bj_DEGTORAD)
local real y = GetUnitY(caster) + 100 * Sin(GetUnitFacing(caster)*bj_DEGTORAD)
local unit missile = CreateUnit(GetOwningPlayer(caster), missileid, x, y, GetUnitFacing(caster))
call UnitFly(missile)
call SetUnitFlyHeight(missile, height, 0)
call MSS.setMissileSingle(target, missile, damage, speed, sfx)
set missile = null
endfunction
function SetMissileSingleTargetByUnit takes unit caster, unit target, unit missile, real damage, real speed, real height, string sfx returns nothing
call UnitFly(missile)
call SetUnitFlyHeight(missile, height, 0)
call MSS.setMissileSingle(target, missile, damage, speed, sfx)
endfunction
function SetMissileAoeByUnit takes unit missile, real xDist, real yDist, real aoe, real damage, real speed, real height, integer abilId, integer orderId, integer level, boolean firsttarget returns nothing
local real x = GetUnitX(missile)
local real y = GetUnitY(missile)
local real angle = Atan2(yDist-y, xDist-x)
local real distance = SquareRoot((xDist-x)*(xDist-x) + (yDist-y)*(yDist-y))
call UnitFly(missile)
call SetUnitFlyHeight(missile, height, 0)
call MS.setMissileAoE(missile,angle,distance,aoe,damage,speed,abilId,orderId,level,firsttarget)
endfunction
endlibrary
//TESH.scrollpos=57
//TESH.alwaysfold=0
/*
ColorUtils
Created by Mckill2009
Applies 50 colors to your texts
Source site:
[url]www.computerhope.com/htmcolor.htm[/url] (credits to ALONE for providing this site)
*/
library ColorUtils initializer init
globals
private string array Color
private integer MaxColor = 50
endglobals
private function ColorSetup takes nothing returns nothing
set Color[0] = "|cffff0000" //red
set Color[1] = "|cff0000ff" //blue
set Color[2] = "|cff00f5ff" //Teal
set Color[3] = "|cff551A8B" //Purple
set Color[4] = "|cffffff00" //Yellow
set Color[5] = "|cffEE9A00" //Orange
set Color[6] = "|cff00CD00" //Green
set Color[7] = "|cffFF69B4" //Pink
set Color[8] = "|cffC0C0C0" //Gray
set Color[9] = "|cffB0E2FF" //Light Blue
set Color[10] = "|cff006400" //Dark Green
set Color[12] = "|cff342D7E" //State Blue
set Color[13] = "|cff2B60DE" //Royal Blue
set Color[14] = "|cff3BB9FF" //Deep Sky Blue
set Color[15] = "|cff25587E" //Deep Sky Blue 4
set Color[16] = "|cff8D38C9" //Violet
set Color[17] = "|cffF52887" //Deep Pink
set Color[18] = "|cff437C17" //Chartreuse4
set Color[19] = "|cff800517" //Firebrick
set Color[20] = "|cff810541" //Maroon
set Color[21] = "|cffFF00FF" //Magenta
set Color[22] = "|cffB048B5" //Medium Orchid
set Color[23] = "|cff6A287E" //Medium Orchid 4
set Color[24] = "|cff8E35EF" //Purple
set Color[25] = "|cffB93B8F" //Plum
set Color[26] = "|cffC3FDB8" //Dark Sea Green1
set Color[27] = "|cffE3E4FA" //Lavender
set Color[28] = "|cffAF7817" //Dark Goldenrod
set Color[29] = "|cff00FFFF" //Cryan
set Color[30] = "|cff43C6DB" //Turquoise
set Color[31] = "|cff82CAFF" //Sky Blue
set Color[32] = "|cff4E8975" //Sea Green
set Color[33] = "|cff254117" //Dark Green
set Color[34] = "|cffA52A2A" //Brown
set Color[35] = "|cffC0C0C0" //Silver
set Color[36] = "|cff808000" //Olive
set Color[37] = "|cffFF00FF" //Fuchsia
set Color[38] = "|cff00FF00" //Lime
set Color[39] = "|cffF76541" //Coral
set Color[40] = "|cffFFF8C6" //Lemon Chiffon
set Color[41] = "|cffB38481" //Rosy Brown
set Color[42] = "|cff7D2252" //Hot Pink4
set Color[43] = "|cffF660AB" //Hot Pink
set Color[44] = "|cffC85A17" //Chocolate
set Color[45] = "|cffD4A017" //Gold
set Color[46] = "|cffE18B6B" //Dark Salmon
set Color[47] = "|cff8A4117" //Sienna
set Color[48] = "|cffADA96E" //Khaki
set Color[49] = "|cff8AFB17" //Chartreuse
set Color[50] = "|cffADDFFF" //Light Blue
//set Color[51] = "|cff" //
endfunction
function RandomColor takes string s returns string
return Color[GetRandomInt(0, MaxColor)] + s +"|r"
endfunction
function FixedColor takes integer colorindex, string s returns string
return Color[colorindex] + s +"|r"
endfunction
private function init takes nothing returns nothing
call ColorSetup()
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Created by Mckill2009
HOW TO USE:
- Just copy and paste this code to your map and you're done.
- Adjust the configurables when necessary.
*/
scope RespawnThem
globals
private constant hashtable RES_HASH = InitHashtable() //never touch this!
private constant boolean ENABLE_RESPAWN_ALL = false //respawns all units in map area
private constant boolean ENABLE_REVIVE_HERO = false //set to true if you wanna respawn including heroes
private constant real RESPAWN_DELAY = 40.
private constant integer PLAYER_TO_RESPAWN = 12 //sets which player to respawn, player 11 is actually player 13
//if you dont want and effect just put ""
private constant string SFX = "Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl"
endglobals
native UnitAlive takes unit u returns boolean
private function FilterMore takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_STRUCTURE) and GetOwningPlayer(u)==Player(PLAYER_TO_RESPAWN)
endfunction
private function RespawnGet takes nothing returns boolean
local unit first
local integer ID
call GroupEnumUnitsInRect(bj_lastCreatedGroup, bj_mapInitialPlayableArea, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) then
set ID = GetHandleId(first)
if ENABLE_RESPAWN_ALL then
call SaveReal(RES_HASH, ID, 0, GetUnitX(first))
call SaveReal(RES_HASH, ID, 1, GetUnitY(first))
call SaveReal(RES_HASH, ID, 2, GetUnitFacing(first))
call SaveUnitHandle(RES_HASH, ID, 3, first)
elseif FilterMore(first) then
call SaveReal(RES_HASH, ID, 0, GetUnitX(first))
call SaveReal(RES_HASH, ID, 1, GetUnitY(first))
call SaveReal(RES_HASH, ID, 2, GetUnitFacing(first))
call SaveUnitHandle(RES_HASH, ID, 3, first)
endif
endif
call GroupRemoveUnit(bj_lastCreatedGroup,first)
endloop
return false
endfunction
private function RespawnNow takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
//getting the dead unit's info from the id of the timer
local unit hero
local real x = LoadReal(RES_HASH, tID, 0)
local real y = LoadReal(RES_HASH, tID, 1)
local real facing = LoadReal(RES_HASH, tID, 2)
local integer utype = LoadInteger(RES_HASH, tID, 3)
local unit newunit
local integer newunitID
//Sets the new unit creation
if ENABLE_REVIVE_HERO and LoadUnitHandle(RES_HASH, tID, 5)!= null then
set hero = LoadUnitHandle(RES_HASH, tID, 5)
call ReviveHero(hero, x, y, true)
set newunit = hero
else
call DestroyEffect(AddSpecialEffect(SFX, x, y))
set newunit = CreateUnit(LoadPlayerHandle(RES_HASH, tID, 4), utype, x, y, facing)
endif
set newunitID = GetHandleId(newunit)
call SaveReal(RES_HASH, newunitID, 0, GetUnitX(newunit))
call SaveReal(RES_HASH, newunitID, 1, GetUnitY(newunit))
call SaveReal(RES_HASH, newunitID, 2, GetUnitFacing(newunit))
call SaveUnitHandle(RES_HASH, newunitID, 3, newunit)
call FlushChildHashtable(RES_HASH, tID)
call PauseTimer(t)
call DestroyTimer(t)
set t = null
set hero = null
set newunit = null
endfunction
private function RespawnDeath takes nothing returns boolean
local unit u = GetTriggerUnit()
local timer t
local integer tID
local integer uID
if HaveSavedHandle(RES_HASH, GetHandleId(u), 3) then
set t = CreateTimer()
set tID = GetHandleId(t)
set uID = GetHandleId(u)
call SaveReal(RES_HASH, tID, 0, LoadReal(RES_HASH, uID, 0)) //x
call SaveReal(RES_HASH, tID, 1, LoadReal(RES_HASH, uID, 1)) //y
call SaveReal(RES_HASH, tID, 2, LoadReal(RES_HASH, uID, 2)) //facing
call SaveInteger(RES_HASH, tID, 3, GetUnitTypeId(u))
call SavePlayerHandle(RES_HASH, tID, 4, GetTriggerPlayer())
if ENABLE_REVIVE_HERO and IsUnitType(u, UNIT_TYPE_HERO) then
call SaveUnitHandle(RES_HASH, tID, 5, u)
endif
call FlushChildHashtable(RES_HASH, uID)
call TimerStart(t, RESPAWN_DELAY, false, function RespawnNow)
set t = null
endif
set u = null
return false
endfunction
private struct Res
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t, 0.1, false)
call TriggerAddCondition(t, Condition(function RespawnGet))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t, Condition(function RespawnDeath))
set t = null
endmethod
endstruct
endscope
//TESH.scrollpos=12
//TESH.alwaysfold=0
//Spell Name: Item Drop System
//Made By: Mckill2009
function ItemCondition takes unit u, unit r, integer i returns boolean
return IsUnitEnemy(u, GetOwningPlayer(r)) and GetOwningPlayer(u)==Player(5) and i==6 or i==12 or i==18 or i==24 or i==30
endfunction
function ItemAction takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit r = GetKillingUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local integer i = GetRandomInt(1, 30)
local integer lev = GetUnitLevel(u)
local integer set1items = GetRandomInt(0, 1)
local integer set2items = GetRandomInt(1, 2)
local integer set3items = GetRandomInt(1, 2)
local integer set4items = GetRandomInt(2, 3)
local integer set5items = GetRandomInt(4, 5)
if ItemCondition(u, r, i) then
if lev==1 or lev==2 or lev==3 then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_POWERUP, set1items), x, y)
elseif lev==4 or lev==5 then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_PERMANENT, set2items), x, y)
elseif lev==6 or lev==7 then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_ANY, set3items), x, y)
elseif lev==8 or lev==9 then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_PERMANENT, set4items), x, y)
if i==10 then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_CHARGED, set4items), x, y)
endif
elseif lev==10 or IsUnitType(u, UNIT_TYPE_HERO) then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_ANY, set5items), x, y)
if i==20 then
call CreateItem(ChooseRandomItemEx(ITEM_TYPE_ARTIFACT, 8), x, y)
endif
endif
endif
set u = null
endfunction
function InitTrig_ItemDrop takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction(t, function ItemAction )
set t = null
endfunction
//TESH.scrollpos=14
//TESH.alwaysfold=0
//THESE TRIGGER IS USED FOR THE AI IN LEARNING THE SPELLS
function GainAction takes nothing returns nothing
local unit c
if GetPlayerController(GetTriggerPlayer())==MAP_CONTROL_COMPUTER then
set c = GetTriggerUnit()
//=============Human AI
call SelectHeroSkill(c, 'A02T') //Flame Blast(Human AI)
call SelectHeroSkill(c, 'A02V') //Crushing Wave(Human AI)
call SelectHeroSkill(c, 'A02W') //Life Mana(Human AI)
call SelectHeroSkill(c, 'A02R') //Lightning Shield(Human AI-PASSIVE)
//=============Undead AI
call SelectHeroSkill(c, 'A032') //Soul Release(Undead AI)
call SelectHeroSkill(c, 'A036') //Death Trap(Undead AI)
call SelectHeroSkill(c, 'A02X') //Cripple(Undead AI)
call SelectHeroSkill(c, 'A02Q') //Blood Curse(Undead AI-PASSIVE)
//=============Orc AI
call SelectHeroSkill(c, 'A03A') //Leap Blow(Orc AI)
call SelectHeroSkill(c, 'A031') //Trample(Orc AI)
call SelectHeroSkill(c, 'A039') //Sweeping Strike(Orc AI)
call SelectHeroSkill(c, 'A000') //Critical Strike(Orc AI-PASSIVE)
//=============Night Elf AI
call SelectHeroSkill(c, 'A02Z') //Mass Root(NE AI)
call SelectHeroSkill(c, 'A01G') //Soul Drain(NE AI)
call SelectHeroSkill(c, 'A01H') //Whirlwind(NE AI)
call SelectHeroSkill(c, 'A02S') //Faeriefire(Night Elf AI-PASSIVE)
set c = null
endif
endfunction
//===========================================================================
function InitTrig_LearnSkillForAI takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_LEVEL, function GainAction)
endfunction
//TESH.scrollpos=15
//TESH.alwaysfold=0
library CastSpellSystem uses Table
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
struct CastSpellSystem
unit caster
integer oidNone
integer oidLoc
integer oidUnit
static Table chk
method filt takes unit u1, unit u2 returns boolean
return IsUnitEnemy(u1,GetOwningPlayer(u2)) and UnitAlive(u1)
endmethod
static method looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = chk[GetHandleId(t)]
local integer random
local unit first
local real x
local real y
if UnitAlive(.caster) then
set x = GetUnitX(.caster)
set y = GetUnitY(.caster)
set random = GetRandomInt(0,2)
if random==0 then //target None
//! runtextmacro FOG_ADD("x","y","375")
if filt(first,.caster) then
call IssueImmediateOrderById(.caster, .oidNone)
endif
//! runtextmacro FOG_REMOVE()
elseif random==1 then //target Point
//! runtextmacro FOG_ADD("x","y","700")
if filt(first,.caster) then
call IssuePointOrderById(.caster, .oidLoc, GetUnitX(first), GetUnitY(first))
endif
//! runtextmacro FOG_REMOVE()
elseif random==2 then //target Unit
//! runtextmacro FOG_ADD("x","y","700")
if filt(first,.caster) then
call IssueTargetOrderById(.caster, .oidUnit, first)
endif
//! runtextmacro FOG_REMOVE()
endif
else
call .destroy()
call PauseTimer(t)
call DestroyTimer(t)
endif
set t = null
endmethod
static method castEnemy takes unit caster, integer oidNone, integer oidLoc, integer oidUnit returns nothing
local thistype this = create()
local timer t = CreateTimer()
set chk[GetHandleId(t)] = this
set .caster = caster
set .oidNone = oidNone
set .oidLoc = oidLoc
set .oidUnit = oidUnit
call TimerStart(t,3.0,true,function thistype.looper)
set t = null
endmethod
static method onInit takes nothing returns nothing
set chk = Table.create()
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
===KnockBackMe
===by Mckill2009
REQUIRES:
- CTL by Nesthaurus
- IsTerrainWalkable by Anitarf
*/
library KnockbackMe uses CTL, IsTerrainWalkable
globals
private constant real SFX_INTERVAL = 0.1
endglobals
struct KM extends array
unit u
real xU
real yU
real distance
real angle
real speed
real interval
string sfx
implement CTL
local real x
local real y
implement CTLExpire
set x = GetUnitX(.u)
set y = GetUnitY(.u)
if .distance > 0 and not IsUnitType(.u, UNIT_TYPE_DEAD) and IsTerrainWalkable(x, y) then
set .distance = .distance - .speed
call SetUnitX(.u, x+.speed*Cos(.angle))
call SetUnitY(.u, y+.speed*Sin(.angle))
set .interval = .interval + 0.03125
if .interval > SFX_INTERVAL then
call DestroyEffect(AddSpecialEffect(.sfx, x, y))
endif
else
set .u = null
call .destroy()
endif
implement CTLNull
implement CTLEnd
static method knockUnit takes unit u, real angle, real distance, real speed, string sfx returns nothing
local thistype this = create()
set .u = u
set .xU = GetUnitX(u)
set .yU = GetUnitY(u)
set .angle = angle
set .distance = distance
set .speed = speed
set .sfx = sfx
set .interval = 0
endmethod
endstruct
endlibrary
//TESH.scrollpos=24
//TESH.alwaysfold=0
/*
===StringTag
===by mckill2009
Simple TextTag wrapper
API:
static method txUnit takes unit u returns thistype
- Above unit
static method txPosition takes real x, real y returns thistype
- Above ground
method operator text= takes string txt returns nothing
method operator height= takes real h returns nothing
method operator size= takes real s returns nothing
- Base is 0.01
method operator life= takes real l returns nothing
- This destroys the texttag
method operator fade= takes real f returns nothing
method operator velocity= takes real v returns nothing
- Higher number is faster, 1 recommended as fastest
method operator permanent= takes boolean p returns nothing
method launchUnit takes nothing returns nothing
- Above unit
method launchLoc takes nothing returns nothing
- Above ground
*/
library StringTag
struct StringTag
private unit u
private texttag tag
private string txt
private real x //position Y
private real y //position X
private real h //hight offset
private real s //height or size
private real l //life span
private real v //velocity
private real f //fade point
private boolean p //permanent
private method launch takes nothing returns nothing
call SetTextTagText(.tag, .txt, .s) //size is 0.025 OK
call SetTextTagPermanent(.tag, .p) //false OK
call SetTextTagVelocity(.tag, .v, .v) //0.03 OK
call SetTextTagLifespan(.tag, .l) //3 OK
call SetTextTagFadepoint(.tag, .f) //0.01 OK
//call BJDebugMsg(I2S(GetHandleId(.tag)))
set .tag = null
call .deallocate()
endmethod
method operator text= takes string txt returns nothing
set .txt = txt
endmethod
method operator height= takes real h returns nothing
set .h = h
endmethod
method operator size= takes real s returns nothing
set .s = s*0.01
endmethod
method operator life= takes real l returns nothing
set .l = l
endmethod
method operator fade= takes real f returns nothing
set .f = f*0.01
endmethod
method operator velocity= takes real v returns nothing
set .v = v*0.01
endmethod
method operator permanent= takes boolean p returns nothing
set .p = p
endmethod
method launchUnit takes nothing returns nothing
call SetTextTagPosUnit(.tag, .u, .h)
call .launch()
endmethod
method launchLoc takes nothing returns nothing
call SetTextTagPos(.tag, .x, .y, .h)
call .launch()
endmethod
static method txUnit takes unit u returns thistype
local thistype this = thistype.allocate()
set .u = u
set .tag = CreateTextTag()
return this
endmethod
static method txPosition takes real x, real y returns thistype
local thistype this = allocate()
set .tag = CreateTextTag()
set .x = x
set .y = y
return this
endmethod
endstruct
endlibrary
//TESH.scrollpos=56
//TESH.alwaysfold=0
/*
===Vortex
===by mckill2009
*/
library Vortex uses CTL
struct Vortex extends array
unit v
real x
real y
real a //angle
real h //height
real hs //height speed
real mh //min height
real d //duration
real o //offset
real s //speed
boolean clockwise
effect sfx
implement CTL
implement CTLExpire
if .clockwise then
set .a = .a - .s
else
set .a = .a +.s
endif
call SetUnitX(.v, .x+.o*Cos(.a))
call SetUnitY(.v, .y+.o*Sin(.a))
if .h > .mh then
set .h = .h - .hs
call SetUnitFlyHeight(.v, .h, 0)
else
if .d > 0 then
set .d = .d - 0.03125
//run here
else
call DestroyEffect(.sfx)
call UnitApplyTimedLife(.v, 'BTLF', 2.0)
set .v = null
call .destroy()
endif
endif
implement CTLNull
implement CTLEnd
method operator []= takes real height, real heightSpeed returns nothing
set .h = height
set .hs = heightSpeed
endmethod
method operator angle= takes real ang returns nothing
set .a = ang
endmethod
method operator offset= takes real ofs returns nothing
set .o = ofs
endmethod
method operator duration= takes real dur returns nothing
set .d = dur
endmethod
method operator minHeight= takes real min returns nothing
set .mh = min
endmethod
method operator scale= takes real sc returns nothing
call SetUnitScale(.v, sc, sc, sc)
endmethod
method operator speed= takes real spd returns nothing
set .s = spd
endmethod
method operator effect= takes string eff returns nothing
set .sfx = AddSpecialEffectTarget(eff, .v, "origin")
endmethod
static method spin takes unit v, real x, real y, boolean clockwise returns thistype
local thistype this = create()
set .v = v
set .x = x
set .y = y
set .clockwise = clockwise
set .hs = 0
set .mh = 0
set .sfx = null
return this
endmethod
endstruct
endlibrary
//TESH.scrollpos=40
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+) 2.0
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3c.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* set t=NewTimerEx(x) : Get a timer (alternative to CreateTimer), call
//* Initialize timer data as x, instead of 0.
//*
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Multi-flavor:
//* Set USE_HASH_TABLE to true if you don't want to complicate your life.
//*
//* If you like speed and giberish try learning about the other flavors.
//*
//********************************************************************
//================================================================
globals
//How to tweak timer utils:
// USE_HASH_TABLE = true (new blue)
// * SAFEST
// * SLOWEST (though hash tables are kind of fast)
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true (orange)
// * kinda safe (except there is a limit in the number of timers)
// * ALMOST FAST
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
// * THE FASTEST (though is only faster than the previous method
// after using the optimizer on the map)
// * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
// work)
//
private constant boolean USE_HASH_TABLE = true
private constant boolean USE_FLEXIBLE_OFFSET = false
private constant integer OFFSET = 0x100000
private integer VOFFSET = OFFSET
//Timers to preload at map init:
private constant integer QUANTITY = 500
//Changing this to something big will allow you to keep recycling
// timers even when there are already AN INCREDIBLE AMOUNT of timers in
// the stack. But it will make things far slower so that's probably a bad idea...
private constant integer ARRAY_SIZE = 8190
endglobals
//==================================================================================================
globals
private integer array data[ARRAY_SIZE]
private hashtable ht
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
static if(USE_HASH_TABLE) then
// new blue
call SaveInteger(ht,0,GetHandleId(t), value)
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-VOFFSET]=value
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-OFFSET]=value
endif
endfunction
function GetTimerData takes timer t returns integer
static if(USE_HASH_TABLE) then
// new blue
return LoadInteger(ht,0,GetHandleId(t) )
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-VOFFSET]
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-OFFSET]
endif
endfunction
//==========================================================================================
globals
private timer array tT[ARRAY_SIZE]
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
private boolean didinit = false
endglobals
private keyword init
//==========================================================================================
// I needed to decide between duplicating code ignoring the "Once and only once" rule
// and using the ugly textmacros. I guess textmacros won.
//
//! textmacro TIMERUTIS_PRIVATE_NewTimerCommon takes VALUE
// On second thought, no.
//! endtextmacro
function NewTimerEx takes integer value returns timer
if (tN==0) then
if (not didinit) then
//This extra if shouldn't represent a major performance drawback
//because QUANTITY rule is not supposed to be broken every day.
call init.evaluate()
set tN = tN - 1
else
//If this happens then the QUANTITY rule has already been broken, try to fix the
// issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
set tT[0]=CreateTimer()
static if( not USE_HASH_TABLE) then
debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
static if( USE_FLEXIBLE_OFFSET) then
if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
else
if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
endif
endif
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],value)
return tT[tN]
endfunction
function NewTimer takes nothing returns timer
return NewTimerEx(0)
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==ARRAY_SIZE) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
local integer i=0
local integer o=-1
local boolean oops = false
if ( didinit ) then
return
else
set didinit = true
endif
static if( USE_HASH_TABLE ) then
set ht = InitHashtable()
loop
exitwhen(i==QUANTITY)
set tT[i]=CreateTimer()
call SetTimerData(tT[i], HELD)
set i=i+1
endloop
set tN = QUANTITY
else
loop
set i=0
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set VOFFSET = GetHandleId(tT[i])
static if(USE_FLEXIBLE_OFFSET) then
set o=VOFFSET
else
set o=OFFSET
endif
endif
if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
exitwhen true
endif
if (GetHandleId(tT[i])-o>=0) then
set i=i+1
endif
endloop
set tN = i
exitwhen(tN == QUANTITY)
set oops = true
exitwhen not USE_FLEXIBLE_OFFSET
debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")
endloop
if(oops) then
static if ( USE_FLEXIBLE_OFFSET) then
debug call BJDebugMsg("The problem has been fixed.")
//If this message doesn't appear then there is so much
//handle id fragmentation that it was impossible to preload
//so many timers and the thread crashed! Therefore this
//debug message is useful.
elseif(DEBUG_MODE) then
call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
endif
endif
endif
endfunction
endlibrary
//TESH.scrollpos=51
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Timer32 ~~ By Jesus4Lyf ~~ Version 1.06 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Timer32?
// - Timer32 implements a fully optimised timer loop for a struct.
// - Instances can be added to the loop, which will call .periodic every
// PERIOD until .stopPeriodic() is called.
//
// =Pros=
// - Efficient.
// - Simple.
//
// =Cons=
// - Only allows one period.
// - The called method must be named ".periodic".
//
// Methods:
// - struct.startPeriodic()
// - struct.stopPeriodic()
//
// - private method periodic takes nothing returns nothing
//
// This must be defined in structs that implement Periodic Module.
// It will be executed by the module every PERIOD until .stopPeriodic() is called.
// Put "implement T32x" BELOW this method.
//
// Modules:
// - T32x
// Has no safety on .stopPeriodic or .startPeriodic (except debug messages
// to warn).
//
// - T32xs
// Has safety on .stopPeriodic and .startPeriodic so if they are called
// multiple times, or while otherwise are already stopped/started respectively,
// no error will occur, the call will be ignored.
//
// - T32
// The original, old version of the T32 module. This remains for backwards
// compatability, and is deprecated. The periodic method must return a boolean,
// false to continue running or true to stop.
//
// Details:
// - Uses one timer.
//
// - Do not, within a .periodic method, follow a .stopPeriodic call with a
// .startPeriodic call.
//
// How to import:
// - Create a trigger named T32.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Infinitegde for finding a bug in the debug message that actually altered
// system operation (when in debug mode).
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library T32 initializer OnInit
globals
public constant real PERIOD=0.03125
public constant integer FPS=R2I(1/PERIOD)
public integer Tick=0 // very useful.
//==============================================================================
private trigger Trig=CreateTrigger()
endglobals
//==============================================================================
// The standard T32 module, T32x.
//
module T32x
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
method stopPeriodic takes nothing returns nothing
debug if this.prev==0 and thistype(0).next!=this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had stopPeriodic called while not running!")
debug endif
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The standard T32 module with added safety checks on .startPeriodic() and
// .stopPeriodic(), T32xs.
//
module T32xs
private thistype next
private thistype prev
private boolean runningPeriodic
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
if not this.runningPeriodic then
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
set this.runningPeriodic=true
endif
endmethod
method stopPeriodic takes nothing returns nothing
if this.runningPeriodic then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
set this.runningPeriodic=false
endif
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The original T32 module, for backwards compatability only.
//
module T32 // deprecated.
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
if this.periodic() then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endif
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// System Core.
//
private function OnExpire takes nothing returns nothing
set Tick=Tick+1
call TriggerEvaluate(Trig)
endfunction
private function OnInit takes nothing returns nothing
call TimerStart(CreateTimer(),PERIOD,true,function OnExpire)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TimedLoop
//********************************************************
//* TimedLoop
//* ---------
//*
//* Requires jasshelper 0.9.G.1 or greater.
//*
//* A library + module that are meant to make those
//* array + timer loops easy, yet still faster than
//* other alternatives meant to be easy (In other words
//* no TriggerEvaluate is involved).
//*
//* The OOPness is interesting.
//*
//* Before implementing TimedLoop
//* your struct needs an onTimedLoop method that takes
//* nothing and returns boolean, if the method
//* returns false, the instance will get removed
//* from the loop and destroyed, else it will continue,
//* think of it as if the call asks the method a
//* question: "Should I continue the loop afterwards?"
//*
//* Alternatively, if you are not convinced, you may
//* use the TimedLoop_CONTINUE and TimedLoop_STOP
//* constants in the method's returns.
//*
//* After implementing TimedLoop, you can call
//* the startTimedLoop method to add the periodic event
//* to that instance, only call it once per instance.
//*
//* I recommend to call implement just bellow the
//* declaration of the onLoop method, else it will
//* actually use TriggerEvaluate, which is lame. Remind
//* me to implement a topsort in jasshelper.
//*
//* If you feel the need to destroy the struct outside
//* the loop, well, you'll have to add a flag to it so
//* you send a message to onLoop to make it return false.
//* A more complicated module to allow that easily would
//* come later.
//*
//********************************************************
//========================================================
// config:
globals
public constant real PERIOD = 0.025
// A lower value and everything using the module will
// look better, yet performance will drop.
endglobals
//========================================================
// implementation:
//
globals
public constant boolean STOP = false
public constant boolean CONTINUE = true
endglobals
//===========================
module TimedLoop
// god bless private module members.
//
private static thistype array V // The array
private static integer N = 0 // The count
private static timer T = null // the timer, one per
// struct that implements this
private static method onExpire takes nothing returns nothing
local integer n = 0
local thistype this // yay for odd-sounding syntax constructs
local integer i = 0
loop
exitwhen (i== thistype.N)
set this = .V[i]
if ( this.onTimedLoop() == CONTINUE ) then
set .V[n] = this
set n=n+1
else
call this.destroy()
endif
set i=i+1
endloop
set thistype.N = n
if (n== 0) then
call PauseTimer(.T)
endif
endmethod
public method startTimedLoop takes nothing returns nothing
set .V[.N] = this
set .N=.N + 1
if (.N == 1) then
if (.T == null) then
set .T = CreateTimer()
endif
call TimerStart(.T, PERIOD, true, function thistype.onExpire)
endif
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CTL /* v1.2.0.1
*************************************************************************************
*
* CTL or Constant Timer Loop provides a loop for constant merged timers of timeout .03125
*
* Similar to T32 but pauses timer when no structs have instances and removes structs
* from timer trigger when those structs have no instances.
*
* This can also create new timers after destroying a previous timer and generates less
* code in the module. It also generates no triggers so long as the module is implemented
* at the top of the struct.
*
************************************************************************************
*
* module CTL
*
* Allows creation/destruction of timers in a struct. Provides instancing of those timers.
*
* - static method create takes nothing returns thistype
* - method destroy takes nothing returns nothing
*
* CTL (optional)
* local variables, code before running any timers
* CTLExpire (not optional)
* timer code
* CTLNull (optional)
* null any locals, runs after all timers
* CTLEnd (not optional)
*
* module CT32
*
* Converts struct into a timer group. Allows the timer group to be started and stopped.
* Instancing and looping through active timers is up to the user.
*
* - static method start takes nothing returns nothing
* - static method stop takes nothing returns nothing
*
* CT32 (not optional)
* timer code
* CT32End (not optional)
*
* struct TimerGroup32 extends array
*
* Allows for the creation of timer groups. Timer instancing and looping is entirely up
* to the user.
*
* - static method create takes code func returns thistype
* - method destroy takes nothing returns nothing
* - method start takes nothing returns nothing
* - method stop takes nothing returns nothing
*
************************************************************************************/
globals
private integer tgc = 0 //timer group count
private integer array tgr //timer group recycler
private integer ic=0 //instance count
private integer tc=0 //timer count
private integer array rf //root first
private integer array n //next
private integer array p //previous
private integer array th //timer head
private integer array ns //next stack
private trigger t=CreateTrigger()
private timer m=CreateTimer()
private triggercondition array ct
private conditionfunc array rc
private boolean array e32 //enabled
private integer array i32r //ct32 recycler
private integer i32cr = 0 //ct32 count recycler
private boolean array ir32 //is recycling
private boolean array id32 //is destroying
endglobals
private function E takes nothing returns nothing
local integer i=ns[0]
set ns[0]=0
loop
exitwhen 0==i
if (0==p[i]) then
if (0==n[i]) then
call TriggerRemoveCondition(t,ct[th[i]])
set ct[th[i]]=null
set tc=tc-1
set rf[th[i]]=0
else
set rf[th[i]]=n[i]
set p[n[i]]=0
endif
else
set p[n[i]]=p[i]
set n[p[i]]=n[i]
endif
set n[i]=n[0]
set n[0]=i
set i=ns[i]
endloop
loop
exitwhen 0 == i32cr
set i32cr = i32cr - 1
set i = i32r[i32cr]
if (not e32[i]) then
call TriggerRemoveCondition(t,ct[i])
set ct[i] = null
if (id32[i]) then
set tgr[i] = tgr[0]
set tgr[0] = i
set id32[i] = false
set e32[i] = false
set ir32[i] = false
endif
endif
endloop
if (0==tc) then
call PauseTimer(m)
else
call TriggerEvaluate(t)
endif
endfunction
private function CT takes integer r returns integer
local integer i
local integer f
if (0==n[0]) then
set i=ic+1
set ic=i
else
set i=n[0]
set n[0]=n[i]
endif
set th[i]=r
set ns[i]=-1
set f=rf[r]
if (0==f) then
set n[i]=0
set p[i]=0
set rf[r]=i
set ct[r]=TriggerAddCondition(t,rc[r])
//set ct[r] = null
if (0==tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc=tc+1
else
set n[i]=f
set p[i]=0
set p[f]=i
set rf[r]=i
endif
return i
endfunction
private function DT takes integer t returns nothing
debug if (0>ns[t]) then
set ns[t]=ns[0]
set ns[0]=t
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"TIMER LOOP ERROR: ATTEMPT TO DESTROY NULL TIMER")
debug endif
endfunction
private function A takes code c returns integer
local integer i = tgr[0]
if (0 == i) then
set i = tgc + 1
set tgc = i
else
set tgr[0] = tgr[i]
endif
set rc[i]=Condition(c)
return i
endfunction
private function A32 takes integer i returns nothing
if (not e32[i]) then
if (not ir32[i] and not id32[i]) then
set ct[i] = TriggerAddCondition(t, rc[i])
endif
if (0 == tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc = tc + 1
set e32[i] = true
endif
endfunction
private function SR32 takes integer i returns nothing
if (e32[i]) then
if (not ir32[i] and not id32[i]) then
set i32r[i32cr] = i
set i32cr = i32cr + 1
set ir32[i] = true
endif
set e32[i] = false
set tc = tc - 1
endif
endfunction
private function DT32 takes integer i returns nothing
if (not id32[i]) then
if (not ir32[i]) then
set ir32[i] = true
set tc = tc - 1
set i32r[i32cr] = i
set i32cr = i32cr + 1
set e32[i] = false
endif
set id32[i] = true
endif
endfunction
private keyword r
private keyword e
module CTL
static integer rctl32
static method create takes nothing returns thistype
return CT(rctl32)
endmethod
method destroy takes nothing returns nothing
call DT(this)
endmethod
static method ectl32 takes nothing returns boolean
local thistype this=rf[rctl32]
endmodule
module CTLExpire
implement CTL
loop
exitwhen 0==this
endmodule
module CTLNull
set this=n[this]
endloop
endmodule
module CTLEnd
implement CTLNull
return false
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
module CT32
static integer rctl32
static method ectl32 takes nothing returns boolean
endmodule
module CT32End
return false
endmethod
static method start takes nothing returns nothing
call A32(rctl32)
endmethod
static method stop takes nothing returns nothing
call SR32(rctl32)
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
struct TimerGroup32 extends array
static method create takes code c returns thistype
return A(c)
endmethod
method destroy takes nothing returns nothing
call DT32(this)
endmethod
method start takes nothing returns nothing
call A32(this)
endmethod
method stop takes nothing returns nothing
call SR32(this)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library IsTerrainWalkable initializer Init
//*****************************************************************
//* IsTerrainWalkable
//*
//* rewritten in vJass by: Anitarf
//* original implementation: Vexorian
//*
//* A function for checking if a point is pathable for ground
//* units (it does so by attempting to move an item there and
//* checking where it ended up), typically used to stop sliding
//* units before they end up stuck in trees. If the point is not
//* pathable, the function will also determine the nearest point
//* that is (the point where the item ends up).
//*****************************************************************
globals
// this value is how far from a point the item may end up for the point to be considered pathable
private constant real MAX_RANGE = 10.0
// the following two variables are set to the position of the item after each pathing check
// that way, if a point isn't pathable, these will be the coordinates of the nearest point that is
public real X = 0.0
public real Y = 0.0
// END OF CALIBRATION SECTION
// ================================================================
private rect r
private item check
private item array hidden
private integer hiddenMax = 0
endglobals
private function Init takes nothing returns nothing
set check = CreateItem('ciri',0,0)
call SetItemVisible(check,false)
set r = Rect(0.0,0.0,128.0,128.0)
endfunction
private function HideBothersomeItem takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set hidden[hiddenMax]=GetEnumItem()
call SetItemVisible(hidden[hiddenMax],false)
set hiddenMax=hiddenMax+1
endif
endfunction
// ================================================================
function IsTerrainWalkable takes real x, real y returns boolean
// first, hide any items in the area so they don't get in the way of our item
call MoveRectTo(r, x,y)
call EnumItemsInRect(r,null,function HideBothersomeItem)
// try to move the check item and get it's coordinates
call SetItemPosition(check,x,y)//this unhides the item...
set X = GetItemX(check)
set Y = GetItemY(check)
call SetItemVisible(check,false)//...so we must hide it again
// before returning, unhide any items that got hidden at the start
loop
exitwhen hiddenMax<=0
set hiddenMax=hiddenMax-1
call SetItemVisible(hidden[hiddenMax],true)
set hidden[hiddenMax]=null
endloop
// return pathability status
return (x-X)*(x-X)+(y-Y)*(y-Y) < MAX_RANGE*MAX_RANGE
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DamageEvent/* v 1.0.0.2
**********************************************************************************
*
* Physical Damage Detection Engine
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* By looking_for_help aka eey
*
* This system is able to detect, modify and deal damage. It can differentiate
* between physical and spell damage, as well as block, reduce or increase the
* applied damage to a desired value. You can also allocate damage events from
* running damage events.
*
**********************************************************************************
*
* Supported Systems
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* */ uses optional TriggerRefresh /* by Nestharus
*
* Available at:
* [url]http://www.hiveworkshop.com/forums/submissions-414/trigger-refresh-systems-[/url]
* using-single-unit-events-like-dds-231167/
*
* This system optionaly supports the Trigger Refresh library by Nestharus. You
* do not need to use this to avoid leaks, the system is free of leaks with or
* without this library. To use it get the latest version of TriggerRefresh and
* put the following textmacro at the very end of the DamageEvent library:
*
* //! runtextmacro TRIGGER_REFRESH("80", "EVENT_UNIT_DAMAGED", "function DamageEngine")
*
**********************************************************************************
*
* Implementation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Copy this trigger to your map. With the AddDamageHandler function you can
* add as many handlers as you like (compare the OnDamage scope).
* 2. Copy the two custom abilities to your map and make sure they have the
* correct ID in the globals variable block.
* 3. Go to the locust swarm ability and invert its damage return portion
* from (default) 0.75 to -0.75.
* 4. Remove the spell damage reduction ability from the spell damage reduction
* items you use (runed bracers). You can configure the resistance of this
* item in the globals block, modifying BRACERS_SPELL_DAMAGE_REDUCTION.
*
**********************************************************************************
*
* Important Notes
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Life Drain does not work with this system, so you should use a triggered
* version of this spell if you want to use it.
* 2. Same for Finger of Death, if you want to use this spell bug free with this
* system, you should use a triggered version of it.
* 3. If you use damage modifiers by setting the damage amount variable, you have
* to use GetUnitLife, GetUnitMaxLife and SetUnitLife instead of GetWidgetLife,
* GetUnitState for UNIT_STATE_MAX_LIFE and SetWidgetLife in your whole map to
* ensure there occure no bugs.
* 4. The boolean USE_SPELL_RESISTANCE_AUTO_DETECT is only neccessary set to true
* if you want to use a customized damage table with spell damage resistance
* above 100%. If this is not the case, it should be set to false, as the
* system is faster then and still works correct.
* 5. As already mentioned you can't use the spell reduction ability when using this
* system (runed bracers and elunes grace). If you want to use them, you can
* trigger them by using the damage modifiers. Runed bracers is already considered
* in this system, so you don't have to code it.
*
**********************************************************************************
*
* System API
* ¯¯¯¯¯¯¯¯¯¯
* unit target
* - In this global unit variable, the damaged unit is saved. Don't write any-
* thing into this variable, use it as readonly.
*
* unit source
* - In this global unit variable, the damage source is saved. Don't write any-
* thing into this variable, use it as readonly.
*
* real amount
* - In this global real variable, the amount of damage is saved. This amount
* can be modified by simply setting it to the desired amount that should be
* applied to the target. Set the amount to 0.0 to block the damage completly.
* Negative values will result in heal.
*
* integer damageType
* - In this global integer variable, the damage type of the current damage is
* saved. Use it to differentiate between physical, spell and code damage. The
* variable can takes the values PHYSICAL == 0, SPELL == 1 and CODE == 2. Don't
* write anything into this variable, use it as readonly.
*
* function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount,
* boolean attack, boolean ranged, attacktype localAttackType,
* damagetype localDamageType, weapontype localWeaponType
* returns boolean
* - Use this function to allocate attacks from a running damage event. You can use
* it in exactly the same way as the standard native UnitDamageTarget. The function
* is designed recursive, so you can allocate as many attacks as you want. Do not
* use this function outside of a damage event.
*
* function GetUnitLife takes unit u returns real
* - Use this function instead of the GetWidgetLife native. It ensures that you
* get the correct health value, even when damage modifiers are applied. If
* you don't use damage modifiers at all, you don't need this function.
*
* function GetUnitMaxLife takes unit u returns real
* - Use this function instead of the GetUnitState(u, UNIT_STATE_MAX_LIFE) native.
* It will return the correct value, even when damage modifiers are applied. If
* you don't use damage modifiers at all, you don't need this function.
*
* function SetUnitLife takes unit u, real newLife returns nothing
* - Use this function instead of the SetWidgetLife(u, newLife) native if you use
* damage modifiers in your map. Same rules as for the GetUnitMaxLife and the
* GetUnitMaxLife functions.
*
* function AddDamageHandler takes code damageHandler returns nothing
* - Allows you to add a damage handler function to the system. Compare the
* OnDamage scope for an example usage.
*
* function RemoveDamageHandler takes code damageHandler returns nothing
* - Allows you to remove a damage handler function from the system dynamic-
* ally. If you added the same handler function multiple times to the sys-
* tem, this function will remove all of these equal functions.
*
*********************************************************************************/
globals
/*************************************************************************
* Customizable globals
*************************************************************************/
private constant integer DAMAGE_TYPE_DETECTOR = 'damD'
private constant integer SET_MAX_LIFE = 'damL'
private constant integer SPELL_DAMAGE_REDUCTION_ITEM = 'brac'
private constant boolean USE_SPELL_RESISTANCE_AUTO_DETECT = false
private constant real ETHEREAL_DAMAGE_FACTOR = 1.66
private constant real BRACERS_SPELL_DAMAGE_REDUCTION = 0.33
private constant real TRIGGER_CLEANUP_PERIOD = 60.0
/*************************************************************************
* End of Customizable globals
*************************************************************************/
constant integer PHYSICAL = 0
constant integer SPELL = 1
constant integer CODE = 2
constant real UNIT_MIN_LIFE = 0.406
private constant attacktype ATTACK_TYPE_UNIVERSAL = ConvertAttackType(7)
private hashtable h
private real pureAmount
private trigger damageEvent
private trigger damageHandler
private trigger runAllocatedAttacks
private integer allocatedAttacks
private integer totalAllocs
private integer allocCounter
unit source
unit target
real amount
integer damageType
real damageEventTrigger
endglobals
/******************************************************************************
* User functions
******************************************************************************/
function AddDamageHandler takes code func returns nothing
local integer id = GetHandleId(Condition(func))
local integer index = 0
// Loop to manage equal damage handlers
loop
exitwhen ( LoadTriggerConditionHandle(h, id, index) == null )
set index = index + 1
endloop
// Store the desired damage handler function
call SaveTriggerConditionHandle(h, id, index, TriggerAddCondition(damageHandler, Filter(func)))
endfunction
function RemoveDamageHandler takes code func returns nothing
local integer id = GetHandleId(Condition(func))
local integer index = 0
// Loop through all equal damage handlers
loop
exitwhen ( LoadTriggerConditionHandle(h, id, index) == null )
call TriggerRemoveCondition(damageHandler, LoadTriggerConditionHandle(h, id, index))
set index = index + 1
endloop
// Clean things up
call FlushChildHashtable(h, id)
endfunction
function GetUnitLife takes unit u returns real
local boolean duringModification
local integer uId = GetHandleId(u)
local real health
local real storedHealth = LoadReal(h, uId, 2)
local real storedDamage = LoadReal(h, uId, 1)
// Check if the unit is being rescued from damage
set duringModification = GetUnitAbilityLevel(u, SET_MAX_LIFE) > 0
if duringModification then
call UnitRemoveAbility(u, SET_MAX_LIFE)
endif
// Get the correct health value of the unit
if storedHealth != 0.0 then
set health = storedHealth - storedDamage
else
set health = GetWidgetLife(u) - storedDamage
endif
// Restore the rescue ability and return
if duringModification then
call UnitAddAbility(u, SET_MAX_LIFE)
endif
return health
endfunction
function GetUnitMaxLife takes unit u returns real
local real maxHealth
// Check if the unit is being rescued from damage
if GetUnitAbilityLevel(u, SET_MAX_LIFE) > 0 then
call UnitRemoveAbility(u, SET_MAX_LIFE)
set maxHealth = GetUnitState(u, UNIT_STATE_MAX_LIFE)
call UnitAddAbility(u, SET_MAX_LIFE)
return maxHealth
endif
// If the unit isn't being rescued, use the standard native
return GetUnitState(u, UNIT_STATE_MAX_LIFE)
endfunction
function SetUnitLife takes unit u, real newLife returns nothing
local integer targetId
local integer oldTimerId
local real oldHealth
// Check if the unit is being rescued from damage
if GetUnitAbilityLevel(u, SET_MAX_LIFE) > 0 then
call UnitRemoveAbility(u, SET_MAX_LIFE)
call SetWidgetLife(u, newLife)
call UnitAddAbility(u, SET_MAX_LIFE)
// Get the unit specific timer information
set targetId = GetHandleId(u)
set oldHealth = LoadReal(h, targetId, 0)
// Update the unit specific timer information
if oldHealth != 0.0 then
set oldTimerId = LoadInteger(h, targetId, 3)
call SaveReal(h, targetId, 2, newLife)
call SaveReal(h, targetId, 0, newLife)
call SaveReal(h, oldTimerId, 4, newLife)
endif
return
endif
// If the unit isn't being rescued, use the standard native
call SetWidgetLife(u, newLife)
endfunction
function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, /*
*/boolean ranged, attacktype localAttackType, damagetype localDamageType, /*
*/weapontype localWeaponType returns boolean
// Avoid infinite loop due to recursion
if damageType == CODE then
return false
endif
// Avoid allocating attacks on units that are about to be killed
if ( localTarget == target and GetUnitLife(localTarget) - amount < UNIT_MIN_LIFE ) then
return false
endif
// Store all damage parameters determined by the user
set allocatedAttacks = allocatedAttacks + 1
call SaveUnitHandle(h, allocatedAttacks, 0, localSource)
call SaveUnitHandle(h, allocatedAttacks, 1, localTarget)
call SaveReal(h, allocatedAttacks, 2, localAmount)
call SaveBoolean(h, allocatedAttacks, 3, attack)
call SaveBoolean(h, allocatedAttacks, 4, ranged)
call SaveInteger(h, allocatedAttacks, 5, GetHandleId(localAttackType))
call SaveInteger(h, allocatedAttacks, 6, GetHandleId(localDamageType))
call SaveInteger(h, allocatedAttacks, 7, GetHandleId(localWeaponType))
// Return true if the damage was allocated
return true
endfunction
/******************************************************************************
* Sub functions
******************************************************************************/
private function DealFixDamage takes unit source, unit target, real pureAmount returns nothing
local real MAX_DAMAGE = 1000000.0
local real beforeHitpoints
local real newHitpoints
// Ensure the amount is positive
if pureAmount < 0 then
set pureAmount = -pureAmount
endif
// Save the targets hitpoints
set beforeHitpoints = GetWidgetLife(target)
set newHitpoints = beforeHitpoints - pureAmount
// Apply the desired, fixed amount
if newHitpoints >= UNIT_MIN_LIFE then
call SetUnitState(target, UNIT_STATE_LIFE, newHitpoints)
else
if ( IsUnitType(target, UNIT_TYPE_ETHEREAL) == false ) then
call SetWidgetLife(target, 1.0)
call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, ATTACK_TYPE_UNIVERSAL, DAMAGE_TYPE_UNIVERSAL, null)
else
call UnitRemoveAbility(target, DAMAGE_TYPE_DETECTOR)
call SetWidgetLife(target, 1.0)
call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
endif
endif
endfunction
private function GetUnitSpellResistance takes unit u returns real
local real originalHP
local real beforeHP
local real afterHP
local real resistance
local real DUMMY_DAMAGE = 100
local real DUMMY_FACTOR = 0.01
// Deal spell damage in order to get the units resistance
call UnitRemoveAbility(target, DAMAGE_TYPE_DETECTOR)
set originalHP = GetWidgetLife(target)
call UnitAddAbility(target, SET_MAX_LIFE)
call SetWidgetLife(target, 20000.0)
set beforeHP = GetWidgetLife(target)
call DisableTrigger(damageEvent)
call UnitDamageTarget(source, target, DUMMY_DAMAGE, true, false, null, DAMAGE_TYPE_UNIVERSAL, null)
call EnableTrigger(damageEvent)
set afterHP = GetWidgetLife(target)
call UnitRemoveAbility(target, SET_MAX_LIFE)
call SetWidgetLife(target, originalHP)
call UnitAddAbility(target, DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(target, true, DAMAGE_TYPE_DETECTOR)
// Calculate this resistance
set resistance = DUMMY_FACTOR*(beforeHP - afterHP)
// If the resistance was greater than 100%, return it
if resistance > 1.0 then
return resistance
else
return 1.0
endif
endfunction
private function UnitHasItemOfType takes unit u, integer itemId returns integer
local integer index = 0
local item indexItem
// Check if the target has a spell damage reducing item
loop
set indexItem = UnitItemInSlot(u, index)
if ( indexItem != null ) and ( GetItemTypeId(indexItem) == itemId ) then
return index + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
return 0
endfunction
/******************************************************************************
* Damage Engine
******************************************************************************/
private function AfterDamage takes nothing returns nothing
local timer time = GetExpiredTimer()
local integer id = GetHandleId(time)
local unit localSource = LoadUnitHandle(h, id, 0)
local unit localTarget = LoadUnitHandle(h, id, 1)
local real pureAmount = LoadReal(h, id, 2)
local real amount = LoadReal(h, id, 3)
local real originalHealth = LoadReal(h, id, 4)
// If the damage was modified, restore units health
if originalHealth != 0.0 then
call UnitRemoveAbility(localTarget, SET_MAX_LIFE)
call SetWidgetLife(localTarget, originalHealth)
endif
// Apply the desired amount of damage
if amount > 0.0 then
call DisableTrigger(damageEvent)
call DealFixDamage(localSource, localTarget, amount)
call EnableTrigger(damageEvent)
else
call SetWidgetLife(localTarget, originalHealth - amount)
endif
// Clean things up
call FlushChildHashtable(h, id)
call FlushChildHashtable(h, GetHandleId(localTarget))
call DestroyTimer(time)
set time = null
set localSource = null
set localTarget = null
endfunction
private function DamageEngine takes nothing returns nothing
local timer time
local integer id
local real health
local real rawAmount
local real originalHealth
local integer targetId
local integer oldTimerId
local real oldHealth
local real oldOriginalHealth
local real oldAmount
// Set damage variables
set source = GetEventDamageSource()
set target = GetTriggerUnit()
set rawAmount = GetEventDamage()
// Determine the damage type
if damageType == CODE and rawAmount != 0.0 then
set damageType = CODE
elseif rawAmount > 0.0 then
set damageType = PHYSICAL
elseif rawAmount < 0.0 then
set damageType = SPELL
else
return
endif
// Correct the damage amount
if rawAmount < 0.0 then
set amount = -rawAmount
else
set amount = rawAmount
endif
// Register spell reduction above 100%
static if USE_SPELL_RESISTANCE_AUTO_DETECT then
set amount = GetUnitSpellResistance(target)*amount
else
if ( IsUnitType(target, UNIT_TYPE_ETHEREAL) and IsUnitEnemy(target, GetOwningPlayer(source)) and rawAmount < 0.0 ) then
set amount = ETHEREAL_DAMAGE_FACTOR*amount
endif
endif
// Register spell damage reducing items like runed bracers
if ( IsUnitType(target, UNIT_TYPE_HERO) and UnitHasItemOfType(target, SPELL_DAMAGE_REDUCTION_ITEM) > 0 ) and rawAmount < 0.0 then
set amount = (1 - BRACERS_SPELL_DAMAGE_REDUCTION)*amount
endif
// Save health and damage variables
if damageType != CODE then
call UnitRemoveAbility(target, SET_MAX_LIFE)
endif
set pureAmount = amount
set originalHealth = GetWidgetLife(target)
set oldTimerId = 0
// Call damage handlers
set damageEventTrigger = 1.0
set damageEventTrigger = 0.0
// If the damage was modified, apply the rescue ability
if amount != pureAmount then
call UnitAddAbility(target, SET_MAX_LIFE)
call SetWidgetLife(target, GetWidgetLife(target) + pureAmount)
endif
// Check if a previous timer didn't yet expire
set targetId = GetHandleId(target)
set oldHealth = LoadReal(h, targetId, 0)
// If this is the case, update the timer information
if oldHealth != 0.0 then
set oldTimerId = LoadInteger(h, targetId, 3)
set oldOriginalHealth = LoadReal(h, targetId, 2)
set oldAmount = LoadReal(h, targetId, 1)
set originalHealth = oldOriginalHealth - oldAmount
call SaveReal(h, oldTimerId, 4, oldOriginalHealth)
endif
// Call after damage event if damage was spell, modified, code or parallel
if ( rawAmount < 0.0 or pureAmount != amount or oldTimerId != 0 or allocatedAttacks > 0 ) then
set time = CreateTimer()
set id = GetHandleId(time)
// Save handles for after damage event
call SaveUnitHandle(h, id, 0, source)
call SaveUnitHandle(h, id, 1, target)
call SaveReal(h, id, 2, pureAmount)
call SaveReal(h, id, 3, amount)
call SaveReal(h, id, 4, originalHealth)
// Save this extra to manage parallel damage instances
call SaveReal(h, targetId, 0, GetWidgetLife(target))
call SaveReal(h, targetId, 1, amount)
call SaveReal(h, targetId, 2, originalHealth)
call SaveInteger(h, targetId, 3, id)
// Avoid healing of negative spell damage
if rawAmount < 0.0 then
call DisableTrigger(damageEvent)
call DealFixDamage(source, target, -rawAmount)
if ( originalHealth - amount < UNIT_MIN_LIFE ) then
call UnitRemoveAbility(target, SET_MAX_LIFE)
call DealFixDamage(source, target, amount)
endif
call EnableTrigger(damageEvent)
endif
// Guarantee unit exploding
if originalHealth - amount < UNIT_MIN_LIFE then
if rawAmount > 0.0 then
call UnitRemoveAbility(target, SET_MAX_LIFE)
call SetWidgetLife(target, UNIT_MIN_LIFE)
endif
endif
// Start the after damage event
call TimerStart(time, 0.0, false, function AfterDamage)
endif
// Handle allocated attacks from UnitDamageTargetEx
if totalAllocs == 0 then
set totalAllocs = allocatedAttacks
endif
if allocatedAttacks > 0 then
set allocatedAttacks = allocatedAttacks - 1
set allocCounter = allocCounter + 1
call TriggerEvaluate(runAllocatedAttacks)
endif
// Reset all required variables
set totalAllocs = 0
set allocCounter = -1
set damageType = -1
endfunction
/******************************************************************************
* Initialization
******************************************************************************/
private function RestoreTriggers takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
// Re-register units that are alive
if GetWidgetLife(enumUnit) >= UNIT_MIN_LIFE then
call TriggerRegisterUnitEvent(damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
endif
set enumUnit = null
endfunction
private function ClearMemory_Actions takes nothing returns nothing
local group g = CreateGroup()
local code c = function DamageEngine
// Reset the damage event
call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, null)
call ResetTrigger(damageEvent)
call DestroyTrigger(damageEvent)
set damageEvent = null
// Rebuild it then
set damageEvent = CreateTrigger()
call TriggerAddCondition(damageEvent, Filter(c))
call ForGroup(g, function RestoreTriggers)
// Clean things up
call DestroyGroup(g)
set g = null
set c = null
endfunction
private function MapInit takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
// Register units on map initialization
call UnitAddAbility(enumUnit, DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(enumUnit, true, DAMAGE_TYPE_DETECTOR)
static if not LIBRARY_TriggerRefresh then
call TriggerRegisterUnitEvent(damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
endif
set enumUnit = null
endfunction
private function UnitEntersMap takes nothing returns nothing
local unit triggerUnit = GetTriggerUnit()
// Register units that enter the map
if ( GetUnitAbilityLevel(triggerUnit, DAMAGE_TYPE_DETECTOR) < 1 ) then
call UnitAddAbility(triggerUnit, DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(triggerUnit, true, DAMAGE_TYPE_DETECTOR)
static if not LIBRARY_TriggerRefresh then
call TriggerRegisterUnitEvent(damageEvent, triggerUnit, EVENT_UNIT_DAMAGED)
endif
endif
set triggerUnit = null
endfunction
private function RunAllocatedAttacks takes nothing returns nothing
local integer localAllocAttacks = allocatedAttacks + 1
// Calculate the correct sequence of allocated attacks
set localAllocAttacks = localAllocAttacks - totalAllocs + 1 + 2*allocCounter
// Deal code damage if the unit isn't exploding
set damageType = CODE
if GetUnitLife(LoadUnitHandle(h, localAllocAttacks, 1)) >= UNIT_MIN_LIFE then
call UnitDamageTarget(LoadUnitHandle(h, localAllocAttacks, 0), LoadUnitHandle(h, localAllocAttacks, 1), /*
*/LoadReal(h, localAllocAttacks, 2), LoadBoolean(h, localAllocAttacks, 3), /*
*/LoadBoolean(h, localAllocAttacks, 4), ConvertAttackType(LoadInteger(h, /*
*/localAllocAttacks, 5)), ConvertDamageType(LoadInteger(h, localAllocAttacks, 6)), /*
*/ConvertWeaponType(LoadInteger(h, localAllocAttacks, 7)))
else
call FlushChildHashtable(h, localAllocAttacks - 1)
endif
// Clean things up
call FlushChildHashtable(h, localAllocAttacks)
endfunction
private module Inits
private static method onInit takes nothing returns nothing
local group g = CreateGroup()
local region r = CreateRegion()
local trigger UnitEnters = CreateTrigger()
local trigger ClearMemory = CreateTrigger()
local code cDamageEngine = function DamageEngine
local code cUnitEnters = function UnitEntersMap
local code cClearMemory = function ClearMemory_Actions
local code cRunAllocatedAttacks = function RunAllocatedAttacks
// Initialize variables
set h = InitHashtable()
set damageEvent = CreateTrigger()
set damageHandler = CreateTrigger()
set damageType = -1
set allocatedAttacks = 0
set runAllocatedAttacks = CreateTrigger()
set totalAllocs = 0
set allocCounter = -1
// Register units on map initialization
call TriggerRegisterVariableEvent(damageHandler, "damageEventTrigger", EQUAL, 1.0)
call TriggerAddCondition(damageEvent, Filter(cDamageEngine))
call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, null)
call ForGroup(g, function MapInit)
// Register units that enter the map
call RegionAddRect(r, bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(UnitEnters, r, null)
call TriggerAddCondition(UnitEnters, Filter(cUnitEnters))
// Register trigger for allocated attacks
call TriggerAddCondition(runAllocatedAttacks, Filter(cRunAllocatedAttacks))
// Clear memory leaks
call TriggerRegisterTimerEvent(ClearMemory, TRIGGER_CLEANUP_PERIOD, true)
call TriggerAddCondition(ClearMemory, Filter(cClearMemory))
// Clean things up
call DestroyGroup(g)
set UnitEnters = null
set ClearMemory = null
set cDamageEngine = null
set cUnitEnters = null
set cClearMemory = null
set cRunAllocatedAttacks = null
set g = null
set r = null
endmethod
endmodule
private struct Init extends array
implement Inits
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SimError initializer init
//**************************************************************************************************
//*
//* SimError by Vexorian
//*
//* Mimic an interface error message
//* call SimError(ForPlayer, msg)
//* ForPlayer : The player to show the error
//* msg : The error
//*
//* To implement this function, copy this trigger and paste it in your map.
//* Unless of course you are actually reading the library from wc3c's scripts section, then just
//* paste the contents into some custom text trigger in your map.
//*
//**************************************************************************************************
//==================================================================================================
globals
private sound error
endglobals
//====================================================================================================
function SimError takes player ForPlayer, string msg returns nothing
set msg="\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+msg+"|r"
if (GetLocalPlayer() == ForPlayer) then
call ClearTextMessages()
call DisplayTimedTextToPlayer( ForPlayer, 0.52, 0.96, 2.00, msg )
call StartSound( error )
endif
endfunction
private function init takes nothing returns nothing
set error=CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
//call StartSound( error ) //apparently the bug in which you play a sound for the first time
//and it doesn't work is not there anymore in patch 1.22
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//============================================================================
// SpellEffectEvent
// - Version 1.1.0.0
//
// API
// ---
// RegisterSpellEffectEvent(integer abil, code onCast)
//
// Requires
// --------
// RegisterPlayerUnitEvent: hiveworkshop.com/forums/showthread.php?t=203338
//
// Optional
// --------
// Table: hiveworkshop.com/forums/showthread.php?t=188084
//
library SpellEffectEvent requires RegisterPlayerUnitEvent, optional Table
//============================================================================
private module M
static if LIBRARY_Table then
static Table tb
else
static hashtable ht = InitHashtable()
endif
static method onCast takes nothing returns nothing
static if LIBRARY_Table then
call TriggerEvaluate(.tb.trigger[GetSpellAbilityId()])
else
call TriggerEvaluate(LoadTriggerHandle(.ht, 0, GetSpellAbilityId()))
endif
endmethod
private static method onInit takes nothing returns nothing
static if LIBRARY_Table then
set .tb = Table.create()
endif
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endmodule
//============================================================================
private struct S extends array
implement M
endstruct
//============================================================================
function RegisterSpellEffectEvent takes integer abil, code onCast returns nothing
static if LIBRARY_Table then
if not S.tb.handle.has(abil) then
set S.tb.trigger[abil] = CreateTrigger()
endif
call TriggerAddCondition(S.tb.trigger[abil], Filter(onCast))
else
if not HaveSavedHandle(S.ht, 0, abil) then
call SaveTriggerHandle(S.ht, 0, abil, CreateTrigger())
endif
call TriggerAddCondition(LoadTriggerHandle(S.ht, 0, abil), Filter(onCast))
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.1.0.0
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must either
* return a boolean (false) or nothing. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
* - Don't destroy a trigger unless you really know what you're doing.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent takes playerunitevent whichEvent, code whichFunction returns nothing
* - Registers code that will execute when an event fires.
* - function RegisterPlayerUnitEventForPlayer takes playerunitevent whichEvent, code whichFunction, player whichPlayer returns nothing
* - Registers code that will execute when an event fires for a certain player.
* - function GetPlayerUnitEventTrigger takes playerunitevent whichEvent returns trigger
* - Returns the trigger corresponding to ALL functions of a playerunitevent.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 260 + 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function GetPlayerUnitEventTrigger takes playerunitevent p returns trigger
return t[GetHandleId(p)]
endfunction
endlibrary
//TESH.scrollpos=12
//TESH.alwaysfold=0
library BoundSentinel initializer init
//*************************************************
//* BoundSentinel
//* -------------
//* Don't leave your units unsupervised, naughty
//* them may try to get out of the map bounds and
//* crash your game.
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//*************************************************
//==================================================
//=========================================================================================
globals
private constant boolean ALLOW_OUTSIDE_PLAYABLE_MAP_AREA = false
private real maxx
private real maxy
private real minx
private real miny
endglobals
//=======================================================================
private function dis takes nothing returns boolean
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local region r = CreateRegion()
local rect map
local rect rc
if ALLOW_OUTSIDE_PLAYABLE_MAP_AREA then
set map = GetWorldBounds()
else
set map = bj_mapInitialPlayableArea
endif
set minx = GetRectMinX(map)
set miny = GetRectMinY(map)
set maxx = GetRectMaxX(map)
set maxy = GetRectMaxY(map)
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
if ALLOW_OUTSIDE_PLAYABLE_MAP_AREA then
call RemoveRect(map)
endif
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddCondition(t, Condition(function dis))
set rc=null
set map = null
endfunction
endlibrary
//TESH.scrollpos=320
//TESH.alwaysfold=0
library Table // made by Bribe, special thanks to Nestharus, version 3.0.0.0
/*
API
------------
struct Table
| static method create takes nothing returns Table
| create a new Table
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush all stored values inside of it
|
| method remove takes integer key returns nothing
| remove the value at index "key"
|
| method operator []= takes integer key, $TYPE$ value returns nothing
| assign "value" to index "key"
|
| method operator [] takes integer key returns $TYPE$
| load the value at index "key"
|
| method has takes integer key returns boolean
| whether or not the key was assigned
|
----------------
struct TableArray
| static method operator [] takes integer array_size returns TableArray
| create a new array of Tables of size "array_size"
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush and destroy it
|
| method operator size takes nothing returns integer
| returns the size of the TableArray
|
| method operator [] takes integer key returns Table
| returns a Table accessible exclusively to index "key"
*/
globals
private hashtable ht = InitHashtable() //The last hashtable you need
private integer more = 2 //Index generation for Tables (above 2)
private integer less = 0 //Index generation for TableArrays (below 0)
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return 1
endmethod
static method operator list takes nothing returns Table
return 2
endmethod
endstruct
private struct handles extends array
method has takes integer key returns boolean
return HaveSavedHandle(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedHandle(ht, this, key)
endmethod
endstruct
private struct agents extends array
method operator []= takes integer key, agent value returns nothing
call SaveAgentHandle(ht, this, key, value)
endmethod
endstruct
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$(ht, this, key, value)
endmethod
method has takes integer key returns boolean
return HaveSaved$SUPER$(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSaved$SUPER$(ht, this, key)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$Handle(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$Handle(ht, this, key, value)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
struct Table extends array
// Implement modules for intuitive type-syntax
implement realm
implement booleanm
implement stringm
implement playerm
implement widgetm
implement destructablem
implement itemm
implement unitm
implement abilitym
implement timerm
implement triggerm
implement triggerconditionm
implement triggeractionm
implement eventm
implement forcem
implement groupm
implement locationm
implement rectm
implement boolexprm
implement soundm
implement effectm
implement unitpoolm
implement itempoolm
implement questm
implement questitemm
implement defeatconditionm
implement timerdialogm
implement leaderboardm
implement multiboardm
implement multiboarditemm
implement trackablem
implement dialogm
implement buttonm
implement texttagm
implement lightningm
implement imagem
implement ubersplatm
implement regionm
implement fogstatem
implement fogmodifierm
implement hashtablem
method operator handle takes nothing returns handles
return this
endmethod
method operator agent takes nothing returns agents
return this
endmethod
// set this = a[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key)
endmethod
// set a[389034] = 8192
method operator []= takes integer key, Table a returns nothing
call SaveInteger(ht, this, key, a)
endmethod
// set b = a.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key)
endmethod
// call a.remove(294080)
method remove takes integer key returns nothing
call RemoveSavedInteger(ht, this, key)
endmethod
// Remove all data from a Table instance
method flush takes nothing returns nothing
call FlushChildHashtable(ht, this)
endmethod
// local Table a = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set more = more + 1
set this = more
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this)
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call a.destroy()
//
method destroy takes nothing returns nothing
debug if dex.list[this] != -1 then
debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
debug return
debug endif
call this.flush()
set dex.list[this] = dex.list[0]
set dex.list[0] = this
endmethod
endstruct
struct TableArray extends array
//Returns a new TableArray to do your bidding. Simply use:
//
// local TableArray ta = TableArray[array_size]
//
static method operator [] takes integer array_size returns TableArray
local Table a = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = a[0] //The last-destroyed TableArray that had this array size
debug if array_size <= 0 then
debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
debug return 0
debug endif
if this == 0 then
set less = less - array_size
set this = less
else
set a[0] = a[this] //Set the last destroyed to the last-last destroyed
call a.remove(this) //Clear hash memory
endif
set dex.size[this] = array_size //This remembers the array size
return this
endmethod
//Returns the size of the TableArray
method operator size takes nothing returns integer
return dex.size[this]
endmethod
//da[integer a].unit[integer b] = unit u
//da[integer a][integer c] = integer d
//
//Inline-friendly when not running in debug mode
//
method operator [] takes integer key returns Table
static if DEBUG_MODE then
local integer i = this.size
if i == 0 then
call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
return 0
elseif key < 0 or key >= i then
call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
return 0
endif
endif
return this + key
endmethod
//Destroys a TableArray without flushing it; assumed you'd call .flush()
//if you want it flushed too. This is public so that if you are flushing
//instances the whole time you don't waste efficiency when disposing the
//TableArray.
//
method destroy takes nothing returns nothing
local Table a = dex.size[this.size]
debug if this.size <= 0 then
debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
debug return
debug endif
if a == 0 then
//Create an array to index recycled instances with their array size
set a = Table.create()
set dex.size[this.size] = a
endif
call dex.size.remove(this) //Clear the array size from hash memory
set a[this] = a[0]
set a[0] = this
endmethod
//All you need to know about this one is that it won't hit the op limit.
private static method clean takes Table a, integer end returns nothing
local integer i = a + 5000
if i < end then
call clean.evaluate(i, end)
set end = i
endif
loop
call a.flush()
set a = a + 1
exitwhen a == end
endloop
endmethod
//Flushes the TableArray and also destroys it. Doesn't get any more
//similar to the FlushParentHashtable native than this.
//
method flush takes nothing returns nothing
local integer end = this.size + this
debug if this == end then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
call clean.evaluate(this, end)
call this.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DestructableLib initializer Initialization
//* ============================================================================ *
//* Made by PitzerMike *
//* *
//* I made this to detect if a destructable is a tree or not. It works not only *
//* for the standard trees but also for custom destructables created with the *
//* object editor. It uses a footie as a dummy with the goul's harvest ability. *
//* The dummy ids can be changed though. I also added the IsDestructableDead *
//* function for completeness. *
//* ============================================================================ *
globals
private constant integer DUMMY_UNIT_ID = 'hfoo' // footman
private constant integer HARVEST_ID = 'Ahrl' // ghouls harvest
private constant player OWNING_PLAYER = Player(15)
private unit dummy = null
endglobals
function IsDestructableDead takes destructable dest returns boolean
return GetDestructableLife(dest) <= 0.405
endfunction
function IsDestructableTree takes destructable dest returns boolean
local boolean result = false
if (dest != null) then
call PauseUnit(dummy, false)
set result = IssueTargetOrder(dummy, "harvest", dest)
call PauseUnit(dummy, true) // stops order
endif
return result
endfunction
private function Initialization takes nothing returns nothing
set dummy = CreateUnit(OWNING_PLAYER, DUMMY_UNIT_ID, 0.0, 0.0, 0.0)
call ShowUnit(dummy, false) // cannot enumerate
call UnitAddAbility(dummy, HARVEST_ID)
call UnitAddAbility(dummy, 'Aloc') // unselectable, invulnerable
call PauseUnit(dummy, true)
endfunction
endlibrary
//TESH.scrollpos=52
//TESH.alwaysfold=0
/**************************************
*
* IsUnitChanneling
* v2.1.0.0
* By Magtheridon96
*
* - Tells whether a unit is channeling or not.
*
* Requirements:
* -------------
*
* - RegisterPlayerUnitEvent by Magtheridon96
* - hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
*
* Optional:
* ---------
*
* - UnitIndexer by Nestharus
* - hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
* - Table by Bribe
* - hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
* API:
* ----
*
* - function IsUnitChanneling takes unit whichUnit returns boolean
* - Tells whether a unit is channeling or not.
* (This function is only available if you have UnitIndexer)
*
* - function IsUnitChannelingById takes integer unitIndex returns boolean
* - Tells whether a unti is channeling or not given the unit index.
*
**************************************/
library IsUnitChanneling requires optional UnitIndexer, optional Table, RegisterPlayerUnitEvent
private struct OnChannel extends array
static if LIBRARY_UnitIndexer then
static boolean array channeling
else
static if LIBRARY_Table then
static key k
static Table channeling = k
else
static hashtable hash = InitHashtable()
endif
endif
private static method onEvent takes nothing returns nothing
static if LIBRARY_UnitIndexer then
local integer id = GetUnitUserData(GetTriggerUnit())
set channeling[id] = not channeling[id]
else
static if LIBRARY_Table then
local integer id = GetHandleId(GetTriggerUnit())
set channeling.boolean[id] = not channeling.boolean[id]
else
local integer id = GetHandleId(GetTriggerUnit())
call SaveBoolean(hash, 0, id, not LoadBoolean(hash, 0, id))
endif
endif
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CHANNEL, function thistype.onEvent)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_ENDCAST, function thistype.onEvent)
endmethod
endstruct
static if LIBRARY_UnitIndexer then
function IsUnitChannelingById takes integer id returns boolean
return OnChannel.channeling[id]
endfunction
endif
function IsUnitChanneling takes unit u returns boolean
static if LIBRARY_UnitIndexer then
return OnChannel.channeling[GetUnitUserData(u)]
else
static if LIBRARY_Table then
return OnChannel.channeling.boolean[GetHandleId(u)]
else
return LoadBoolean(OnChannel.hash, 0, GetHandleId(u))
endif
endif
endfunction
endlibrary
//TESH.scrollpos=4
//TESH.alwaysfold=0
scope FlameBlast initializer init
//uses SpellEffectEvent, RegisterPlayerUnitEvent, Fundamentals, MuiDummyCasters
globals
private constant integer SPELL_ID = 'A02T'
private constant integer DUMMY_SPELL_ID = 'A02U'
private constant integer ORDER = 852231
endglobals
private function Actions takes nothing returns nothing
local unit hero = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local real x = GetUnitX(hero)
local real y = GetUnitY(hero)
local real distance = 200
local real angle = -4.5
local real x1
local real y1
local integer level = GetUnitAbilityLevel(hero, SPELL_ID)
local integer i = 0
loop
set x1 = x + distance*Cos(GetUnitFacing(hero)*angle)
set y1 = y + distance*Sin(GetUnitFacing(hero)*angle)
call MuiDummyCasters.hitTarget(GetTriggerPlayer(),target,x1,y1,DUMMY_SPELL_ID,ORDER,level)
set angle = angle + 1.5
set i = i+1
exitwhen i==3
endloop
set hero = null
set target = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call PreloadSpell(SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope LifeMana initializer init
globals
private constant integer SPELL_ID = 'A02W'
private constant string SFX = "Abilities\\Spells\\Items\\ResourceItems\\ResourceEffectTarget.mdl"//"Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl"
endglobals
private function Cond takes nothing returns nothing
local unit caster = GetTriggerUnit()
local unit first
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
local real life = (level*75)+25
//! runtextmacro FOG_ADD("x","y","500")
if IsUnitAlly(first, GetTriggerPlayer()) and FUN_UnitAlive(first) and first!=caster then
call DestroyEffect(AddSpecialEffectTarget(SFX, first, "overhead"))
call SetWidgetLife(first, GetWidgetLife(first)+life)
endif
//! runtextmacro FOG_REMOVE()
set caster = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Cond)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope LightningVortex initializer init
globals
private constant integer SPELL_ID = 'A02R'
private constant integer DUMMY_SPELL_ID = 'A00L'
private constant integer BUFF = 'Blsh'
endglobals
private function Cond takes nothing returns nothing
local unit attacker
if FilterEnemyAndSpellLevel(GetOwningPlayer(GetAttacker()), GetTriggerUnit(), SPELL_ID) then
set attacker = GetAttacker()
if GetChance(GetTriggerUnit(), SPELL_ID) then
if GetUnitAbilityLevel(attacker, BUFF)==0 then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), attacker, GetUnitX(attacker), GetUnitY(attacker), DUMMY_SPELL_ID, OrderId("lightningshield"), GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID))
//call HitTarget(GetTriggerPlayer(), attacker, GetUnitX(attacker), GetUnitY(attacker), DUMMY_SPELL_ID, OrderId("lightningshield"), GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID))
endif
endif
set attacker = null
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=30
//TESH.alwaysfold=0
scope SweepingStrike initializer init
globals
private constant integer SPELL_ID = 'A039'
private constant string SFX = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
private constant real ANIM_DELAY = 0.6
endglobals
private function UnitAlive takes unit u returns boolean
return not (IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId(u)==0)
endfunction
private function GetStrikes takes integer i returns real
return 2 + i * 2.
endfunction
private function GetDamage takes integer i returns real
return 5 + i * 10.
endfunction
private function Looper takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
local unit u = GetUnitHandle(tID, 1)
local unit tar = GetUnitHandle(tID, 2)
local real strikes = GetReal(tID, 3)
local real facing = GetReal(tID, 4)
local real damage = GetReal(tID, 5)
if strikes > 0 and UnitAlive(u) and UnitAlive(tar) then
call PauseUnit(u, true)
call SetReal(tID, 3, strikes-ANIM_DELAY)
call SetUnitAnimation(u, "Attack Slam")
call IssueTargetOrder(u, "attack", tar)
call UnitDamageTarget(u, tar, damage, false, false, ATK, DMG, null)
call SetUnitX(u, GetUnitX(tar) - 150 * Cos(facing))
call SetUnitY(u, GetUnitY(tar) - 150 * Sin(facing))
call DestroyEffect(AddSpecialEffectTarget(SFX, tar, "origin"))
else
if UnitAlive(u) then
call SetUnitPosition(u, GetReal(tID, 6), GetReal(tID, 7))
endif
call SetUnitInvulnerable(u, false)
call PauseUnit(u, false)
call PauseUnit(tar, false)
call Flush(tID)
call StopTimer(GetExpiredTimer())
endif
set u = null
set tar = null
endfunction
private function Actions takes nothing returns nothing
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local unit u = GetTriggerUnit()
local unit tar = GetSpellTargetUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
call SetUnitInvulnerable(u, true)
call PauseUnit(tar, true)
call SetUnitHandle(tID, 1, u)
call SetUnitHandle(tID, 2, tar)
call SetReal(tID, 3, GetStrikes(level))
call SetReal(tID, 4, Atan2(GetUnitY(tar)-GetUnitY(u), GetUnitX(tar)-GetUnitX(u)))//facing
call SetReal(tID, 5, GetDamage(level))
call SetReal(tID, 6, GetUnitX(u))
call SetReal(tID, 7, GetUnitY(u))
call TimerStart(t, ANIM_DELAY, true, function Looper)
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=54
//TESH.alwaysfold=0
/*
===Leap Blow v1.0
===By Mckill2009
REQUIRED LIBRARIES:
- Timer32 by Jesys4Lyf
- RegisterPlayerUnitEvent by Magtheridon96
*/
scope LeapBlow
globals
private constant integer SPELL_ID = 'A03A'
private constant integer ANIMATION_INDEX = 12 //should be 12, blademaster's spin
private constant string SFX = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
endglobals
private function GetAoE takes integer level returns real
return 50 * level + 100.
endfunction
private function GetDamage takes integer level returns real
return 25 * level + 25.
endfunction
private function GetHeight takes integer level returns real
return 75 * level + 100.
endfunction
private function GetSpeed takes integer level returns real
return 3 * level + 12.
endfunction
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function FilterDamagedUnit takes unit c, unit u, boolean flying returns boolean
if UnitAlive(u) and IsUnitEnemy(c, GetOwningPlayer(u))and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
if flying then
return not IsUnitType(u, UNIT_TYPE_GROUND)
else
return IsUnitType(u, UNIT_TYPE_GROUND)
endif
endif
return false
endfunction
private function ParabolaZ takes real h, real d, real x returns real
return (5 * h / d) * (d - x) * (x / d)
endfunction
struct LeapBlow
unit caster
real aoe
real damage
real damageAir
real xSpell
real ySpell
real maxDist
real distX
real angle
real speed
real height
boolean on
boolean flying
boolean pause
method damageThem takes real x, real y, integer animIndex returns nothing
local unit first
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, .aoe, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if FilterDamagedUnit(.caster, first, .flying) then
if .flying then
call UnitDamageTarget(.caster, first, .damageAir, false, false, ATK, DMG, null)
else
call UnitDamageTarget(.caster, first, .damage, false, false, ATK, DMG, null)
endif
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
call SetUnitAnimationByIndex(.caster, animIndex)
endmethod
method periodic takes nothing returns nothing
local unit first
local real x = GetUnitX(.caster)
local real y = GetUnitY(.caster)
if UnitAlive(.caster) and .on then
if .pause then
set .pause = false
call PauseUnit(.caster, true)
endif
if .maxDist > .distX then
set .distX = .distX + .speed
call SetUnitX(.caster, x+.speed*Cos(.angle))
call SetUnitY(.caster, y+.speed*Sin(.angle))
call SetUnitFlyHeight(.caster, ParabolaZ(.height, .maxDist, .distX) ,0)
call .damageThem(x, y, ANIMATION_INDEX)
else
set .on = false
endif
else
set .flying = false
if UnitAlive(.caster) then
call .damageThem(x, y, 3)
call DestroyEffect(AddSpecialEffect(SFX, x, y))
endif
call SetUnitInvulnerable(.caster, false)
call SetUnitPathing(.caster, true)
call PauseUnit(.caster, false)
call SetUnitFlyHeight(.caster, GetUnitDefaultFlyHeight(.caster), 0)
call .destroy()
call .stopPeriodic()
endif
endmethod
implement T32x
static method create takes unit u returns thistype
local thistype this = allocate()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x1 = GetSpellTargetX()
local real y1 = GetSpellTargetY()
set .caster = u
set .aoe = GetAoE(level)
set .damage = GetDamage(level)
set .damageAir = GetDamage(level)*0.1
set .angle = Atan2(y1-y,x1-x)
set .speed = GetSpeed(level)
set .height = GetHeight(level)
set .maxDist = SquareRoot((x1-x) * (x1-x) + (y1-y) * (y1-y))
set .distX = 0
set .on = true
set .flying = true
set .pause = true
call SetUnitInvulnerable(u, true)
call SetUnitPathing(u, false)
if UnitAddAbility(u, 'Arav') then
call UnitRemoveAbility(u, 'Arav')
endif
call .startPeriodic()
return this
endmethod
static method onCast takes nothing returns nothing
if GetSpellAbilityId()==SPELL_ID then
call thistype.create(GetTriggerUnit())
endif
endmethod
static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endstruct
endscope
//TESH.scrollpos=4
//TESH.alwaysfold=0
//Slams the ground, stunning and damaging nearby enemy land units.
//Additionaly, any enemy in 400 AoE will crippled in fear and making their size greatly reduced,
//when in Mini state, they gain 20% Attack speed , but Lose 50% Movement Speed.
//Mini Last for 5 sesonds.
//|cffffcc00Level 1|r - 50 damage, 1.5 second stun.
//|cffffcc00Level 2|r - 75 damage, 2 second stun.
//|cffffcc00Level 3|r - 100 damage, 2.5 second stun.
//|cffffcc00Level 4|r - 125 damage, 3 second stun.
//|cffffcc00Level 5|r - 150 damage, 3.5 second stun.
scope Trample initializer init
globals
//the SPELL_ID and ORDER_ID must match to each other because of channeling reasons
private constant integer SPELL_ID = 'A031'
private constant integer DUMMY_SPELL_ID = 'A030'
private constant real AOE_RANGE = 400
endglobals
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit first
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
//! runtextmacro FOG_ADD("GetUnitX(u)","GetUnitY(u)","AOE_RANGE")
if IsUnitEnemy(first, GetTriggerPlayer()) and FUN_UnitAlive(first) and FUN_OrganicUnits(first) then
//call HitTarget(GetTriggerPlayer(),first,GetUnitX(first), GetUnitY(first),DUMMY_SPELL_ID,OrderId("bloodlust"), level)
call MuiDummyCasters.hitTarget(GetTriggerPlayer(),first,GetUnitX(first), GetUnitY(first),DUMMY_SPELL_ID,OrderId("bloodlust"), level)
endif
//! runtextmacro FOG_REMOVE()
set u = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope SoulDrain initializer init
globals
private constant integer SPELL_ID = 'A01G'
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant string SFX = "Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl"
private constant real INTERVAL = 0.1
endglobals
private function GetDuration takes integer i returns real
return 5 + i * 5.
endfunction
private function GetDamage takes integer i returns real
return 7 + i * 6.25
endfunction
private function GetMana takes integer i returns real
return i * 2.
endfunction
private function DrainLoop takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
local unit u = GetUnitHandle(tID, 1)
local unit tar = GetUnitHandle(tID, 2)
local real duration = GetReal(tID, 3)
local real damage = GetReal(tID, 4)
local real mana = GetReal(tID, 5)
if duration > 0 and FUN_UnitAlive(tar) then
call SetReal(tID, 3, duration-INTERVAL)
call UnitDamageTarget(u, tar, damage, false, false, ATT, DAM, null)
if GetUnitState(tar, UNIT_STATE_MANA) > 0 then
call SetUnitState(tar, UNIT_STATE_MANA, GetUnitState(tar, UNIT_STATE_MANA)- mana)
endif
else
call DestroyEffect(GetEffectHandle(tID, 6))
call StopTimer(GetExpiredTimer())
call Flush(tID)
endif
set u = null
set tar = null
endfunction
private function Actions takes nothing returns nothing
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local unit u = GetTriggerUnit()
local unit tar = GetSpellTargetUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local effect sfx = AddSpecialEffectTarget(SFX, tar, "overhead")
call SetUnitHandle(tID, 1, u)
call SetUnitHandle(tID, 2, tar)
call SetReal(tID, 3, 4) //duration
call SetReal(tID, 4, (GetDamage(level))*INTERVAL)
call SetReal(tID, 5, GetMana(level))
call SetEffectHandle(tID, 6, sfx)
call TimerStart(t, INTERVAL, true, function DrainLoop)
set u = null
set tar = null
set sfx = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=6
//TESH.alwaysfold=0
scope Whirlwind initializer init
globals
private constant integer SPELL_ID = 'A01H'
private constant integer DUMMY_SPELL_ID = 'A037'
private constant integer WIND_ID = 'h00P' //unit
private constant integer BUFF_ID = 'Bcy2'
private constant real SPEED = 30.
private constant real INTERVAL = 0.4
private constant real AOE = 300.
endglobals
private function WindLoop takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
local unit first
local unit wind = GetUnitHandle(tID, 1)
local real travel = GetReal(tID, 2)
local real angle = GetReal(tID, 3)
local real maxdistance = GetReal(tID, 4)
if maxdistance > travel then
call SetReal(tID, 2, travel+SPEED)
call SetUnitX(wind, GetUnitX(wind)+SPEED*Cos(angle))
call SetUnitY(wind, GetUnitY(wind)+SPEED*Sin(angle))
//! runtextmacro FOG_ADD("GetUnitX(wind)","GetUnitY(wind)","AOE")
if IsUnitEnemy(first, GetOwningPlayer(wind)) and FUN_UnitAlive(first) and FUN_OrganicUnits(first) and GetUnitAbilityLevel(first, BUFF_ID)==0 then
call MuiDummyCasters.hitTarget(GetOwningPlayer(wind),first,GetUnitX(first), GetUnitY(first), DUMMY_SPELL_ID, OrderId("Cyclone"), GetInteger(tID, 5))
endif
//! runtextmacro FOG_REMOVE()
else
call KillUnit(wind)
call StopTimer(GetExpiredTimer())
call Flush(tID)
endif
set wind = null
endfunction
private function Actions takes nothing returns nothing
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local unit u = GetTriggerUnit()
local unit tar = GetSpellTargetUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x1 = GetSpellTargetX()
local real y1 = GetSpellTargetY()
call SetUnitHandle(tID, 1, CreateUnit(GetTriggerPlayer(), WIND_ID, x+100*Cos(GetUnitFacing(u)), y+100*Sin(GetUnitFacing(u)), 0))
call SetReal(tID, 2, 0)
call SetReal(tID, 3, Atan2(y1-y, x1-x))
call SetReal(tID, 4, SquareRoot((x1-x) * (x1-x) + (y1-y) * (y1-y)))
call SetInteger(tID, 5, GetUnitAbilityLevel(u, SPELL_ID))
call TimerStart(t, INTERVAL, true, function WindLoop)
set u = null
set t = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//The Keeper of the grove use his ancient magic, Mass root, when this skill used, Roots nearby
//500AoE enemy unit or heroes.
//|cffffcc00Level 1|r - Deals 5 damage, lasts 6 seconds.
//|cffffcc00Level 2|r - Deals 10 damage, lasts 9 seconds.
//|cffffcc00Level 3|r - Deals 15 damage, lasts 12 seconds.
//|cffffcc00Level 4|r - Deals 20 damage, lasts 15 seconds.
//|cffffcc00Level 5|r - Deals 25 damage, lasts 18 seconds.
scope MassRoot initializer init
globals
private constant integer SPELL_ID = 'A02Z'
private constant integer DUMMY_SPELL_ID = 'A02Y'
private constant real AOE_RANGE = 400
endglobals
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit first
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
//! runtextmacro FOG_ADD("GetUnitX(u)","GetUnitY(u)","AOE_RANGE")
if IsUnitEnemy(first, GetTriggerPlayer()) and FUN_UnitAlive(first) and FUN_OrganicUnits(first) then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(),first,GetUnitX(first), GetUnitY(first),DUMMY_SPELL_ID,OrderId("entanglingroots"), level)
endif
//! runtextmacro FOG_REMOVE()
set u = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Faeriefire initializer init
globals
private constant integer SPELL_ID = 'A02S'
private constant integer DUMMY_SPELL_ID = 'ACff'
private constant integer BUFF = 'Bfae'
endglobals
private function Cond takes nothing returns nothing
local unit attacker
if FilterEnemyAndSpellLevel(GetOwningPlayer(GetAttacker()), GetTriggerUnit(), SPELL_ID) then
set attacker = GetAttacker()
if GetChance(GetTriggerUnit(), SPELL_ID) then
if GetUnitAbilityLevel(attacker, BUFF)==0 then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), attacker, GetUnitX(attacker), GetUnitY(attacker), DUMMY_SPELL_ID, OrderId("faeriefire"), 1)
endif
endif
set attacker = null
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope SoulRelease initializer init
globals
private constant integer SPELL_ID = 'A032'
private constant integer ORDER_ID = 852089
private constant string SFX = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"
private constant attacktype ATT = ATTACK_TYPE_CHAOS
private constant damagetype DAM = DAMAGE_TYPE_NORMAL
private constant real DELAY = 0.5
private constant real AOE = 400
endglobals
private function GetDamage takes integer i returns real
return i * 0.1 //percentage of max life of caster
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit first
local real initdam = GetDamage(GetUnitAbilityLevel(u, SPELL_ID))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE, null)
//! runtextmacro FOG_ADD("GetUnitX(u)","GetUnitY(u)","AOE")
if IsUnitEnemy(u, GetOwningPlayer(first)) and FUN_UnitAlive(first) and FUN_OrganicUnits(first) then
call DestroyEffect(AddSpecialEffectTarget(SFX, first, "origin"))
call UnitDamageTarget(u, first, GetWidgetLife(first) * initdam, false, false,ATT,DAM, null)
endif
//! runtextmacro FOG_REMOVE()
set u = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=24
//TESH.alwaysfold=0
scope DeathTrap initializer init
globals
private constant integer SPELL_ID = 'A036'
private constant integer DUMMY_SPELL_ID = 'A038'
private constant integer TRAP_ID = 'h00Q'
private constant real INTERVAL = 0.1
private constant real GAP = 1.5 //rotation gap in radians
endglobals
private function GetDuration takes integer i returns real
return 10 + i * 5.
endfunction
private function Looper takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
local unit trap = GetUnitHandle(tID, 1)
local real duration = GetReal(tID, 2)
local real angle = GetReal(tID, 3)
local real x = GetUnitX(trap)
local real y = GetUnitY(trap)
local real x1
local real y1
if duration > 0 then
call SetReal(tID, 2, duration-INTERVAL)
call SetReal(tID, 3, angle + GAP)
set x1 = x + 75 * Cos(angle)
set y1 = y + 75 * Sin(angle)
call MuiDummyCasters.hitPoint(GetOwningPlayer(trap), x,y,x1,y1, DUMMY_SPELL_ID,OrderId("carrionswarm"),GetInteger(tID, 4))
else
call KillUnit(trap)
call StopTimer(GetExpiredTimer())
call Flush(tID)
endif
set trap = null
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local unit trap = CreateUnit(GetTriggerPlayer(), TRAP_ID, GetSpellTargetX(), GetSpellTargetY(), 0)
call SetUnitHandle(tID, 1, trap)
call SetReal(tID, 2, GetDuration(level))
call SetReal(tID, 3, 0) //angle
call SetInteger(tID, 4, level)
call TimerStart(t, INTERVAL, true, function Looper)
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call PreloadUnit(TRAP_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BloodCurse initializer init
globals
private constant integer SPELL_ID = 'A02Q'
private constant integer DUMMY_SPELL_ID = 'ACcs'
private constant integer BUFF = 'Bcrs'
endglobals
private function Cond takes nothing returns nothing
local unit attacker
if FilterEnemyAndSpellLevel(GetOwningPlayer(GetAttacker()), GetTriggerUnit(), SPELL_ID) then
set attacker = GetAttacker()
if GetChance(GetTriggerUnit(), SPELL_ID) then
if GetUnitAbilityLevel(attacker, BUFF)==0 then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), attacker, GetUnitX(attacker), GetUnitY(attacker), DUMMY_SPELL_ID, OrderId("curse"), GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID))
endif
endif
set attacker = null
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=9
//TESH.alwaysfold=0
scope SpreadShot
//uses SimpleMissileSystem, MuiDummyCasters
globals
private constant integer SPELL_ID = 'A03N' //chain lightning
private constant integer DUMMY_ID = 'h004'
private constant integer DUMMY_SPELL_ID = 'A02U' //uses FlameBolt
private constant string SFX = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
private constant string ATTACHMENT = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
private Table chk
endglobals
private struct SpreadShot
unit caster
unit target
real damage
real duration
static method cast takes nothing returns nothing
local unit c = GetTriggerUnit()
local unit missile = CreateUnit(GetTriggerPlayer(), DUMMY_ID, GetUnitX(c), GetUnitY(c), 0)
local integer ID = GetHandleId(missile)
call SetMissileSingleTargetByUnit(c, GetSpellTargetUnit(), missile, 100., 15., 100., SFX)
set chk.effect[ID] = AddSpecialEffectTarget(ATTACHMENT, missile, "chest")
set chk[ID] = 1
set c = null
set missile = null
endmethod
static method dies takes nothing returns nothing
local unit missile = GetTriggerUnit()
local integer ID = GetHandleId(missile)
local unit first
if chk.has(ID) then
call DestroyEffect(chk.effect[ID])
//! runtextmacro FOG_ADD("GetUnitX(missile)", "GetUnitY(missile)", "800" )
if UnitAlive(first) and IsUnitEnemy(first, GetTriggerPlayer())then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), first, GetUnitX(missile), GetUnitY(missile), DUMMY_SPELL_ID, OrderId("firebolt"), 1)
endif
//! runtextmacro FOG_REMOVE()
endif
set missile = null
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.dies)
call PreloadSpell(DUMMY_SPELL_ID)
set chk = Table.create()
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope ColdVortex
globals
private constant integer SPELL_ID = 'A007' //howl of terror
private constant integer DUMMY_ID = 'h004'
private constant integer ARMOR_RED_ID = 'A03R' //faire fire
private constant string ATTACHMENT = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl"
private constant string MISSILE_DEATH = "Objects\\Spawnmodels\\NightElf\\NEDeathSmall\\NEDeathSmall.mdl"
private constant string ARMOUR_RED = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
private constant real DISTANCE = 600
private constant real MISSILE_SPEED = 5
endglobals
private function GetMissileCount takes integer i returns integer
return 4 //2*i+1
endfunction
private function GetDamage takes integer i returns real
return (20*i+10)*0.03125
endfunction
private function FilterUnits takes unit c, unit f returns boolean
return not IsUnitType(f, UNIT_TYPE_DEAD) and not IsUnitType(f, UNIT_TYPE_FLYING) and IsUnitEnemy(c, GetOwningPlayer(f))
endfunction
private struct CV
unit caster
unit missile
integer level
real xC
real yC
real angle
real damage
real dist
effect sfx
private static real a
private static real aoe
private static group g = CreateGroup()
method periodic takes nothing returns nothing
local unit first
if DISTANCE > .dist then
set .dist = .dist + MISSILE_SPEED
set .angle = .angle + a
call SetUnitX(.missile, .xC+.dist*Cos(.angle))
call SetUnitY(.missile, .yC+.dist*Sin(.angle))
call GroupEnumUnitsInRange(g, GetUnitX(.missile), GetUnitY(.missile), 135, null)
loop
set first = FirstOfGroup(g)
exitwhen first==null
if FilterUnits(.caster, first) then
call UnitDamageTarget(.missile, first, .damage, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_COLD, null)
endif
call GroupRemoveUnit(g, first)
endloop
else
call UnitApplyTimedLife(.missile, 'BTLF', 2.0)
call DestroyEffect(.sfx)
call DestroyEffect(AddSpecialEffectTarget(MISSILE_DEATH, .missile, "origin"))
call GroupEnumUnitsInRange(g, GetUnitX(.missile), GetUnitY(.missile), aoe, null)
loop
set first = FirstOfGroup(g)
exitwhen first==null
if FilterUnits(.caster, first) then
call IssueTargetOrderById(.missile, 852149, first)
call DestroyEffect(AddSpecialEffectTarget(ARMOUR_RED, first, "chest"))
endif
call GroupRemoveUnit(g, first)
endloop
set .caster = null
set .missile = null
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method run takes unit c, unit m, integer l, real a, real x, real y, effect sf returns nothing
local thistype this = allocate()
set .caster = c
set .missile = m
set .level = l
set .angle = a*bj_DEGTORAD
set .xC = x
set .yC = y
set .sfx = sf
set .dist = 0
set .damage = GetDamage(l)
call SetUnitFlyHeight(m, 50, 0)
call .startPeriodic()
endmethod
static method cast takes nothing returns nothing
local integer index = 0
local unit c = GetTriggerUnit()
local unit m
local integer lvl = GetUnitAbilityLevel(c, SPELL_ID)
local integer missileCount = GetMissileCount(lvl)
local real a = 0
local real aGap = 360/missileCount
local real x = GetUnitX(c)
local real y = GetUnitY(c)
loop
set m = CreateUnit(GetTriggerPlayer(), DUMMY_ID, x, y, 0)
call UnitRemoveAbility(m, 'Amov')
call thistype.run(c, m, lvl, a, x, y, AddSpecialEffectTarget(ATTACHMENT, m, "origin"))
call UnitAddAbility(m, ARMOR_RED_ID)
set a = a+aGap
set index = index+1
exitwhen index==missileCount
endloop
set c = null
set m = null
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
set a = MISSILE_SPEED*0.01
set aoe = DISTANCE*0.7
endmethod
endstruct
endscope
//TESH.scrollpos=42
//TESH.alwaysfold=0
/* ==============================================================================
============================== SHATTERING FROST ==============================
=================================== v1.1.0 ===================================
================================= by Mr_Bean =================================
==============================================================================
Requirements:
- JASS NewGen Pack by Vexorian (http://www.hiveworkshop.com/forums/miscellaneous-tutorials-456/how-download-install-confige-jngp-160547).
- TimerUtils by Vexorian (included in this map).
How To Install:
- Copy this trigger over to your map.
- Copy the "TimerUtils" trigger over to your map. Don't change anything in that trigger.
- Copy the "Shattering Frost" spell over to your map. Change the raw code below (SPELL_ID) to the correct one for this spell in your map.
- Copy the "Shattering Frost [dummy]" spell over to your map. Change the raw code below (DUMMY_SPELL_ID) to the correct one for this spell in your map.
- Copy the "Dummy" unit over to your map (or make your own: http://www.thehelper.net/forums/showthread.php/26751-Spells-Dummy-Casters). Change the raw code below (DUMMY_ID) to the correct one for your dummy.
What You Can Change:
*** In the Object Editor ***
- Damage to targeted unit ("Shattering Frost"; DataB1, DataB2, DataB3).
NOTE: I recommend leaving "Data - Area of Effect Damage" ("Shattering Frost"; DataA1, DataA2, DataA3) as 0 for all levels.
- Area of effect of slow, i.e. how close units have to be to the target to get slowed ("Shattering Frost"; Area1, Area2, Area3).
- Slow duration of affected units ("Shattering Frost"; Dur1, Dur2, Dur3 and HeroDur1, HeroDur2, HeroDur3).
- Damage of frost shards ("Shattering Frost [dummy]"; DataA1, DataA2, DataA3).
- Stun duration of frost shards ("Shattering Frost [dummy]"; Dur1, Dur2, Dur3 and HeroDur1, HeroDur2, HeroDur3).
*** Below, in the code ***
- Area of effect of ice shards, i.e. how close units have to be to the target to get stunned ("Other Confugurables"; INITIAL_RANGE).
- By how much the AoE changes with each level ("Other Confugurables"; RANGE_IMPROVEMENT).
- Delay between when the unit casts the spell and when the units get stunned ("Other Confugurables"; INITIAL_DELAY).
- By how much the delay changes with each level ("Other Confugurables"; DELAY_IMPROVEMENT).
Other Notes:
- This spell is MUI. This means that multiple units can safely cast it at the same time.
- The spell's icon is imported. If you wish to use it, you will have to export the two .blp files from this map and then import them into yours.
Otherwise, you can choose any other icon (like the "Frost Nova" one).
If you have any issues importing these, feel free to email me ([email protected]).
- To check if there are newer releases of this spell, visit http://www.hiveworkshop.com/forums/spells-569/shattering-frost-v1-0-1-a-208595.
- I am Mr_Bean987 on the HiveWorkshop.com :D
Credits:
- Vexorian for TimerUtils (http://www.wc3c.net/showthread.php?t=101322)
- watermelon_1234
- dudeim
- Maker
- OxygenD
- Ruke
- Magtheridon96
- Bribe
*/
library ShatteringFrost requires TimerUtils
globals
// Important Configurables:
private constant integer SPELL_ID = 'A03S' // Change A000 to the raw code of the "Shattering Frost" spell.
private constant integer DUMMY_SPELL_ID = 'A03T' // Change A001 to the raw code of "Shattering Frost [dummy]" spell.
private constant integer DUMMY_ID = 'h004' // Change h001 to the raw code of your dummy unit.
// Other Configurables:
private constant real INITIAL_RANGE = 200 // How close units have to be to the target to get stunned. This value is used for level 1 and then is modified by the following line.
private constant real RANGE_IMPROVEMENT = 50 // How much the range increases per level. A positive value means the range INCREASES.
// Current range is 200/250/300.
private constant real INITIAL_DELAY = 0.5 // The delay between the ice blast and when the units get stunned. This value is for level 1 and is modified by the following line.
private constant real DELAY_IMPROVEMENT = 0.1 // How much the delay DECREASES per level. A positive value means the delay DECREASES.
// Current delay is 0.5/0.4/0.3 seconds.
// End Of Configurables.
// Don't change anything past this point!
endglobals
private struct Data
unit caster
unit target
integer level
real range
real delay
method destroy takes nothing returns nothing
set this.caster = null
set this.target = null
call this.deallocate()
endmethod
static method Timer_Actions takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype D = GetTimerData(t)
local real x = GetUnitX(D.target)
local real y = GetUnitY(D.target)
local player owner = GetOwningPlayer(D.caster)
local unit dummy
local unit u
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, D.range, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u == null
if (u != D.target)and (IsUnitEnemy(u, owner)) and (not(IsUnitType(u, UNIT_TYPE_DEAD))) then
set dummy = CreateUnit(owner, DUMMY_ID, x, y, 0)
call UnitAddAbility(dummy, DUMMY_SPELL_ID)
call SetUnitAbilityLevel(dummy, DUMMY_SPELL_ID, D.level)
call IssueTargetOrder(dummy, "thunderbolt", u)
call UnitApplyTimedLife(dummy, 'BTLF', 1)
set dummy = null
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
call ReleaseTimer(t)
set t = null
set owner = null
call D.destroy()
endmethod
static method create takes nothing returns thistype
local timer t = NewTimer()
local thistype D = thistype.allocate()
set D.caster = GetTriggerUnit()
set D.target = GetSpellTargetUnit()
set D.level = GetUnitAbilityLevel(D.caster, SPELL_ID)
set D.range = INITIAL_RANGE + (RANGE_IMPROVEMENT * (D.level - 1))
set D.delay = INITIAL_DELAY - (DELAY_IMPROVEMENT * (D.level - 1))
call SetTimerData(t, D)
call TimerStart(t, D.delay, false, function thistype.Timer_Actions)
set t = null
return D
endmethod
static method Conditions takes nothing returns boolean
if (GetSpellAbilityId() == SPELL_ID) then
call thistype.create()
endif
return false
endmethod
static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.Conditions))
set t = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BackShot
globals
private constant integer SPELL_ID = 'A03U'
private constant integer DUMMY_ID = 'h004'
private constant integer WAVE_SPELL_ID = 'A03Q' //crushing wave, 852218
private constant string ATTACHMENT = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl"
private constant real DISTANCE = 600
private constant real SPEED = 30
private constant real WAVE_CAST_SPEED = 0.08
private constant integer WAVE_COUNT = 6
endglobals
struct BS extends array
unit caster
real angle
real angle1
real angle2
real angleGap
real distXY
real distance
real xC
real yC
real delay1
real delay2
integer count
boolean turn
boolean castDelay
boolean isOn
private static integer castCount
private static constant real turnDelay = 1.5
implement CTL
local unit u
local real x
local real y
implement CTLExpire
if not IsUnitType(.caster, UNIT_TYPE_DEAD) and .isOn then
if .turn then
if .distance > .distXY and .turn then
set .distXY = .distXY + SPEED
call SetUnitX(.caster, .xC+.distXY*Cos(.angle))
call SetUnitY(.caster, .yC+.distXY*Sin(.angle))
else
set .turn = false
endif
else
set .delay1 = .delay1 + 0.03125
if .delay1 > 0.5 then
call SetUnitTurnSpeed(.caster, 1000)
call SetUnitFacing(.caster, .angle1)
if .delay1 > turnDelay then
if .castDelay then
set .delay2 = .delay2 + 0.03125
if .delay2 > WAVE_CAST_SPEED then
set .delay2 = 0
set .count = .count + 1
if .count < castCount then
//cast here
set x = GetUnitX(.caster)
set y = GetUnitY(.caster)
call MuiDummyCasters.hitPoint(GetOwningPlayer(.caster), x, y, x+100*Cos(.angle2*bj_DEGTORAD), y+100*Sin(.angle2*bj_DEGTORAD), WAVE_SPELL_ID, 852218, 1)
set .angle2 = .angle2 + .angleGap
endif
endif
if .count==castCount then
set .castDelay = false
endif
else
if .distXY > 0 then
set .distXY = .distXY - SPEED
call SetUnitX(.caster, .xC+.distXY*Cos(.angle))
call SetUnitY(.caster, .yC+.distXY*Sin(.angle))
else
set .isOn = false
endif
endif
endif
endif
endif
else
call UnitRemoveAbility(.caster, 'Abun')
call SetUnitPathing(.caster, true)
call SetUnitTurnSpeed(.caster, GetUnitDefaultTurnSpeed(.caster))
set .caster = null
call .destroy()
endif
implement CTLNull
implement CTLEnd
static method cast takes nothing returns nothing
local thistype this = create()
local unit u
local real xSP
local real ySP
set .caster = GetTriggerUnit()
set .xC = GetUnitX(.caster)
set .yC = GetUnitY(.caster)
set xSP = GetSpellTargetX()
set ySP = GetSpellTargetY()
set .angle = Atan2(ySP-.yC, xSP-.xC)
set .angle1 = (.angle*bj_RADTODEG)+180
set .angle2 = ((.angle*bj_RADTODEG)+90)
set .angleGap = 360/(WAVE_COUNT*2)
set .distance = SquareRoot((xSP-.xC)*(xSP-.xC)+(ySP-.yC)*(ySP-.yC))
set .distXY = 0
set .delay1 = 0
set .delay2 = 0
set .count = 0
set .turn = true
set .castDelay = true
set .isOn = true
call SetUnitTurnSpeed(.caster, 0)
call SetUnitPathing(.caster, false)
call UnitAddAbility(.caster, 'Abun')
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
set castCount = WAVE_COUNT + 1
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Refresh initializer init
//uses SpellEffectEvent, RegisterPlayerUnitEvent, Fundamentals
globals
private constant integer SPELL_ID = 'A03P'
private constant integer DUMMY_ID = 'h004' //General Id
private constant integer DUMMY_SPELL_ID = 'A008'
private constant real AOE = 400
endglobals
private function Run takes unit u, integer level returns nothing
local unit first
local unit d
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE ,null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if FUN_UnitAlive(first) and not IsUnitEnemy(first, GetOwningPlayer(u)) and FUN_OrganicUnits(first) and FUN_LifeTaken(first) then
set d = CreateUnit(GetOwningPlayer(first), DUMMY_ID, GetUnitX(first), GetUnitY(first), 0)
call UnitApplyTimedLife(d, 'BTLF', 2.)
call UnitAddAbility(d, DUMMY_SPELL_ID)
call SetUnitAbilityLevel(d, DUMMY_SPELL_ID, level)
call IssueTargetOrder(d, "rejuvination", first)
set d = null
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endfunction
private function Actions takes nothing returns nothing
call Run(GetTriggerUnit(), GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID))
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=66
//TESH.alwaysfold=0
scope ImpedeVortices initializer init
//uses SpellEffectEvent, RegisterPlayerUnitEvent, T32
globals
private constant integer SPELL_ID = 'A004'
private constant integer DUMMY_ID = 'h004' //General Id
private constant integer BLUE_ID = 'h009'
private constant integer FIRE_ID = 'h00C'
private constant integer BLUE_SPELL_ID = 'A034' //casted when blue dies
private constant integer FIRE_SPELL_ID = 'A028' //casted when fire dies
private constant integer BUFF_ID = 'Bslo'
private constant integer SLOW_SPELL_ID = 'S001'
private constant real ROTATION_SPEED = 0.1
endglobals
private function GetAoE takes integer i returns real
return 200 + i * 100.
endfunction
private function GetDuration takes integer i returns real
return 10.
endfunction
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private struct IV
unit caster
unit fire
unit blue
unit dummy
real angle1
real angle2
real duration
real aoe
integer level
private method periodic takes nothing returns nothing
local unit dummy
local real x = GetUnitX(.caster)
local real y = GetUnitY(.caster)
local real x1
local real y1
local integer blueint
local integer fireint
set .duration = .duration - T32_PERIOD
if .aoe > 0 and UnitAlive(.caster) then
set .angle1 = .angle1 + ROTATION_SPEED
set .angle2 = .angle2 - ROTATION_SPEED
call SetUnitX(.blue, x + .aoe * Cos(.angle1))
call SetUnitY(.blue, y + .aoe * Sin(.angle1))
call SetUnitX(.fire, x + .aoe * Cos(.angle2))
call SetUnitY(.fire, y + .aoe * Sin(.angle2))
call SetUnitX(.dummy, x)
call SetUnitY(.dummy, y)
if .duration <= 0 then
set .aoe = .aoe - 10
if UnitAlive(.dummy) then
call KillUnit(.dummy)
endif
endif
else
set blueint = 0
loop
set dummy = CreateUnit(GetOwningPlayer(.caster), DUMMY_ID, GetUnitX(.blue), GetUnitY(.blue), 0)
call UnitAddAbility(dummy, BLUE_SPELL_ID)
call SetUnitAbilityLevel(dummy, BLUE_SPELL_ID, .level)
call UnitApplyTimedLife(dummy, 'BTLF', 2)
set x1 = GetUnitX(.blue) + 30 * Cos(blueint * bj_DEGTORAD)
set y1 = GetUnitY(.blue) + 30 * Sin(blueint * bj_DEGTORAD)
call IssuePointOrder(dummy, "breathoffire", x1, y1)
set blueint = blueint + 60
set dummy = null
exitwhen blueint >= 360
endloop
set fireint = 30
loop
set dummy = CreateUnit(GetOwningPlayer(.caster), DUMMY_ID, GetUnitX(.fire), GetUnitY(.fire), 0)
call UnitAddAbility(dummy, FIRE_SPELL_ID)
call SetUnitAbilityLevel(dummy, FIRE_SPELL_ID, .level)
call UnitApplyTimedLife(dummy, 'BTLF', 2)
set x1 = GetUnitX(.fire) + 30 * Cos(fireint * bj_DEGTORAD)
set y1 = GetUnitY(.fire) + 30 * Sin(fireint * bj_DEGTORAD)
call IssuePointOrder(dummy, "breathoffire", x1, y1)
set fireint = fireint + 60
set dummy = null
exitwhen fireint >= 390
endloop
call KillUnit(.fire)
call KillUnit(.blue)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit u returns thistype
local thistype this = allocate()
set .caster = u
set .level = GetUnitAbilityLevel(u, SPELL_ID)
set .blue = CreateUnit(GetOwningPlayer(u), BLUE_ID, 0, 0, 0)
set .fire = CreateUnit(GetOwningPlayer(u), FIRE_ID, 0, 0, 0)
set .dummy = CreateUnit(GetOwningPlayer(u), DUMMY_ID, 0, 0, 0)
call UnitAddAbility(dummy, SLOW_SPELL_ID)
call SetUnitAbilityLevel(dummy, SLOW_SPELL_ID, .level)
set .angle1 = 0
set .angle2 = 0
set .aoe = GetAoE(.level)
set .duration = GetDuration(.level)
call .startPeriodic()
return this
endmethod
endstruct
private function Actions takes nothing returns nothing
call IV.create(GetTriggerUnit())
endfunction
private function init takes nothing returns nothing
call PreloadSpell(SLOW_SPELL_ID)
call PreloadSpell(BLUE_SPELL_ID)
call PreloadSpell(FIRE_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=26
//TESH.alwaysfold=0
scope HolySeal initializer init
//uses RegisterPlayerUnitEvent, T32, Fundamentals
globals
private constant integer SPELL_ID = 'A00K'
private constant integer DUMMY_ID = 'h004' //General Id
private constant integer DUMMY_SPELL_ID = 'A00M'
private constant real GAP = 60
endglobals
private function FilterThings takes player p, unit u returns boolean
if IsUnitEnemy(u, p) and GetUnitAbilityLevel(u, SPELL_ID) > 0 then
return true
endif
return false
endfunction
private struct HolySeal
unit caster
integer level
real angle
real maxangle
private method periodic takes nothing returns nothing
local real x = GetUnitX(.caster)
local real y = GetUnitY(.caster)
local unit dummy
if .maxangle > .angle and FUN_UnitAlive(.caster) then
set .angle = .angle + GAP
set dummy = CreateUnit(GetOwningPlayer(.caster), DUMMY_ID, x, y, 0)
call UnitApplyTimedLife(dummy, 'BTLF', 2.0)
call UnitAddAbility(dummy, DUMMY_SPELL_ID)
call SetUnitAbilityLevel(dummy, DUMMY_SPELL_ID, .level)
call IssuePointOrder(dummy, "carrionswarm", x + (GAP/2) * Cos(.angle * bj_DEGTORAD), y + (GAP/2) * Sin(.angle * bj_DEGTORAD))
else
call .stopPeriodic()
call .destroy()
endif
set dummy = null
endmethod
implement T32x
static method create takes unit u returns thistype
local thistype this = allocate()
set .caster = u
set .angle = GetUnitFacing(u)
set .maxangle = GetUnitFacing(u) + 360
set .level = GetUnitAbilityLevel(u, SPELL_ID)
call .startPeriodic()
return this
endmethod
endstruct
private function Actions takes nothing returns nothing
if FilterThings(GetTriggerPlayer(), GetAttacker()) then
if GetChance(GetAttacker(), SPELL_ID) then
call HolySeal.create(GetAttacker())
endif
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Vindication initializer init
//uses SpellEffectEvent, RegisterPlayerUnitEvent, T32, Fundamentals
globals
private constant integer SPELL_ID = 'A00E'
private constant integer DUMMY_ID = 'h004' //General Id
private constant integer DUMMY_SPELL_ID = 'A006'
endglobals
private struct Vindication
unit caster
unit dummy
real duration
private method periodic takes nothing returns nothing
local real x = GetUnitX(.caster)
local real y = GetUnitY(.caster)
if .duration > 0 and FUN_UnitAlive(.caster) then
call SetUnitX(.dummy, x)
call SetUnitY(.dummy, y)
set .duration = .duration - T32_PERIOD
else
call KillUnit(.dummy)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit u, unit dummy returns thistype
local thistype this = allocate()
set .caster = u
set .dummy = dummy
set .duration = 30.
call .startPeriodic()
return this
endmethod
endstruct
private function Actions takes nothing returns nothing
local unit u = CreateUnit(GetTriggerPlayer(), DUMMY_ID, 0,0,0)
call UnitAddAbility(u, DUMMY_SPELL_ID)
call Vindication.create(GetTriggerUnit(), u)
set u = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=131
//TESH.alwaysfold=0
/*
=====Confinement v1.3
=====Made by: Mckill2009
REQUIRES and CREDITS:
- JassNewGenPack by Vexorian
- T32 by Jesus4Lyf
- BoundSentinel by Vexorian
HOW TO USE:
- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
- Copy ALL that is written here (overwrite the existing texts in the trigger)
- Copy the Dummy unit and the custom ability OR make your own
- You MUST input or change the correct raw ID's (see below)
- To view raw ID, press CTRL+D in the object editor
FULL DESCRIPTION:
Creates two magical fence that loops around a targeted point. Enemy units that is inside or caught within the fence's AoE cannot get out. If an enemy unit touches the fence it will deal damage as well.
|cffffcc00Level 1|r - Spell lasts 10 seconds, vortex damages 8 per touch.
|cffffcc00Level 2|r - Spell lasts 15 seconds, vortex damages 13 per touch.
|cffffcc00Level 3|r - Spell lasts 20 seconds, vortex damages 18 per touch.
|cffffcc00Level 4|r - Spell lasts 25 seconds, vortex damages 23 per touch.
|cffffcc00Level 5|r - Spell lasts 30 seconds, vortex damages 28 per touch.
*/
library Confinement uses T32, BoundSentinel
globals
//the SPELL_ID and ORDER_ID must match to each other because of channeling reasons
private constant integer SPELL_ID = 'A005' //blizzard
private constant integer FENCE1_ID = 'e000'
private constant integer FENCE2_ID = 'h009'
private constant integer AURA_ID = 'h004'
private constant integer ORDER_ID = 852089 //blizzard
private constant attacktype ATT = ATTACK_TYPE_PIERCE
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant real AOE_RANGE = 400 //this is the prison range
private constant real AOE_DAM = 80 //this is the damage range of the fence
private constant real ROTATION_SPEED = 0.1 //rotation in radians, so this should be low
endglobals
private function GetDuration takes integer i returns real
return 5 + i * 5.
endfunction
private function GetDamage takes integer i returns real
return 3 + i * 5.
endfunction
private struct Confinement
unit caster
unit aura
unit fence1
unit fence2
real x
real y
real hurt
real angle1
real angle2
real duration
private method filterunits takes unit u1, unit u2 returns boolean
return IsUnitEnemy(u1, GetOwningPlayer(u2)) and not IsUnitType(u1, UNIT_TYPE_DEAD) and not /*
*/ IsUnitType(u1, UNIT_TYPE_STRUCTURE) and not IsUnitType(u1, UNIT_TYPE_MECHANICAL)
endmethod
method periodic takes nothing returns nothing
local real angle
local real dist
local real x1
local real y1
local real x2
local real y2
local unit u
if .duration > 0 and GetUnitCurrentOrder(.caster)==ORDER_ID then
set .angle1 = .angle1 + ROTATION_SPEED
set .angle2 = .angle2 - ROTATION_SPEED
set .duration = .duration - T32_PERIOD
call SetUnitX(.fence1, .x + AOE_RANGE * Cos(.angle1))
call SetUnitY(.fence1, .y + AOE_RANGE * Sin(.angle1))
call SetUnitX(.fence2, .x + AOE_RANGE * Cos(.angle2))
call SetUnitY(.fence2, .y + AOE_RANGE * Sin(.angle2))
//===ConfineThem
call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, AOE_RANGE, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u==null
if filterunits(u, .aura) then
set x1 = GetUnitX(u)
set y1 = GetUnitY(u)
set x2 = x1-.x
set y2 = y1-.y
set angle = Atan2(y-y1, x-x1)
set dist = (x2*x2) + (y2*y2)
if dist > (AOE_RANGE-50)*(AOE_RANGE-50) then
call SetUnitX(u, x1 + 30 * Cos(angle))
call SetUnitY(u, y1 + 30 * Sin(angle))
endif
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
//===Fence1, DamageThem
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.fence1), GetUnitY(.fence1), AOE_DAM, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u==null
if filterunits(u, .aura) then
call UnitDamageTarget(.aura, u, .hurt , false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
//===Fence2, DamageThem
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.fence2), GetUnitY(.fence2), AOE_DAM, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u==null
if filterunits(u, .aura) then
call UnitDamageTarget(.aura, u, .hurt , false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
else
call IssueImmediateOrder(.caster, "stop")
call KillUnit(.aura)
call KillUnit(.fence1)
call KillUnit(.fence2)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit caster, player p returns thistype
local thistype this = thistype.allocate()
local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
set .caster = caster
set .x = GetSpellTargetX()
set .y = GetSpellTargetY()
set .aura = CreateUnit(p, AURA_ID, .x, .y, 0)
set .fence1 = CreateUnit(p, FENCE1_ID, .x, .y, 0)
set .fence2 = CreateUnit(p, FENCE2_ID, .x, .y, 0)
set .duration = GetDuration(level)
set .hurt = GetDamage(level)
set .angle1 = 0
set .angle2 = 0
call .startPeriodic()
return this
endmethod
private static method cond takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call Confinement.create(GetTriggerUnit(), GetTriggerPlayer())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function thistype.cond)
set t = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope PlunkDown initializer init
//uses SpellEffectEvent, TimerUtils, HashT
globals
private constant integer SPELL_ID = 'A00S'
endglobals
private function GetAoE takes integer i returns real
return i * 350.
endfunction
//===10,15,20,25,30
private function GetDuration takes integer i returns real
return 5 + i * 5.
endfunction
private function TimerLooper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer ID = GetTimerData(t)
local real duration = GetReal(ID, 1)
local unit u
if duration > 0 then
call SetReal(ID, 1, duration-1)
else
set u = GetUnitHandle(ID, 0)
call PauseUnit(u,false)
call SetUnitAnimation(u,"stand")
call SetUnitInvulnerable(u,false)
call RemoveInteger(GetHandleId(u), SPELL_ID)
call ReleaseTimer(t)
set u = null
endif
set t = null
endfunction
private function Actions takes nothing returns nothing
local timer t
local integer ID
local unit u = GetTriggerUnit()
local unit tar
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), GetAoE(1) , null)
loop
set tar = FirstOfGroup(bj_lastCreatedGroup)
exitwhen tar==null
if FUN_UnitAlive(tar) and IsUnitEnemy(tar, GetTriggerPlayer()) and FUN_OrganicUnits(tar) and not IsUnitType(tar, UNIT_TYPE_FLYING) and not IsUnitType(tar, UNIT_TYPE_HERO) and GetInteger(GetHandleId(tar), SPELL_ID)==0 then
set t = NewTimer()
set ID = GetHandleId(t)
call SetUnitHandle(ID, 0, tar)
call SetReal(ID, 1, GetDuration(GetUnitAbilityLevel(u, SPELL_ID)))
//targetID
call SetInteger(GetHandleId(tar), SPELL_ID, 1)
call PauseUnit(tar,true)
call SetUnitAnimation(tar,"death")
call SetUnitInvulnerable(tar,true)
call SetTimerData(t, ID)
call TimerStart(t, 1.0, true, function TimerLooper)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, tar)
set tar = null
endloop
set u = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope SuddenBlow initializer init
//uses RegisterPlayerUnitEvent, StringTag
globals
private constant integer SPELL_ID = 'A00P' //passive
private constant integer MAX_UNIT = 3
private constant string SFX = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"
private Table sb
endglobals
//5, 10, 15, 20, 25
private function GetPercent takes integer i returns real
return i * 0.05
endfunction
private function DeathEvent takes nothing returns nothing
local unit killing = GetKillingUnit()
local unit u
local integer ID
local integer count
local real life
local real damage
local StringTag tag
if GetUnitAbilityLevel(killing, SPELL_ID) > 0 then
set u = GetTriggerUnit()
if IsUnitEnemy(killing, GetTriggerPlayer()) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
set ID = GetHandleId(killing)
if (sb[ID])<(MAX_UNIT) then
set life = GetUnitState(u, UNIT_STATE_MAX_LIFE)*GetPercent(GetUnitAbilityLevel(killing, SPELL_ID) )
set sb[ID] = sb[ID] + 1
set sb.real[ID] = sb.real[ID] + life
set tag = tag.txUnit(killing)
set tag.text = I2S(sb[ID])+"/"+I2S(MAX_UNIT)
set tag.height = 0
set tag.size = 2.5
set tag.velocity = 2.0
set tag.life = 3
set tag.fade = 1
set tag.permanent = false
call tag.launchUnit()
endif
endif
set u = null
endif
set killing = null
endfunction
private function onDamage takes nothing returns nothing
local integer ID
if damageType==PHYSICAL then
set ID = GetHandleId(source)
if sb[ID]==MAX_UNIT then
set amount = amount+sb.real[ID]
call UnitDamageTarget(source, target, amount, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
call DestroyEffect(AddSpecialEffectTarget(SFX, target, "chest"))
set sb[ID] = 0
set sb.real[ID] = 0
endif
endif
endfunction
private function init takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function DeathEvent)
call AddDamageHandler(function onDamage)
set sb = Table.create()
endfunction
endscope
//TESH.scrollpos=48
//TESH.alwaysfold=0
scope ChargedBolt initializer init
//uses SpellEffectEvent, SimpleMissileSystem, SimError, HashT
globals
private constant integer SPELL_ID = 'A00Y'
private constant integer DUMMY_ID = 'e000'
private constant integer MIN_UNITS = 2
private constant real MAX_DAMAGE = 1500
private constant real AOE = 700
private constant string SFX = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
endglobals
private function FilterEnemies takes unit u returns boolean
if not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL)/*
*/ and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u, UNIT_TYPE_FLYING) then
return true
endif
return false
endfunction
private function GetPercent takes integer i returns real
return 0.4
endfunction
private function Actions2 takes unit k, unit trig returns nothing
local integer ID = GetHandleId(k)
local integer level
local integer count
local real life
local real damage
if GetReal(ID, SPELL_ID+2) < MAX_DAMAGE then
set level = GetUnitAbilityLevel(k, SPELL_ID)
set life = GetUnitState(trig, UNIT_STATE_MAX_LIFE)*GetPercent(level)
call SetInteger(ID, SPELL_ID, GetInteger(ID, SPELL_ID) + 1) //counter
call SetReal(ID, SPELL_ID+1, GetReal(ID, SPELL_ID+1) + life) //max life,damage
endif
endfunction
private function Cond takes nothing returns nothing
local unit u = GetTriggerUnit()
local real damage
local integer id
local integer i
if GetUnitAbilityLevel(GetKillingUnit(), SPELL_ID) > 0 then
call Actions2(GetKillingUnit(), u)
endif
if GetUnitTypeId(u)==DUMMY_ID and GetReal(GetHandleId(u), SPELL_ID) > 10 then
set damage = GetReal(GetHandleId(u), SPELL_ID)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE, null)
loop
set bj_lastCreatedUnit = FirstOfGroup(bj_lastCreatedGroup)
exitwhen bj_lastCreatedUnit==null
if IsUnitEnemy(bj_lastCreatedUnit, GetTriggerPlayer()) and FilterEnemies(bj_lastCreatedUnit) then
call SetMissileSingleTargetById(u, bj_lastCreatedUnit, DUMMY_ID, damage, 30., 100, SFX)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, FirstOfGroup(bj_lastCreatedGroup))
endloop
endif
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit missile
local integer id = GetHandleId(u)
local real damage = GetReal(id, SPELL_ID+1)+GetHeroAgi(u, false)+GetHeroInt(u, false)+GetHeroStr(u, false)
local real x = GetUnitX(u) + 100 * Cos(GetUnitFacing(u)*bj_DEGTORAD)
local real y = GetUnitY(u) + 100 * Sin(GetUnitFacing(u)*bj_DEGTORAD)
set missile = CreateUnit(GetTriggerPlayer(), DUMMY_ID, x, y, GetUnitFacing(u))
call SetReal(GetHandleId(missile), SPELL_ID, damage)
call SetMissileSingleTargetByUnit(u, GetSpellTargetUnit(), missile, damage/2, 30., 100, SFX)
call SetInteger(id, SPELL_ID, 0)
call SetReal(id, SPELL_ID+1, 0)
set u = null
endfunction
private function CastCond takes nothing returns nothing
local unit u
local integer id
if GetSpellAbilityId()==SPELL_ID then
set u = GetTriggerUnit()
set id = GetHandleId(u)
if GetInteger(id, SPELL_ID) <= MIN_UNITS then
call IssueImmediateOrder(u, "stop")
call SimError(GetTriggerPlayer(), "You must kill at least "+FixedColor(14, I2S(MIN_UNITS+1)+ " units"))
endif
endif
set u = null
endfunction
private function init takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function CastCond)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function Cond)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=3
//TESH.alwaysfold=0
//=====Fire Vortex 1.6
//=====Made by: Mckill2009
//HOW TO USE:
//- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
//- The trigger name MUST be >>> FireVortex
//- Copy ALL that is written here and overwrite the existing texts in the custom text
//- Copy the Dummy/custom abilities/buffs etc... to your object editor
//- Make sure you inputed the correct raw codes of the base spell/buffs/dummy etc...
//- You can view the raw codes by pressing CTRL+D in the object editor
//- Examples of raw codes are 'A000', 'h000' etc...
//REQUIRED VARIABLES: If you dont have this yet
//- HASH = Hashtable (Create a HASH variable in the trigger editor)
//===CONFIGURABLES:
function FV_SPELLID takes nothing returns integer
return 'A01Q' //raw code of the spell
endfunction
function FV_DUMMYID takes nothing returns integer
return 'e000' //raw code of the dummy fire
endfunction
function FV_ANGLE_SPEED takes nothing returns real
return 0.05
endfunction
function FV_AOE_GAP takes nothing returns real
return 70.
endfunction
function FV_AOE_DAM takes nothing returns real
return 80.
endfunction
function FV_LOOP_INDEX takes nothing returns integer
return 10
endfunction
function FV_DAMAGE takes integer i returns real
return (4 + i * 3.) * 0.3
endfunction
function FV_DURATION takes integer i returns real
return 10.
endfunction
constant function FV_ATT takes nothing returns attacktype
return ATTACK_TYPE_MAGIC
endfunction
constant function FV_DAM takes nothing returns damagetype
return DAMAGE_TYPE_FIRE
endfunction
//===END OF CONFIGURABLES
function FV_FILTER takes unit u, unit first returns boolean
return IsUnitEnemy(u, GetOwningPlayer(first)) and not IsUnitType(first, UNIT_TYPE_FLYING) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) and not IsUnitType(first, UNIT_TYPE_MECHANICAL) and not IsUnitType(first, UNIT_TYPE_DEAD)
endfunction
function FV_LOOP takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local integer i
local unit first
local unit dummy
local unit caster
local real angle
local real damage
local real x
local real y
local real duration = LoadReal(udg_HASH, tID, 6)
local real distx
local real mana
if duration > 0 then
set angle = LoadReal(udg_HASH, tID, 2)
call SaveReal(udg_HASH, tID, 6, duration - 0.03125)
call SaveReal(udg_HASH, tID, 2, angle + FV_ANGLE_SPEED())
//===setting
set caster = LoadUnitHandle(udg_HASH, tID, 1)
set x = LoadReal(udg_HASH, tID, 3) //SpellTargetX
set y = LoadReal(udg_HASH, tID, 4) //SpellTargetY
set i = 0
set distx = 0
loop
set i = i + 1
set distx = distx + FV_AOE_GAP()
set dummy = LoadUnitHandle(udg_HASH, tID, i+0x789)
call SetUnitX(dummy, x + distx * Cos(angle))
call SetUnitY(dummy, y + distx * Sin(angle))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(dummy), GetUnitY(dummy), FV_AOE_DAM(), null)
set damage = LoadReal(udg_HASH, tID, 5)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if FV_FILTER(caster,first) then
call UnitDamageTarget(dummy,first,damage,false,false,FV_ATT(),FV_DAM(),null)
set mana = GetUnitState(first, UNIT_STATE_MANA)
if mana > 0 then
call SetUnitState(first, UNIT_STATE_MANA, mana - damage)
endif
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
set dummy = null
exitwhen i > FV_LOOP_INDEX()
endloop
else
set i = 0
loop
set i = i + 1
call KillUnit(LoadUnitHandle(udg_HASH, tID, i+0x789))
exitwhen i > FV_LOOP_INDEX()
endloop
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_HASH, tID)
endif
set caster = null
set t = null
endfunction
function FV_ACTION takes nothing returns nothing
local timer t = CreateTimer()
local integer tID = GetHandleId(t)
local unit u = GetTriggerUnit()
local unit dummy
local integer i = 0
local integer level = GetUnitAbilityLevel(u, FV_SPELLID())
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
loop
set i = i + 1
set dummy = CreateUnit(GetTriggerPlayer(), FV_DUMMYID(), 0, 0, 0)
call SaveUnitHandle(udg_HASH, tID, i+0x789, dummy)
set dummy = null
exitwhen i > FV_LOOP_INDEX()
endloop
call SaveUnitHandle(udg_HASH, tID, 1, u)
call SaveReal(udg_HASH, tID, 2, 0) //angle
call SaveReal(udg_HASH, tID, 3, x)
call SaveReal(udg_HASH, tID, 4, y)
call SaveReal(udg_HASH, tID, 5, FV_DAMAGE(level))
call SaveReal(udg_HASH, tID, 6, FV_DURATION(level))
call TimerStart(t, 0.03125, true, function FV_LOOP)
set u = null
set t = null
endfunction
function FV_CAST_COND takes nothing returns boolean
return GetSpellAbilityId()==FV_SPELLID()
endfunction
function InitTrig_FireVortex takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function FV_CAST_COND))
call TriggerAddAction(t, function FV_ACTION)
if udg_HASH==null then
set udg_HASH = InitHashtable()
endif
set t = null
endfunction
//TESH.scrollpos=99
//TESH.alwaysfold=0
/*
=====Ignition v1.4
=====Made by: Mckill2009
REQUIRES:
- Jass New Gen Pack (JNGP) by Vexorian
- T32 by Jesus4Lyf
- RegisterPlayerUnitEvent by Magtheridon96
HOW TO USE:
- Make a trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
- Copy ALL that is written here and overwrite the existing texts in the custom text
- Copy the necessary libraries (T32 and RegisterPlayerUnitEvent)
- Replace the raw code as stated below if necessary...
- You can view the raw codes by pressing CTRL+B in the object editor
*/
library Ignition uses T32, RegisterPlayerUnitEvent
globals
private constant integer SPELL_ID = 'A00Z' //spell raw code
//Configurables
private constant real AOE = 90 //highly recommended
private constant real GAP_DIST = 7 //the bigger this, the longer the line
private constant real SFX_SPEED = 0.1 //lower value will cause lag, this is recommended
private constant attacktype ATK = ATTACK_TYPE_PIERCE
private constant damagetype DMG = DAMAGE_TYPE_FIRE
private constant string SFX = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
private constant string LIG = "DRAL"
//Not configurable
private location LOC = Location(0,0)
endglobals
//Configurables:
private constant function GetDamage takes integer i returns real
return 10 + i * 15.
endfunction
private constant function GetDuration takes integer i returns real
return 2 + i * 2.
endfunction
//End of Configurables:
//Never touch the code below unless you know what you're doing
private constant function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function GetUnitZ takes unit u returns real
call MoveLocation(LOC, GetUnitX(u), GetUnitY(u))
return GetLocationZ(LOC) + GetUnitFlyHeight(u)
endfunction
private struct IG
unit caster
real effectgap
real duration
real damage
real maxdist
lightning lig
method periodic takes nothing returns nothing
local unit u
local real x
local real y
local real angle
local real dist = 0
if .duration > 0 and UnitAlive(.caster) then
set angle = GetUnitFacing(.caster) * bj_DEGTORAD
set .duration = .duration - T32_PERIOD
loop
set dist = dist + AOE
set x = GetUnitX(.caster) + dist * Cos(angle)
set y = GetUnitY(.caster) + dist * Sin(angle)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, AOE, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u==null
if UnitAlive(u) and not IsUnitType(u, UNIT_TYPE_FLYING) and IsUnitEnemy(.caster, GetOwningPlayer(u)) then
call UnitDamageTarget(.caster, u, .damage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
exitwhen dist >= .maxdist
endloop
call MoveLightningEx(.lig, true, GetUnitX(.caster), GetUnitY(.caster), GetUnitZ(.caster)+100, x, y, GetUnitZ(.caster)+100)
//To avoid lag
set .effectgap = .effectgap + T32_PERIOD
if .effectgap >= SFX_SPEED then
set .effectgap = 0
call DestroyEffect(AddSpecialEffect(SFX, x, y))
endif
else
call DestroyLightning(.lig)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
private static method create takes unit u returns thistype
local thistype this = thistype.allocate()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
set .caster = u
set .duration = GetDuration(level)
set .damage = GetDamage(level) * T32_PERIOD
set .lig = AddLightning(LIG, true, 0, 0, 0, 0)
set .maxdist = AOE * GAP_DIST
set .effectgap = 0
call .startPeriodic()
return this
endmethod
private static method cond takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call IG.create(GetTriggerUnit())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.cond)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Burn initializer init
private function Actions takes unit attacked, unit attacker, integer level returns nothing
if not IsUnitType(attacker, UNIT_TYPE_STRUCTURE) and not IsUnitType(attacker, UNIT_TYPE_MECHANICAL) and IsUnitEnemy(attacked, GetOwningPlayer(attacker)) then
call MuiDummyCasters.hitTarget(GetOwningPlayer(attacked),attacker,GetUnitX(attacker), GetUnitY(attacker),'A01J',OrderId("innerfire"),level)
endif
endfunction
private function Cond takes nothing returns nothing
local unit u
local integer level
if GetUnitAbilityLevel(GetTriggerUnit(), 'A01I') > 0 and GetUnitAbilityLevel(GetAttacker(), 'B009')==0 then
set u = GetTriggerUnit()
set level = GetUnitAbilityLevel(GetTriggerUnit(), 'A01I')
if GetChance(u, 'A01I') then
call Actions(GetTriggerUnit(), GetAttacker(), level)
endif
set u = null
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell('A01J')
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=45
//TESH.alwaysfold=0
//Spell Name: Meteor Shower v1.3
//===HOW TO USE:
//- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
//- Copy ALL that is written here and overwrite the existing texts in the custom text
//- Copy the Dummy/custom abilities/buffs etc... to your object editor
//- Make sure you inputed the correct raw codes of the base spell/buffs/dummy etc...
//- If your raw code is different, you MUST CHANGE IT...
//- You can view the raw codes by pressing CTRL+D in the object editor
//- Examples of raw codes are 'A000', 'h000' etc...
//REQUIRES:
//- TimerUtils by Vexorian
//- Jass New Gen Pack by Vexorian
scope MS initializer init
globals
private constant integer SPELLID = 'A001' //raw code of the spell
private constant integer METEORID = 'h00I' //raw code of the meteor dummy
private constant attacktype ATT = ATTACK_TYPE_CHAOS
private constant damagetype DAM = DAMAGE_TYPE_FIRE
private constant real AOE = 150. //the damage AOE when meteor hits the ground
private constant real SUMMONSPEED = 0.5
private constant real FALLSPEED = 40.
private constant string SFX1 = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
private constant string SFX2 = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
endglobals
private function MS_DAMAGE takes integer i returns real
return 100.
endfunction
private function MS_AOE takes integer i returns real
return 300. + i * 200
endfunction
private function MS_DURATION takes integer i returns real
return 15.
endfunction
private struct MShower
unit caster
unit meteor
integer level
real damage
real AoE
real duration
real flyheight
real x
real y
static method onLoop2 takes nothing returns nothing
local unit first
local timer t = GetExpiredTimer()
local thistype MR = GetTimerData(t)
local real x
local real y
if MR.flyheight > 0 then
set MR.flyheight = MR.flyheight-FALLSPEED
call SetUnitFlyHeight(MR.meteor, MR.flyheight, 0)
else
call UnitApplyTimedLife(MR.meteor, 'BTLF', 0.01)
set x = GetUnitX(MR.meteor)
set y = GetUnitY(MR.meteor)
call DestroyEffect(AddSpecialEffect(SFX1, x, y))
call DestroyEffect(AddSpecialEffect(SFX2, x, y))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, AOE, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(first, GetOwningPlayer(MR.meteor)) and GetWidgetLife(first) > 0.405 and not IsUnitType(first, UNIT_TYPE_FLYING) then
call UnitDamageTarget(MR.meteor, first, MR.damage, false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
call ReleaseTimer(t)
endif
set t = null
endmethod
static method onLoop takes nothing returns nothing
local timer t = GetExpiredTimer()
local timer t2
local thistype MR = GetTimerData(t)
local thistype this
local real x1
local real y1
local real offset
local real angle
if MR.duration > 0 and GetWidgetLife(MR.caster) > 0.405 and GetUnitCurrentOrder(MR.caster)==852183 then //Starfall
set this = thistype.allocate()
set angle = GetRandomReal(-1,1)*bj_RADTODEG
set offset = GetRandomReal(100, MR.AoE)
set t2 = NewTimer()
set MR.duration = MR.duration-SUMMONSPEED
set x1 = MR.x + offset * Cos(angle)
set y1 = MR.y + offset * Sin(angle)
//Saves thistype into another type and starts another timer
set .meteor = CreateUnit(GetOwningPlayer(MR.caster),METEORID, x1, y1, 0)
set .flyheight = 1000
set .damage = MR.damage
set .AoE = MR.AoE
call SetTimerData(t2, this)
call TimerStart(t2, 0.03125, true, function thistype.onLoop2)
set t2 = null
else
call IssueImmediateOrder(MR.caster, "stop")
call ReleaseTimer(t)
endif
set t = null
endmethod
static method create takes unit u returns thistype
local thistype this = thistype.allocate()
local timer t = NewTimer()
set .caster = u
set .level = GetUnitAbilityLevel(u, SPELLID)
set .damage = MS_DAMAGE(.level)
set .AoE = MS_AOE(.level)
set .duration = MS_DURATION(.level)
set .x = GetUnitX(u)
set .y = GetUnitY(u)
call SetTimerData(t, this)
call TimerStart(t, SUMMONSPEED, true, function thistype.onLoop)
set t = null
return this
endmethod
endstruct
private function Cast takes nothing returns boolean
if GetSpellAbilityId()==SPELLID then
call MShower.create(GetTriggerUnit())
endif
return false
endfunction
private function init takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function Cast)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Sting
//uses T32
globals
private constant integer SPELL_ID = 'A00A' //stormbolt
private constant attacktype ATK = ATTACK_TYPE_PIERCE
private constant damagetype DMG = DAMAGE_TYPE_POISON
private constant string SFX = "Abilities\\Spells\\Other\\Parasite\\ParasiteTarget.mdl"
endglobals
private function GetDuration takes integer i returns real
return 1 + i * 1.
endfunction
private function GetDamage takes integer i returns real
return i * 15.
endfunction
private struct Sting
unit caster
unit target
real damage
real duration
effect sfx
method periodic takes nothing returns nothing
set .duration = .duration - T32_PERIOD
if .duration < 0 then
call SetUnitInvulnerable(.target, false)
call UnitDamageTarget(.caster, .target, .damage, false, false, ATK, DMG, null)
call DestroyEffect(.sfx)
call PauseUnit(.target, false)
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local integer level
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .target = GetSpellTargetUnit()
set .sfx = AddSpecialEffectTarget(SFX, .target, "overhead")
set .duration = GetDuration(level)
set .damage = GetDamage(level)
call PauseUnit(.target, true)
call SetUnitInvulnerable(.target, true)
call .startPeriodic()
return this
endmethod
private static method cond takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call thistype.create()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.cond)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Dig
//uses T32
globals
private constant integer SPELL_ID = 'A01K' //howl of terror
endglobals
private function GetRegeneration takes integer i returns real
return i * 0.5
endfunction
private struct Dig
unit caster
real maxlife
real maxmana
real rege
real duration
method periodic takes nothing returns nothing
if .duration > 0 and (GetWidgetLife(.caster)!=.maxlife or GetUnitState(.caster, UNIT_STATE_MANA)!=.maxmana) then
set .duration = .duration - T32_PERIOD
call SetWidgetLife(.caster, GetWidgetLife(.caster)+.rege)
call SetUnitState(.caster, UNIT_STATE_MANA, GetUnitState(.caster, UNIT_STATE_MANA)+.rege)
call PauseUnit(.caster, true)
else
call SetUnitInvulnerable(.caster, false)
call SetUnitAnimation(.caster, "morph alternate")
call SetUnitPathing(.caster, false)
call PauseUnit(.caster, false)
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local integer level
local unit u = GetTriggerUnit()
set .maxlife = GetUnitState(u, UNIT_STATE_MAX_LIFE)
set .maxmana = GetUnitState(u, UNIT_STATE_MAX_MANA)
if GetWidgetLife(u) != .maxlife or GetUnitState(u, UNIT_STATE_MANA) != .maxmana then
set .caster = u
set level = GetUnitAbilityLevel(u, SPELL_ID)
set .rege = (GetHeroAgi(.caster, false)*GetRegeneration(level)) * T32_PERIOD
set .duration = 7
call SetUnitInvulnerable(u, true)
call SetUnitAnimation(u, "morph")
call SetUnitPathing(u, false)
call .startPeriodic()
else
call SimError(GetTriggerPlayer(), "can't use this yet!")
call IssueImmediateOrder(u, "stop")
call .deallocate()
endif
set u = null
return this
endmethod
private static method cond takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call thistype.create()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.cond)
endmethod
endstruct
endscope
//TESH.scrollpos=30
//TESH.alwaysfold=0
/*
REQUIRES:
- Jass New Gen Pack (JNGP) by Vexorian
- RegisterPlayerUnitEvent by Magtheridon96
- T32 by Jesus4Lyf
- Table by Bribe
*/
scope Outbreak
globals
private constant integer SPELL_ID = 'A00C' //starfall
private constant integer UNIT_ID = 'n00A' //Arachnathid units
private constant integer ORDER_ID = 852183 //starfall
private constant integer MIN_AOE = 400
private constant integer MAX_AOE = 1100
private Table cast
endglobals
private function GetUnitQty takes integer i returns integer
return 10 + i * 10
endfunction
private function GetUnitLife takes integer i returns real
return 10 + i * 10.
endfunction
private function GetDuration takes integer i returns real
return 50 + i * 10.
endfunction
private interface Use
unit caster
real interval
real xLoc
real yLoc
endinterface
private struct Attacking extends Use
unit spawn
method periodic takes nothing returns nothing
local real xEn
local real yEn
local real angle
local integer distx
local integer casterID
if not IsUnitType(.spawn, UNIT_TYPE_DEAD) then
set .interval = .interval + T32_PERIOD
if .interval > 2 then
set .interval = 0
if GetUnitCurrentOrder(.spawn)!=851990 then //patrol
set distx = GetRandomInt(MIN_AOE, MAX_AOE)
set angle = GetRandomReal(-5,5)
call IssuePointOrderById(.spawn, 851990, .xLoc + distx * Cos(angle), .yLoc + distx * Sin(angle))
endif
endif
else
set casterID = GetHandleId(.caster)
set cast[casterID] = cast[casterID] - 1
if not IsUnitType(.spawn, UNIT_TYPE_DEAD) then
call KillUnit(.spawn)
endif
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
static method create takes unit c,unit u, real x, real y returns thistype
local thistype this = thistype.allocate()
set .caster = c
set .spawn = u
set .xLoc = x
set .yLoc = y
set .interval = 0
call .startPeriodic()
return this
endmethod
endstruct
private struct Outbreak extends Use
static integer castindex = 0
real duration
real life
integer maxunit
method periodic takes nothing returns nothing
local unit d
local integer count
local integer casterID
if .duration > 0 and not IsUnitType(.caster, UNIT_TYPE_DEAD) then
if GetUnitCurrentOrder(.caster)==ORDER_ID then
set .interval = .interval + T32_PERIOD
set .duration = .duration - T32_PERIOD
if .interval > 1 then
set .interval = 0
if .maxunit > (cast[GetHandleId(.caster)]) then
set casterID = GetHandleId(.caster)
set cast[casterID] = cast[casterID] + 1
set d = CreateUnit(GetOwningPlayer(.caster), UNIT_ID, .xLoc, .yLoc, 0)
call SetUnitAnimation(d, "stand alternate")
call UnitApplyTimedLife(d, 'BTLF', .life)
call Attacking.create(.caster, d, .xLoc, .yLoc)
set d = null
endif
endif
else
set .duration = 0
endif
else
set .castindex = .castindex - 1
if .castindex==0 then
call cast.flush()
endif
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local integer level = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)
set .caster = GetTriggerUnit()
set .xLoc = GetUnitX(.caster)
set .yLoc = GetUnitY(.caster)
set .interval = 0.
set .duration = GetDuration(level)
set .maxunit = GetUnitQty(level)
set .life = 30.//GetUnitLife(level)
set .castindex = .castindex + 1
call .startPeriodic()
return this
endmethod
private static method cond takes nothing returns nothing
if GetSpellAbilityId()==SPELL_ID then
call thistype.create()
endif
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.cond)
set cast = Table.create()
endmethod
endstruct
endscope
//TESH.scrollpos=21
//TESH.alwaysfold=0
/*
===Fire Erruption v1.4
===By: Mckill2009
INSTALLATION:
- Copy the "Fire Erruption" (see left) folder to your map
- Copy the custom units and abilities to your map
- Make sure you inputed the correct raw ID's of the custom units and abilities
- You can view raw ID's by pressing CTRL+D in the object editor
- Examples of raw ID's are 'A001', 'A003' etc...
- See the Note below for more info
REQUIRES:
- RegisterPlayerUnitEvent by Magtheridon96
- SpellEffectEvent by Bribe
CREDITS:
- This spell was originally made by defskull in GUI (requested by me)
*/
scope FireErruption
/*
Note:
- SPELL_ID and CHANNEL_ID must match/synchronize to each other
- FE_DUMSPELLID and ORDER_ID must match/synchronize to each other.
- If you create your FE_DUMMY manually from the object editor make
sure that the "Animation - Cast Backswing/Point" is set to 0.
- The cooldown and mana of your Breath of Fire must be 0.
*/
globals
private constant integer SPELL_ID = 'A00F' //Main spell raw ID, Blizzard
private constant integer FE_DUMSPELLID = 'A00J' //Dummy spell raw ID, Breath of Fire
private constant integer FE_DUMMYID = 'h004' //Dummy raw ID
private constant integer FIREBALL_ID = 'h00B' //Fireball Dummy raw ID
private constant integer CHANNEL_ID = 852089 //Blizzard orderID (for hero)
private constant integer ORDER_ID = 852580 //Breath of Fire orderID (for dummy)
//=============================================
private constant boolean PRELOAD = true
//Sets how many times the fireball will spit fire
private constant integer CAST_COUNT = 12
//This is the ground shaking SFX
private constant string FE_SFX = "Abilities\\Spells\\Orc\\EarthQuake\\EarthQuakeTarget.mdl"
//This is the angle between spitting fire
private constant real FE_BALL_GAP = 30.
//Sets how fast the fireball grows
private constant real SCALE_INTERVAL = 0.05
//Minimum 0.03, this is the speed of the rotating fire casted
private constant real CAST_SPEED = 0.03
//Maximum size of the fireball
private constant real MAX_SCALE = 10
endglobals
private struct FireErruption extends array
unit u
unit fireball
real x
real y
real scale
real angle
real castspeed
integer castcount
integer level
effect sfx
boolean isChanneling
static constant real delay = 0.03125
static unit dummy = null //used a global dummy for the fire casting
static timer t
static integer index = 0
static integer array indexAR
//=====allocator and destructor for this struct
static integer ins = 0
static integer array insAR
static method allocate takes nothing returns integer
local thistype this = insAR[0]
if this==0 then
set ins = ins + 1
set this = ins
else
set insAR[0] = insAR[this]
endif
return this
endmethod
method deallocate takes nothing returns nothing
set insAR[this] = insAR[0]
set insAR[0] = this
endmethod
//=====
static method periodic takes nothing returns nothing
local thistype this
local integer i = 0
local real x1
local real y1
loop
set i = i+1
set this = indexAR[i]
if not IsUnitType(.u, UNIT_TYPE_DEAD) and .isChanneling then
if GetUnitCurrentOrder(.u)==CHANNEL_ID then
if MAX_SCALE > .scale then
set .scale = .scale + SCALE_INTERVAL
call SetUnitScale(.fireball, .scale, 0, 0)
elseif .fireball != null then
call DestroyEffect(.sfx)
call RemoveUnit(.fireball)
set .fireball = null
elseif CAST_COUNT > .castcount then
set .castspeed = .castspeed + delay
if .castspeed > CAST_SPEED then
set .castspeed = 0
set .castcount = .castcount + 1
set .angle = .angle + FE_BALL_GAP
call SetUnitOwner(dummy, GetOwningPlayer(.u), false)
call SetUnitPosition(dummy, .x, .y)
set x1 = .x + 100 * Cos(.angle*bj_DEGTORAD)
set y1 = .y + 100 * Sin(.angle*bj_DEGTORAD)
call SetUnitAbilityLevel(dummy, FE_DUMSPELLID, .level)
call IssuePointOrderById(dummy, ORDER_ID, x1, y1)
endif
else
call IssueImmediateOrder(.u, "stop")
set .isChanneling = false
endif
else
set .isChanneling = false
endif
else
call DestroyEffect(.sfx)
call RemoveUnit(.fireball)
set .u = null
set .fireball = null
set .sfx = null
call .deallocate()
set indexAR[i] = indexAR[index]
set indexAR[index] = this
set index = index - 1
set i = i - 1
if index==0 then
call PauseTimer(t)
call DestroyTimer(t)
call RemoveUnit(dummy)
endif
endif
exitwhen i==index
endloop
endmethod
static method cast takes nothing returns nothing
local thistype this = allocate()
set .u = GetTriggerUnit()
set .x = GetSpellTargetX()
set .y = GetSpellTargetY()
set .fireball = CreateUnit(Player(15), FIREBALL_ID, .x, .y, 0)
set .level = GetUnitAbilityLevel(.u, SPELL_ID)
set .sfx = AddSpecialEffect(FE_SFX, .x, .y)
call SetUnitScale(.fireball, 0,0,0)
set .scale = 0
set .angle = 0
set .castcount = 0
set .castspeed = CAST_SPEED
set .isChanneling = true
call SetUnitFlyHeight(.fireball, 100, 0)
if index==0 then
set t = CreateTimer()
call TimerStart(t, delay, true, function thistype.periodic)
set dummy = CreateUnit(Player(15),FE_DUMMYID,0,0,0)
call UnitAddAbility(dummy, FE_DUMSPELLID)
call UnitRemoveAbility(dummy, 'Amov')
endif
set index = index + 1
set indexAR[index] = this
endmethod
static method onInit takes nothing returns nothing
//Setting up the spell effect
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
static if PRELOAD then
//Preloading dummies and abilities
set dummy = CreateUnit(Player(15),FE_DUMMYID,0,0,0)
call ShowUnit(dummy,false)
call RemoveUnit(dummy)
set dummy = CreateUnit(Player(15),FIREBALL_ID,0,0,0)
call ShowUnit(dummy,false)
call UnitAddAbility(dummy, FE_DUMSPELLID)
call RemoveUnit(dummy)
endif
endmethod
endstruct
endscope
//TESH.scrollpos=18
//TESH.alwaysfold=0
function NEC_Damage takes integer i returns integer
return 5 + i * 1
endfunction
function NEC_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit first
local integer level = GetUnitAbilityLevel(u, 'A01A')
local integer health = 0
local integer size = 0
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 600, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(first, GetTriggerPlayer()) and IsUnitType(first, UNIT_TYPE_DEAD) and not IsUnitType(first, UNIT_TYPE_HERO)then
set size = size + 1
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl", GetUnitX(first), GetUnitY(first)))
call RemoveUnit(first)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
if size > 0 then
set health = size * NEC_Damage(level)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 600, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if not IsUnitEnemy(first, GetTriggerPlayer()) and not IsUnitType(first, UNIT_TYPE_DEAD) and GetWidgetLife(first)!=GetUnitState(first, UNIT_STATE_MAX_LIFE) then
call SetWidgetLife(first, GetWidgetLife(first)+health)
set bj_lastCreatedTextTag = CreateTextTag()
call SetTextTagPosUnit(bj_lastCreatedTextTag, first, 0.1) //heightoffset is 0 OK
call SetTextTagText(bj_lastCreatedTextTag, "+"+I2S(health)+"!", 0.03) //size is 0.025 OK
call SetTextTagPermanent(bj_lastCreatedTextTag, false)
call SetTextTagVelocity(bj_lastCreatedTextTag, 0.03, 0.03)
call SetTextTagLifespan(bj_lastCreatedTextTag, 3)
call SetTextTagFadepoint(bj_lastCreatedTextTag, 0.01)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Unsummon\\UnsummonTarget.mdl", first, "overhead"))
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
set u = null
endfunction
function NEC_Condition takes nothing returns boolean
return GetSpellAbilityId() == 'A01A'
endfunction
function InitTrig_Necrogenesis takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function NEC_Condition)
call TriggerAddAction(t, function NEC_Actions)
set t = null
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope MoltenRocks initializer init
//uses TimerLooper, RegisterPlayerUnitEvent
globals
private constant integer SPELL_ID = 'A01B'
private constant integer ROCK_ID = 'h00A'
private constant attacktype ATK = ATTACK_TYPE_MAGIC
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
private constant string SFX = "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl"
endglobals
private function GetDamage takes integer i returns real
return i * 25.
endfunction
private function FilterUnit takes unit a, unit u returns boolean
return IsUnitEnemy(a, GetOwningPlayer(u)) and not IsUnitType(a, UNIT_TYPE_STRUCTURE) and IsUnitType(a, UNIT_TYPE_GROUND)
endfunction
private function FallLoop takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local unit u = GetUnitHandle(tID, 1) //The attacked
local unit a = GetUnitHandle(tID, 2) //The attacker
local unit rock = GetUnitHandle(tID, 3)
local real damage = GetReal(tID, 4)
local real height = GetReal(tID, 5) //height
if height > 0 then
call SetReal(tID, 5, height - 15)
call SetUnitX(rock, GetUnitX(a))
call SetUnitY(rock, GetUnitY(a))
call SetUnitFlyHeight(rock, height, 0)
else
call KillUnit(rock)
call SetUnitExploded(rock, true)
if not IsUnitType(a, UNIT_TYPE_DEAD) then
call UnitDamageTarget(u, a, damage, false, false, ATK, DMG, null)
call DestroyEffect(AddSpecialEffectTarget(SFX, a, "overhead"))
else
call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(rock), GetUnitY(rock)))
endif
call Flush(tID)
call StopTimer(t)
endif
set t = null
set u = null
set a = null
set rock = null
endfunction
private function Actions takes unit trg, unit atr, integer level returns nothing
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local unit rock = CreateUnit(GetOwningPlayer(trg), ROCK_ID, GetUnitX(atr), GetUnitY(atr), 0)
call SetUnitFlyHeight(rock, 500, 0)
call SetUnitHandle(tID, 1, trg)
call SetUnitHandle(tID, 2, atr)
call SetUnitHandle(tID, 3, rock)
call SetReal(tID, 4, GetDamage(level)) //The damage
call SetReal(tID, 5, GetUnitFlyHeight(rock))
call TimerStart(t, 0.03, true, function FallLoop) //The first timer
set t = null
set rock = null
endfunction
private function Cond takes nothing returns nothing
local unit u
if GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID) > 0 then
set u = GetTriggerUnit()
// if GetChance(u, SPELL_ID) and FilterUnit(GetAttacker(), u) then
call Actions(u, GetAttacker(), GetUnitAbilityLevel(u, SPELL_ID))
// endif
set u = null
endif
endfunction
private function init takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope WrathOfFire
//uses TimerLooper, RegisterPlayerUnitEvent
globals
private constant integer SPELL_ID = 'A01D'
private constant attacktype ATT = ATTACK_TYPE_CHAOS
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant real AOE_RANGE = 600
private constant real AOE_DAM = 250
private constant real INTERVAL = 0.2
private constant string SFX = "Abilities\\Spells\\NightElf\\Immolation\\ImmolationTarget.mdl"
endglobals
private function GetDuration takes integer i returns real
return 40.
endfunction
private function GetDamage takes integer i returns real
return 20.
endfunction
private struct WOF
unit caster
real damage
real duration
effect sfx
private static method filterAlly takes unit u1, unit u2 returns boolean
return not IsUnitEnemy(u1, GetOwningPlayer(u2)) and not IsUnitType(u1, UNIT_TYPE_DEAD) and not /*
*/ IsUnitType(u1, UNIT_TYPE_STRUCTURE) and not IsUnitType(u1, UNIT_TYPE_MECHANICAL)
endmethod
private static method filterEnemies takes unit u1, unit u2 returns boolean
return IsUnitEnemy(u1, GetOwningPlayer(u2)) and not (IsUnitType(u1, UNIT_TYPE_DEAD) and /*
*/ IsUnitType(u1, UNIT_TYPE_STRUCTURE) and IsUnitType(u1, UNIT_TYPE_MECHANICAL))
endmethod
private static method periodic takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local integer this = GetInteger(tID, 1)
local unit first
if not IsUnitType(.caster, UNIT_TYPE_DEAD) and .duration > 0 then
set .duration = .duration - INTERVAL
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.caster), GetUnitY(.caster), AOE_DAM, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if filterEnemies(first, .caster) then
call UnitDamageTarget(.caster, first, .damage , false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
else
call DestroyEffect(.sfx)
call Flush(tID)
call StopTimer(t)
endif
endmethod
static method create takes unit cast, integer level returns thistype
local thistype this = thistype.allocate()
local timer t = GetTimer()
set .caster = cast
set .damage = GetDamage(level)*INTERVAL
set .duration = GetDuration(level)
set .sfx = AddSpecialEffectTarget(SFX, cast, "origin")
call SetInteger(GetHandleId(t), 1, this)
call TimerStart(t, INTERVAL, true, function thistype.periodic)
return this
endmethod
private static method actions takes unit u returns nothing
local unit first
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE_RANGE, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if filterAlly(first, u) then
call thistype.create(first,level)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endmethod
private static method cond takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call actions(GetTriggerUnit())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.cond)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BloodShed initializer init
globals
private constant integer SPELL_ID = 'A00G'
private constant integer ALLY_TARGET = 'A00H'
private constant integer ENEMY_TARGET = 'A02A'
endglobals
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
if IsUnitEnemy(target, GetTriggerPlayer()) then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(),target,GetUnitX(target),GetUnitY(target),ENEMY_TARGET,OrderId("unholyfrenzy"),level)
else
call MuiDummyCasters.hitTarget(GetTriggerPlayer(),target,GetUnitX(target),GetUnitY(target),ALLY_TARGET,OrderId("rejuvination"),level)
endif
set u = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(ALLY_TARGET)
call PreloadSpell(ENEMY_TARGET)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=15
//TESH.alwaysfold=0
scope DeathWaves initializer init
globals
private constant integer SPELL_ID = 'A00V'
private constant integer DUMMY_SPELL_ID = 'A029'
private constant integer CHANNEL = 852183 //change to starfall
private constant real INTERVAL = 0.1
endglobals
private function Looper takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
local unit u = GetUnitHandle(tID, 1)
local real duration = GetReal(tID, 2)
local real angle = GetReal(tID, 3)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x1
local real y1
if duration > 0 and FUN_UnitAlive(u) and GetUnitCurrentOrder(u)==CHANNEL then
call SetReal(tID, 2, duration-INTERVAL)
call SetReal(tID, 3, angle + 0.7)
set x1 = x + 75 * Cos(angle)
set y1 = y + 75 * Sin(angle)
call MuiDummyCasters.hitPoint(GetOwningPlayer(u), x,y,x1,y1, DUMMY_SPELL_ID,OrderId("carrionswarm"),GetInteger(tID, 4))
else
call StopTimer(GetExpiredTimer())
call Flush(tID)
endif
set u = null
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
call SetUnitHandle(tID, 1, u)
call SetReal(tID, 2, 15.)
call SetReal(tID, 3, 0) //angle
call SetInteger(tID, 4, level)
call TimerStart(t, INTERVAL, true, function Looper)
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope RiseDeathLords initializer init
globals
private constant integer SPELL_ID = 'A02B'
private constant integer DEATH_LORD_ID = 'n007'
private constant string SFX = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"
private integer array Abilities
endglobals
private function Cond takes nothing returns nothing
local unit attacked
local integer level
local integer i
if FilterEnemyAndSpellLevel(GetOwningPlayer(GetAttacker()), GetTriggerUnit(), SPELL_ID) then
set attacked = GetTriggerUnit()
if ManaNeeded(attacked,200) and GetRandomInt(0,100) <= 10 then
call SetUnitState(attacked, UNIT_STATE_MANA, GetUnitState(attacked, UNIT_STATE_MANA)-200)
set level = GetUnitAbilityLevel(attacked, SPELL_ID)
set i = 0
set bj_lastCreatedUnit = CreateUnit(GetTriggerPlayer(), DEATH_LORD_ID, GetUnitX(GetAttacker()), GetUnitY(GetAttacker()), 0)
call FUN_SpecialEffectXY(SFX, GetUnitX(bj_lastCreatedUnit), GetUnitY(bj_lastCreatedUnit))
call UnitApplyTimedLife(bj_lastCreatedUnit, 'BTLF', 30)
loop
set i = i+1
exitwhen i==level
call UnitAddAbility(bj_lastCreatedUnit, Abilities[i])
endloop
set bj_lastCreatedUnit = null
endif
set attacked = null
endif
endfunction
private function init takes nothing returns nothing
call Preload(SFX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
set Abilities[1] = 'ACbh' //bash
set Abilities[2] = 'ACpu' //purge
set Abilities[3] = 'ACen' //ensnare
set Abilities[4] = 'ACbl' //blood lust
endfunction
endscope
//TESH.scrollpos=59
//TESH.alwaysfold=0
scope Decay initializer init
globals
private constant integer SPELL_ID = 'A002'
private constant string SFX = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl"
private constant real INTERVAL = 0.5
private integer array Uids
private integer Counter = 0
endglobals
private function GetDuration takes integer i returns real
return 40 + i * 20.
endfunction
private function GetMaxUnit takes integer i returns integer
return 15
endfunction
private function CountUnits takes nothing returns nothing
if FUN_UnitAlive(GetEnumUnit()) then
set Counter = Counter + 1
endif
endfunction
private function Looper takes nothing returns nothing
local integer tID = GetHandleId(GetExpiredTimer())
local unit skeletons
local unit target = GetUnitHandle(tID, 1)
local unit u = GetUnitHandle(tID, 2)
local real duration = GetReal(tID, 3)
local real x = GetUnitX(target)
local real y = GetUnitY(target)
local real x1
local real y1
local integer count
local integer i
local group g
if duration > 0 then
call SetReal(tID, 3, duration-INTERVAL)
set count = GetInteger(tID, 5)
set g = GetGroupHandle(tID,6)
if GetInteger(tID, 4) > count then
call SetInteger(tID, 5, count+1)
set x1 = x+150*GetRandomReal(-1,1)
set y1 = y+150*GetRandomReal(-1,1)
set skeletons = CreateUnit(GetOwningPlayer(u), Uids[GetRandomInt(1,2)], x1,y1,0)
call FUN_SpecialEffectXY(SFX, GetUnitX(skeletons), GetUnitY(skeletons))
call UnitApplyTimedLife(skeletons, 'BTLF', 15)
call GroupAddUnit(g,skeletons)
set skeletons = null
endif
set Counter = 0
call ForGroup(g, function CountUnits)
call SetInteger(tID, 5, Counter)
set g = null
else
call DestroyGroup(GetGroupHandle(tID,6))
call SetUnitInvulnerable(target, false)
call SetUnitAnimation(target, "stand")
call StopTimer(GetExpiredTimer())
call Flush(tID)
endif
set u = null
set target = null
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
call SetUnitInvulnerable(target, true )
call SetUnitAnimation(target, "death" )
call SetUnitHandle(tID, 1, target)
call SetUnitHandle(tID, 2, u)
call SetReal(tID, 3, GetDuration(level))
call SetInteger(tID, 4, GetMaxUnit(level))
call SetInteger(tID, 5, 0) //count
call SetGroupHandle(tID, 6, CreateGroup())
call TimerStart(t, INTERVAL, true, function Looper)
set u = null
set target = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
set Uids[1] = 'nskf'
set Uids[2] = 'nskg'
endfunction
endscope
//TESH.scrollpos=5
//TESH.alwaysfold=0
scope BoulderRoll initializer init
globals
private constant integer SPELL_ID = 'A02E'
private constant attacktype ATT = ATTACK_TYPE_PIERCE
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant real AOE_RANGE = 400
private constant string SFX = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"
endglobals
private function GetDamage takes integer i returns real
return i * 15.
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local unit first
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local real damage = GetDamage(level) + GetHeroStr(u, true)
call FUN_DamageTarget(u,target,damage,ATT,DAM)
//! runtextmacro FOG_ADD("GetUnitX(target)","GetUnitY(target)","AOE_RANGE")
if FUN_UnitAlive(first) and IsUnitEnemy(first, GetTriggerPlayer()) and FUN_OrganicUnits(first) and target!=first then
call FUN_SpecialEffectXY(SFX, GetUnitX(first), GetUnitY(first))
call FUN_DamageTarget(u,first,damage/2,ATT,DAM)
endif
//! runtextmacro FOG_REMOVE()
set u = null
set target = null
endfunction
private function init takes nothing returns nothing
call Preload(SFX)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Shatter initializer init
globals
private constant integer SPELL_ID = 'A00W'
private constant integer ARMOUR = 'A02H'
private constant integer ORDER = 852183 //starfall
private constant string SFX = "Abilities\\Weapons\\RockBoltMissile\\RockBoltMissile.mdl"
private constant attacktype ATT = ATTACK_TYPE_PIERCE
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant real AOE = 400
private constant real INTERVAL = 0.1
endglobals
private function GetDuration takes integer i returns real
return 13. //ability dur must be the same
endfunction
private function GetDamage takes integer i returns real
return i * 30.
endfunction
private function Looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local unit u = GetUnitHandle(tID, 1)
local real duration = GetReal(tID, 2)
if duration > 0 and FUN_UnitAlive(u) and GetUnitCurrentOrder(u)==ORDER then
call SetReal(tID, 2, duration-INTERVAL)
if duration < 3 then
call UnitRemoveAbility(u, ARMOUR)
endif
else
call PauseUnit(u, false)
call SetUnitAnimation(u, "stand")
call UnitRemoveAbility(u, ARMOUR)
call StopTimer(t)
call Flush(tID)
endif
set u = null
set t = null
endfunction
private function Actions takes nothing returns nothing
local unit first
local unit u = GetTriggerUnit()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
call SetUnitAnimation(u, "death")
//! runtextmacro FOG_ADD("GetUnitX(u)","GetUnitY(u)","AOE")
if FUN_UnitAlive(first) and FUN_OrganicUnits(first) then
call FUN_DamageGroundUnits(u,first,GetDamage(level),ATT,DAM)
call FUN_SpecialEffectTarget(first,SFX,"overhead")
endif
//! runtextmacro FOG_REMOVE()
call UnitAddAbility(u, ARMOUR)
call SetUnitAbilityLevel(u, ARMOUR, level)
call SetUnitHandle(tID, 1, u)
call SetReal(tID, 2, GetDuration(level))
call TimerStart(t, INTERVAL, true, function Looper)
set u = null
set first = null
set t = null
endfunction
private function init takes nothing returns nothing
call Preload(SFX)
call PreloadSpell(ARMOUR)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=33
//TESH.alwaysfold=0
scope DeadMaterial initializer init
globals
private constant integer SPELL_ID = 'A02I'
private constant integer DUMMY_SPELL_ID = 'Aams'
private constant integer BUFF = 'Bams'
private constant real INTERVAL = 0.5
endglobals
private function HeroStr takes unit u, integer i returns integer
return GetHeroStr(u, false) + (1 + i * 2)
endfunction
private function HeroInt takes unit u, integer i returns integer
return GetHeroInt(u, false) - (2 + i * 2)
endfunction
private function Looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local integer uID
local unit u = GetUnitHandle(tID, 1)
local real dur = GetReal(tID, 2)
local integer bf = GetUnitAbilityLevel(u, BUFF)
if FUN_UnitAlive(u) and dur > 0 and bf > 0 then
call SetReal(tID, 2, dur-INTERVAL)
else
set uID = GetHandleId(u)
call SetHeroStr(u, GetInteger(uID, SPELL_ID), true)
call SetHeroInt(u, GetInteger(uID, SPELL_ID+1), true)
call RemoveInteger(uID, SPELL_ID)
call RemoveInteger(uID, SPELL_ID+1)
call StopTimer(t)
call Flush(tID)
endif
set t = null
set u = null
endfunction
private function Cond takes nothing returns nothing
local unit attacker
if FilterEnemyAndSpellLevel(GetTriggerPlayer(), GetAttacker(), SPELL_ID) then
set attacker = GetAttacker()
if GetChance(attacker, SPELL_ID) then
if GetUnitAbilityLevel(attacker, BUFF)==0 then
if not HasInteger(GetHandleId(attacker), SPELL_ID) then
call SetInteger(GetHandleId(attacker), SPELL_ID, GetHeroStr(attacker, false))
call SetInteger(GetHandleId(attacker), SPELL_ID+1, GetHeroInt(attacker, false))
set bj_forLoopAIndex = GetUnitAbilityLevel(attacker, SPELL_ID)
call SetHeroStr(attacker, HeroStr(attacker,bj_forLoopAIndex), false)
call SetHeroInt(attacker, HeroInt(attacker,bj_forLoopAIndex), false)
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), attacker, GetUnitX(attacker), GetUnitY(attacker), DUMMY_SPELL_ID, OrderId("antimagicshell"), 1)
set bj_gameStartedTimer = GetTimer()
set bj_forLoopBIndex = GetHandleId(bj_gameStartedTimer)
call SetUnitHandle(bj_forLoopBIndex, 1,attacker)
call SetReal(bj_forLoopBIndex, 2, 10)
call TimerStart(bj_gameStartedTimer, INTERVAL, true, function Looper)
set bj_gameStartedTimer = null
set bj_forLoopAIndex = 0
set bj_forLoopBIndex = 0
endif
endif
endif
set attacker = null
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(BUFF)
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Decoy initializer init
globals
private constant integer SPELL_ID = 'A00X'
private constant real AOE = 600
private constant real INTERVAL = 0.5
private group GRP = CreateGroup()
endglobals
private function GetDuration takes integer i returns real
return 30.
endfunction
private function Looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local unit first
local unit u = GetUnitHandle(tID, 1)
local real duration = GetReal(tID, 2)
if duration > 0 and FUN_UnitAlive(u) then
call SetReal(tID, 2, duration-INTERVAL)
//! runtextmacro FOG_ADD("GetUnitX(u)","GetUnitY(u)","AOE")
if IsUnitEnemy(u, GetOwningPlayer(first)) and FUN_UnitAlive(first) and FUN_OrganicUnits(first) then
call IssueTargetOrder(first, "move", u)
endif
//! runtextmacro FOG_REMOVE()
else
call GroupRemoveUnit(GRP,u)
call StopTimer(t)
call Flush(tID)
endif
set t = null
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
call SetUnitHandle(tID, 1, u)
call SetReal(tID, 2, GetDuration(level))
call GroupAddUnit(GRP,u)
call TimerStart(t, INTERVAL, true, function Looper)
endfunction
private function Attacked takes nothing returns nothing
if IsUnitInGroup(GetTriggerUnit(), GRP) then
call IssueImmediateOrder(GetAttacker(), "stop")
endif
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Attacked)
endfunction
endscope
//TESH.scrollpos=12
//TESH.alwaysfold=0
scope AirRaid initializer init
globals
private constant integer SPELL_ID = 'A011'
private constant integer COPTER_ID = 'h00J'
private constant integer BOMB_ID = 'h00L'
private constant attacktype ATT = ATTACK_TYPE_SIEGE
private constant damagetype DAM = DAMAGE_TYPE_NORMAL
private constant real AOE = 400
private constant real HEIGHT = 600
private constant string SFX = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
private rect Rct
endglobals
private function GetDamage takes integer i returns real
return 10 + i * 10.
endfunction
private struct BombDamage
unit bomb
real damage
real height
static real fallspeed = 5
static method getDestructables takes nothing returns boolean
local destructable d = GetFilterDestructable()
if IsDestructableTree(d) then
call KillDestructable(d)
endif
set d = null
return false
endmethod
method filterUnits takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL) /*
*/ and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u, UNIT_TYPE_DEAD)
endmethod
method periodic takes nothing returns nothing
local unit first
if .height > 0 then
set .height = .height - fallspeed
call SetUnitFlyHeight(.bomb, .height, 0)
else
call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(.bomb), GetUnitY(.bomb)))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.bomb), GetUnitY(.bomb), 150, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(first, GetOwningPlayer(.bomb)) and filterUnits(first) then
call UnitDamageTarget(.bomb,first,.damage,false,false,ATT,DAM,null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
call MoveRectTo(Rct, GetUnitX(.bomb), GetUnitY(.bomb))
call EnumDestructablesInRect(Rct, function thistype.getDestructables, null)
call KillUnit(.bomb)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit b, real d returns thistype
local thistype this = thistype.allocate()
set .bomb = b
set .damage = d
set .height = GetUnitFlyHeight(b)
call .startPeriodic()
return this
endmethod
endstruct
private struct AirRaid
unit copter
real distance
real damage
real angle
real begindist
real enddist
real delay
static real speed = 10
static real interval = 0.3
method periodic takes nothing returns nothing
local real x = GetUnitX(.copter)
local real y = GetUnitY(.copter)
local unit bomb
set .begindist = .begindist + .speed
call SetUnitX(.copter, x+.speed*Cos(.angle))
call SetUnitY(.copter, y+.speed*Sin(.angle))
if .distance > .begindist then
set .delay = .delay + T32_PERIOD
if .delay > .interval then
set .delay = 0
set bomb = CreateUnit(GetOwningPlayer(.copter), BOMB_ID, x,y, GetUnitFacing(.copter))
call SetUnitFlyHeight(bomb, GetUnitFlyHeight(.copter)-50, 0)
call BombDamage.create(bomb, .damage)
set bomb = null
endif
elseif .begindist > .enddist then
call KillUnit(.copter)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit c, real d, real a, real dm returns thistype
local thistype this = thistype.allocate()
set .copter = c
set .distance = d
set .angle = a
set .damage = dm
set .begindist = 0
set .enddist = d * 2
set .delay = 0
call .startPeriodic()
return this
endmethod
endstruct
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local real facing = GetUnitFacing(u)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x1 = GetSpellTargetX()
local real y1 = GetSpellTargetY()
local real distx = 150
local real distance = SquareRoot((x1-x) * (x1-x) + (y1-y) * (y1-y))
local real angle = Atan2(y1-y, x1-x)
local real damage = GetDamage(level)+BoostDamage(u)
local unit copter = CreateUnit(GetTriggerPlayer(), COPTER_ID, x+distx*Cos(facing), y+distx*Sin(facing), facing)
call SetUnitFlyHeight(copter, HEIGHT, 0)
call AirRaid.create(copter, distance, angle, damage)
set u = null
set copter = null
endfunction
private function init takes nothing returns nothing
local unit u = CreateUnit(Player(15), COPTER_ID,0,0,0)
call UnitApplyTimedLife(u, 'BTLF', 1.0)
call ShowUnit(u, false)
set u = CreateUnit(Player(15), BOMB_ID,0,0,0)
call UnitApplyTimedLife(u, 'BTLF', 1.0)
call ShowUnit(u, false)
set Rct = Rect(-AOE, -AOE, AOE, AOE)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
set u = null
endfunction
endscope
//TESH.scrollpos=37
//TESH.alwaysfold=0
scope Grenade initializer init
//Uses RegisterSpellEffectEvent, HashT, TimerLooper, Textmacros
globals
private constant integer SPELL_ID = 'A01C'
private constant integer GRENADE_ID = 'h00K'
private constant string SFX = "Objects\\Spawnmodels\\Human\\HCancelDeath\\HCancelDeath.mdl"
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
private constant real INTERVAL = 0.03125
private constant real SPEED = 20
private constant real HEIGHT = 350
endglobals
private function GetDamage takes integer i returns real
return 75 + i * 25.
endfunction
private function GetAoE takes integer i returns real
return 150 + i * 50.
endfunction
private function Trees takes nothing returns boolean
local destructable d = GetFilterDestructable()
if not IsDestructableDead(d) and IsDestructableTree(d) then
call KillDestructable(d)
endif
set d = null
return false
endfunction
private function Looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local unit first
local unit u = GetUnitHandle(tID, 1)
local real angle = GetReal(tID, 2)
local real distance = GetReal(tID, 3)
local real maxdistance = GetReal(tID, 4)
local real x
local real y
local real aoe
local rect r
if distance > 0 then
call SetReal(tID, 3, distance-SPEED) //distance
call FUN_MoveDummyXY(u,GetUnitX(u),GetUnitY(u),SPEED,angle)
call SetUnitFlyHeight(u, FUN_GetParabolaZ(HEIGHT, maxdistance, distance), 0)
else
set aoe = GetReal(tID,6)
set x = GetUnitX(u)
set y = GetUnitY(u)
call SetUnitFlyHeight(u, 0, 0)
call DestroyEffect(AddSpecialEffect(SFX, x, y))
//! runtextmacro FOG_ADD("x","y","aoe")
call FUN_DamageGroundUnits(u,first,GetReal(tID,5),ATK,DMG)
//! runtextmacro FOG_REMOVE()
set r = Rect(-aoe,-aoe,aoe,aoe)
call MoveRectTo(r, x, y)
call EnumDestructablesInRect(r,function Trees,null)
call KillUnit(u)
call RemoveRect(r)
set r = null
call StopTimer(t)
call Flush(tID)
endif
set u = null
set t = null
endfunction
private function Actions takes nothing returns nothing
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local unit u = GetTriggerUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x1 = GetSpellTargetX()
local real y1 = GetSpellTargetY()
local real distance = SquareRoot((x1-x) * (x1-x) + (y1-y) * (y1-y))
local unit grenade = CreateUnit(GetTriggerPlayer(), 'h00K', x,y,0)
call SetUnitFlyHeight(grenade, GetUnitFlyHeight(u)+100, 0)
call FUN_MakeUnitFly(u)
call SetUnitPathing(u, false)
call SetUnitHandle(tID, 1, grenade)
call SetReal(tID, 2, Atan2(y1-y, x1-x)) //angle
call SetReal(tID, 3, distance) //distance
call SetReal(tID, 4, distance) //max distance
call SetReal(tID, 5, GetDamage(level)+BoostDamage(u))
call SetReal(tID, 6, GetAoE(level))
call TimerStart(t, INTERVAL, true, function Looper)
set t = null
set u = null
set grenade = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Boost
globals
private constant integer BOOST_ID = 'A012'
endglobals
private function GetDamage takes integer i returns real
return 10 + i * 10.
endfunction
function BoostDamage takes unit u returns real
local real dam
if GetUnitAbilityLevel(u, BOOST_ID) > 0 then
return (GetDamage(GetUnitAbilityLevel(u, BOOST_ID)))
endif
return 0.
endfunction
endlibrary
//TESH.scrollpos=182
//TESH.alwaysfold=0
/*
=====Spell Name: Bombardment v1.4a
=====Created by: Mckill2009
REQUIRES:
- JassNewGenPack by Vexorian
REQUIRED LIBRARIES:
- DestructableLib by PitzerMike (http://www.wc3c.net/showthread.php?t=103927)
- T32 by Jesus4Lyf (http://www.thehelper.net/forums/showthread.php/132538-Timer32)
- RegisterSpellEffectEvent by Bribe (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/)
- RegisterPlayerUnitEvent by Magtheridon96 (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/)
OPTIONAL LIBRARIES:
- BoundSentinel by Vexorian (http://www.wc3c.net/showthread.php?t=102576)
HOW TO USE:
- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
- Copy ALL that is written here (overwrite the existing texts in the trigger)
- Copy ALL the required libraries stated above
- Copy the Dummy unit and the custom ability OR make your own
- You MUST input or change the correct raw ID's (see below)
- To view raw ID, press CTRL+D in the object editor
*/
scope Bombardment
globals
//NOTE: The custom ability should be 'Rain of Fire', or change it if you like
//but the ability order should be equal to CHANNEL_ORDER_ID
private constant integer SPELL_ID = 'A01F' //raw code (rain of fire)
private constant integer COPTER_ID = 'h00J' //raw code
private constant integer BOMB_ID = 'h00O' //raw code
private constant integer CHANNEL_ORDER_ID = 852238 //rain of fire
private constant real FALL_SPEED = 10. //fall speed of the bomb
private constant real MOVE_SPEED = 15. //copter move speed
private constant real COPTER_HEIGHT = 300. //copter default height at creation time
private constant real CREATION_INTERVAL = 1.5 //interval for copter creation
private constant real COPTER_LIFE = 5.0 //life of copter after bomb is released
private constant real AOE = 300.//area of effect for damage
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
private constant string SFX = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
private rect Rct
endglobals
private function GetDamage takes integer i returns real
return 75.
endfunction
private function GetDuration takes integer i returns real
return 30.
endfunction
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private interface Bomb
unit caster
unit copter
real damage
real distance
real xSpell
real ySpell
endinterface
//===Bombs Explode
private struct BombExplode extends Bomb
unit bomb
real height
static method getDestructables takes nothing returns boolean
local destructable d = GetFilterDestructable()
if IsDestructableTree(d) then
call KillDestructable(d)
endif
set d = null
return false
endmethod
method periodic takes nothing returns nothing
local real x
local real y
local unit first
if .height > 0 then
set .height = .height - FALL_SPEED
call SetUnitFlyHeight(.bomb, .height, 0)
else
set x = GetUnitX(.bomb)
set y = GetUnitY(.bomb)
call DestroyEffect(AddSpecialEffect(SFX, x, y))
call MoveRectTo(Rct, x, y)
call EnumDestructablesInRect(Rct, function thistype.getDestructables, null)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, AOE, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.bomb)) or IsUnitType(first, UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(.bomb, first, .damage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
call KillUnit(.bomb)
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit b, real d, real h returns thistype
local thistype this = thistype.allocate()
set .bomb = b
set .damage = d
set .height = h
call .startPeriodic()
return this
endmethod
endstruct
//Copters Appear
private struct Copter extends Bomb
real angle
integer chk
method periodic takes nothing returns nothing
local unit bomb
if UnitAlive(.copter) then
call SetUnitPosition(.copter, GetUnitX(.copter)+MOVE_SPEED*Cos(.angle), GetUnitY(.copter)+MOVE_SPEED*Sin(.angle))
if .distance > 0 then
set .distance = .distance - MOVE_SPEED
elseif .chk==1 then
set .chk = 0
set bomb = CreateUnit(GetOwningPlayer(.copter), BOMB_ID, .xSpell, .ySpell, GetUnitFacing(.copter))
call SetUnitFlyHeight(bomb, COPTER_HEIGHT, 0)
call BombExplode.create(bomb, .damage, COPTER_HEIGHT)
call UnitApplyTimedLife(.copter, 'BTLF', COPTER_LIFE)
endif
else
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method create takes unit copter, real damage, real distance, real x, real y returns thistype
local thistype this = thistype.allocate()
set .copter = copter
set .damage = damage
set .angle = Atan2(y-GetUnitY(copter), x-GetUnitX(copter))
set .distance = distance
set .chk = 1
set .xSpell = x
set .ySpell = y
call .startPeriodic()
return this
endmethod
endstruct
//===Cast
private struct Bombardment extends Bomb
real xUnit
real yUnit
real duration
real creationgap
method periodic takes nothing returns nothing
local unit copter
if .duration > 0 and GetUnitCurrentOrder(.caster)==CHANNEL_ORDER_ID and UnitAlive(.caster) then
set .duration = .duration - T32_PERIOD
set .creationgap = .creationgap + T32_PERIOD
if .creationgap >= CREATION_INTERVAL then
set .creationgap = 0
set copter = CreateUnit(GetOwningPlayer(.caster), COPTER_ID, .xUnit, .yUnit, GetUnitFacing(.caster))
call SetUnitFlyHeight(copter, COPTER_HEIGHT, 0)
call Copter.create(copter, .damage, .distance, .xSpell, .ySpell)
set copter = null
endif
else
call IssueImmediateOrder(.caster, "stop")
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
private static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local integer level
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .xUnit = GetUnitX(.caster)
set .yUnit = GetUnitY(.caster)
set .xSpell = GetSpellTargetX()
set .ySpell = GetSpellTargetY()
set .duration = GetDuration(level)
set .damage = GetDamage(level)+GetDamage(level)
set .distance = SquareRoot((.xSpell-.xUnit) * (.xSpell-.xUnit) + (.ySpell-.yUnit) * (.ySpell-.yUnit))
set .creationgap = CREATION_INTERVAL
call .startPeriodic()
return this
endmethod
private static method onInit takes nothing returns nothing
set Rct = Rect(-AOE, -AOE, AOE, AOE)
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
call Preload(SFX)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope IceShot initializer init
globals
private constant integer SPELL_ID = 'A00D'
private constant integer DUMMY_SPELL_ID = 'A01P'
private constant real AOE = 600
endglobals
private function GetQty takes integer i returns integer
return 1 + i * 2
endfunction
private function Actions takes nothing returns nothing
local unit first
local unit u = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local integer qty = GetQty(level)
//! runtextmacro FOG_ADD("GetUnitX(target)", "GetUnitY(target)", "AOE")
if IsUnitEnemy(first, GetTriggerPlayer()) and first!=target and qty > 0 and FUN_OrganicUnits(first) then
set qty = qty - 1
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), first, GetUnitX(target), GetUnitY(target), DUMMY_SPELL_ID, OrderId("firebolt"), level)
endif
//! runtextmacro FOG_REMOVE()
set target = null
set u = null
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Freeze initializer init
globals
private constant integer SPELL_ID = 'A01M'
private constant real AOE = 300
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_COLD
private constant string SFX = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
private constant real INTERVAL = 0.1
private Table fr
endglobals
//4,6,8,10,12
private function GetDuration takes integer i returns real
return 2 + i * 2.
endfunction
//5,7,9,11,13
private function GetDamage takes integer i returns real
return 3 + i * 2.
endfunction
private struct Freeze
unit caster
unit target
real duration
real damage
real effinterval
private static method looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer this = LoadData(t)
if FUN_UnitAlive(.target) and .duration > 0 then
set .duration = .duration - INTERVAL
set .effinterval = .effinterval + INTERVAL
call UnitDamageTarget(.caster, .target, .damage, false, false, ATT, DAM, null)
if .effinterval > 0.8 then
set .effinterval = 0
call DestroyEffect(AddSpecialEffectTarget(SFX, .target, "origin"))
endif
//call BJDebugMsg(R2S(.duration))
else
call fr.remove(GetHandleId(.target))
call PauseUnit(.target, false)
call StopTimer(t)
call .deallocate()
endif
set t = null
endmethod
static method create takes unit u, unit tar, real dur, real dam returns thistype
local thistype this = thistype.allocate()
local timer t = GetTimer()
set .caster = u
set .target = tar
set .duration = dur
set .damage = dam*INTERVAL
set .effinterval = 0
call DestroyEffect(AddSpecialEffectTarget(SFX, tar, "origin"))
call PauseUnit(tar, true)
call SaveData(t, this)
call TimerStart(t, INTERVAL, true, function thistype.looper)
set t = null
return this
endmethod
endstruct
private function Actions takes nothing returns nothing
local unit first
local unit u = GetTriggerUnit()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
//! runtextmacro FOG_ADD("GetSpellTargetX()", "GetSpellTargetY()", "AOE")
if IsUnitEnemy(first, GetTriggerPlayer()) and FUN_OrganicUnits(first) then
if not fr.has(GetHandleId(first)) then
set fr[GetHandleId(first)] = 1
call Freeze.create(u, first, GetDuration(level), GetDamage(level))
endif
endif
//! runtextmacro FOG_REMOVE()
set u = null
endfunction
private function init takes nothing returns nothing
set fr = Table.create()
call RegisterSpellEffectEvent(SPELL_ID, function Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope FrostShield initializer init
globals
private constant integer SPELL_ID = 'A01X'
private constant integer DUMMY_SPELL_ID = 'A01U'
private constant integer AURA = 'B00C'
private constant integer BUFF = 'B00D' //frostarmor
endglobals
private function Cond takes nothing returns nothing
local unit attacker
local unit first
local integer level
if IsUnitEnemy(GetAttacker(), GetTriggerPlayer()) then
set attacker = GetAttacker()
if SpellLevel(attacker, AURA) and GetUnitAbilityLevel(attacker, BUFF)==0 then
set level = GetAuraLevel(attacker, SPELL_ID, AURA, 900)
//call BJDebugMsg(I2S(level))
if GetChance2(level) then
call MuiDummyCasters.hitTarget(GetOwningPlayer(attacker), attacker, GetUnitX(attacker), GetUnitY(attacker), DUMMY_SPELL_ID, OrderId("frostarmor"), level)
endif
endif
set attacker = null
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=12
//TESH.alwaysfold=0
scope MindControl initializer init
globals
private constant integer SPELL_ID = 'A00I'
private constant string SFX = "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"
private constant real INTERVAL = 0.1
private Table chk
endglobals
private struct MC
unit target
real duration
player owner
method GetDuration takes integer i returns real
return 3 + i * 2.
endmethod
private static method Looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer this = LoadData(t)
if .duration > 0 and FUN_UnitAlive(.target) then
set .duration = .duration - INTERVAL
else
call SetUnitOwner(.target, .owner, false)
call chk.remove(GetHandleId(.target))
call .deallocate()
call StopTimer(t)
endif
set t = null
endmethod
static method create takes nothing returns thistype
local thistype this
local timer t
local unit tar = GetSpellTargetUnit()
if not chk.has(GetHandleId(tar)) then
set chk[GetHandleId(tar)] = 1
set this = thistype.allocate()
set t = GetTimer()
set .target = tar
set .owner = GetOwningPlayer(tar)
set .duration = GetDuration(GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID))
call FUN_SpecialEffectTarget(tar, SFX, "origin")
call SaveData(t, this)
call SetUnitOwner(.target, GetTriggerPlayer(), false)
call TimerStart(t, INTERVAL, true, function thistype.Looper)
set t = null
else
call SimError(GetTriggerPlayer(), "You can't control this unit")
call IssueImmediateOrder(GetTriggerUnit(), "stop")
endif
set tar = null
return this
endmethod
endstruct
private function init takes nothing returns nothing
set chk = Table.create()
call RegisterSpellEffectEvent(SPELL_ID, function MC.create)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Seize initializer init
globals
private constant integer SPELL_ID = 'A00U'
private constant integer DUMMY_SPELL_ID = 'A00T'
private constant integer DUMMY_ID = 'h004'
endglobals
private function FilterThem takes unit u returns boolean
return FUN_OrganicUnits(u) and not IsUnitType(u, UNIT_TYPE_HERO) and GetUnitLevel(u) < 6
endfunction
private function Cond takes nothing returns nothing
local unit attacked
local unit attacker
local unit dummy
local integer level
if SpellLevel(GetTriggerUnit(), SPELL_ID) and IsUnitEnemy(GetAttacker(), GetTriggerPlayer()) and FilterThem(GetAttacker()) then
if GetRandomInt(0,100) < 11 then
set attacked = GetTriggerUnit()
set attacker = GetAttacker()
set level = GetUnitAbilityLevel(attacked, SPELL_ID)
set dummy = CreateUnit(GetTriggerPlayer(), DUMMY_ID, GetUnitX(attacked), GetUnitY(attacked), 0)
call UnitAddAbility(dummy, DUMMY_SPELL_ID)
call SetUnitAbilityLevel(dummy, DUMMY_SPELL_ID, level)
call IssueTargetOrder(dummy, "possession", attacker)
call UnitApplyTimedLife(attacker, 'BTLF', (level*15)+2)
set attacker = null
set attacked = null
set dummy = null
endif
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function Cond)
endfunction
endscope
//TESH.scrollpos=128
//TESH.alwaysfold=0
//Spell Name: Doppelganger v1.5
//Created by: Mckill2009
//===HOW TO USE:
//- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
//- The trigger name MUST be >>> Doppelganger (see the name below)
//- Copy ALL that is written here and overwrite the existing texts in the custom text
//- Copy the Dummy/custom abilities/buffs etc... to your object editor
//- Make sure you inputed the correct raw codes of the base spell/buffs/dummy etc...
//- If your raw code is different, you MUST CHANGE IT...
//- You can view the raw codes by pressing CTRL+D in the object editor
//- Examples of raw codes are 'A000', 'h000' etc...
//===REQUIRED VARIABLES:
// DPL_Hash = hashtable
// DPL_DPL_Group = group
// DPL_Timer = timer
// DPL_Portal = unit
// DPL_Counter = integer
//==========CONFIGURABLES==========
//===IMPORTANT NOTICE: Raw codes MUST BE CHANGED if your raw code has changed as indicated below
function DPL_SpellId takes nothing returns integer
return 'A00B' //the main spell
endfunction
function DPL_SleepId takes nothing returns integer
return 'A009' //the portal will cast this spell to enemy units
endfunction
function DPL_ImageCasterId takes nothing returns integer
return 'H008' //a dummy unit hero, this is the caster of the image
endfunction
function DPL_PortalId takes nothing returns integer
return 'h007' //raw code of the portal unit, it is recommended to use the Shimmering Portal
endfunction
function DPL_ItemId takes nothing returns integer
return 'I000' //this is an item which is given to the dummy hero
endfunction
function DPL_GetDuration takes integer i returns real
return 60. //the life of the portal
endfunction
constant function DPL_TimerInterval takes nothing returns real
return 0.1 //dont change
endfunction
constant function DPL_AoE takes nothing returns real
return 400. //the reach of the portal casting the sleep
endfunction
//==========END OF CONFIGURABLES==========
function DPL_LoopAction takes nothing returns nothing
local unit portal = GetEnumUnit()
local unit first
local integer portalID = GetHandleId(portal)
local real maxduration = LoadReal(udg_HASH, portalID, 1)
local real mindur = LoadReal(udg_HASH, portalID, 2)
if maxduration > 0 then
call SaveReal(udg_HASH, portalID, 1, maxduration - DPL_TimerInterval())
call SaveReal(udg_HASH, portalID, 2, mindur + DPL_TimerInterval())
if mindur >= 9 and (LoadInteger(udg_HASH, portalID, 3)==0) then
//setting the saved integer to 1 in order for this not to run again
//otherwise the add ability will always run
call SaveInteger(udg_HASH, portalID, 3, 1)
call UnitAddAbility(portal, DPL_SleepId())
elseif mindur > 9 then //it takes 9 seconds for the portal to animate it's birth
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(portal), GetUnitY(portal), DPL_AoE(), null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(portal, GetOwningPlayer(first)) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) and not IsUnitType(first, UNIT_TYPE_SLEEPING) and not IsUnitType(first, UNIT_TYPE_DEAD) then
call IssueTargetOrder(portal, "sleep", first)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
else
call KillUnit(portal)
call FlushChildHashtable(udg_HASH, portalID)
call GroupRemoveUnit(udg_DPL_Group, portal)
set udg_DPL_Counter = udg_DPL_Counter - 1
if udg_DPL_Counter == 0 then
call PauseTimer(udg_DPL_Timer)
endif
endif
set portal = null
endfunction
function DPL_CastOn takes unit u, integer spellId, integer portalId returns nothing
local real facing = GetUnitFacing(u) * bj_DEGTORAD
local real x = GetUnitX(u)+100*Cos(facing)
local real y = GetUnitY(u)+100*Sin(facing)
local integer portalID
local integer level = GetUnitAbilityLevel(u, spellId)
local unit portal = CreateUnit(GetTriggerPlayer(), portalId, x, y, facing)
set portalID = GetHandleId(portal)
call SetUnitAnimation(portal, "birth")
call SaveReal(udg_HASH, portalID, 1, DPL_GetDuration(level))
call SaveReal(udg_HASH, portalID, 2, 0) //mindur
call SaveInteger(udg_HASH, portalID, 3, 0) //this is used for checking only
call GroupAddUnit(udg_DPL_Group, portal)
set portal = null
endfunction
function DPL_GroupLooper takes nothing returns nothing
call ForGroup(udg_DPL_Group, function DPL_LoopAction)
endfunction
function DPL_CastCond takes nothing returns boolean
local unit u
local unit imagecaster
if GetSpellAbilityId()==DPL_SpellId() then
if udg_DPL_Counter == 0 then
call TimerStart(udg_DPL_Timer, DPL_TimerInterval(), true, function DPL_GroupLooper)
endif
set udg_DPL_Counter = udg_DPL_Counter + 1
call DPL_CastOn(GetTriggerUnit(), DPL_SpellId(), DPL_PortalId())
elseif GetSpellAbilityId()==DPL_SleepId() then
set u = GetSpellTargetUnit()
set imagecaster = CreateUnit(GetTriggerPlayer(), DPL_ImageCasterId(), GetUnitX(u), GetUnitY(u), 0)
call UnitApplyTimedLife(imagecaster, 'BTLF', 1.0)
call UnitUseItemTarget(imagecaster, UnitAddItemById(imagecaster, DPL_ItemId()), u)
set u = null
set imagecaster = null
endif
return false
endfunction
function InitTrig_Doppelganger takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function DPL_CastCond)
set t = null
//set udg_DPL_Hash = InitHashtable() //hashtable
//Preloading
set bj_lastCreatedUnit = CreateUnit(Player(15), DPL_ImageCasterId(),0,0,0)
call UnitAddAbility(bj_lastCreatedUnit, DPL_SleepId())
call RemoveUnit(bj_lastCreatedUnit)
set bj_lastCreatedUnit = CreateUnit(Player(15), DPL_PortalId(),0,0,0)
call RemoveUnit(bj_lastCreatedUnit)
endfunction
//TESH.scrollpos=18
//TESH.alwaysfold=0
/*
=====Field Medic
=====by Mckill2009
REQUIRES:
- Table by Bribe
- TimerUtils by Vexorian (not the version 2.0)
- RegisterPlayerUnitEvent by Magtheridon
- SpellEffectEvent by Bribe
- Simerror by Vexorian
HOW TO USE/INSTALL:
- Make a trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
- Copy ALL that is written here and overwrite the existing texts in the custom text
- Copy the necessary libraries (as mentioned on top - REQUIRES)
- Replace the raw code as stated below if necessary...
- You can view the raw codes by pressing CTRL+B in the object editor
- It's recommended to make a custom ability based on rejuvenation
DESCRIPTION:
Heals a target friendly non-mechanical wounded unit but drains caster's mana. Stackable up to 3 units.
|cffffcc00Level 1|r - Heals 1.0 hp/sec, drains 3.0 mana/sec.
|cffffcc00Level 2|r - Heals 1.5 hp/sec, drains 2.5 mana/sec.
|cffffcc00Level 3|r - Heals 2.0 hp/sec, drains 2.0 mana/sec.
|cffffcc00Level 4|r - Heals 2.5 hp/sec, drains 1.5 mana/sec.
|cffffcc00Level 5|r - Heals 3.0 hp/sec, drains 1.0 mana/sec.
|cffffcc00Requires:|r 100 mana to cast.
|cffffcc00Lasts while:|r Caster and target is alive, and life of target is not full, and mana of caster is more than the required value.
*/
scope FieldMedic
globals
private constant integer SPELL_ID = 'A01N' //rejuvenation (recommended, for AI purposes)
private constant real INTERVAL = 0.1
private constant string SFX = "Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl"
private constant string REQ_MANA = "not enough mana"
private constant string MAX_UNIT = "can't heal more than " //there should be a space at the end
private constant string SFX_ATT = "chest" //attachment of SFX
//NEVER TOUCH THE TABLE!
private Table casterH
endglobals
private struct FieldMedic
unit caster
unit target
real heal
real mana
real tmaxhealth
effect sfx
private static constant real requiredmana = 100.
private static constant integer maxheal = 3
private method getheal takes integer i returns real
return 0.5 + i * 0.5
endmethod
private method manareduction takes integer i returns real
return 3.5 - (i * 0.5)
endmethod
private method unitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endmethod
private static method looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer this = GetTimerData(t)
local integer uID = GetHandleId(.caster)
local real manastate
local real targetlife
if unitAlive(.caster) then
set targetlife = GetWidgetLife(.target)
set manastate = GetUnitState(.caster, UNIT_STATE_MANA)
if unitAlive(.target) and (.tmaxhealth > targetlife) and (manastate > .requiredmana) then
//heals the target
call SetWidgetLife(.target, targetlife + .heal)
//reduce mana for caster
call SetUnitState(.caster, UNIT_STATE_MANA, manastate - .mana)
else
//reduces maxheal if target dies
call DestroyEffect(.sfx)
set casterH[uID] = casterH[uID]-1
call ReleaseTimer(t)
call .deallocate()
endif
else
//remove everything when caster dies, recycle timer
call DestroyEffect(.sfx)
call casterH.remove(uID)
call ReleaseTimer(t)
call .deallocate()
endif
set t = null
endmethod
private static method create takes nothing returns thistype
local thistype this
local unit u = GetTriggerUnit()
local timer t
local integer tID
local integer uID
local integer level
if GetUnitState(u, UNIT_STATE_MANA) > .requiredmana then
set uID = GetHandleId(u)
if (.maxheal) > (casterH[uID]) then
set casterH[uID] = casterH[uID]+1
set this = thistype.allocate()
set t = NewTimer()
set tID = GetHandleId(t)
set level = GetUnitAbilityLevel(u, SPELL_ID)
set casterH.unit[uID] = u
set .caster = u
set .target = GetSpellTargetUnit()
set .tmaxhealth = GetUnitState(.target, UNIT_STATE_MAX_LIFE)
set .heal = getheal(level)*INTERVAL
set .mana = manareduction(level)*INTERVAL
set .sfx = AddSpecialEffectTarget(SFX, .target, SFX_ATT)
call SetTimerData(t, this)
call TimerStart(t, INTERVAL, true, function thistype.looper)
set t = null
//call BJDebugMsg(I2S(casterH[uID]))
else
call IssueImmediateOrder(u, "stop")
call SimError(GetTriggerPlayer(), MAX_UNIT+I2S(maxheal)+" units")
endif
else
call IssueImmediateOrder(u, "stop")
call SimError(GetTriggerPlayer(), REQ_MANA)
endif
set u = null
return this
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
set casterH = Table.create()
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope MedicalPowa
globals
private constant integer SPELL_ID = 'A015' //healing wave
private constant string SFX = "Objects\\Spawnmodels\\Human\\FragmentationShards\\FragBoomSpawn.mdl"
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_FIRE
endglobals
private struct MedicalPowa extends array
private method getdamage takes integer i returns real
return 20 + i * 10.
endmethod
private static method create takes nothing returns thistype
local thistype this = 0
local unit u = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local unit first
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
local real damage = getdamage(level)
//! runtextmacro FOG_ADD("GetUnitX(target)", "GetUnitY(target)", "300")
if FUN_UnitAlive(first) and IsUnitEnemy(first, GetTriggerPlayer()) and FUN_OrganicUnits(first) then
call FUN_SpecialEffectTarget(first, SFX, "chest")
call UnitDamageTarget(u, first, damage, false, false, ATT, DAM, null)
endif
//! runtextmacro FOG_REMOVE()
set u = null
set target = null
return this
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
endmethod
endstruct
endscope
//TESH.scrollpos=7
//TESH.alwaysfold=0
scope Overload initializer init
globals
private constant integer PASSIVE_ID = 'A016'
private constant integer FM_SPELL_ID = 'A01N' //rejuvenation
private constant integer MP_SPELL_ID = 'A015' //healing wave
private constant integer DUMMY_SPELL_ID = 'A013' //use firebolt with negative values
private constant integer MAX_OVERLOAD = 5
private Table overL
endglobals
private function Actions takes unit u, unit target, integer abilID returns nothing
local unit first
local integer uID = GetHandleId(u)
local integer level
set overL[uID] = overL[uID]+1
if (overL[uID]) > (MAX_OVERLOAD) then
set level = GetUnitAbilityLevel(u, abilID)
call overL.remove(uID)
//! runtextmacro FOG_ADD("GetUnitX(target)", "GetUnitY(target)", "800")
if FUN_UnitAlive(first) and IsUnitAlly(first, GetOwningPlayer(u)) and FUN_OrganicUnits(first) then
if GetWidgetLife(first) < GetUnitState(first, UNIT_STATE_MAX_LIFE) then
call MuiDummyCasters.hitTarget(GetOwningPlayer(u), first, GetUnitX(target), GetUnitY(target), DUMMY_SPELL_ID, OrderId("firebolt"), level)
endif
endif
//! runtextmacro FOG_REMOVE()
endif
endfunction
private function Cond takes nothing returns nothing
if GetUnitAbilityLevel(GetTriggerUnit(), PASSIVE_ID) > 0 then
call Actions(GetTriggerUnit(), GetSpellTargetUnit(), GetSpellAbilityId())
endif
endfunction
private function init takes nothing returns nothing
call PreloadSpell(DUMMY_SPELL_ID)
call RegisterSpellEffectEvent(FM_SPELL_ID, function Cond)
call RegisterSpellEffectEvent(MP_SPELL_ID, function Cond)
set overL = Table.create()
endfunction
endscope
//TESH.scrollpos=93
//TESH.alwaysfold=0
/*
=====Mechanical Reboot
=====by Mckill2009
REQUIRES:
- Table by Bribe
- TimerUtils by Vexorian (not the version 2.0) XXXX
- RegisterPlayerUnitEvent by Magtheridon
- SpellEffectEvent by Bribe
- DestructableLib by PitzerMike
HOW TO USE/INSTALL:
- Make a trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
- Copy ALL that is written here and overwrite the existing texts in the custom text
- Copy the necessary libraries (as mentioned on top - REQUIRES)
- Replace the raw code as stated below if necessary...
- You can view the raw codes by pressing CTRL+B in the object editor
DESCRIPTION:
Yamai reboots himself by not moving, causing to regenerate 5hp per second and creates an image of himself.
The image will explode after 45 seconds or when it's life is zero, dealing 400 damage to a large area.
The damage affects all units including allies and can level trees.
*/
scope MechanicalReboot
globals
private constant integer SPELL_ID = 'A018' //roar
private constant integer AVATAR_ID = 'h001' //siege engine
private constant string EXPLODE = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
private constant string HEAL = "Abilities\\Spells\\Orc\\AncestralSpirit\\AncestralSpiritCaster.mdl"
private constant string SFX = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
private constant real INTERVAL = 0.5
private constant attacktype ATT = ATTACK_TYPE_CHAOS
private constant damagetype DAM = DAMAGE_TYPE_NORMAL
//NEVER TOUCH THESE!
private rect R
private Table avr
endglobals
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function KillTrees takes nothing returns boolean
local destructable d = GetFilterDestructable()
if IsDestructableTree(d) then
call KillDestructable(d)
endif
set d = null
return false
endfunction
private struct MechanicalReboot
unit caster
unit avatar
real duration
real life
integer check
private method getDamage takes integer i returns real
return 50.
endmethod
private method getHeal takes integer i returns real
return 5.0
endmethod
private method getDuration takes integer i returns real
return 45.
endmethod
private static method looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer this = LoadData(t)
//call BJDebugMsg(R2S(.duration))
if .duration > 0 and UnitAlive(.caster) and UnitAlive(.avatar) then
set .duration = .duration - INTERVAL
call SetWidgetLife(.caster, GetWidgetLife(.caster)+.life)
call DestroyEffect(AddSpecialEffectTarget(HEAL, .caster, "overhead"))
if .check==0 then
set .check = 1
call PauseUnit(.caster, true)
endif
else
call SetUnitPathing(.caster, true)
call SetUnitAnimation(.caster, "stand")
call PauseUnit(.caster, false)
call KillUnit(.avatar)
call StopTimer(t)
call .deallocate()
endif
set t = null
endmethod
private static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local timer t = GetTimer()
local integer tID = GetHandleId(t)
local integer level
local real facing
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(.caster, SPELL_ID)
set facing = GetUnitFacing(.caster)
set .avatar = CreateUnit(GetTriggerPlayer(), AVATAR_ID, GetUnitX(.caster)+250*Cos(facing*0.0174533),GetUnitY(.caster)+250*Sin(facing*0.0174533),facing)
set .duration = getDuration(level)
set .life = getHeal(level)
set .check = 0
set avr.real[GetHandleId(.avatar)] = getDamage(level)
call DestroyEffect(AddSpecialEffectTarget(SFX, .avatar, "origin"))
call SetUnitPathing(.caster, false)
call SetUnitAnimation(.caster, "spell")
call SaveData(t, this)
call TimerStart(t, INTERVAL, true, function thistype.looper)
set t = null
return this
endmethod
private static method avatarDies takes nothing returns nothing
local unit u
local unit first
local real x
local real y
local real x1
local real y1
local real damage
local integer i
if GetUnitTypeId(GetTriggerUnit())==AVATAR_ID then
set u = GetTriggerUnit()
set x = GetUnitX(u)
set y = GetUnitY(u)
set damage = avr.real[GetHandleId(u)]
set i = 0
loop
set i = i+1
exitwhen i==8
set x1 = x+300*Cos(i)
set y1 = y+300*Sin(i)
call DestroyEffect(AddSpecialEffect(EXPLODE,x1,y1))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x1, y1, 300, null)
call MoveRectTo(R,x1,y1)
call EnumDestructablesInRect(R,function KillTrees,null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) then
call UnitDamageTarget(u,first,damage,false,false,ATT,DAM,null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endloop
call avr.remove(GetHandleId(u))
set u = null
endif
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.avatarDies)
set avr = Table.create()
set R = Rect(-300,-300,300,300)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope FallenCorpseBombardment
//uses TimerLooper v2.0
globals
private constant integer SPELL_ID = 'A02M' //Blizzard
private constant integer CORPSE_ID = 'h00M'
private constant integer SLOW_ID = 'S002'
private constant real HIT_AOE = 128.
private constant string SFX = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodLarge0.mdl"
private constant attacktype ATT = ATTACK_TYPE_NORMAL
private constant damagetype DAM = DAMAGE_TYPE_NORMAL
endglobals
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private struct FCB
unit corpse
real damage
real height
private static real fallspeed = 15.
private method periodic takes nothing returns nothing
local unit first
if .height > 0 then
set .height = .height - fallspeed
call SetUnitFlyHeight(corpse, .height, 0)
else
//do damage here
call DestroyEffect(AddSpecialEffect(SFX,GetUnitX(.corpse),GetUnitY(.corpse)))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.corpse), GetUnitY(.corpse), HIT_AOE, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.corpse)) then
call UnitDamageTarget(.corpse, first, .damage, false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
call KillUnit(.corpse)
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
static method create takes unit c, real d returns thistype
local thistype this = thistype.allocate()
set .corpse = c
set .damage = d
set .height = GetUnitFlyHeight(c)
call .startPeriodic()
return this
endmethod
endstruct
private struct FallenCorpseBombardment
unit caster
unit dummy
real xLoc
real yLoc
real damage
real duration
real interval
private method getdamage takes integer i returns real
return i * 15.
endmethod
private method getduration takes integer i returns real
return 10.
endmethod
private method periodic takes nothing returns nothing
local unit corpse
local integer order = GetUnitCurrentOrder(.caster) //should be blizzard, 852089
local real x
local real y
local integer ran
local real angle
if .duration > 0 and UnitAlive(.caster) and order==852089 then
set .duration = .duration - T32_PERIOD
set .interval = .interval + T32_PERIOD
if .interval > 0.4 then
call SetUnitAnimationByIndex(.caster, 3)
set .interval = 0
set ran = GetRandomInt(75,350)
set angle = GetRandomReal(0,6)
set x = .xLoc+ran*Cos(angle)
set y = .yLoc+ran*Sin(angle)
set corpse = CreateUnit(GetOwningPlayer(.dummy), CORPSE_ID, x,y,0)
call SetUnitFlyHeight(corpse, 700., 0)
call FCB.create(corpse,.damage)
set corpse = null
endif
else
call IssueImmediateOrder(.caster, "stop")
call SetUnitAnimationByIndex(.caster, 0)
call KillUnit(.dummy)
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
private static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local integer level = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)
set .caster = GetTriggerUnit()
set .xLoc = GetSpellTargetX()
set .yLoc = GetSpellTargetY()
set .duration = getduration(level)
set .damage = getdamage(level)
set .dummy = CreateUnit(GetTriggerPlayer(), 'h004', xLoc, yLoc, 0)
set .interval = 0
call UnitAddAbility(.dummy,SLOW_ID)
call SetUnitAbilityLevel(.dummy,SLOW_ID,level)
call PauseUnit(.dummy, true)
call .startPeriodic()
return this
endmethod
private static method onInit takes nothing returns nothing
call PreloadUnit(CORPSE_ID)
call PreloadSpell(SLOW_ID)
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
endmethod
endstruct
endscope
//TESH.scrollpos=60
//TESH.alwaysfold=0
scope WindOfDecay
//uses T32x
globals
private constant integer SPELL_ID = 'A01O' //Carrion Swarn
private constant integer WIND_ID = 'h003'
private constant integer MAX_AOE = 400
private constant string SFX = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
private constant attacktype ATT = ATTACK_TYPE_MAGIC
private constant damagetype DAM = DAMAGE_TYPE_FIRE
endglobals
private struct WindOfDecay
unit caster
unit tornado
real duration
real scale
real interval
real size
real aoe
real damage
real maxdamage
integer check
private static real intr = 0.1
private static real dmginc = 0.1
private method unitAlive takes unit u returns boolean
return not IsUnitType(u,UNIT_TYPE_DEAD)
endmethod
private method getMaxDamage takes integer i returns real
return 0.15 + i * 0.1
endmethod
private method getSize takes integer i returns real
return 1 + i * 1.
endmethod
private method getDuration takes integer i returns real
return 2 + i * 5.
endmethod
private method periodic takes nothing returns nothing
local unit first
if .size > .scale then
set .interval = .interval + T32_PERIOD
if .interval > .intr then
set .interval = 0
set .scale = .scale + T32_PERIOD
if MAX_AOE > .aoe then
//increases the AOE
set .aoe = .aoe + 20
endif
call SetUnitScale(.tornado,.scale,.scale,.scale)
endif
if .maxdamage > .damage then
set .damage = .damage + T32_PERIOD
endif
elseif .check==0 then
set .check = 1
call UnitApplyTimedLife(.tornado,'BTLF',5.0)
endif
if unitAlive(.tornado) then
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.tornado), GetUnitY(.tornado), .aoe, null)
//call BJDebugMsg(R2S(.damage))
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if unitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.tornado)) then
call UnitDamageTarget(.tornado,first,.damage,false,false,ATT,DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
else
call .stopPeriodic()
call .deallocate()
endif
endmethod
implement T32x
private static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local integer level
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .tornado = CreateUnit(GetTriggerPlayer(),WIND_ID,GetSpellTargetX(),GetSpellTargetY(),0)
set .duration = getDuration(level)
set .size = getSize(level) //max size to reach
set .maxdamage = getMaxDamage(level)
set .damage = 0
set .scale = 0
set .interval = 0
set .check = 0
set .aoe = 50
call SetUnitScale(.tornado,0,0,0)
call SetUnitFlyHeight(.tornado,0,0)
call .startPeriodic()
return this
endmethod
private static method onInit takes nothing returns nothing
call PreloadUnit(WIND_ID)
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope WingsOfLife
//uses TimerLooper v2.0
globals
private constant integer SPELL_ID = 'A01R' //roar
private constant integer DOUBLE_DAM_ID = 'A02O' //critical strike
private constant integer ADD_DAM_ID = 'A02P' //claws of attack
private constant real INTERVAL = 0.05
private Table wol
endglobals
private struct WingsOfLife
unit caster
real duration
private method getDuration takes integer i returns real
return 20.
endmethod
private static method looper takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer this = LoadData(t)
local real maxlife
if .duration > 0 and not IsUnitType(.caster, UNIT_TYPE_DEAD) then
set .duration = .duration - INTERVAL
set maxlife = GetUnitState(.caster, UNIT_STATE_MAX_LIFE)
if GetWidgetLife(.caster) < maxlife then
call SetWidgetLife(.caster, maxlife)
endif
else
call UnitRemoveAbility(.caster,DOUBLE_DAM_ID)
call UnitRemoveAbility(.caster,ADD_DAM_ID)
call wol.remove(GetHandleId(.caster))
call StopTimer(t)
call .deallocate()
endif
set t = null
endmethod
private static method create takes nothing returns thistype
local thistype this
local unit u = GetTriggerUnit()
local timer t
local integer tID
local integer level
if not wol.has(GetHandleId(u)) then
call BJDebugMsg("OK")
set wol[GetHandleId(u)] = 1
set this = thistype.allocate()
set t = GetTimer()
set tID = GetHandleId(t)
set level = GetUnitAbilityLevel(u, SPELL_ID)
set .caster = u
set .duration = getDuration(level)
call SaveData(t, this)
call UnitAddAbility(u,DOUBLE_DAM_ID)
call UnitAddAbility(u,ADD_DAM_ID)
call TimerStart(t,INTERVAL,true,function thistype.looper)
set t = null
endif
set u = null
return this
endmethod
private static method onInit takes nothing returns nothing
call PreloadSpell(DOUBLE_DAM_ID)
call PreloadSpell(ADD_DAM_ID)
call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
set wol = Table.create()
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Garlamesh
//uses Physical Damage Detection Engine, Table
globals
private constant integer SPELL_ID = 'A03E' //howl of terror
private constant string SFX_GOLD = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
private constant string SFX_HAND = "Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl"
private Table c
endglobals
private function GetDuration takes integer i returns real
return 20. //10+i*10.
endfunction
private function GetDamage takes real dam, integer level returns real
return (level*0.1)*dam
endfunction
private function GetGold takes integer i returns integer
return 5*i
endfunction
private struct GM extends array
unit caster
effect sfx
private static group g = CreateGroup()
implement CTL
local integer id
implement CTLExpire
set id = GetHandleId(.caster)
if UnitAlive(.caster) and c.real[id] > 0 then
set c.real[id] = c.real[id]-0.03125
else
call GroupRemoveUnit(g, .caster)
call DestroyEffect(.sfx)
set .sfx = null
set .caster = null
call .destroy()
endif
implement CTLNull
implement CTLEnd
static method cast takes nothing returns nothing
local thistype this = create()
local integer id
local integer level
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(.caster, SPELL_ID)
set id = GetHandleId(.caster)
if IsUnitInGroup(.caster, g) then
set c.real[id] = c.real[id]+GetDuration(level)
else
set c.real[id] = GetDuration(level)
set .sfx = AddSpecialEffectTarget(SFX_HAND, .caster, "hand")
endif
call GroupAddUnit(g, .caster)
set c[id] = level
endmethod
static method onDam takes nothing returns nothing
local integer id
if damageType==PHYSICAL then
if IsUnitInGroup(source, g) then
set amount = GetDamage(amount, c[GetHandleId(source)])
call UnitDamageTarget(source, target, amount, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
endif
endif
endmethod
static method deathEvent takes nothing returns nothing
local unit killing = GetKillingUnit()
local unit u
if IsUnitInGroup(killing, g) then
if IsUnitEnemy(killing, GetTriggerPlayer()) and (GetRandomInt(0,100)<30) then
call SetPlayerState(GetOwningPlayer(killing), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetOwningPlayer(killing), PLAYER_STATE_RESOURCE_GOLD)+GetGold(c[GetHandleId(killing)]))
call DestroyEffect(AddSpecialEffectTarget(SFX_GOLD, GetTriggerUnit(), "overhead"))
endif
endif
set killing = null
endmethod
static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.deathEvent)
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
call AddDamageHandler(function thistype.onDam)
set c = Table.create()
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Invoke
//uses KnockBackMe
globals
private constant integer SPELL_ID = 'A03W' //carrion swarm
private constant integer WARRIOR_ID = 'nsog' //skeleton warrior
private constant string SFX_RAISE = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl"
private constant string SFX_BANG = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
private constant string SFX_KNOCK = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
private constant attacktype ATK = ATTACK_TYPE_NORMAL
private constant damagetype DAM = DAMAGE_TYPE_NORMAL
private integer array abil
endglobals
private function GetDamage takes integer level returns real
return 10*level+10. //20,30,40,50,60
endfunction
private function Pick takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_FLYING)
endfunction
private struct IN
unit caster
real x
real y
real angle
integer level
group g
private static real Damage
private static unit TempU
static method enume takes nothing returns nothing
local unit u = GetEnumUnit()
call DestroyEffect(AddSpecialEffect(SFX_BANG, GetUnitX(u), GetUnitY(u)))
call UnitDamageTarget(TempU, u, Damage, false, false, ATK, DAM, null)
set u = null
endmethod
static method doo takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local unit warrior
local integer ran1 = GetRandomInt(1,5)
local integer ran2
set Damage = GetDamage(.level)
set TempU = .caster
call ForGroup(.g, function thistype.enume)
call DestroyEffect(AddSpecialEffect(SFX_RAISE, .x, .y))
set warrior = CreateUnit(GetOwningPlayer(.caster), WARRIOR_ID, .x, .y, .angle)
call SetUnitAnimation(warrior, "birth")
call DestroyGroup(.g)
call UnitAddAbility(warrior, abil[ran1])
loop
set ran2 = GetRandomInt(1,5)
exitwhen ran1!=ran2
endloop
call UnitAddAbility(warrior, abil[ran2])
call UnitApplyTimedLife(warrior, 'BTLF', 40)
set .g = null
set .caster = null
set warrior = null
call ReleaseTimer(GetExpiredTimer())
endmethod
static method cast takes nothing returns nothing
local thistype this = allocate()
local unit first
set .caster = GetTriggerUnit()
set .level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .x = GetSpellTargetX()
set .y = GetSpellTargetY()
set .g = CreateGroup()
set .angle = (Atan2(GetUnitY(.caster)-.y, GetUnitX(.caster)-.x)*bj_RADTODEG)+180
call DestroyEffect(AddSpecialEffect(SFX_BANG, .x, .y))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, 500, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(first, GetTriggerPlayer()) and Pick(first) then
call GroupAddUnit(.g, first)
call KM.knockUnit(first, Atan2(GetUnitY(first)-.y, GetUnitX(first)-.x), 300, 30, SFX_KNOCK)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
call TimerStart(NewTimerEx(this), 1.5, false, function thistype.doo)
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
set abil[1] = 'ACcr' //cripple
set abil[2] = 'ACcs' //curse
set abil[3] = 'ACdc' //death coil
set abil[4] = 'ACrd' //raise dead
set abil[5] = 'ACls' //lightning shield
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope ShamanicFury
//uses Physical Damage Detection Engine, Table, MuiDummyCasters
globals
private constant integer SPELL_ID = 'gnoP' //passive
private constant integer DUMMY_ID = 'h004'
private constant integer DUMMY_SPELL_ID = 'shfu' //bloodlust
private constant integer BUFF_ID = 'sfuB'
private constant integer MAX = 2
private constant real AOE = 500.
private Table c
endglobals
private function GetChance takes integer level returns integer
return 10*level+10
endfunction
private struct SF extends array
static method onDam takes nothing returns nothing
local integer id
local integer level
local unit first
if damageType==PHYSICAL then
set level = GetUnitAbilityLevel(source, SPELL_ID)
if level > 0 then
set id = GetHandleId(source)
set c[id] = c[id]+1
if c[id]==MAX then
if GetRandomInt(0,100) < GetChance(level) then
//! runtextmacro FOG_ADD("GetUnitX(source)", "GetUnitY(source)", "AOE")
if UnitAlive(first) and not IsUnitEnemy(first, GetOwningPlayer(source)) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) and GetUnitAbilityLevel(first, BUFF_ID)==0 then
call MuiDummyCasters.hitTarget(GetOwningPlayer(first), first, 0, 0, DUMMY_SPELL_ID, 852101, level)
endif
//! runtextmacro FOG_REMOVE()
endif
set c[id] = 0
endif
endif
endif
endmethod
static method deathEvent takes nothing returns nothing
local unit u = GetTriggerUnit()
if GetUnitAbilityLevel(u, SPELL_ID) > 0 then
set c[GetHandleId(u)] = 0
endif
set u = null
endmethod
static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.deathEvent)
call AddDamageHandler(function thistype.onDam)
set c = Table.create()
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Sacrifice
globals
private constant integer SPELL_ID = 'gnoU'
private constant integer DUMMY_SMALL = 'h004'
private constant integer COUNT = 12 //means 6
private constant string SFX_KILL = "Abilities\\Spells\\Undead\\DarkRitual\\DarkRitualTarget.mdl"
private constant string SFX_HEAL = "Abilities\\Spells\\Undead\\DarkRitual\\DarkRitualCaster.mdl"
private constant string SFX_DAM = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
private constant string SFX_DUMMY = "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl"
private constant real AOE = 500.
private constant real SPIN_SPEED = 0.1
private constant real OFFSET = 80. //minimum
private real CenterOffset
private real AoeDamage
endglobals
private function GetDamage takes integer level returns real
return 50.
endfunction
private function GetDuration takes integer level returns real
return 10. //30.
endfunction
private struct Spin extends array
unit child
real damage
real interval
implement CTL
local unit first
implement CTLExpire
if not IsUnitType(.child, UNIT_TYPE_DEAD) then
if GetUnitFlyHeight(.child) < 80 then
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.child), GetUnitY(.child), AoeDamage, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if not IsUnitType(first, UNIT_TYPE_DEAD) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) then
if IsUnitEnemy(first, GetOwningPlayer(.child)) then
call UnitDamageTarget(.child, first, .damage, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
set .interval = .interval+0.03125
if .interval >0.3 then
set .interval = 0
call DestroyEffect(AddSpecialEffectTarget(SFX_DAM, first, "origin"))
endif
else
call SetWidgetLife(first, GetWidgetLife(first)+.damage)
set .interval = .interval+0.03125
if .interval >0.3 then
set .interval = 0
call DestroyEffect(AddSpecialEffectTarget(SFX_HEAL, first, "origin"))
endif
endif
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
else
set .child = null
call .destroy()
endif
implement CTLNull
implement CTLEnd
static method childSet takes unit ch, real dam returns nothing
local thistype this = create()
set .child = ch
set .damage = dam*0.03125
set .interval = 0
endmethod
static method onCast takes unit u, unit target returns nothing
local real angle
local real damage
local real offset
local real offset2
local real offset3
local real xTar
local real yTar
local integer i
local integer level
local unit dum
local Vortex v
if GetUnitState(u, UNIT_STATE_MAX_LIFE)==GetWidgetLife(u) then
call IssueImmediateOrder(u, "stop")
call SimError(GetTriggerPlayer(), "life already full")
elseif IsUnitType(target, UNIT_TYPE_HERO) then
call IssueImmediateOrder(u, "stop")
call SimError(GetTriggerPlayer(), "can't target heroes")
else
set xTar = GetUnitX(target)
set yTar = GetUnitY(target)
set angle = Atan2(yTar-GetUnitY(u), xTar-GetUnitX(u))*bj_RADTODEG
set i = 0
set offset = 0
set offset2 = 0
set level = GetUnitAbilityLevel(u, SPELL_ID)
loop
if offset < CenterOffset then
set offset = offset + OFFSET
set dum = CreateUnit(GetOwningPlayer(u), DUMMY_SMALL, xTar+offset*Cos(angle), yTar+offset*Sin(angle), 0)
set v = v.spin(dum, xTar, yTar, true)
set v.offset = offset
else
set offset2 = offset2 - OFFSET
set dum = CreateUnit(GetOwningPlayer(u), DUMMY_SMALL, xTar+offset2*Cos(angle), yTar+offset2*Sin(angle), 0)
set v = v.spin(dum, xTar, yTar, true)
set v.offset = offset2
endif
call thistype.childSet(dum, GetDamage(level))
set v[800] = 2.0
set v.angle = angle
set v.duration = GetDuration(level)
set v.speed = SPIN_SPEED
set v.minHeight = 75
set v.effect = SFX_DUMMY
set v.scale = 2
set dum = null
set i = i+1
exitwhen i==COUNT
endloop
set v.speed = 0.1
call SetWidgetLife(u, GetWidgetLife(u)+GetWidgetLife(target))
call KillUnit(target)
call DestroyEffect(AddSpecialEffectTarget(SFX_HEAL, u, "origin"))
call DestroyEffect(AddSpecialEffectTarget(SFX_KILL, target, "origin"))
endif
endmethod
static method cast takes nothing returns nothing
if GetSpellAbilityId()==SPELL_ID then
call thistype.onCast(GetTriggerUnit(), GetSpellTargetUnit())
endif
endmethod
static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function thistype.cast)
set CenterOffset = (COUNT/2.0)*OFFSET
set AoeDamage = OFFSET-10
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope HowlingWail
globals
private constant integer SPELL_ID = 'tor1'
private constant integer DUMMY_ID = 'h004'
private constant string SFX = "Abilities\\Weapons\\WingedSerpentMissile\\WingedSerpentMissile.mdl"
private constant real AOE = 300.
private constant real SPEED = 20.
private constant real MAX_DISTANCE = 700
private constant real CREATION_INTERVAL = 1.
private constant real DURATION = 20.
private constant integer MAX_MISSILE = 8
private group G = CreateGroup()
endglobals
private function GetDuration takes integer level returns real
return 3.*level+2 //5,8,11,14,17
endfunction
struct Ret extends array
unit u
real dur
real in
real xmap
real ymap
implement CTLExpire
if not IsUnitType(.u, UNIT_TYPE_DEAD) and .dur > 0 then
set .dur = .dur - 0.03125
set .in = .in + 0.03125
if .in > 1.0 then
set .in = 0
call IssuePointOrder(u, "move", .xmap, .ymap)
endif
else
call GroupRemoveUnit(G, .u)
set .u = null
call .destroy()
endif
implement CTLEnd
static method ret takes unit u, real d returns nothing
local thistype this = create()
set .u = u
set .dur = d
set .in = 0
set .xmap = GetRandomReal(GetRectMinX(bj_mapInitialPlayableArea), GetRectMaxX(bj_mapInitialPlayableArea))
set .ymap = GetRandomReal(GetRectMinY(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea))
call IssuePointOrder(u, "move", .xmap, .ymap)
endmethod
endstruct
struct HW extends array
unit caster
unit wave
effect sfx
real a //angle
real dist
real duration
real scale
private static real scaling = SPEED*0.01
implement CTL
local unit first
implement CTLExpire
if MAX_DISTANCE > .dist and GetUnitCurrentOrder(.caster)==852183 then
set .scale = .scale + scaling
set .dist = .dist + SPEED
call SetUnitPosition(.wave, GetUnitX(.wave)+SPEED*Cos(.a), GetUnitY(.wave)+SPEED*Sin(.a))
call SetUnitScale(.wave, .scale, .scale, .scale)
//! runtextmacro FOG_ADD("GetUnitX(.wave)", "GetUnitY(.wave)", "AOE")
if not IsUnitType(first, UNIT_TYPE_DEAD) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) and IsUnitEnemy(first, GetOwningPlayer(.wave)) then
if not IsUnitInGroup(first, G) then
call GroupAddUnit(G, first)
call Ret.ret(first, .duration)
endif
endif
//! runtextmacro FOG_REMOVE()
else
call DestroyEffect(.sfx)
call KillUnit(.wave)
set .sfx = null
set .wave = null
call .destroy()
endif
implement CTLNull
implement CTLEnd
static method make takes unit u, unit w, real angle returns nothing
local thistype this = create()
set .caster = u
set .wave = w
set .scale = 0
set .sfx = AddSpecialEffectTarget(SFX, .wave, "origin")
set .a = angle*bj_DEGTORAD
set .dist = 0
set .duration = GetDuration(GetUnitAbilityLevel(u, SPELL_ID))
call SetUnitScale(w, 0, 0, 0)
endmethod
endstruct
struct HWCast
unit u
real dur
implement DTloop
local unit mis
local integer i = 0
local real a = 0
local real a2 = 360/MAX_MISSILE
if .dur > 0 and GetUnitCurrentOrder(.u)==852183 then
set .dur = .dur - CREATION_INTERVAL
loop
exitwhen i==MAX_MISSILE
set i = i+1
set a = a+a2
set mis = CreateUnit(GetOwningPlayer(.u), DUMMY_ID, GetUnitX(u), GetUnitY(u), a)
call HW.make(u, mis, a)
set mis = null
endloop
implement DTnulls
set .u = null
implement DTend
static method cast takes nothing returns nothing
local thistype this = create(CREATION_INTERVAL)
set .u = GetTriggerUnit()
set .dur = DURATION
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Suffucate
globals
private constant integer SPELL_ID = 'tor2'
private constant string SFX = "Abilities\\Spells\\Human\\Banish\\BanishTarget.mdl"
private constant string TELEPORT_SFX = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl"
endglobals
private function GetDamage takes integer level returns real
return 20.*level+30 //50, 70, 90, 110, 130
endfunction
private function GetStrikeCount takes integer level returns integer
return 8 //3*level+2
endfunction
struct Suf1
unit caster
unit im
unit target
real damage
real dur
real facing
real xTar
real yTar
real animInterval
integer strikeCount
effect sfx
method reset takes nothing returns nothing
call SetUnitPropWindow(.target, 1)
call SetUnitPropWindow(.caster, 1)
call SetUnitAnimation(.caster, "stand")
call SetUnitInvulnerable(.caster, false)
call ShowUnit(.caster, true)
call DestroyEffect(AddSpecialEffect(TELEPORT_SFX, GetUnitX(.caster), GetUnitY(.caster)))
call KillUnit(.im)
call UnitRemoveAbility(.caster, 'Abun')
endmethod
implement CTL
implement CTLExpire
set .dur = .dur + 0.05
call SetUnitFacing(.im, .facing)
call SetUnitX(.im, .xTar)
call SetUnitY(.im, .yTar)
if not IsUnitType(.target, UNIT_TYPE_DEAD) then
if .dur==2 then
call ShowUnit(.caster, false)
call ShowUnit(.im, true)
set .sfx = AddSpecialEffectTarget(SFX, .target, "origin")
call DestroyEffect(AddSpecialEffectTarget(TELEPORT_SFX, .im, "origin"))
elseif .dur > 2 and .dur < .strikeCount then
set .animInterval = .animInterval + 0.03125
if .animInterval > 1 then
set .animInterval = 0
call SetUnitAnimation(.im, "spell")
call UnitDamageTarget(.caster, .target, .damage, FALSE, FALSE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, null)
endif
elseif .dur==strikeCount+1 then
call DestroyEffect(.sfx)
call .reset()
set .caster = null
set .im = null
set .target = null
call .destroy()
endif
else
call .reset()
set .caster = null
set .im = null
set .target = null
call .destroy()
endif
implement CTLEnd
static method cast takes nothing returns nothing
local thistype this = create()
local integer level
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .target = GetSpellTargetUnit()
set .animInterval = 0
set .dur = 0
set .im = CreateUnit(Player(15), GetUnitTypeId(.caster) ,0 ,0 ,0)
set .xTar = GetUnitX(.target)-100*Cos(GetUnitFacing(.target)*bj_DEGTORAD)
set .yTar = GetUnitY(.target)-100*Sin(GetUnitFacing(.target)*bj_DEGTORAD)
set .sfx = null
set .facing = GetUnitFacing(.target)
set .strikeCount = GetStrikeCount(level)
set .damage = GetDamage(level)
call UnitAddAbility(.im, 'Aloc')
call ShowUnit(.im, false)
call SetUnitPropWindow(.target, 0)
call PauseUnit(.im, true)
if GetUnitFlyHeight(.target) > 0 then
if UnitAddAbility(.im, 'Arav') then
call UnitRemoveAbility(.im, 'Arav')
call SetUnitFlyHeight(.im, GetUnitFlyHeight(.target), 0)
endif
endif
//caster
call UnitAddAbility(.caster, 'Abun')
call SetUnitPropWindow(.caster, 0)
call SetUnitAnimation(.caster, "death")
call SetUnitInvulnerable(.caster, true)
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope CurseOfSilence
globals
private constant integer SPELL_ID = 'tor3'
private constant integer DUMMY_SPELL_ID = 'cur1' //sleep 852227
endglobals
private function FilterUnit takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_MECHANICAL) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)
endfunction
private struct CuS extends array
static method onDam takes nothing returns nothing
local integer level
local integer m
local real mana
if damageType==PHYSICAL then
set level = GetUnitAbilityLevel(source, SPELL_ID)
if level > 0 then
set m = 150-(level*25)
if GetUnitState(source, UNIT_STATE_MANA) > m then
if GetRandomInt(0, 100) < (5*level) and IsUnitEnemy(source, GetOwningPlayer(target)) and FilterUnit(target) then
set mana = GetUnitState(source, UNIT_STATE_MANA)
call SetUnitState(source, UNIT_STATE_MANA, mana-m)
call MuiDummyCasters.hitTarget(GetOwningPlayer(source), target, GetUnitX(target), GetUnitY(target), DUMMY_SPELL_ID, 852227, level)
endif
endif
endif
endif
endmethod
static method onInit takes nothing returns nothing
call AddDamageHandler(function thistype.onDam)
call PreloadSpell(DUMMY_SPELL_ID)
endmethod
endstruct
endscope
//TESH.scrollpos=27
//TESH.alwaysfold=0
scope TimerTemplate
//uses SpellEffectEvent
globals
private constant integer SPELL_ID = 'torU' //flame strike
private constant integer DUMMY_SPELL_ID = 'cur1' //sleep 852227
private constant integer MINIMUM_UNIT_LEVEL = 6
private constant real AOE = 300
private constant string SFX_AFFECT = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"
private constant string SFX_DAMAGE = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
private constant string SFX_APPEAR = "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl"
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_DEATH
private Table c
private integer array gUnitID
private integer array fUnitID
endglobals
private function FilterUnit takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL) /*
*/ and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)
endfunction
private function GetDamage takes integer level returns real
return 100.
endfunction
struct TT
unit caster
unit sleeper
static group g = CreateGroup()
implement CTL
local unit summoned
implement CTLExpire
if not IsUnitType(.sleeper, UNIT_TYPE_SLEEPING) then
if GetUnitLevel(.sleeper) < MINIMUM_UNIT_LEVEL then
if IsUnitType(.sleeper, UNIT_TYPE_FLYING) then
set summoned = CreateUnit(GetOwningPlayer(.caster), fUnitID[GetRandomInt(1,3)], GetUnitX(.sleeper), GetUnitY(.sleeper), 0)
else
set summoned = CreateUnit(GetOwningPlayer(.caster), gUnitID[GetRandomInt(1,3)], GetUnitX(.sleeper), GetUnitY(.sleeper), 0)
endif
call SetUnitUseFood(summoned, false)
call DestroyEffect(AddSpecialEffectTarget(SFX_APPEAR, summoned, "origin"))
set summoned = null
call KillUnit(.sleeper)
else
//damage
call DestroyEffect(AddSpecialEffectTarget(SFX_DAMAGE, .sleeper, "origin"))
call UnitDamageTarget(.caster, .sleeper, GetDamage(c[GetHandleId(.sleeper)]), false, false, ATK, DMG, null)
endif
call c.remove(GetHandleId(.sleeper))
set .caster = null
set .sleeper = null
call .destroy()
endif
implement CTLNull
implement CTLEnd
static method run takes unit caster, unit sleeper returns nothing
local thistype this
if not c.has(GetHandleId(sleeper)) then
set this = create()
set .caster = caster
set .sleeper = sleeper
call DestroyEffect(AddSpecialEffectTarget(SFX_AFFECT, sleeper, "origin"))
set c[GetHandleId(sleeper)] = GetUnitAbilityLevel(.caster, SPELL_ID)
endif
endmethod
static method cast takes nothing returns nothing
local unit first
call GroupEnumUnitsInRange(g, GetSpellTargetX(), GetSpellTargetY(), AOE, null)
loop
set first = FirstOfGroup(g)
exitwhen first==null
if FilterUnit(first) and IsUnitEnemy(first, GetTriggerPlayer()) then
if IsUnitType(first, UNIT_TYPE_SLEEPING) and not IsUnitType(first, UNIT_TYPE_HERO) then
call thistype.run(GetTriggerUnit(), first)
else
call MuiDummyCasters.hitTarget(GetTriggerPlayer(), first, GetUnitX(first), GetUnitY(first), DUMMY_SPELL_ID, 852227, 1)
endif
endif
call GroupRemoveUnit(g, first)
endloop
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.cast)
set c = Table.create()
set gUnitID[1] = 'nvdg' //greater voidwalker, level 6
set gUnitID[2] = 'nfor' //faceless one trickster, level 6
set gUnitID[3] = 'nfov' //overlord, level 6
set fUnitID[1] = 'ngdk' //green drake, level 6
set fUnitID[2] = 'nndk' //nether drake, level 6
set fUnitID[3] = 'nadk' //blue drake, level 6
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope RuneStats
//uses Table, TimerUtils, RegisterPlayerUnitEvent, SimError
globals
private constant integer AGILITY = 'I004'
private constant integer INTELLIGENCE = 'I005'
private constant integer STRENGTH = 'I003'
private constant integer BONUS = 30
private constant integer GOLD_COST = 400
private constant integer LUMBER_COST = 150
private constant real DURATION = 90
private Table agi
private Table inl
private Table str
private TableArray bon
endglobals
private struct RuneStats
readonly unit hero
readonly real duration
static real interval = 0.5
private static method remove takes item it, player p, integer gold, integer lumber returns nothing
call RemoveItem(it)
call SimError(p,"you cannot have another item of this type!")
call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,gold+GOLD_COST)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,lumber+LUMBER_COST)
endmethod
private static method filterItem takes item it returns boolean
return GetItemTypeId(it)==AGILITY or GetItemTypeId(it)==INTELLIGENCE or GetItemTypeId(it)==STRENGTH
endmethod
private static method onLoop takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local integer uID
if .duration > 0 and UnitAlive(.hero) then
set .duration = .duration - interval
//call BJDebugMsg(R2S(.duration))
else
set uID = GetHandleId(.hero)
if bon[5][uID]==AGILITY then
call SetHeroAgi(.hero,bon[1][uID],false)
//call BJDebugMsg("agility")
set bon[5][uID] = 0
call agi.remove(uID)
elseif bon[6][uID]==INTELLIGENCE then
call SetHeroInt(.hero,bon[2][uID],false)
//call BJDebugMsg("intelligence")
set bon[6][uID] = 0
call inl.remove(uID)
elseif bon[7][uID]==STRENGTH then
call SetHeroStr(.hero,bon[3][uID],false)
//call BJDebugMsg("strength")
set bon[7][uID] = 0
call str.remove(uID)
endif
set .hero = null
call ReleaseTimer(GetExpiredTimer())
call .deallocate()
endif
endmethod
private static method runTime takes unit u, integer itemID, item it returns nothing
local thistype this
local integer uID = GetHandleId(u)
local player p = GetOwningPlayer(u)
local integer gold = GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
local integer lumber = GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
if itemID==AGILITY then
if not agi.has(uID) then
set this = allocate()
set .duration = DURATION
set .hero = u
set agi[uID] = 1
set bon[1][uID] = GetHeroAgi(u,false)
set bon[5][uID] = itemID
call SetHeroAgi(u,bon[1][uID]+BONUS,false)
call TimerStart(NewTimerEx(this), interval, true, function thistype.onLoop)
else
call thistype.remove(it, p, gold, lumber)
endif
elseif itemID==INTELLIGENCE then
if not inl.has(uID) then
set this = allocate()
set .duration = DURATION
set .hero = u
set inl[uID] = 1
set bon[2][uID] = GetHeroInt(u,false)
set bon[6][uID] = itemID
call SetHeroInt(u,bon[2][uID]+BONUS,false)
call TimerStart(NewTimerEx(this), interval, true, function thistype.onLoop)
else
call thistype.remove(it, p, gold, lumber)
endif
elseif itemID==STRENGTH then
if not str.has(uID) then
set this = allocate()
set .duration = DURATION
set .hero = u
set str[uID] = 1
set bon[3][uID] = GetHeroStr(u,false)
set bon[7][uID] = itemID
call SetHeroStr(u,bon[3][uID]+BONUS,false)
call TimerStart(NewTimerEx(this), interval, true, function thistype.onLoop)
else
call thistype.remove(it, p, gold, lumber)
endif
endif
set p = null
endmethod
private static method take takes nothing returns nothing
if filterItem(GetManipulatedItem()) then
call runTime(GetTriggerUnit(), GetItemTypeId(GetManipulatedItem()), GetManipulatedItem())
endif
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM, function thistype.take)
set agi = Table.create()
set inl = Table.create()
set str = Table.create()
set bon = TableArray[0x2000]
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope MassSleep
globals
private constant integer SPELL_ID = 'A02J'
private constant integer SLEEP_ID = 'ACsl'
endglobals
private struct MassSleep
private static method run takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit first
//! runtextmacro FOG_ADD("GetUnitX(u)", "GetUnitY(u)", "350")
if UnitAlive(first) and FUN_OrganicUnits(first) and IsUnitEnemy(first,GetTriggerPlayer()) then
call MuiDummyCasters.hitTarget(GetTriggerPlayer(),first,GetUnitX(first),GetUnitY(first),SLEEP_ID, OrderId("sleep"), 1)
//call TargetCast(GetTriggerPlayer(), first, GetUnitX(first), GetUnitY(first), SLEEP_ID, OrderId("sleep"), 1)
endif
//! runtextmacro FOG_REMOVE()
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.run)
call PreloadSpell(SLEEP_ID)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//===========================================================================
//The caster uses his light powers to summon waves of Light Rays around him,
//damaging enemy Undead units nearby, and healing allied units
//
//Requires TimerUtils
//
//@author Flame_Phoenix
//
//@credits
//- Blackroot (aka Modeler), the first creator, gave me the basic idea and concept
//- the-thingy, by telling me where to use bj_DEGTORAD and why
//- Alexander244, for helping me fixing a bug with parenthesis ... lol
//- Anitarf, for suggesting a slight improvement for the code
//- My first teacher of vJASS: Blue_Jeans
//- All other people I forgot or ignored
//
//@version 1.5
//===========================================================================
scope SunRay initializer Init
//needed for spell's core, don't change
private keyword tmpPlayer
//===========================================================================
//=============================SETUP START===================================
//===========================================================================
globals
private constant integer AID = 'A033' //raecode of ability
private constant real LIGHT_RADIUS = 100 //radius of each single light
private constant string LIGHT_EFFECT = "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl" //the effect of the light
private constant real LIGHT_INTERVAL = 0.2 //the interval that separates each light
private constant boolean CASTER_ANG = true //if true we consider the caster's facing angle, else we don't
endglobals
private constant function Damage takes integer level returns real
return 20. //the damage the enemy undead units will take
endfunction
private constant function Heal takes integer level returns real
return 40. //the heal your allied units will receive
endfunction
private constant function LightNumber takes integer level returns integer
//each Sun Ray of (4 + level) lights
return 4 + level
endfunction
private constant function RayNumber takes integer level returns integer
//the number of Sun Rays of the spell
return 5 + level
endfunction
private function AllyTargets takes nothing returns boolean
//what allied units will be affected by the spell
return IsUnitAlly(GetFilterUnit(), tmpPlayer) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false) and (GetWidgetLife(GetFilterUnit()) > 0.405)
endfunction
private function EnemyTargets takes nothing returns boolean
//what enemy units will be affected by the spell
return IsUnitEnemy(GetFilterUnit(), tmpPlayer) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false) and (GetUnitRace(GetFilterUnit()) == RACE_UNDEAD) and (GetWidgetLife(GetFilterUnit()) > 0.405)
endfunction
//===========================================================================
//=============================SETUP END=====================================
//===========================================================================
globals
private player tmpPlayer
private group g
private boolexpr enemies
private boolexpr allies
endglobals
private struct MyStruct
unit caster
real casterX
real casterY
integer level
timer t
real distInc
integer lightsCreated
static method create takes unit caster returns MyStruct
local MyStruct data = MyStruct.allocate()
//setting variables
set data.caster = caster
set data.casterX = GetUnitX(caster)
set data.casterY = GetUnitY(caster)
set data.level = GetUnitAbilityLevel(caster, AID)
set data.t = NewTimer() //this will create the lights =)
set data.distInc = LIGHT_RADIUS
set data.lightsCreated = 0
return data
endmethod
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
endmethod
endstruct
//===========================================================================
private function CreateLights takes nothing returns nothing
local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer()))
local unit f
local real x //the X position of the effect
local real y //the Y position of the effect
local real angle
local integer i //a counter for the loop
//we set this variable depending if we want to consider the
//caster's angle or not
if CASTER_ANG then
set angle = GetUnitFacing(data.caster)
else
set angle = 0
endif
//if we didn't pass the number of lights, than we create lights
//again, however, if we did, we end everything
if data.lightsCreated < LightNumber(data.level) then
//in this outer loop we create the Sun Rays
set i = 0
loop
exitwhen(i == RayNumber(data.level))
set x = data.casterX + data.distInc * Cos(angle)
set y = data.casterY + data.distInc * Sin(angle)
call DestroyEffect(AddSpecialEffect(LIGHT_EFFECT, x, y))
//in this first double inner loop we select the enemy units and damage them
set tmpPlayer = GetOwningPlayer(data.caster)
call GroupEnumUnitsInRange(g, x, y, LIGHT_RADIUS, enemies)
loop
set f = FirstOfGroup(g)
exitwhen(f == null)
call GroupRemoveUnit(g, f)
call UnitDamageTarget(data.caster, f, Damage(data.level), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
endloop
//in this second double inner loop we select the allied units and heal them
set tmpPlayer = GetOwningPlayer(data.caster)
call GroupEnumUnitsInRange(g, x, y, LIGHT_RADIUS, allies)
loop
set f = FirstOfGroup(g)
exitwhen(f == null)
call GroupRemoveUnit(g, f)
call SetWidgetLife(f, GetWidgetLife(f) + Heal(data.level))
endloop
set angle = angle + (360 / RayNumber(data.level)) * bj_DEGTORAD
set i = i + 1
endloop
set data.distInc = data.distInc + LIGHT_RADIUS
set data.lightsCreated = data.lightsCreated + 1
else
call data.destroy()
endif
endfunction
//===========================================================================
private function Conditions takes nothing returns boolean
local MyStruct data
if GetSpellAbilityId() == AID then
set data = MyStruct.create(GetTriggerUnit())
//now we start the timer !
call SetTimerData(data.t, integer(data))
call TimerStart(data.t, LIGHT_INTERVAL, true, function CreateLights)
endif
return false
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger SunRayTrg = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( SunRayTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( SunRayTrg, Condition( function Conditions ) )
set SunRayTrg = null
//setting globals
set g = CreateGroup()
set enemies = Condition(function EnemyTargets)
set allies = Condition(function AllyTargets)
//preloading effect
call Preload(LIGHT_EFFECT)
endfunction
endscope
//TESH.scrollpos=5
//TESH.alwaysfold=0
//***************************************************************************************************************
//* *
//* Runes Spell (vJASSified). *
//* By Moyack. *
//* V.2.3. *
//* *
//***************************************************************************************************************
//*
library Runes initializer init requires TimedLoop, SpellEffectEvent
//***************************************************************************************************************
//* The constant data where you can modify the ability properties
//*
globals
private constant integer SpellID = 'A035' // Returns the spell ID. Spell based on Serpent Ward
private constant attacktype AttackT = ATTACK_TYPE_SIEGE // Sets the Attack type deal to the units
private constant damagetype DamageT = DAMAGE_TYPE_NORMAL // Sets the Damage type deal to the units
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 100.
endfunction
private constant function Duration takes integer lvl returns real
return 25.
endfunction
//***************************************************************************************************************
private struct rune
unit caster
player player
effect effect
real x
real y
real duration
integer level
static string blow = "Objects\\Spawnmodels\\Other\\ToonBoom\\ToonBoom.mdl"
static string sfx = "Doodads\\Cityscape\\Props\\MagicRunes\\MagicRunes0.mdl"
static unit dummy
private method destroy takes nothing returns nothing
call DestroyEffect(.effect)
if .duration < Duration(.level) then
call DestroyEffect(AddSpecialEffect(blow, .x, .y))
call DestroyEffect(AddSpecialEffect(blow, .x, .y))
endif
endmethod
private method onTimedLoop takes nothing returns boolean
local unit u
set .duration = .duration + TimedLoop_PERIOD
call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, Range(.level), null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u == null
if UnitAlive(u) then
call SetUnitOwner(dummy, .player, false)
call UnitDamageTarget(dummy, u, Damage(.level), false, false, AttackT, DamageT, WEAPON_TYPE_ROCK_HEAVY_BASH)
call SetUnitOwner(dummy, Player(15), false)
return false
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
if .duration > Duration(.level) then
return false
endif
return true
endmethod
implement TimedLoop
static method Start takes unit c, real x, real y returns nothing
local thistype R = thistype.allocate()
set R.effect = AddSpecialEffect(sfx, x, y)
set R.caster = c
set R.player = GetOwningPlayer(c)
set R.x = x
set R.y = y
set R.level = 1//GetUnitAbilityLevel(c, SpellID)
call R.startTimedLoop()
endmethod
endstruct
//***************************************************************************************************************
//* *
//* Runes Casting Functions *
//* *
//***************************************************************************************************************
private function Conditions takes nothing returns nothing
local unit c = GetTriggerUnit()
local real lx = GetSpellTargetX()
local real ly = GetSpellTargetY()
local real fc = GetUnitFacing(c) * bj_DEGTORAD
local real a = Amount(1)
local real R = Radius(1)
local real angle = 2 * bj_PI / a
local integer count = 0
local real x
local real y
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
endfunction
//===========================================================================
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(SpellID, function Conditions)
set rune.dummy = CreateUnit(Player(15), 'hpea', 0,0,0)
call ShowUnit(rune.dummy, false)
endfunction
endlibrary
//TESH.scrollpos=96
//TESH.alwaysfold=0
scope RotatingBlades initializer Init
//by AdityaHegde
globals
//edit the values to customize
private integer AbilityCode = 'A02N'
private integer DummyUnitCode = 'h00F'
private attacktype AttackType = ATTACK_TYPE_HERO
private damagetype DamageType = DAMAGE_TYPE_NORMAL
private real LoopInterval = 0.0315
private real DistFromTarDurHover = 150
private real DistFromTarDurDam = 50
private real BladeMoveSpeed = 20
private real BladeRotateSpeed = 1.5 //in degrees
private integer DamDur = 16
private integer HoverDur = 33
private string ModelName = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" //effect when dealing damage
private string AttachPoint = "chest"
//do not edit below
private timer LoopTimer = CreateTimer()
private Blade array Data
private integer top = 0
endglobals
//edit the return value to change the no of times blade swoops per level
private function NoOfSwoopsPerLevel takes integer lvl returns integer
return 30
endfunction
//edit the return value to change the damage dealt by blade per loop
private function DamagePerLevel takes integer lvl returns real
return 5.0
endfunction
struct Blade
unit blade
unit caster
unit target
integer lvl
integer dur
integer swoops
integer status
real angle
effect model
private static method BladeLoop takes nothing returns nothing
local integer i = 1
local Blade bld
local real dist
local real x
local real y
local real tx
local real ty
local boolean kill
loop
exitwhen i > top
set kill = false
set bld = Data[i]
if bld.status == 2 then
set bld.angle = bld.angle + BladeRotateSpeed
set dist = DistFromTarDurHover
if bld.dur < 5 then
set dist = DistFromTarDurHover*(bld.dur)/5
else
if HoverDur - bld.dur < 5 then
set dist = DistFromTarDurHover*(HoverDur - bld.dur)/5
endif
endif
set x = GetUnitX(bld.target)
set y = GetUnitY(bld.target)
set bld.dur = bld.dur - 1
if bld.dur == 0 then
set bld.status = 3
set bld.dur = DamDur
set bld.model = AddSpecialEffectTarget(ModelName, bld.target, AttachPoint)
endif
else
if bld.status == 1 then
set tx = GetUnitX(bld.target)
set ty = GetUnitY(bld.target)
set x = GetUnitX(bld.blade)
set y = GetUnitY(bld.blade)
set bld.angle = bj_RADTODEG * Atan2(ty - y, tx - x)
set dist = BladeMoveSpeed
if RAbsBJ(x - tx) < DistFromTarDurHover and RAbsBJ(y - ty) < DistFromTarDurHover then
set bld.status = 2
set bld.dur = HoverDur
set bld.swoops = NoOfSwoopsPerLevel(bld.lvl)
endif
else
set bld.dur = bld.dur - 1
set dist = DistFromTarDurDam
set x = GetUnitX(bld.target)
set y = GetUnitY(bld.target)
call UnitDamageTarget(bld.caster, bld.target, DamagePerLevel(bld.lvl), true, false, AttackType, DamageType, WEAPON_TYPE_WHOKNOWS)
if bld.dur == 0 then
set bld.swoops = bld.swoops - 1
set bld.status = 2
set bld.dur = HoverDur
call DestroyEffect(bld.model)
set bld.model = null
endif
endif
endif
call SetUnitPosition(bld.blade, x + dist*Cos(bld.angle*bj_DEGTORAD), y + dist*Sin(bld.angle*bj_DEGTORAD))
//call SetUnitX(bld.blade, x + dist*Cos(bld.angle*bj_DEGTORAD))
//call SetUnitY(bld.blade, y + dist*Sin(bld.angle*bj_DEGTORAD))
if GetWidgetLife(bld.target) < 0.405 or bld.swoops == 0 then
call RemoveUnit(bld.blade)
call bld.destroy()
set Data[i] = Data[top]
set top = top - 1
if top == 0 then
call PauseTimer(LoopTimer)
return
endif
else
set i = i + 1
endif
endloop
endmethod
public static method Create takes nothing returns Blade
local Blade bld
local unit trig = GetTriggerUnit()
local unit tar = GetSpellTargetUnit()
local real x = GetUnitX(trig)
local real y = GetUnitY(trig)
local real tx = GetUnitX(tar)
local real ty = GetUnitY(tar)
if GetSpellAbilityId() == AbilityCode then
set bld = .allocate()
set bld.caster = GetTriggerUnit()
set bld.target = GetSpellTargetUnit()
set bld.angle = bj_RADTODEG * Atan2(ty - y, tx - x)
set bld.blade = CreateUnit(GetTriggerPlayer(), DummyUnitCode, x, y, bld.angle)
set bld.lvl = GetUnitAbilityLevel(bld.caster, AbilityCode)
set bld.status = 1
set bld.dur = 1
set bld.swoops = 1
set top = top + 1
set Data[top] = bld
if top == 1 then
call TimerStart(LoopTimer, LoopInterval, true, function Blade.BladeLoop)
endif
return bld
endif
return 0
endmethod
endstruct
function Init takes nothing returns nothing
call RegisterSpellEffectEvent(AbilityCode, function Blade.Create)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope LightningWard initializer Init
globals
private constant integer LIGHTNING_WARD = 'A03B'
private constant integer DUMMY_RAWCODE = 'o003'
private constant integer SWARM_RAWCODE = 'A03C'
private constant real OFFSET_DISTANCE = 500.
private constant integer MAX_WARDS = 5
endglobals
private function LightningWard takes nothing returns nothing
local unit LTU
local unit LV
local player P
local real X
local real Y
local real LD
local integer LI
local unit LU
local real RAD
set LTU = GetTriggerUnit()
set LV = GetSpellTargetUnit()
set X = GetUnitX(LV)
set Y = GetUnitY(LV)
set LD = (GetUnitAbilityLevel(LTU, LIGHTNING_WARD)*5)+5.
set RAD = (2.*bj_PI)/MAX_WARDS
set P = GetOwningPlayer(LTU)
set LI = 0
loop
exitwhen (LI >= MAX_WARDS)
set LU = CreateUnit(P, DUMMY_RAWCODE, X+OFFSET_DISTANCE*Cos(RAD*LI), Y+OFFSET_DISTANCE*Sin(RAD*LI), 0.)
call UnitApplyTimedLife(LU, 'BTLF', LD)
call UnitAddAbility(LU, SWARM_RAWCODE)
call IssueImmediateOrder(LU, "locustswarm" )
call IssueTargetOrder(LU, "attack", LV)
set LI = LI + 1
endloop
set LU = null
set P = null
set LTU = null
set LV = null
endfunction
// ===========================================================================
private constant function DummyFilter takes nothing returns boolean
return true
endfunction
private function Init takes nothing returns nothing
call RegisterSpellEffectEvent(LIGHTNING_WARD, function LightningWard)
call PreloadSpell(SWARM_RAWCODE)
endfunction
endscope
//TESH.scrollpos=80
//TESH.alwaysfold=0
/*
=====Spell Name: Shockwave Thrust
=====Made by: Mckill2009
REQUIRES:
- Timer32 by Jesus4lyf
*/
scope SWT
globals
private constant integer SPELL_ID = 'A03D' //Based on Carrion swarm
private constant real THRUST_SPEED = 30.
private constant real AOE = 100
private constant string THRUST_SFX = "Abilities\\Spells\\Orc\\Shockwave\\ShockwaveMissile.mdl"
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
endglobals
//native UnitAlive takes unit i returns boolean
private function Damage takes integer i returns real
return 75.//25 + i * 25.
endfunction
private struct ST
unit caster
integer level
real angle
real distance
real damage
real x
real y
effect sfx
method periodic takes nothing returns nothing
local unit first
local real x
local real y
local real x1 = GetUnitX(.caster)
local real y1 = GetUnitY(.caster)
if .distance > 0 then
set .distance = .distance - THRUST_SPEED
set x = x1+THRUST_SPEED*Cos(.angle)
set y = y1+THRUST_SPEED*Sin(.angle)
call SetUnitX(.caster, x)
call SetUnitY(.caster, y)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x1, y1, AOE, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(.caster, GetOwningPlayer(first)) and not IsUnitType(first, UNIT_TYPE_FLYING) then
call UnitDamageTarget(.caster, first, .damage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup,first)
endloop
else
call DestroyEffect(.sfx)
call SetUnitInvulnerable(.caster, false)
call SetUnitPathing(.caster, true)
set .caster = null
set .sfx = null
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method cast takes nothing returns boolean
local thistype this
local real x1
local real y1
local real dx
local real dy
if GetSpellAbilityId()==SPELL_ID then
set this = create()
set x1 = GetSpellTargetX()
set y1 = GetSpellTargetY()
set .caster = GetTriggerUnit()
set .level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .x = GetUnitX(.caster)
set .y = GetUnitY(.caster)
set dx = x1-.x
set dy = y1-.y
set .angle = Atan2(y1-.y, x1-.x)
set .distance = SquareRoot(dx*dx+dy*dy)
set .damage = Damage(.level)*T32_PERIOD
set .sfx = AddSpecialEffectTarget(THRUST_SFX, .caster, "origin")
call SetUnitInvulnerable(.caster, true)
call SetUnitPathing(.caster, false)
call .startPeriodic()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function thistype.cast)
set t = null
endmethod
endstruct
endscope