- Joined
- Mar 8, 2009
- Messages
- 360
//===========================================================================
//
// Time Stop
//
// Stops the time for all enemy units within
// an area around the caster
// Does not target magic immune or mechanical units
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
// Import
// ¯¯¯¯¯¯
// Copy and paste these triggers* to your map:
// - Time Stop
// - TimerUtils
// - GroupUtils
// - PauseUtils
// Copy and paste these objects to your map:
// - Abilities\\SPELL_ID
// - Units\\EFFECT_DUMMY_ID
// - Units\\DUMMY_ID
// Make sure the Setup section contains all the correct rawcodes:
// - SPELL_ID
// - DUMMY_ID
// - EFFECT_DUMMY_ID
//
// * Trigger window objects
//
//
// Pros and Cons
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
// [+] Follows the JESP standard (document included in this map)
// [+] Fully customizable in a clear Setup section
// [+] 100% Multi User Instancable
// [+] Easy to import with no configuration problems
// [+] Neat special effect with lots of customization
// [+] Should be leakless, though one can never be sure
// [-] Requires an additional unit
// [-] Special effect settings outside the Setup section
// [-] If you use other spells with the PauseUnit() native,
// you have to replace it with PauseUnitEx() or Time Stop
// will cause bugs
//
//
// For more information please check out this map's documentation folder,
// or - if you found it in a public map - the official upload page:
// hiveworkshop.com/forums/spells-569/vjass-jesp-time-stop-1-2-a-133719/
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
//
// ____________________
// I Version 1.3 I
// I Made by Cheezeman I
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
//===========================================================================
scope TimeStop initializer Initialize
//===========================================================================
//=============================== SETUP =====================================
//===========================================================================
globals
private constant integer SPELL_ID = 'A000' //The rawcode of the spell the Hero uses
private constant integer DUMMY_ID = 'h000' //The rawcode of the normal dummy unit (used for preload)
private constant integer EFFECT_DUMMY_ID = 'h003' //The rawcode of the special effect dummy unit
//NOTE: To change the special effect, open the EFFECT_DUMMY_ID inside the Object Editor and change "Art - Model File"
endglobals
private constant function Duration takes integer level returns real
return 3. + ( 2. * level ) //The duration of the spell
endfunction
private constant function AreaOfEffect takes integer level returns real
return 150. + ( 150. * level ) //The area the spell affects
endfunction
private function AllowedTargets takes unit caster, unit target returns boolean
//These are the conditions the target must meet.
//If you want to add more, simply copy a line, paste it inside the block
//and modify it to a statement.
return /*
//==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== //The target...
*/ IsUnitEnemy( target, GetOwningPlayer( caster ) ) and /* //- must be an enemy
*/ GetWidgetLife( target ) > 0.405 and /* //- must be alive
*/ IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false and /* //- mustn't be magic immune
*/ IsUnitType( target, UNIT_TYPE_STRUCTURE ) == false and /* //- mustn't be a structure
*/ IsUnitType( target, UNIT_TYPE_MECHANICAL ) == false and /* //- mustn't be mechanical
//==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
*/ true
endfunction
//========================== Advanced Setup =========================
//======= These functions are for 'advanced' Jass/vJass users =======
private function AdditionalSpecialEffects takes unit Effect, real casters_current_height returns nothing
call SetUnitScale( Effect, 2., 2., 2. )
call SetUnitFlyHeight( Effect, casters_current_height + 100., 0. )
//Here you can tweak the special effect even more.
//You can colorize it, make it move, spin and lots of other things
//(the 'effect' is a unit, so it has all the options a normal unit has)
endfunction
private function RevertTimeScale takes unit target returns nothing
call SetUnitTimeScale( target, 1. )
//If your map already utilize the TimeScale for other purposes,
//you can add an If/Then/Else statement to revert its TimeScale
//to the one it had before ('original' TimeScale)
endfunction
private function PreloadTimeStop takes nothing returns nothing
set bj_lastCreatedUnit = CreateUnit( Player( 15 ), DUMMY_ID, 0, 0, 0 )
call UnitAddAbility( bj_lastCreatedUnit, SPELL_ID )
call KillUnit( bj_lastCreatedUnit )
//This is the preload the ability is using.
//If you're using xe in your map, just replace this with XE_PreloadAbility(SPELL_ID)
//(or whatever the function is named)
//Before I get any stupid comments on these lines, note that bj_ variables are not
//evil. Only BJ >>Functions<< are evil.
endfunction
//===========================================================================
//============================= END SETUP ===================================
//================ Don't mess with the code below this line =================
//===========================================================================
globals
private hashtable Hash
private unit TemporareCaster
private boolexpr Target_Checker
private boolexpr DummyFilter
private trigger BugfixTrigger
private integer ReferanceCounter = 0
endglobals
//===========================================================================
private function Pick takes nothing returns boolean
return AllowedTargets( TemporareCaster, GetFilterUnit() )
endfunction
private constant function AntiLeakFilter takes nothing returns boolean
return true
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endfunction
private function Bugfix_Conditions takes nothing returns boolean
return LoadInteger( Hash, 1, GetHandleId( GetTriggerUnit() ) ) > 0
endfunction
//============================ Main script ==================================
private function PauseTargets takes nothing returns nothing
local unit enum = GetEnumUnit()
call SaveInteger( Hash, 1, GetHandleId( enum ), LoadInteger( Hash, 1, GetHandleId( enum ) ) + 1 )
call PauseUnitEx( enum, true )
call SetUnitTimeScale( enum, 0. )
set enum = null
endfunction
private function UnpauseTargets takes nothing returns nothing
local unit enum = GetEnumUnit()
local integer enum_id = GetHandleId( enum )
//Although it uses PauseUtils, it still requires to check if it should reset time scale
call PauseUnitEx( enum, false )
call SaveInteger( Hash, 1, enum_id, LoadInteger( Hash, 1, enum_id ) - 1 )
if LoadInteger( Hash, 1, enum_id ) <= 0 then
call RemoveSavedInteger( Hash, 1, enum_id )
call RevertTimeScale( enum )
endif
set enum = null
endfunction
private function ActionsContinued takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer t_dat = GetHandleId( t )
call ForGroup( LoadGroupHandle( Hash, 2, t_dat ), function UnpauseTargets )
call SetUnitTimeScale( LoadUnitHandle( Hash, 3, t_dat ), 5. )
set ReferanceCounter = ReferanceCounter - 1
if ReferanceCounter <= 0. then
set ReferanceCounter = 0
call DisableTrigger( BugfixTrigger )
endif
call ReleaseGroup( LoadGroupHandle( Hash, 2, t_dat ) )
call ReleaseTimer( t )
call RemoveSavedHandle( Hash, 2, t_dat )
call RemoveSavedHandle( Hash, 3, t_dat )
set t = null
endfunction
private function Actions takes nothing returns nothing
local unit caster = GetTriggerUnit()
local integer caster_id = GetHandleId( caster )
local real casterX = GetUnitX( caster )
local real casterY = GetUnitY( caster )
local integer level = GetUnitAbilityLevel( caster, SPELL_ID )
local real duration = Duration( level )
local real caster_fly = GetUnitFlyHeight( caster )
local timer t = NewTimer()
local unit dummy = CreateUnit( GetOwningPlayer( caster ), EFFECT_DUMMY_ID, casterX, casterY, 0.00 )
local group g = NewGroup()
set TemporareCaster = caster
set ReferanceCounter = ReferanceCounter + 1
call EnableTrigger( BugfixTrigger )
call SaveUnitHandle( Hash, 3, caster_id, dummy )
call AdditionalSpecialEffects( dummy, caster_fly )
call UnitApplyTimedLife( dummy, 'BTLF', duration )
call SetUnitTimeScale( dummy, 1. / duration )
call GroupEnumUnitsInRange( g, casterX, casterY, AreaOfEffect( level ), Target_Checker )
call SaveGroupHandle( Hash, 2, GetHandleId( t ), g )
call ForGroup( g, function PauseTargets )
call TimerStart( t, duration, false, function ActionsContinued )
set caster = null
set dummy = null
set t = null
set g = null
endfunction
private function Bugfix_Actions takes nothing returns nothing
call RevertTimeScale( GetTriggerUnit() )
endfunction
//============================= Initialze ===================================
private function Initialize takes nothing returns nothing
local integer ForLoop = 0
local trigger spell = CreateTrigger()
set BugfixTrigger = CreateTrigger()
set Target_Checker = Condition( function Pick )
set DummyFilter = Condition( function AntiLeakFilter )
set Hash = InitHashtable()
call DisableTrigger( BugfixTrigger )
call PreloadTimeStop()
loop
exitwhen ForLoop > 15
call TriggerRegisterPlayerUnitEvent( spell, Player(ForLoop), EVENT_PLAYER_UNIT_SPELL_EFFECT, DummyFilter )
call TriggerRegisterPlayerUnitEvent( BugfixTrigger, Player( ForLoop ), EVENT_PLAYER_UNIT_DEATH, DummyFilter )
set ForLoop = ForLoop + 1
endloop
call TriggerAddCondition( spell, Condition( function Conditions ) )
call TriggerAddAction( spell, function Actions )
call TriggerAddCondition( BugfixTrigger, Condition( function Bugfix_Conditions ) )
call TriggerAddAction( BugfixTrigger, function Bugfix_Actions )
endfunction
endscope
//===========================================================================
//
// Time Stop
// [Jass version]
//
// Stops the time for all enemy units within
// an area around the caster
// Does not target magic immune or mechanical units
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
// Import
// ¯¯¯¯¯¯
// - Copy this trigger* (only this trigger) to your map
// - Copy and paste these objects to your map:
// Abilities\\udg_TimeStop__SPELL_ID
// Units\\udg_TimeStop__EFFECT_DUMMY_ID
// Units\\udg_TimeStop__DUMMY_ID
// - Create these variables in your map:
// [Name] [Type]
// TimeStop__Bugfix trigger
// TimeStop__DUMMY_ID integer
// TimeStop__EFFECT_DUMMY_ID integer
// TimeStop__Hash hashtable
// TimeStop__RefCount integer
// TimeStop__SPELL_ID integer
// TimeStop__TempCast unit
// //You may rename these later, as long as the first time you
// //create them they have these names.
// - Make sure the Setup section contains all the correct rawcodes:
// udg_TimeStop__SPELL_ID
// udg_TimeStop__DUMMY_ID
// udg_TimeStop__EFFECT_DUMMY_ID
// - If you get a compile error, make sure the name of this trigger is "TimeStop Jass"
// You can rename it after you've saved.
//
// * Trigger window object
//
//
// Pros and Cons
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
// [+] Follows the JESP standard (document included in this map)
// [+] Fully customizable in a clear Setup section
// [+] 100% Multi User Instancable
// [+] Easy to import with no configuration problems
// [+] Neat special effect with lots of customization
// [+] Should be leakless, though one can never be sure
// [-] Requires an additional unit
// [-] Special effect settings outside the Setup section
// [-] If you use other spells with the PauseUnit() native,
// this spell will cause bugs.
//
//
// For more information please check out this map's documentation folder,
// or - if you found it in a public map - the official upload page:
// hiveworkshop.com/forums/spells-569/vjass-jesp-time-stop-1-2-a-133719/
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
//
// ____________________
// I Version 1.3.2 I
// I Made by Cheezeman I
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
//===========================================================================
//===========================================================================
//=============================== SETUP =====================================
//===========================================================================
function TimeStop__Setup takes nothing returns nothing
set udg_TimeStop__SPELL_ID = 'A000' //The rawcode of the spell the Hero uses
set udg_TimeStop__DUMMY_ID = 'h000' //The rawcode of the normal dummy unit (used for preload)
set udg_TimeStop__EFFECT_DUMMY_ID = 'h003' //The rawcode of the special effect dummy unit
endfunction
constant function TimeStop__Duration takes integer level returns real
return 3. + ( 2. * level ) //The duration of the spell
endfunction
constant function TimeStop__AreaOfEffect takes integer level returns real
return 150. + ( 150. * level ) //The area the spell affects
endfunction
function TimeStop__AllowedTargets takes unit caster,unit target returns boolean
local boolean b = true
//These are the conditions the target must meet.
//If you want to add more, simply copy a line, paste it inside the block
//and modify it to a statement.
set b = b and IsUnitEnemy(target , GetOwningPlayer(caster))
set b = b and GetWidgetLife(target) > 0.405
set b = b and IsUnitType(target , UNIT_TYPE_MAGIC_IMMUNE) == false
set b = b and IsUnitType(target , UNIT_TYPE_STRUCTURE) == false
set b = b and IsUnitType(target , UNIT_TYPE_MECHANICAL) == false
return b
endfunction
//========================== Advanced Setup =========================
//======= These functions are for 'advanced' Jass/vJass users =======
function TimeStop__AdditionalSpecialEffects takes unit Effect,real casters_current_height returns nothing
call SetUnitScale(Effect , 2. , 2. , 2.)
call SetUnitFlyHeight(Effect , casters_current_height + 100. , 0.)
//Here you can tweak the special effect even more.
//You can colorize it, make it move, spin and lots of other things
//(the 'effect' is a unit, so it has all the options a normal unit has)
endfunction
function TimeStop__RevertTimeScale takes unit target returns nothing
call SetUnitTimeScale(target , 1.)
//If your map already utilize the TimeScale for other purposes,
//you can add an If/Then/Else statement to revert its TimeScale
//to the one it had before ('original' TimeScale)
endfunction
function TimeStop__PreloadTimeStop takes nothing returns nothing
set bj_lastCreatedUnit = CreateUnit(Player(15) , udg_TimeStop__DUMMY_ID , 0 , 0 , 0)
call UnitAddAbility(bj_lastCreatedUnit , udg_TimeStop__SPELL_ID)
call KillUnit(bj_lastCreatedUnit)
//This is the preload the ability is using.
//If you're using xe in your map, just replace this with XE_PreloadAbility(SPELL_ID)
//(or whatever the function is named)
//Before I get any stupid comments on these lines, note that bj_ variables are not
//evil. Only BJ >>Functions<< are evil.
endfunction
//===========================================================================
//============================= END SETUP ===================================
//================ Don't mess with the code below this line =================
//===========================================================================
function TimeStop__Pick takes nothing returns boolean
return TimeStop__AllowedTargets(udg_TimeStop__TempCast , GetFilterUnit())
endfunction
function TimeStop__Conditions takes nothing returns boolean
return GetSpellAbilityId() == udg_TimeStop__SPELL_ID
endfunction
function TimeStop__Bugfix_Conditions takes nothing returns boolean
return LoadInteger(udg_TimeStop__Hash , 1 , GetHandleId(GetTriggerUnit())) > 0
endfunction
//============================ Main script ==================================
function TimeStop__PauseTargets takes nothing returns nothing
local unit enum= GetEnumUnit()
call SaveInteger(udg_TimeStop__Hash , 1 , GetHandleId(enum) , LoadInteger(udg_TimeStop__Hash , 1 , GetHandleId(enum)) + 1)
call PauseUnit(enum , true)
call SetUnitTimeScale(enum , 0.)
set enum = null
endfunction
function TimeStop__UnpauseTargets takes nothing returns nothing
local unit enum= GetEnumUnit()
local integer enum_id= GetHandleId(enum)
call SaveInteger(udg_TimeStop__Hash , 1 , enum_id , LoadInteger(udg_TimeStop__Hash , 1 , enum_id) - 1)
if LoadInteger(udg_TimeStop__Hash , 1 , enum_id) <= 0 then
call RemoveSavedInteger(udg_TimeStop__Hash , 1 , enum_id)
call TimeStop__RevertTimeScale(enum)
call PauseUnit(enum , false)
endif
set enum = null
endfunction
function TimeStop__ActionsContinued takes nothing returns nothing
local timer t= GetExpiredTimer()
local integer t_dat= GetHandleId(t)
call ForGroup(LoadGroupHandle(udg_TimeStop__Hash , 2 , t_dat) , function TimeStop__UnpauseTargets)
call SetUnitTimeScale(LoadUnitHandle(udg_TimeStop__Hash , 3 , t_dat) , 5.)
set udg_TimeStop__RefCount = udg_TimeStop__RefCount - 1
if udg_TimeStop__RefCount <= 0. then
set udg_TimeStop__RefCount = 0
call DisableTrigger(udg_TimeStop__Bugfix)
endif
call DestroyGroup(LoadGroupHandle(udg_TimeStop__Hash , 2 , t_dat))
call DestroyTimer(t)
call RemoveSavedHandle(udg_TimeStop__Hash , 2 , t_dat)
call RemoveSavedHandle(udg_TimeStop__Hash , 3 , t_dat)
set t = null
endfunction
function TimeStop__Actions takes nothing returns nothing
local unit caster= GetTriggerUnit()
local integer caster_id= GetHandleId(caster)
local real casterX= GetUnitX(caster)
local real casterY= GetUnitY(caster)
local integer level= GetUnitAbilityLevel(caster , udg_TimeStop__SPELL_ID)
local real duration= TimeStop__Duration(level)
local real caster_fly= GetUnitFlyHeight(caster)
local timer t= CreateTimer()
local unit dummy= CreateUnit(GetOwningPlayer(caster) , udg_TimeStop__EFFECT_DUMMY_ID , casterX , casterY , 0.00)
local group g= CreateGroup()
local boolexpr b= Condition(function TimeStop__Pick)
set udg_TimeStop__TempCast = caster
set udg_TimeStop__RefCount = udg_TimeStop__RefCount + 1
call EnableTrigger(udg_TimeStop__Bugfix)
call SaveUnitHandle(udg_TimeStop__Hash , 3 , caster_id , dummy)
call TimeStop__AdditionalSpecialEffects(dummy , caster_fly)
call UnitApplyTimedLife(dummy , 'BTLF' , duration)
call SetUnitTimeScale(dummy , 1. / duration)
call GroupEnumUnitsInRange(g , casterX , casterY , TimeStop__AreaOfEffect(level) , b)
call SaveGroupHandle(udg_TimeStop__Hash , 2 , GetHandleId(t) , g)
call ForGroup(g , function TimeStop__PauseTargets)
call TimerStart(t , duration , false , function TimeStop__ActionsContinued)
set caster = null
set dummy = null
set t = null
set g = null
endfunction
function TimeStop__Bugfix_Actions takes nothing returns nothing
call TimeStop__RevertTimeScale(GetTriggerUnit())
endfunction
//============================= Initialze ===================================
function InitTrig_TimeStop_Jass takes nothing returns nothing
local integer ForLoop= 0
local trigger spell= CreateTrigger()
call TimeStop__Setup()
set udg_TimeStop__Bugfix = CreateTrigger()
set udg_TimeStop__Hash = InitHashtable()
call DisableTrigger(udg_TimeStop__Bugfix)
call TimeStop__PreloadTimeStop()
loop
exitwhen ForLoop > 15
call TriggerRegisterPlayerUnitEvent(spell , Player(ForLoop) , EVENT_PLAYER_UNIT_SPELL_EFFECT , null )
call TriggerRegisterPlayerUnitEvent(udg_TimeStop__Bugfix , Player(ForLoop) , EVENT_PLAYER_UNIT_DEATH , null)
set ForLoop = ForLoop + 1
endloop
call TriggerAddCondition(spell , Condition(function TimeStop__Conditions))
call TriggerAddAction(spell , function TimeStop__Actions)
call TriggerAddCondition(udg_TimeStop__Bugfix , Condition(function TimeStop__Bugfix_Conditions))
call TriggerAddAction(udg_TimeStop__Bugfix , function TimeStop__Bugfix_Actions)
endfunction