//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
HASH | hashtable | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
[COLOR="Yellow"][B][SIZE="3"]Confinement v1.5:[/SIZE][/B][/COLOR]
[COLOR="yellow"][B][SIZE="3"]Short Description:[/SIZE][/B][/COLOR]
Some sort of a Prison for enemy units.
[COLOR="yellow"][B][SIZE="3"]Full Description:[/SIZE][/B][/COLOR]
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.
[jass]
/*
===Confinement v1.5
===Made by: Mckill2009
REQUIRES and CREDITS:
- 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
*/
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 = 'A000' //blizzard
private constant integer FENCE1_ID = 'h002'
private constant integer FENCE2_ID = 'h003'
private constant integer AURA_ID = 'h000'
private constant integer ORDER_ID = 852089 //blizzard
private constant attacktype ATT = ATTACK_TYPE_PIERCE
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant real PRISON_AOE = 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
private real Pull
endglobals
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and u!=null
endfunction
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
boolean isChanneling
private method filterunits takes unit u returns boolean
return IsUnitEnemy(u, GetOwningPlayer(.aura)) and UnitAlive(u) and not /*
*/ IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL)
endmethod
private method damageThem takes unit u returns nothing
local unit first
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE_DAM, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if .filterunits(first) then
call UnitDamageTarget(.aura, first, .hurt , false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
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 UnitAlive(.caster) and .isChanneling then
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 + PRISON_AOE * Cos(.angle1))
call SetUnitY(.fence1, .y + PRISON_AOE * Sin(.angle1))
call SetUnitX(.fence2, .x + PRISON_AOE * Cos(.angle2))
call SetUnitY(.fence2, .y + PRISON_AOE * Sin(.angle2))
//===ConfineThem
call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, PRISON_AOE, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u==null
if filterunits(u) 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 > Pull 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 damageThem(.fence1)
//===Fence2, DamageThem
call damageThem(.fence2)
else
set .isChanneling = false
call IssueImmediateOrder(.caster, "stop")
endif
else
call KillUnit(.aura)
call KillUnit(.fence1)
call KillUnit(.fence2)
set .aura = null
set .fence1 = null
set .fence2 = null
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method cast takes nothing returns boolean
local thistype this
local integer level
local player p
if GetSpellAbilityId()==SPELL_ID then
set this = create()
set p = GetTriggerPlayer()
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(caster, SPELL_ID)
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
set .isChanneling = true
call .startPeriodic()
set p = null
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 Pull = (PRISON_AOE-50)*(PRISON_AOE-50)
set t = null
endmethod
endstruct
endlibrary
[/jass]
[hidden=Changelogs]
v1.5
- Fixed the caster will automatically stop when duration is done
v1.4
- Code optimized and shortened
v1.3
- Scope converted to library
- Added BoundSentinel library
- Dummy removed as it's useless
- Degrees converted to radians
- Code fully optimized
v1.2
- StructRecycler removed.
- Some constants & text adjustments.
v1.1
- TimerUtils replaced by T32.
- Struct recyling applied.
- Codes fully optimized and efficient.
[/hidden]
//TESH.scrollpos=36
//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 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=84
//TESH.alwaysfold=0
/*
===Confinement v1.5
===Made by: Mckill2009
REQUIRES and CREDITS:
- 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
*/
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 = 'A000' //blizzard
private constant integer FENCE1_ID = 'h002'
private constant integer FENCE2_ID = 'h003'
private constant integer AURA_ID = 'h000'
private constant integer ORDER_ID = 852089 //blizzard
private constant attacktype ATT = ATTACK_TYPE_PIERCE
private constant damagetype DAM = DAMAGE_TYPE_DEATH
private constant real PRISON_AOE = 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
private real Pull
endglobals
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and u!=null
endfunction
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
boolean isChanneling
private method filterunits takes unit u returns boolean
return IsUnitEnemy(u, GetOwningPlayer(.aura)) and UnitAlive(u) and not /*
*/ IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL)
endmethod
private method damageThem takes unit u returns nothing
local unit first
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE_DAM, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if .filterunits(first) then
call UnitDamageTarget(.aura, first, .hurt , false, false, ATT, DAM, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
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 UnitAlive(.caster) and .isChanneling then
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 + PRISON_AOE * Cos(.angle1))
call SetUnitY(.fence1, .y + PRISON_AOE * Sin(.angle1))
call SetUnitX(.fence2, .x + PRISON_AOE * Cos(.angle2))
call SetUnitY(.fence2, .y + PRISON_AOE * Sin(.angle2))
//===ConfineThem
call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, PRISON_AOE, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u==null
if filterunits(u) 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 > Pull 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 damageThem(.fence1)
//===Fence2, DamageThem
call damageThem(.fence2)
else
set .isChanneling = false
call IssueImmediateOrder(.caster, "stop")
endif
else
call KillUnit(.aura)
call KillUnit(.fence1)
call KillUnit(.fence2)
set .aura = null
set .fence1 = null
set .fence2 = null
call .stopPeriodic()
call .destroy()
endif
endmethod
implement T32x
static method cast takes nothing returns boolean
local thistype this
local integer level
local player p
if GetSpellAbilityId()==SPELL_ID then
set this = create()
set p = GetTriggerPlayer()
set .caster = GetTriggerUnit()
set level = GetUnitAbilityLevel(caster, SPELL_ID)
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
set .isChanneling = true
call .startPeriodic()
set p = null
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 Pull = (PRISON_AOE-50)*(PRISON_AOE-50)
set t = null
endmethod
endstruct
endlibrary