function PlaySoundAtPoint takes string f, real x, real y, real p, integer v returns nothing
local sound s = CreateSound( f, false, true, true, 10, 10, "" )
call SetSoundDuration( s, GetSoundFileDuration(f) )
call SetSoundChannel( s, 0 )
call SetSoundVolume( s, v )
call SetSoundPitch( s, p )
call SetSoundPosition(s, x, y, 0)
call StartSound(s)
call KillSoundWhenDone(s)
set s = null
endfunction
Name | Type | is_array | initial_value |
ALE_LOC | location | No | |
ALE_UNIT | unit | No | |
AMR_Pick | unit | No | |
AMR_Point | location | No | |
AMR_Unit | unit | No | |
BB_ATCKD | unit | No | |
BB_ATCKR | unit | No | |
BB_Loc | location | No | |
BC_Hero | unit | No | |
BC_Loc | location | No | |
Bombardment_TempPoint | location | No | |
Bounty_Killer | unit | No | |
Bounty_Target | unit | No | |
CargoEvent | real | No | |
CargoTransportGroup | group | Yes | |
CargoTransportUnit | unit | Yes | |
Caster | unit | No | |
CheckDeathInList | boolean | Yes | |
CheckDeathList | integer | Yes | |
CheckDeathTimer | timer | No | |
DeathEvent | real | No | |
Defeated | player | No | |
DetectRemoveAbility | abilcode | No | |
DetectTransformAbility | abilcode | No | |
DiveAttackAudioInt | integer | No | |
DiveAttackCanceled | boolean | Yes | |
DiveAttackCaster | unit | Yes | |
DiveAttackChaseDur | real | No | |
DiveAttackCooldownMax | real | No | |
DiveAttackCooldownMin | real | No | |
DiveAttackCooldownTimer | real | Yes | |
DiveAttackDamage | real | Yes | |
DiveAttackDamageMax | real | No | |
DiveAttackDamageMin | real | No | |
DiveAttackDir | real | No | |
DiveAttackDist | real | No | |
DiveAttackGroup | group | No | |
DiveAttackGroupAutocast | group | No | |
DiveAttackHeal | real | Yes | |
DiveAttackHealMultiplier | real | No | |
DiveAttackHeight | real | Yes | |
DiveAttackHeightLoss | real | No | |
DiveAttackIndex | integer | No | |
DiveAttackLocCasterCurrent | location | No | |
DiveAttackLocCasterNew | location | No | |
DiveAttackLocCursor | location | No | |
DiveAttackLoop | integer | No | |
DiveAttackMaxDur | real | Yes | |
DiveAttackMoveSpeed | real | No | |
DiveAttackSpeed | real | Yes | |
DiveAttackSpeedMultiplier | real | No | |
DiveAttackState | integer | Yes | |
DiveAttackTarget | unit | Yes | |
DiveAttackUnit | unit | Yes | |
Enemies | group | No | |
EnemyBlue | force | No | |
EnemyPurple | force | No | |
EnemyRed | force | No | |
EnemyTeal | force | No | |
EngulfSha_Damage | real | No | |
EngulfSha_Number | integer | No | |
EngulfSha_Point | location | No | |
EngulfSha_Unit | unit | No | |
FD | integer | No | |
FD_Angle | real | Yes | |
FD_Distance | real | Yes | |
FD_Hero | unit | Yes | |
FD_Off | boolean | Yes | |
FD_Point | location | Yes | |
FD_Skip | integer | No | |
FD_Spam | integer | Yes | |
FD_Speed | real | Yes | |
FD_Times | integer | No | |
Flare_Shot_Caster | unit | No | |
Flare_Shot_Point | location | No | |
GREEN_Angle | real | No | |
GREEN_Caster_Unit | unit | No | |
GREEN_Damage | real | No | |
GREEN_Damaged_UnitGroup | group | No | |
GREEN_Hashtable | hashtable | No | |
GREEN_Speed | real | No | |
GREEN_Travel_Range | real | No | |
GREEN_UnitGroup | group | No | |
Hashtable | hashtable | No | |
HunterBox_Chance | integer | No | |
HunterBox_Loc | location | No | |
HunterBox_User | unit | No | |
I | integer | No | |
I_Angle | real | Yes | |
I_Arc | real | Yes | |
I_Caster | unit | Yes | |
I_CastNumber | integer | No | |
I_ConstDistance | real | Yes | |
I_Damage | real | Yes | |
I_Distance | real | Yes | |
I_Dummie | unit | Yes | |
I_Group | group | No | |
I_Integer | integer | No | |
I_Missile1 | unit | Yes | |
I_Missile2 | unit | Yes | |
I_Off | boolean | Yes | |
I_Offset | real | Yes | |
I_Point | location | Yes | |
I_Speed | real | Yes | |
I_Switch | integer | No | |
Integer | integer | Yes | |
IsUnitAlive | boolean | Yes | |
IsUnitBeingUnloaded | boolean | Yes | |
IsUnitNew | boolean | Yes | |
IsUnitPreplaced | boolean | Yes | |
IsUnitReincarnating | boolean | Yes | |
IsUnitRemoved | boolean | Yes | |
IsUnitTransforming | boolean | Yes | |
KB | integer | No | |
KB_Angle | real | Yes | |
KB_Distance | real | Yes | |
KB_Off | boolean | Yes | |
KB_Point | location | Yes | |
KB_Skip | integer | No | |
KB_Spam | integer | Yes | |
KB_Speed | real | Yes | |
KB_Target | unit | Yes | |
KB_Times | integer | No | |
KillerOfUnit | unit | Yes | |
Level_1_Ruins | unitcode | Yes | |
Level_2_Ruins | unitcode | Yes | |
Level_3_Ruins | unitcode | Yes | |
MS_build_point | location | Yes | |
MS_Caster | unit | No | |
MS_create_point | location | No | |
MS_Group | group | No | |
MS_Loc | location | Yes | |
MS_Rect | rect | No | |
MS_target_point | location | No | |
MS_temp_point | location | Yes | |
Overcharge_Attacker | unit | No | |
Overcharge_Chance | integer | No | |
Overcharge_ChanceNumber | integer | No | |
Overcharge_Point | location | No | |
Overcharge_Unit_Group | group | No | |
PCD_Ability | abilcode | No | |
PCD_DummyAbility | abilcode | No | |
PCD_DummyCaster | unit | No | |
PCD_DummyCasterId | unitcode | No | |
PCD_Hashtable | hashtable | No | |
PCD_IndicatorStartId | abilcode | No | |
PCD_Manacost | real | No | |
PCD_Time | real | No | |
PCD_Unit | unit | No | |
PCD_ValidTargetCheckId | abilcode | No | |
PCD_VTCBaseOrderId | string | No | |
Player_Picked | player | No | |
PlayList | string | No | |
Points | location | Yes | |
QJC_Ally | boolean | No | |
QJC_Amount | real | No | |
QJC_AmountReduce | real | No | |
QJC_AoE | boolean | No | |
QJC_AoERadius | real | No | |
QJC_AoESFX | string | No | |
QJC_AttackType | attacktype | No | |
QJC_Caster | unit | No | |
QJC_ChainEffect | abilcode | No | |
QJC_ChainSFX | lightningtype | No | |
QJC_Damage | boolean | No | |
QJC_DamageType | damagetype | No | |
QJC_Enemy | boolean | No | |
QJC_Gold | boolean | No | |
QJC_Heal | boolean | No | |
QJC_Heatlh | boolean | No | |
QJC_JumpCount | integer | No | |
QJC_JumpDelayTime | real | No | |
QJC_JumpRadius | real | No | |
QJC_Leech | boolean | No | |
QJC_Mana | boolean | No | |
QJC_NoTarget | boolean | No | |
QJC_OnePerUnit | boolean | No | |
QJC_Priority | boolean | No | |
QJC_Slow | boolean | No | |
QJC_SlowEffect | abilcode | No | |
QJC_Stun | boolean | No | |
QJC_StunEffect | abilcode | No | |
QJC_TargetPoint | location | No | |
QJC_TargetSFX | string | No | |
QJC_TargetUnit | unit | No | |
QJCS_aGroup | group | Yes | |
QJCS_Ally | boolean | Yes | |
QJCS_Amount | real | Yes | |
QJCS_AmountReduce | real | Yes | |
QJCS_AoE | boolean | Yes | |
QJCS_AoERadius | real | Yes | |
QJCS_AoESFX | string | No | |
QJCS_AttackType | attacktype | Yes | |
QJCS_baseDummy | unit | Yes | |
QJCS_Caster | unit | Yes | |
QJCS_CasterESFX | string | No | |
QJCS_ChainEffect | abilcode | No | |
QJCS_ChainSFX | lightningtype | Yes | |
QJCS_ChainX | real | Yes | |
QJCS_ChainY | real | Yes | |
QJCS_ChainZ | real | Yes | |
QJCS_currUnit | unit | No | |
QJCS_Damage | boolean | Yes | |
QJCS_DamageType | damagetype | Yes | |
QJCS_dGroup | group | Yes | |
QJCS_Dummy | unit | No | |
QJCS_dummyGroup | group | No | |
QJCS_dummyPOS | location | No | |
QJCS_Enemy | boolean | Yes | |
QJCS_Gold | boolean | Yes | |
QJCS_Heal | boolean | Yes | |
QJCS_Health | boolean | Yes | |
QJCS_index | integer | Yes | |
QJCS_JumpCount | integer | Yes | |
QJCS_JumpDelayTime | real | Yes | |
QJCS_JumpRadius | real | Yes | |
QJCS_Leech | boolean | Yes | |
QJCS_LightningDPos | unit | Yes | |
QJCS_LightningDummy | unit | Yes | |
QJCS_LightningDur | real | Yes | |
QJCS_LightningIndex | integer | Yes | |
QJCS_LightningPos | location | Yes | |
QJCS_LightningSFX | lightning | Yes | |
QJCS_LightningTarget | unit | Yes | |
QJCS_Locust | abilcode | No | |
QJCS_Mana | boolean | Yes | |
QJCS_OnePerUnit | boolean | Yes | |
QJCS_prevTarget | unit | Yes | |
QJCS_Priority | boolean | Yes | |
QJCS_Slow | boolean | Yes | |
QJCS_SlowEffect | abilcode | Yes | |
QJCS_Stun | boolean | Yes | |
QJCS_StunEffect | abilcode | Yes | |
QJCS_SystemCount | integer | Yes | |
QJCS_SystemTime | real | Yes | |
QJCS_TargetSFX | string | Yes | |
QJCS_TargetUnit | unit | Yes | |
QJCS_tempGroup | group | No | |
QJCS_tempPos | location | Yes | |
QJCS_victimGroup | group | No | |
Real | real | Yes | |
SB | integer | No | |
SB_Angle | real | Yes | |
SB_Caster | unit | Yes | |
SB_Colision | real | Yes | |
SB_CountdownTimer | integer | Yes | |
SB_Damage | real | Yes | |
SB_Distance | real | Yes | |
SB_Group | group | No | |
SB_Height | real | Yes | |
SB_Hero | unit | Yes | |
SB_Level | integer | Yes | |
SB_LifeCaster | real | Yes | |
SB_LifeCaster_Reduction | real | Yes | |
SB_Light | lightning | Yes | |
SB_MaxDistance | real | Yes | |
SB_Missile | unit | Yes | |
SB_Off | boolean | Yes | |
SB_On | boolean | Yes | |
SB_Parabola | real | Yes | |
SB_Part | integer | Yes | |
SB_Point | location | Yes | |
SB_Skip | integer | No | |
SB_Special1 | effect | Yes | |
SB_Special2 | effect | Yes | |
SB_Special3 | effect | Yes | |
SB_Speed | real | Yes | |
SB_Sticked | boolean | Yes | |
SB_Target | unit | Yes | |
SB_Timer | real | Yes | |
SB_Times | integer | No | |
SD_Hero | unit | Yes | |
SD_Times | integer | No | |
Shark_Caster | unit | Yes | |
Shark_Damage | integer | Yes | |
Shark_Group | group | Yes | |
Shark_Index | integer | No | |
Shark_Loop | integer | No | |
Shark_MUI | integer | No | |
Shark_Point1 | location | Yes | |
Shark_Point2 | location | Yes | |
Shark_Point3 | location | Yes | |
Shark_Real | real | Yes | |
Shark_Real2 | real | Yes | |
Shark_Spell_Index | integer | Yes | |
Shark_Spell_Max | integer | No | |
Shark_Target | unit | Yes | |
Shock_Mine | unit | No | |
Shock_Mine_Point | location | No | |
Shockwaves | group | No | |
SinsLanding | group | No | |
SinsRising | group | No | |
SummonerOfUnit | unit | Yes | |
Target | unit | No | |
TempKey | integer | No | |
TempLoc | location | No | |
TempPoint1 | location | No | |
TempPoint2 | location | No | |
TempPoint3 | location | No | |
TempUnit | unit | No | |
UDex | integer | No | |
UDexLastRecycled | integer | No | |
UDexMax | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexUnits | unit | Yes | |
UnitInAction | boolean | Yes | |
UnitInActionEvent | real | No | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitName | string | Yes | |
UnitTypeEvent | real | No | |
UnitTypeOf | unitcode | Yes | |
Vendetta_Hero | unit | No | |
Vendetta_Point | location | No | |
WorldMaxX | real | No | |
WorldMaxY | real | No |
JeffQ's Basic Chain System v2.00f
Created Date: 22 January 2010
Author: JeffQ a.k.a JeffreyQ, SmileyJeff
**Official version will only be destributed by ME (JeffQ, JeffreyQ. SmileyJeff). Anyone else who upload this is edited.
I have been working on my AoS map and decided to create a chain system that can do pretty much anything.
Because my AoS have alot of chain spells that are in GUI.
So here it is. After 3 days of hardworking and understanding indexing. I present you JeffQ's Basic Chain System (MUI/GUI using Indexing).
======================
Change Log
======================
v2.00f, 24 Feb 2010
- Chain should no longer jump to buildings/structures.
- Some demo ability can still target buildings, this is because i didn't limit the target allowed at the ability editor. (Nothing to do with the system)
v2.00e, 31 Jan 2010
- Fix lightning height to match cliff or raised terrain.
- Added a raised terrain and cliff to test out.
v2.00d, 25 Jan 2010
- Rearrange Folder for easier implementing in other maps.
- Updated "How To Use" in the README to give a step by step tutorial on how to implement. Please do give it a read.
v2.00c, 24 Jan 2010
- Chain now gets unit height +25. Meaning that if you target a flying unit, the chain height will change accordingly.
- Added a few flying units to let you try out the dynamic chain height.
- Added Chain Globals Trigger to store Locust.
- Chain should now only jump to units that doesn't have locust (This should remove the limitation of where you need to only base all other ability dummies on my dummy as long as your custom dummies have locust).
v2.00b, 23 Jan 2010
- Lightning effect now won't stick to ground.
v2.00a, 23 Jan 2010
- Fix 2 major bugs that make the chain not MUI for chain effect and Stun effect.
- Due to setting the wrong index. Now it has been fixed and should no longer containt any more bugs! Thanks to my sis for testing out this with me [:
v2.00, 22 Jan 2010
- Revamp the chain effect system.
- Remove dummy type. You still have to copy the dummy to your map though.
- Remove finger of death limitations. Now you can choose your chain effect freely.
- Added a new Chain Effect Trigger.
- This allows the chain to follow the unit if it is moving.
- Polish code.
- Fixed a few bugs in code.
- Added Implementation Details Trigger and tidy up the Example 1-8 Implementations.
- Removed all (SFX) ability as now you can use the QJC_ChainSFX to set your lightning effect.
v1.14, 22 Jan 2010
- Added 2 new abilities chain sheep and chain invisible to show the flexibility of this system and how to play around with stun/slow effect to your advantages.
v1.13a, 22 Jan 2010
- Added a sleep ability in the implementation after Kingz asked me what if he wanted to create a chain sleep. (No additional system code added).
- Fix several bugs.
v1.12, 21 Jan 2010
- Periodic Time change to 0.03seconds. And System Time update + 0.03 from 0.01.
v1.11a, 21 Jan 2010
- Fixed Implementation Example Comment for Chain Effect.
v1.11, 21 Jan 2010
- Initial Release.
======================
Customizable Features
======================
- Damage (Boolean: Only damage enemies nomatter what. If you want to damage ally use health and set ally = true)
- Heal (Boolean: Only heal Allies nomatter what)
- Health (Boolean: Make enemy lose health depending on Amount of Damage Type)
- Mana (Boolean: Make enemy lose mana depending on Amount of Damage Type)
- Gold (Boolean: Make enemy lose gold depending on Amount of Damage Type)
- Leech (Boolean: Only affects Health, Mana, Gold. If true, it will transfer Health/Mana/Gold over to the caster)
- Slow (Boolean: If true, it will slow units depending on slow effect)
- Slow Effect (Ability: The ability of slow effect, BASE ALL SLOW ON HUMAN SORCERESS SLOW!!)
- Stun (Boolean: If true, it will stun units depending on stun effect)
- Stun Effect (Ability: The ability of stun effect, BASE ALL STUN ON STORM BOLT!!)
- AoE (Boolean: If true, it will do AoE damage.)
- AoE Radius (Real: Set the radius of AoE Effect)
- Target Effect (String: Lets you insert your effect path)
- Chain Effect (LightningType: Feel free to choose your lightning effect for the chain)
- Amount of Damage Type (Real: Damage, Heal, Health, Mana, Gold)
- Amount Reduction (Real: Each jump reduce a percentage of amount of damage type)
- Jump Count (Integer: How many units it will jump)
- Jump Radius (Real: The range of how far the chain can jump between units)
- Jump Delay (Real: Supports the chain jump delay seconds. 0.10 is the effect of chain lightning, 0.00 is "ALMOST" instant)
- One Per Unit (Boolean: Chain will only hit the unit once if set to true)
- Priority (Boolean: Hit lowest health 1st)
- Ally (Boolean: Hit Ally if set to true, if enemy is also true, it will hit both)
- Enemy (Boolean: Hit Enemy if set to true, if elly is also true, it will hit both)
- Target Unit (Unit: Target Unit, set to No unit if no target or have a target point)
- Point (Point: Target Point, if has a target unit or no target disable this)
- No Target (Boolean: If true, disable point and set unit to no unit)
- Attack (Attack Type: Customize your own attack type)
- Damage Type (Damage Type: Customize your own damage type)
======================
Rules
======================
They are some rules applied to use this system. Is more of a technical limitation.
I will talk more about this after letting you know how to use.
1. Do not touch anything in Chain Create, Chain Jump and Chain Effect Trigger. Those are the system.
2. For implementation examples. Please look at the 8 examples of how flexible you can change the chain to what you want.
3. This system needs you to know the usage of Unit Editor and Ability/Buff Editor.
4. QJC_VarName, This is the only variables you can set.
5. QJCS_VarName are for system variables. So don't even touch it unless you know what you are doing.
======================
How to Use?
======================
If your map is a New Map without any triggers:
1. Open JeffQ's Basic Chain System map.
2. Open Trigger Editor.
3. File > Export Triggers.
4. Open your map.
5. Open Trigger Editor.
6. File > Import Triggers.
7. Remember to copy the Dummy over too.
If your map has existing triggers:
1. Open JeffQ's Basic Chain System map.
2. Copy JeffQ's Chain System folder by right-clicking it and select Copy.
3. Open your map.
4. File > Preference > Check "Automatically create unknown variables while pasting trigger data".
5. Open Object Editor. Create a Dummy base on anything, name it Dummy and give it locust and remove its model. Or just copy the dummy from my map.
6. Open Trigger Editor.
7. Right click on the Map Name, or any other trigger/category/comments, and select Paste.
8. Create a variable by pressing CTRL+B and name it QJCS_ChainZ of type Real, array size of 1.
9. Go to "Chain Create" Trigger, find any Disabled Actions, enable it by right clicking and check Enable.
10.Go to "Chain Jump" Trigger, find any Disabled Actions, enable it by right clicking and check Enable.
11.Go to "Chain effect" Trigger, find any Disabled Actions, enable it by right clicking and check Enable.
======================
Vars you need to set
======================
QJC_Caster : Triggering Unit
- Your caster.
QJC_TargetUnit : Target unit of ability being cast
- Set this to No unit if your spell is target point or instant cast.
QJC_TargetPoint : Target point of ability being cast
- Disable this if you have a target unit or instant cast.
QJC_NoTarget : True/False
- Set this to true if your spell is instant cast.
- Remember to disable QJC_TargetPoint and set QJC_TargetUnit to No Unit.
QJC_Priority : True/False
- If true, it will find the lowest health unit in range first.
QJC_OnePerUnit : True/False
- If true, it will only hit the target once.
QJC_Damage : True/False
- If true, this chain will do damage to enemy depending on QJC_Amount.
QJC_Heal : True/False
- If true, this chain will heal ally depending on QJC_Amount.
QJC_Health : True/False
- If true, it will make enemy lose health.
- If leech is on, it will transfer health over to the caster.
QJC_Mana : True/False
- If true, it will make enemy lose mana.
- If leech is on, it will transfer mana over to the caster.
QJC_Gold : True/False
- If true, it will make enemy lose gold.
- If leech is on, it will transfer gold over to the caster.
QJC_Leech : True/False
- If true, it will apply leeching effect to Health/Mana/Gold type.
QJC_Ally : True/False
- If true, it will hit ally.
- If enemy is also true, it will hit both.
QJC_Enemy : True/False
- If true, it will hit enemy.
- If ally is also true, it will hit both.
QJC_Amount : Real
- The amount of damage type you want this chain to do.
- Eg: QJCGold = true, QJC_Amount = 100, it will make enemy lose 100gold.
QJC_ChainSFX : Lightning Type
- Feel free to choose the lightning type for your chain.
QJC_TargetSFX : String
- Lets you set the special effect for unit when hit by chain.
QJC_AttackType : Attack Type
- Nothing much to say about this.
QJC_DamageType : Damage Type
- Nothing much to say about this.
QJC_AmountReduce: Real
- This is base on percentage.
- If it is 0.00, each chain jump won't reduce QJC_Amount
- If it is 0.10, each chain jump will decreament QJC_Amount by 10%.
- Least is 0.00, Max is 1.00.
QJC_JumpCount : Integer
- Set the amount of jumps for the chain.
QJC_JumpDelayTime: Real
- This is base on seconds.
- Least is 0.00, Max is 1.00
- Set to 0.10 to get the effect of Blizzard Chain Lightning
QJC_JumpRadius : Real
- How far can the chain jump between points.
QJC_Slow : Boolean
- Set to true to slow enemies.
- You have to set QJC_SlowEffect if you want this to work.
QJC_SlowEffect : Ability
- Disable this if Slow Effect is False.
- Slow effect must base on HUMAN SLOW. NO BUTS!
- For example, go to "Ability Editor > Custom Abilities > Neutral Hostile > Units".
- Slow effect will have a (Slow) behind the name.
QJC_Stun : Boolean
- Set to true to stun enemies.
- You have to set QJC_StunEffect if you want this to work.
QJC_StunEffect : Ability
- Disable this if stun effect is false.
- Stun effect must base on STORM BOLT. NO BUTS!
- For example, go to "Ability Editor > Custom Abilities > Neutral Hostile > Units".
- Stun effect will have a (Stun) behind the name)
QJC_AoE : Boolean
- Set to true to do AoE.
- You have to set QJC_AoERadius to make this work. If not the radius will be 0.00.
QJC_AoERadius : Real
- The AoE range you want.
Trigger - Run Chain Create <gen> (checking conditions)
- This must always be included in the trigger of your spell. If not the system won't run.
- Must check conditions.
======================
Limitations
======================
Q: Why i need to base Chain Effect on Finger of Death?
A: I order the dummy unit to cast fingerofdeath order command. And also finger of death let's you do chain effects while channel can't for some reason.
Q: Why i need to base Slow on Human Sorceress Slow?
A: I order the dummy unit to cast Human Sorceress - Slow when i do this. If you base it on other spells, it just won't work.
Q: Why i need to base Stun on Storm Bolt?
A: I order the dummy unit to cast Human Mountain King - Storm Bolt.
Q: Why must dummy be invulnerable and not Locust? And why must it have no model?
A: Because i order the dummy to finger of death the next dummy. If it is locust, it can't be finger of death for the chain effect. No model makes it unselectable on map and won't display health if you hold down ALT key.
Q: Why not ask the dummy to chain the target? Is so much simpler.
A: No. After 3 days of testing. If the target dies the dummy won't be fast enough to cast the chain, and thus, no chain effect.
Q: So where did you hide that dummy? Where can i find it to copy it to my map?
A: It's at the Object Editor > Unit > Custom Units > Night Elf > Melee > Units. There you can find Dummy. Say hi.
======================
Flexibility
======================
1. If you fully know how to use this system. It is quite flexible as you can set the Slow and Stun effect by changing the buffs of the Abilities.
2. Alot of things stack except for a few limitations. You can set all to true and see what happens [:
3. You can target point, target unit or No Target!
======================
Bug Reports & Feedback
======================
Please send an email to [email protected] if you find a bug. Or post it on the comment at Hive Work Shop.
======================
Credits
======================
Thanks to the below who shed some light on me about indexing and leaks.
- Kingz
- YourNameHere
- baassee
- Adiktuz
- Maker
- TitanHex
- D4RK_G4ND4LF
- And other people if i miss out.
Special Thanks to Kingz who show me his simple lightning system. I learned alot from it and after understanding i made 1 my own to fit my system.
***Enjoy this system [:
// ---------------------------------------------------------------- //
// Passive Cooldown System [GUI Friendly] v1.04 //
// by Flux //
// http://www.hiveworkshop.com/forums/members/flux/ //
// ---------------------------------------------------------------- //
// //
// This system allows you to make any unit's ability goes into cooldown via trigger //
// Though written in Jass, it has GUI support and easy to use for GUI users //
// Even if the name shows "Passive Cooldown", it can be applied on Active Abilities as well //
// (as show in Demo 3) but this system is mostly intended for Passive Abilities. //
// //
// HOW TO IMPORT: //
// 1. Copy the PCD_IndicatorStart and PCD_ValidTargetCheck Ability to your map //
// 2. Copy the PCD_DummyCaster Unit to your map //
// 3. Configure the PCD_DummyCasterId, PCD_IndicatorStartId, PCD_ValidTargetCheckId //
// and PCD_VTCBaseOrderId in PCD System Configuration Trigger. //
// 4. Copy PCD Variable Creator to your map to automatically create the system's variables. //
// Make sure you check the "Automatically create unknown variables while pasting trigger //
// data" in File->Preferences of World Editor. After the variables are created, you can //
// then delete the 'PCD Variable Creator' trigger. //
// //
// //
// HOW TO USE: //
// 1. Set the PCD_Unit variable. This refers to the unit that will have its ability //
// goes into cooldown via trigger. //
// 2. Set the PCD_Ability variable. This refers to the ability that will go into cooldown. //
// 3. Set the PCD_DummyAbility variable. This refers to the ability based on Spell Shield //
// that you have created. It must have the same tooltip, manacost and icon. //
// 4. Set the PCD_Time variable. This refers how long the PCD_Ability will be replaced by //
// the PCD_DummyAbility. It should match the 'Stats - Cooldown' of the PCD_DummyAbility. //
// 5. Set the PCD_Manacost variable. This is the manacost of the PCD_Ability which should //
// match the manacost of the PCD_DummyAbility 'Stats - Manacost' if you don't want //
// the unit to lose mana when you trigger it's cooldown. //
// 6. Execute by "Trigger - Run Trigger Cooldown System <gen> (checking conditions)" //
// //
// //
// Notes: //
// - When triggering the cooldown of an active ability, it will reset the original //
// ability's cooldown. Example: Original Ability's is on cooldown for 20 seconds but //
// the triggered cooldown only last 5 seconds, when that 5 seconds is finished, //
// the original ability is now ready to be use again. //
// - Can only trigger Unit ability so far, so to trigger a Hero's ability, a dummy hero //
// ability must be used and when the dummy ability is learned, add the real ability. //
// (As shown in Map Demo 3) //
// //
// Works on: //
// - Invulnerable, Spell Immune, Structures, Ancient, //
// Mechanical, Invisible (but removes it) //
// Does not work on: //
// - Hidden, Cycloned //
// //
// CREDITS: //
// Xonok - for the Spell Block trick to simulate cooldown //
// Wietlol - for finding bugs and suggesting solutions to it. //
//-------------------------------------------------------------------------------------------------//
//-------------------------------------- SYSTEM CORE ----------------------------------------------//
//-------------------------------------------------------------------------------------------------//
function Trig_Passive_Cooldown_System_TimerExpires takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local unit u = LoadUnitHandle(udg_PCD_Hashtable, id, 0)
local integer origAbil = LoadInteger(udg_PCD_Hashtable, id, 0)
local integer fakeAbil = LoadInteger(udg_PCD_Hashtable, id, 1)
local integer lvl = GetUnitAbilityLevel(u, fakeAbil)
call UnitAddAbility(u, origAbil)
if lvl > 1 then
call SetUnitAbilityLevel(u, origAbil, lvl)
endif
call UnitRemoveAbility(u, fakeAbil)
//Destroy the timer reference data
call FlushChildHashtable(udg_PCD_Hashtable, id)
//Destroy the unit reference data
call FlushChildHashtable(udg_PCD_Hashtable, GetHandleId(u))
call DestroyTimer(t)
set t = null
set u = null
endfunction
function Trig_Passive_Cooldown_System_Execute takes nothing returns boolean
local timer t
local integer id
local integer unitId
local integer lvl
set lvl = GetUnitAbilityLevel(udg_PCD_Unit, udg_PCD_Ability)
call SetUnitX(udg_PCD_DummyCaster, GetUnitX(udg_PCD_Unit))
call SetUnitY(udg_PCD_DummyCaster, GetUnitY(udg_PCD_Unit))
//For checking if it is castable
call SetPlayerAlliance(Player(14), GetOwningPlayer(udg_PCD_Unit), ALLIANCE_PASSIVE, true)
if IssueTargetOrder(udg_PCD_DummyCaster, udg_PCD_VTCBaseOrderId, udg_PCD_Unit) then
if lvl > 0 then
call UnitRemoveAbility(udg_PCD_Unit, udg_PCD_Ability)
else
set lvl = GetUnitAbilityLevel(udg_PCD_Unit, udg_PCD_DummyAbility)
call UnitRemoveAbility(udg_PCD_Unit, udg_PCD_DummyAbility)
endif
//Add the fake ability
call UnitAddAbility(udg_PCD_Unit, udg_PCD_DummyAbility)
call SetUnitAbilityLevel(udg_PCD_Unit, udg_PCD_DummyAbility, lvl)
call IssueTargetOrderById(udg_PCD_DummyCaster, 852075, udg_PCD_Unit)
set unitId = GetHandleId(udg_PCD_Unit)
//[unitId][5] is for timers
//If there is already a timer, just reset it
if HaveSavedHandle(udg_PCD_Hashtable, unitId, udg_PCD_Ability) then
call TimerStart(LoadTimerHandle(udg_PCD_Hashtable, unitId, udg_PCD_Ability), udg_PCD_Time, false, function Trig_Passive_Cooldown_System_TimerExpires)
else
set t = CreateTimer()
set id = GetHandleId(t)
//Save the timer in reference to the unit
call SaveTimerHandle(udg_PCD_Hashtable, unitId, udg_PCD_Ability, t)
call TimerStart(t, udg_PCD_Time, false, function Trig_Passive_Cooldown_System_TimerExpires)
set t = null
//Save the unit
call SaveUnitHandle(udg_PCD_Hashtable, id, 0, udg_PCD_Unit)
//Save the original ability replaced
call SaveInteger(udg_PCD_Hashtable, id, 0, udg_PCD_Ability)
//Save the fake ability
call SaveInteger(udg_PCD_Hashtable, id, 1, udg_PCD_DummyAbility)
endif
if udg_PCD_Manacost > 0 then
call SetUnitState(udg_PCD_Unit, UNIT_STATE_MANA, GetUnitState(udg_PCD_Unit, UNIT_STATE_MANA) + udg_PCD_Manacost)
endif
endif
call SetPlayerAlliance(Player(14), GetOwningPlayer(udg_PCD_Unit), ALLIANCE_PASSIVE, false)
return false
endfunction
function Trig_Passive_Cooldown_System_LastInit takes nothing returns nothing
set udg_PCD_DummyCaster = CreateUnit(Player(14), udg_PCD_DummyCasterId, 0, 0, 0)
call SetHeroLevel(udg_PCD_DummyCaster, 6, false)
call UnitAddAbility(udg_PCD_DummyCaster, udg_PCD_IndicatorStartId)
call SelectHeroSkill(udg_PCD_DummyCaster, udg_PCD_IndicatorStartId)
call UnitAddAbility(udg_PCD_DummyCaster, udg_PCD_ValidTargetCheckId)
call DestroyTimer(GetExpiredTimer())
endfunction
//===========================================================================
function InitTrig_Passive_Cooldown_System takes nothing returns nothing
set gg_trg_Passive_Cooldown_System = CreateTrigger()
set udg_PCD_Hashtable = InitHashtable()
call TimerStart(CreateTimer(), 0, false, function Trig_Passive_Cooldown_System_LastInit)
call TriggerAddCondition(gg_trg_Passive_Cooldown_System, Condition(function Trig_Passive_Cooldown_System_Execute))
endfunction
//===========================================================================
function UnitEventDestroyGroup takes integer i returns nothing
if udg_CargoTransportGroup[i] != null then
call DestroyGroup(udg_CargoTransportGroup[i])
set udg_CargoTransportGroup[i] = null
endif
endfunction
function UnitEventCheckAfter takes nothing returns nothing
local integer i = 0
loop
set i = udg_CheckDeathList[i]
exitwhen i == 0
if udg_IsUnitNew[i] then
//The unit was just created.
set udg_IsUnitNew[i] = false
elseif udg_IsUnitTransforming[i] then
//Added 21 July 2017 to fix the issue re-adding this ability in the same instant
set udg_UDex = i
set udg_UnitTypeEvent = 0.00
set udg_UnitTypeEvent = 1.00
set udg_UnitTypeOf[i] = GetUnitTypeId(udg_UDexUnits[i]) //Set this afterward to give the user extra reference
set udg_IsUnitTransforming[i] = false
call UnitAddAbility(udg_UDexUnits[i], udg_DetectTransformAbility)
elseif udg_IsUnitAlive[i] then
//The unit has started reincarnating.
set udg_IsUnitReincarnating[i] = true
set udg_IsUnitAlive[i] = false
set udg_UDex = i
set udg_DeathEvent = 0.50
set udg_DeathEvent = 0.00
endif
set udg_CheckDeathInList[i] = false
endloop
//Empty the list
set udg_CheckDeathList[0] = 0
endfunction
function UnitEventCheckAfterProxy takes integer i returns nothing
if udg_CheckDeathList[0] == 0 then
call TimerStart(udg_CheckDeathTimer, 0.00, false, function UnitEventCheckAfter)
endif
if not udg_CheckDeathInList[i] then
set udg_CheckDeathList[i] = udg_CheckDeathList[0]
set udg_CheckDeathList[0] = i
set udg_CheckDeathInList[i] = true
endif
endfunction
function UnitEventOnUnload takes nothing returns nothing
local integer i = udg_UDex
call GroupRemoveUnit(udg_CargoTransportGroup[GetUnitUserData(udg_CargoTransportUnit[i])], udg_UDexUnits[i])
set udg_IsUnitBeingUnloaded[i] = true
set udg_CargoEvent = 0.00
set udg_CargoEvent = 2.00
set udg_CargoEvent = 0.00
set udg_IsUnitBeingUnloaded[i] = false
if not IsUnitLoaded(udg_UDexUnits[i]) or IsUnitType(udg_CargoTransportUnit[i], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_CargoTransportUnit[i]) == 0 then
set udg_CargoTransportUnit[i] = null
endif
endfunction
function UnitEventOnDeath takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_UDex != 0 then
set udg_KillerOfUnit[udg_UDex] = GetKillingUnit() //Added 29 May 2017 for GIMLI_2
set udg_IsUnitAlive[udg_UDex] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
set udg_KillerOfUnit[udg_UDex] = null
if udg_CargoTransportUnit[udg_UDex] != null then
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnOrder takes nothing returns boolean
local integer pdex = udg_UDex
local unit u = GetFilterUnit()
local integer i = GetUnitUserData(u)
if i > 0 then
set udg_UDex = i
if GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
if not udg_IsUnitRemoved[i] then
set udg_IsUnitRemoved[i] = true
set udg_IsUnitAlive[i] = false
set udg_SummonerOfUnit[i] = null
//For backwards-compatibility:
set udg_DeathEvent = 0.00
set udg_DeathEvent = 3.00
set udg_DeathEvent = 0.00
//Fire deindex event for UDex:
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 2.00
set udg_UnitIndexEvent = 0.00
set udg_UDexNext[udg_UDexPrev[i]] = udg_UDexNext[i]
set udg_UDexPrev[udg_UDexNext[i]] = udg_UDexPrev[i]
// Recycle the index for later use
set udg_UDexUnits[i] = null
set udg_UDexPrev[i] = udg_UDexLastRecycled
set udg_UDexLastRecycled = i
call UnitEventDestroyGroup(i)
endif
elseif not udg_IsUnitAlive[i] then
if not IsUnitType(u, UNIT_TYPE_DEAD) then
set udg_IsUnitAlive[i] = true
set udg_DeathEvent = 0.00
set udg_DeathEvent = 2.00
set udg_DeathEvent = 0.00
set udg_IsUnitReincarnating[i] = false
endif
elseif IsUnitType(u, UNIT_TYPE_DEAD) then
if udg_IsUnitNew[i] then
//This unit was created as a corpse.
set udg_IsUnitAlive[i] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
elseif udg_CargoTransportUnit[i] == null or not IsUnitType(u, UNIT_TYPE_HERO) then
//The unit may have just started reincarnating.
call UnitEventCheckAfterProxy(i)
endif
elseif GetUnitAbilityLevel(u, udg_DetectTransformAbility) == 0 and not udg_IsUnitTransforming[i] then
set udg_IsUnitTransforming[i] = true
call UnitEventCheckAfterProxy(i) //This block has been updated on 21 July 2017
endif
if udg_CargoTransportUnit[i] != null and not udg_IsUnitBeingUnloaded[i] and not IsUnitLoaded(u) or IsUnitType(u, UNIT_TYPE_DEAD) then
call UnitEventOnUnload()
endif
set udg_UDex = pdex
endif
set u = null
return false
endfunction
function UnitEventOnSummon takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_IsUnitNew[udg_UDex] then
set udg_SummonerOfUnit[udg_UDex] = GetSummoningUnit()
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 0.50
set udg_UnitIndexEvent = 0.00
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnLoad takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = GetUnitUserData(GetTriggerUnit())
local integer index
if i != 0 then
set udg_UDex = i
if udg_CargoTransportUnit[i] != null then
call UnitEventOnUnload()
endif
//Loaded corpses do not issue an order when unloaded, therefore must
//use the enter-region event method taken from Jesus4Lyf's Transport.
if not udg_IsUnitAlive[i] then
call SetUnitX(udg_UDexUnits[i], udg_WorldMaxX)
call SetUnitY(udg_UDexUnits[i], udg_WorldMaxY)
endif
set udg_CargoTransportUnit[i] = GetTransportUnit()
set index = GetUnitUserData(udg_CargoTransportUnit[i])
if udg_CargoTransportGroup[index] == null then
set udg_CargoTransportGroup[index] = CreateGroup()
endif
call GroupAddUnit(udg_CargoTransportGroup[index], udg_UDexUnits[i])
set udg_CargoEvent = 0.00
set udg_CargoEvent = 1.00
set udg_CargoEvent = 0.00
set udg_UDex = pdex
endif
return false
endfunction
function UnitEventEnter takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = udg_UDexLastRecycled
local unit u = GetFilterUnit()
if udg_UnitIndexerEnabled and GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
//Generate a unique integer index for this unit
if i == 0 then
set i = udg_UDexMax + 1
set udg_UDexMax = i
else
set udg_UDexLastRecycled = udg_UDexPrev[i]
endif
//Link index to unit, unit to index
set udg_UDexUnits[i] = u
call SetUnitUserData(u, i)
//For backwards-compatibility, add the unit to a linked list
set udg_UDexNext[i] = udg_UDexNext[0]
set udg_UDexPrev[udg_UDexNext[0]] = i
set udg_UDexNext[0] = i
set udg_UDexPrev[i] = 0
set udg_CheckDeathInList[i] = false
call UnitAddAbility(u, udg_DetectRemoveAbility)
call UnitMakeAbilityPermanent(u, true, udg_DetectRemoveAbility)
call UnitAddAbility(u, udg_DetectTransformAbility)
set udg_UnitTypeOf[i] = GetUnitTypeId(u)
set udg_IsUnitNew[i] = true
set udg_IsUnitAlive[i] = true
set udg_IsUnitRemoved[i] = false
set udg_IsUnitReincarnating[i] = false
set udg_IsUnitPreplaced[i] = udg_IsUnitPreplaced[0] //Added 29 May 2017 for Spellbound
call UnitEventCheckAfterProxy(i)
//Fire index event for UDex
set udg_UDex = i
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 1.00
set udg_UnitIndexEvent = 0.00
else
set udg_UDex = GetUnitUserData(u)
if udg_CargoTransportUnit[udg_UDex] != null and not IsUnitLoaded(u) then
//The unit was dead, but has re-entered the map.
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
set u = null
return false
endfunction
//===========================================================================
function UnitEventInit takes nothing returns nothing
local integer i = bj_MAX_PLAYER_SLOTS //update to make it work with 1.29
local player p
local trigger t = CreateTrigger()
local trigger load = CreateTrigger()
local trigger death = CreateTrigger()
local trigger summon = CreateTrigger()
local rect r = GetWorldBounds()
local region re = CreateRegion()
local boolexpr enterB = Filter(function UnitEventEnter)
local boolexpr orderB = Filter(function UnitEventOnOrder)
set udg_WorldMaxX = GetRectMaxX(r)
set udg_WorldMaxY = GetRectMaxY(r)
call RegionAddRect(re, r)
call RemoveRect(r)
call UnitEventDestroyGroup(0)
call UnitEventDestroyGroup(1)
set udg_CheckDeathList[0] = 0
set udg_UnitIndexerEnabled = true
call TriggerRegisterEnterRegion(CreateTrigger(), re, enterB)
call TriggerAddCondition(load, Filter(function UnitEventOnLoad))
call TriggerAddCondition(death, Filter(function UnitEventOnDeath))
call TriggerAddCondition(summon, Filter(function UnitEventOnSummon))
loop
set i = i - 1
set p = Player(i)
call SetPlayerAbilityAvailable(p, udg_DetectRemoveAbility, false)
call SetPlayerAbilityAvailable(p, udg_DetectTransformAbility, false)
call TriggerRegisterPlayerUnitEvent(summon, p, EVENT_PLAYER_UNIT_SUMMON, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, orderB)
call TriggerRegisterPlayerUnitEvent(death, p, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerRegisterPlayerUnitEvent(load, p, EVENT_PLAYER_UNIT_LOADED, null)
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, enterB)
exitwhen i == 0
endloop
set summon = null
set death = null
set load = null
set re = null
set enterB = null
set orderB = null
set p = null
set r = null
set t = null
endfunction
function InitTrig_Unit_Event takes nothing returns nothing
endfunction