Name | Type | is_array | initial_value |
//TESH.scrollpos=26
//TESH.alwaysfold=0
library XYLibrary initializer onInit
globals
private real MinX
private real MaxX
private real MinY
private real MaxY
endglobals
function AngleXY takes real x1, real y1, real x2, real y2 returns real
return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
function DistanceXY takes real x1, real y1, real x2, real y2 returns real
return SquareRoot( (x2-x1) * (x2-x1) + (y2-y1) * (y2-y1))
endfunction
function GetPPX takes real x, real dist, real angle returns real
local real X = x + dist * Cos(angle * bj_DEGTORAD)
if X < MinX then
return MinX
endif
if X > MaxX then
return MaxX
endif
return X
endfunction
function GetPPY takes real y, real dist, real angle returns real
local real Y = y + dist * Sin(angle * bj_DEGTORAD)
if Y < MinY then
return MinY
endif
if Y > MaxY then
return MaxY
endif
return Y
endfunction
function SetUnitZ takes unit u, real h returns nothing
call UnitAddAbility( u , 'Amrf')
call UnitRemoveAbility( u , 'Amrf' )
call SetUnitFlyHeight( u , h, 0. )
endfunction
private function onInit takes nothing returns nothing
set MinX = GetRectMinX( bj_mapInitialPlayableArea )
set MaxX = GetRectMaxX( bj_mapInitialPlayableArea )
set MinY = GetRectMinY( bj_mapInitialPlayableArea )
set MaxY = GetRectMaxY( bj_mapInitialPlayableArea )
endfunction
endlibrary
//TESH.scrollpos=219
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+)
//* ----------
//*
//* 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)
//* 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 = 256
//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.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
//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")
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")
set tT[0]=CreateTimer()
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
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
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
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=201
//TESH.alwaysfold=0
// HOW TO IMPORT THIS SPELL :
// COPY TRIGGER BURNINGSLASH AND SYSTEM FOLDER
// COPY THE ABILITY "BURNING SLASH" AND COPY THE DUMMIES "BURNING SLASH" INTO YOUR MAP
// THEN CHANGE THE RAW CODE TO THE ABILITY AND THE DUMMIES THAT YOU'VE COPIED
// YOU NEED INSTALL JASSNEWGENPACK 1.5D AND JASSHELPER
// THIS SPELL REQUIRES TIMERUTILS AND XYLIBRARY
// CREDIT TO PEOPLE WHO MADE THESE MODELS THAT I'M USING IN BURNING SLASH MAP
scope burningslash initializer Init
globals
private constant integer Slash = 'A000' // Ability Code
private constant integer slash1 = 'h000' // Dummy Code
private constant integer slash2 = 'h001' // Dummy Code
private constant integer slash3 = 'h002' // Dummy Code
private constant integer slash4 = 'h003' // Dummy Code
private constant string a1 = "attack"
private constant string a2 = "spell slam swim"
private constant string a3 = "spell"
private constant string a4 = "death"
private constant string at1 = "weapon" // Attachment point
private constant string at2 = "chest" // Attachment point
private constant string at3 = "origin"
private constant string SFX = "HolyPhoenixFire.mdx" // SFX on weapon
private constant string SFX2 = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdx" // SFX on target
private constant string SFX3 = "RandomSlash.mdl" // SFX on dummy
private constant string SFX4 = "poweraura.MDX" // SFX on caster
private constant attacktype ATT = ATTACK_TYPE_NORMAL
private constant damagetype DAT = DAMAGE_TYPE_NORMAL
private constant weapontype WEP = WEAPON_TYPE_WHOKNOWS
private constant real DummyScale = 3
private constant real CasterSpeed = 5 // Caster's Speed
private constant real Period = 0.04 // Timer
private integer TEMPINT
endglobals
private struct bs
unit trunks
unit target
real angle
real damage
real fdamage
real time
real scale
effect e
effect e2
integer random
integer tick
integer lvl
endstruct
private struct bs2
unit trunks
unit target
unit s2
unit s3
real angle
real damage
real fdamage
integer tick
integer lvl
endstruct
private function SlashC takes nothing returns boolean // Check the ability
return GetSpellAbilityId() == Slash
endfunction
private function SlashD takes integer lvl returns real // Damage per slash
return lvl * 16.
endfunction
private function SlashF takes integer lvl returns real // Damage at last
return lvl * 40.
endfunction
private function SlashK takes nothing returns nothing
local timer ti2 = GetExpiredTimer()
local bs2 data = GetTimerData(ti2)
local unit s2
local unit s4
local real x = GetUnitX(data.s2)
local real y = GetUnitY(data.s2)
local real xx = GetPPX(x,80,data.angle)
local real yy = GetPPY(y,80,data.angle)
call SetUnitX(data.s2,xx)
call SetUnitY(data.s2,yy)
set s2 = CreateUnit(GetOwningPlayer(data.trunks),slash2,x,y,data.angle)
call SetUnitZ(s2,150)
call SetUnitScale(s2,DummyScale,DummyScale,DummyScale)
call SetUnitPathing(s2,false)
call UnitApplyTimedLife(s2,'BLTF',2)
set s4 = CreateUnit(GetOwningPlayer(data.trunks),slash4,x,y,data.angle)
call SetUnitScale(s4,DummyScale,DummyScale,DummyScale)
call SetUnitPathing(s4,false)
call UnitApplyTimedLife(s4,'BLTF',2)
call UnitDamageTarget(data.trunks,data.target,data.fdamage,false,false,ATT,DAT,WEP)
set data.tick = data.tick - 1
if data.tick <= 0 or IsUnitType(data.trunks,UNIT_TYPE_DEAD) or IsUnitType(data.target,UNIT_TYPE_DEAD) then
call KillUnit(data.s2)
call KillUnit(data.s3)
call ShowUnit(data.s3,false)
call PauseUnit(data.trunks,false)
call PauseUnit(data.target,false)
call ReleaseTimer(ti2)
call data.destroy()
endif
set s2 = null
set s4 = null
endfunction
private function SlashT takes nothing returns nothing
local timer ti = GetExpiredTimer()
local timer ti2
local bs d = GetTimerData(ti)
local bs2 data
local real x = GetUnitX(d.target)
local real y = GetUnitY(d.target)
local unit s1
local unit s2
local unit s3
set d.scale = GetRandomReal(0.2,1.2)
set s1 = CreateUnit(GetOwningPlayer(d.trunks),slash1,x,y,GetRandomReal(0,360))
call UnitApplyTimedLife(s1,'BLTF',1.)
call SetUnitScale(s1,d.scale,d.scale,d.scale)
call SetUnitZ(s1,GetRandomReal(0,100))
call DestroyEffect(AddSpecialEffectTarget(SFX3,s1,at2))
call SetUnitAnimation(d.target,a4)
call DestroyEffect(AddSpecialEffectTarget(SFX2,d.target,at2))
call UnitDamageTarget(d.trunks,d.target,d.damage,false,false,ATT,DAT,WEP)
set d.random = GetRandomInt(1,3) + 1
if d.random == 1 then
call SetUnitAnimation(d.trunks,a1)
else
if d.random == 2 then
call SetUnitAnimation(d.trunks,a2)
else
if d.random == 3 then
call SetUnitAnimation(d.trunks,a1)
endif
endif
endif
set d.time = d.time + Period
if d.time >= 3 then
set s2 = CreateUnit(GetOwningPlayer(d.trunks),slash2,GetUnitX(d.target),GetUnitY(d.target),d.angle)
set s3 = CreateUnit(GetOwningPlayer(d.trunks),slash3,GetUnitX(d.target),GetUnitY(d.target),d.angle-180)
call SetUnitZ(s2,150)
call SetUnitZ(s3,200)
call SetUnitPathing(s2,false)
call SetUnitPathing(s3,false)
call SetUnitScale(s2,DummyScale,DummyScale,DummyScale)
call SetUnitScale(s3,DummyScale,DummyScale,DummyScale)
call SetUnitAnimation(d.trunks,a3)
call SetUnitTimeScale(d.trunks,1)
call DestroyEffect(d.e)
call DestroyEffect(d.e2)
set data = bs2.create()
set data.trunks = d.trunks
set data.target = d.target
set data.s2 = s2
set data.s3 = s3
set data.angle = d.angle
set data.tick = d.tick
set data.lvl = d.lvl
set data.damage = d.damage
set data.fdamage = d.fdamage
set ti2 = NewTimer()
call SetTimerData(ti2,data)
call TimerStart(ti2,Period,true,function SlashK)
call ReleaseTimer(ti)
call d.destroy()
endif
if IsUnitType(d.trunks,UNIT_TYPE_DEAD) or IsUnitType(d.target,UNIT_TYPE_DEAD) then
call PauseUnit(d.trunks,false)
call PauseUnit(d.target,false)
call SetUnitTimeScale(d.trunks,1)
call DestroyEffect(d.e)
call DestroyEffect(d.e2)
call ReleaseTimer(ti)
call d.destroy()
endif
set s1 = null
set s2 = null
set s3 = null
endfunction
private function SlashA takes nothing returns nothing
local timer ti
local bs d
local unit c = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local real cx = GetUnitX(c)
local real cy = GetUnitY(c)
local real tx = GetUnitX(target)
local real ty = GetUnitY(target)
call PauseUnit(c,true)
call PauseUnit(target,true)
call SetUnitTimeScale(c,CasterSpeed)
set d = bs.create()
set d.trunks = c
set d.target = target
set d.angle = AngleXY(cx,cy,tx,ty)
set d.time = 0
set d.random = 0
set d.tick = 25
set d.e = AddSpecialEffectTarget(SFX,c,at1)
set d.e2 = AddSpecialEffectTarget(SFX4,c,at3)
set d.lvl = GetUnitAbilityLevel(d.trunks,Slash)
set d.damage = SlashD(d.lvl)
set d.fdamage = SlashF(d.lvl)
set ti = NewTimer()
call SetTimerData(ti,d)
call TimerStart(ti,Period,true,function SlashT)
set c = null
set target = null
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function SlashA)
call TriggerAddCondition(t,Condition(function SlashC))
endfunction
endscope